use crate::unit_type::UnitTypeID; use byteorder::{ReadBytesExt, WriteBytesExt, LE}; use std::convert::TryInto; use std::io::{Read, Result, Write}; #[derive(Debug, Default, Clone)] pub struct RandomMapInfo { id: i32, borders: (i32, i32, i32, i32), border_fade: i32, water_border: i32, base_terrain: i32, land_percent: i32, lands: Vec, terrains: Vec, objects: Vec, elevations: Vec, } impl RandomMapInfo { pub fn read_from(input: &mut R) -> Result { let mut info = Self::default(); info.id = input.read_i32::()?; info.borders = ( input.read_i32::()?, input.read_i32::()?, input.read_i32::()?, input.read_i32::()?, ); info.border_fade = input.read_i32::()?; info.water_border = input.read_i32::()?; info.base_terrain = input.read_i32::()?; info.land_percent = input.read_i32::()?; let _some_id = input.read_i32::()?; let num_lands = input.read_u32::()?; let _pointer = input.read_u32::()?; let num_terrains = input.read_u32::()?; let _pointer = input.read_u32::()?; let num_objects = input.read_u32::()?; let _pointer = input.read_u32::()?; let num_elevations = input.read_u32::()?; let _pointer = input.read_u32::()?; info.lands = vec![RandomMapLand::default(); num_lands.try_into().unwrap()]; info.terrains = vec![RandomMapTerrain::default(); num_terrains.try_into().unwrap()]; info.objects = vec![RandomMapObject::default(); num_objects.try_into().unwrap()]; info.elevations = vec![RandomMapElevation::default(); num_elevations.try_into().unwrap()]; Ok(info) } pub fn finish(&mut self, input: &mut R) -> Result<()> { // duplicate data std::io::copy(&mut input.by_ref().take(44), &mut std::io::sink())?; for land in self.lands.iter_mut() { *land = RandomMapLand::read_from(input)?; } // duplicate data std::io::copy(&mut input.by_ref().take(8), &mut std::io::sink())?; for terrain in self.terrains.iter_mut() { *terrain = RandomMapTerrain::read_from(input)?; } // duplicate data std::io::copy(&mut input.by_ref().take(8), &mut std::io::sink())?; for object in self.objects.iter_mut() { *object = RandomMapObject::read_from(input)?; } // duplicate data std::io::copy(&mut input.by_ref().take(8), &mut std::io::sink())?; for elevation in self.elevations.iter_mut() { *elevation = RandomMapElevation::read_from(input)?; } Ok(()) } pub fn write_to(&self, output: &mut W) -> Result<()> { output.write_i32::(self.id)?; output.write_i32::(self.borders.0)?; output.write_i32::(self.borders.1)?; output.write_i32::(self.borders.2)?; output.write_i32::(self.borders.3)?; output.write_i32::(self.border_fade)?; output.write_i32::(self.water_border)?; output.write_i32::(self.base_terrain)?; output.write_i32::(self.land_percent)?; output.write_i32::(0)?; // some id output.write_u32::(self.lands.len().try_into().unwrap())?; output.write_u32::(0)?; // pointer output.write_u32::(self.terrains.len().try_into().unwrap())?; output.write_u32::(0)?; // pointer output.write_u32::(self.objects.len().try_into().unwrap())?; output.write_u32::(0)?; // pointer output.write_u32::(self.elevations.len().try_into().unwrap())?; output.write_u32::(0)?; // pointer Ok(()) } pub fn write_commands_to(&self, output: &mut W) -> Result<()> { output.write_i32::(self.borders.0)?; output.write_i32::(self.borders.1)?; output.write_i32::(self.borders.2)?; output.write_i32::(self.borders.3)?; output.write_i32::(self.border_fade)?; output.write_i32::(self.water_border)?; output.write_i32::(self.base_terrain)?; output.write_i32::(self.land_percent)?; output.write_u32::(0)?; // some id output.write_u32::(self.lands.len().try_into().unwrap())?; output.write_u32::(0)?; // pointer for land in &self.lands { land.write_to(output)?; } output.write_u32::(self.terrains.len().try_into().unwrap())?; output.write_u32::(0)?; // pointer for terrain in &self.terrains { terrain.write_to(output)?; } output.write_u32::(self.objects.len().try_into().unwrap())?; output.write_u32::(0)?; // pointer for object in &self.objects { object.write_to(output)?; } output.write_u32::(self.elevations.len().try_into().unwrap())?; output.write_u32::(0)?; // pointer for elevation in &self.elevations { elevation.write_to(output)?; } Ok(()) } } #[derive(Debug, Default, Clone)] pub struct RandomMapLand { id: i32, terrain_type: u8, land_avoidance_tiles: i32, base_square_radius: i32, zone: i8, placement_type: i8, x: i32, y: i32, amount_of_land_used_percent: i8, by_player_flag: i8, radius: i32, fade: i32, clumpiness_factor: i32, } impl RandomMapLand { pub fn read_from(input: &mut R) -> Result { let mut land = Self::default(); land.id = input.read_i32::()?; land.terrain_type = input.read_u8()?; let _padding = input.read_u16::()?; let _padding = input.read_u8()?; land.land_avoidance_tiles = input.read_i32::()?; land.base_square_radius = input.read_i32::()?; land.zone = input.read_i8()?; land.placement_type = input.read_i8()?; let _padding = input.read_u16::()?; land.x = input.read_i32::()?; land.y = input.read_i32::()?; land.amount_of_land_used_percent = input.read_i8()?; land.by_player_flag = input.read_i8()?; let _padding = input.read_u16::()?; land.radius = input.read_i32::()?; land.fade = input.read_i32::()?; land.clumpiness_factor = input.read_i32::()?; Ok(land) } pub fn write_to(&self, output: &mut W) -> Result<()> { output.write_i32::(self.id)?; output.write_u8(self.terrain_type)?; output.write_u16::(0)?; output.write_u8(0)?; output.write_i32::(self.land_avoidance_tiles)?; output.write_i32::(self.base_square_radius)?; output.write_i8(self.zone)?; output.write_i8(self.placement_type)?; output.write_u16::(0)?; output.write_i32::(self.x)?; output.write_i32::(self.y)?; output.write_i8(self.amount_of_land_used_percent)?; output.write_i8(self.by_player_flag)?; output.write_u16::(0)?; output.write_i32::(self.radius)?; output.write_i32::(self.fade)?; output.write_i32::(self.clumpiness_factor)?; Ok(()) } } #[derive(Debug, Default, Clone)] pub struct RandomMapTerrain { percent: i32, terrain_type: i32, clumps: i32, spacing: i32, base_terrain_type: i32, clumpiness_factor: i32, } impl RandomMapTerrain { pub fn read_from(input: &mut R) -> Result { let mut terrain = Self::default(); terrain.percent = input.read_i32::()?; terrain.terrain_type = input.read_i32::()?; terrain.clumps = input.read_i32::()?; terrain.spacing = input.read_i32::()?; terrain.base_terrain_type = input.read_i32::()?; terrain.clumpiness_factor = input.read_i32::()?; Ok(terrain) } pub fn write_to(&self, output: &mut W) -> Result<()> { output.write_i32::(self.percent)?; output.write_i32::(self.terrain_type)?; output.write_i32::(self.clumps)?; output.write_i32::(self.spacing)?; output.write_i32::(self.base_terrain_type)?; output.write_i32::(self.clumpiness_factor)?; Ok(()) } } #[derive(Debug, Default, Clone)] pub struct RandomMapObject { unit_type: UnitTypeID, terrain_type: i32, group_flag: i8, scale_flag: i8, group_size: i32, group_size_variance: i32, group_count: i32, group_area: i32, player_id: i32, land_id: i32, min_distance_to_players: i32, max_distance_to_players: i32, } impl RandomMapObject { pub fn read_from(input: &mut R) -> Result { let mut object = Self::default(); object.unit_type = input.read_u32::()?.try_into().unwrap(); object.terrain_type = input.read_i32::()?; object.group_flag = input.read_i8()?; object.scale_flag = input.read_i8()?; let _padding = input.read_u16::()?; object.group_size = input.read_i32::()?; object.group_size_variance = input.read_i32::()?; object.group_count = input.read_i32::()?; object.group_area = input.read_i32::()?; object.player_id = input.read_i32::()?; object.land_id = input.read_i32::()?; object.min_distance_to_players = input.read_i32::()?; object.max_distance_to_players = input.read_i32::()?; Ok(object) } pub fn write_to(&self, output: &mut W) -> Result<()> { output.write_u32::(self.unit_type.try_into().unwrap())?; output.write_i32::(self.terrain_type)?; output.write_i8(self.group_flag)?; output.write_i8(self.scale_flag)?; output.write_u16::(0)?; output.write_i32::(self.group_size)?; output.write_i32::(self.group_size_variance)?; output.write_i32::(self.group_count)?; output.write_i32::(self.group_area)?; output.write_i32::(self.player_id)?; output.write_i32::(self.land_id)?; output.write_i32::(self.min_distance_to_players)?; output.write_i32::(self.max_distance_to_players)?; Ok(()) } } #[derive(Debug, Default, Clone)] pub struct RandomMapElevation { percent: i32, height: i32, clumps: i32, spacing: i32, base_terrain_type: i32, base_elevation_type: i32, } impl RandomMapElevation { pub fn read_from(input: &mut R) -> Result { let mut elevation = Self::default(); elevation.percent = input.read_u32::()?.try_into().unwrap(); elevation.height = input.read_i32::()?; elevation.clumps = input.read_i32::()?; elevation.spacing = input.read_i32::()?; elevation.base_terrain_type = input.read_i32::()?; elevation.base_elevation_type = input.read_i32::()?; Ok(elevation) } pub fn write_to(&self, output: &mut W) -> Result<()> { output.write_i32::(self.percent)?; output.write_i32::(self.height)?; output.write_i32::(self.clumps)?; output.write_i32::(self.spacing)?; output.write_i32::(self.base_terrain_type)?; output.write_i32::(self.base_elevation_type)?; Ok(()) } }