genie_dat/
random_map.rs

1use crate::unit_type::UnitTypeID;
2use byteorder::{ReadBytesExt, WriteBytesExt, LE};
3use std::convert::TryInto;
4use std::io::{Read, Result, Write};
5
6#[derive(Debug, Default, Clone)]
7pub struct RandomMapInfo {
8    id: i32,
9    borders: (i32, i32, i32, i32),
10    border_fade: i32,
11    water_border: i32,
12    base_terrain: i32,
13    land_percent: i32,
14    lands: Vec<RandomMapLand>,
15    terrains: Vec<RandomMapTerrain>,
16    objects: Vec<RandomMapObject>,
17    elevations: Vec<RandomMapElevation>,
18}
19
20impl RandomMapInfo {
21    pub fn read_from<R: Read>(input: &mut R) -> Result<Self> {
22        let mut info = Self::default();
23        info.id = input.read_i32::<LE>()?;
24        info.borders = (
25            input.read_i32::<LE>()?,
26            input.read_i32::<LE>()?,
27            input.read_i32::<LE>()?,
28            input.read_i32::<LE>()?,
29        );
30        info.border_fade = input.read_i32::<LE>()?;
31        info.water_border = input.read_i32::<LE>()?;
32        info.base_terrain = input.read_i32::<LE>()?;
33        info.land_percent = input.read_i32::<LE>()?;
34
35        let _some_id = input.read_i32::<LE>()?;
36        let num_lands = input.read_u32::<LE>()?;
37        let _pointer = input.read_u32::<LE>()?;
38        let num_terrains = input.read_u32::<LE>()?;
39        let _pointer = input.read_u32::<LE>()?;
40        let num_objects = input.read_u32::<LE>()?;
41        let _pointer = input.read_u32::<LE>()?;
42        let num_elevations = input.read_u32::<LE>()?;
43        let _pointer = input.read_u32::<LE>()?;
44
45        info.lands = vec![RandomMapLand::default(); num_lands.try_into().unwrap()];
46        info.terrains = vec![RandomMapTerrain::default(); num_terrains.try_into().unwrap()];
47        info.objects = vec![RandomMapObject::default(); num_objects.try_into().unwrap()];
48        info.elevations = vec![RandomMapElevation::default(); num_elevations.try_into().unwrap()];
49
50        Ok(info)
51    }
52
53    pub fn finish<R: Read>(&mut self, input: &mut R) -> Result<()> {
54        // duplicate data
55        std::io::copy(&mut input.by_ref().take(44), &mut std::io::sink())?;
56        for land in self.lands.iter_mut() {
57            *land = RandomMapLand::read_from(input)?;
58        }
59
60        // duplicate data
61        std::io::copy(&mut input.by_ref().take(8), &mut std::io::sink())?;
62        for terrain in self.terrains.iter_mut() {
63            *terrain = RandomMapTerrain::read_from(input)?;
64        }
65
66        // duplicate data
67        std::io::copy(&mut input.by_ref().take(8), &mut std::io::sink())?;
68        for object in self.objects.iter_mut() {
69            *object = RandomMapObject::read_from(input)?;
70        }
71
72        // duplicate data
73        std::io::copy(&mut input.by_ref().take(8), &mut std::io::sink())?;
74        for elevation in self.elevations.iter_mut() {
75            *elevation = RandomMapElevation::read_from(input)?;
76        }
77        Ok(())
78    }
79
80    pub fn write_to<W: Write>(&self, output: &mut W) -> Result<()> {
81        output.write_i32::<LE>(self.id)?;
82        output.write_i32::<LE>(self.borders.0)?;
83        output.write_i32::<LE>(self.borders.1)?;
84        output.write_i32::<LE>(self.borders.2)?;
85        output.write_i32::<LE>(self.borders.3)?;
86        output.write_i32::<LE>(self.border_fade)?;
87        output.write_i32::<LE>(self.water_border)?;
88        output.write_i32::<LE>(self.base_terrain)?;
89        output.write_i32::<LE>(self.land_percent)?;
90
91        output.write_i32::<LE>(0)?; // some id
92        output.write_u32::<LE>(self.lands.len().try_into().unwrap())?;
93        output.write_u32::<LE>(0)?; // pointer
94        output.write_u32::<LE>(self.terrains.len().try_into().unwrap())?;
95        output.write_u32::<LE>(0)?; // pointer
96        output.write_u32::<LE>(self.objects.len().try_into().unwrap())?;
97        output.write_u32::<LE>(0)?; // pointer
98        output.write_u32::<LE>(self.elevations.len().try_into().unwrap())?;
99        output.write_u32::<LE>(0)?; // pointer
100
101        Ok(())
102    }
103
104    pub fn write_commands_to<W: Write>(&self, output: &mut W) -> Result<()> {
105        output.write_i32::<LE>(self.borders.0)?;
106        output.write_i32::<LE>(self.borders.1)?;
107        output.write_i32::<LE>(self.borders.2)?;
108        output.write_i32::<LE>(self.borders.3)?;
109        output.write_i32::<LE>(self.border_fade)?;
110        output.write_i32::<LE>(self.water_border)?;
111        output.write_i32::<LE>(self.base_terrain)?;
112        output.write_i32::<LE>(self.land_percent)?;
113        output.write_u32::<LE>(0)?; // some id
114
115        output.write_u32::<LE>(self.lands.len().try_into().unwrap())?;
116        output.write_u32::<LE>(0)?; // pointer
117        for land in &self.lands {
118            land.write_to(output)?;
119        }
120        output.write_u32::<LE>(self.terrains.len().try_into().unwrap())?;
121        output.write_u32::<LE>(0)?; // pointer
122        for terrain in &self.terrains {
123            terrain.write_to(output)?;
124        }
125        output.write_u32::<LE>(self.objects.len().try_into().unwrap())?;
126        output.write_u32::<LE>(0)?; // pointer
127        for object in &self.objects {
128            object.write_to(output)?;
129        }
130        output.write_u32::<LE>(self.elevations.len().try_into().unwrap())?;
131        output.write_u32::<LE>(0)?; // pointer
132        for elevation in &self.elevations {
133            elevation.write_to(output)?;
134        }
135        Ok(())
136    }
137}
138
139#[derive(Debug, Default, Clone)]
140pub struct RandomMapLand {
141    id: i32,
142    terrain_type: u8,
143    land_avoidance_tiles: i32,
144    base_square_radius: i32,
145    zone: i8,
146    placement_type: i8,
147    x: i32,
148    y: i32,
149    amount_of_land_used_percent: i8,
150    by_player_flag: i8,
151    radius: i32,
152    fade: i32,
153    clumpiness_factor: i32,
154}
155
156impl RandomMapLand {
157    pub fn read_from<R: Read>(input: &mut R) -> Result<Self> {
158        let mut land = Self::default();
159        land.id = input.read_i32::<LE>()?;
160        land.terrain_type = input.read_u8()?;
161        let _padding = input.read_u16::<LE>()?;
162        let _padding = input.read_u8()?;
163        land.land_avoidance_tiles = input.read_i32::<LE>()?;
164        land.base_square_radius = input.read_i32::<LE>()?;
165        land.zone = input.read_i8()?;
166        land.placement_type = input.read_i8()?;
167        let _padding = input.read_u16::<LE>()?;
168        land.x = input.read_i32::<LE>()?;
169        land.y = input.read_i32::<LE>()?;
170        land.amount_of_land_used_percent = input.read_i8()?;
171        land.by_player_flag = input.read_i8()?;
172        let _padding = input.read_u16::<LE>()?;
173        land.radius = input.read_i32::<LE>()?;
174        land.fade = input.read_i32::<LE>()?;
175        land.clumpiness_factor = input.read_i32::<LE>()?;
176        Ok(land)
177    }
178
179    pub fn write_to<W: Write>(&self, output: &mut W) -> Result<()> {
180        output.write_i32::<LE>(self.id)?;
181        output.write_u8(self.terrain_type)?;
182        output.write_u16::<LE>(0)?;
183        output.write_u8(0)?;
184        output.write_i32::<LE>(self.land_avoidance_tiles)?;
185        output.write_i32::<LE>(self.base_square_radius)?;
186        output.write_i8(self.zone)?;
187        output.write_i8(self.placement_type)?;
188        output.write_u16::<LE>(0)?;
189        output.write_i32::<LE>(self.x)?;
190        output.write_i32::<LE>(self.y)?;
191        output.write_i8(self.amount_of_land_used_percent)?;
192        output.write_i8(self.by_player_flag)?;
193        output.write_u16::<LE>(0)?;
194        output.write_i32::<LE>(self.radius)?;
195        output.write_i32::<LE>(self.fade)?;
196        output.write_i32::<LE>(self.clumpiness_factor)?;
197        Ok(())
198    }
199}
200
201#[derive(Debug, Default, Clone)]
202pub struct RandomMapTerrain {
203    percent: i32,
204    terrain_type: i32,
205    clumps: i32,
206    spacing: i32,
207    base_terrain_type: i32,
208    clumpiness_factor: i32,
209}
210
211impl RandomMapTerrain {
212    pub fn read_from<R: Read>(input: &mut R) -> Result<Self> {
213        let mut terrain = Self::default();
214        terrain.percent = input.read_i32::<LE>()?;
215        terrain.terrain_type = input.read_i32::<LE>()?;
216        terrain.clumps = input.read_i32::<LE>()?;
217        terrain.spacing = input.read_i32::<LE>()?;
218        terrain.base_terrain_type = input.read_i32::<LE>()?;
219        terrain.clumpiness_factor = input.read_i32::<LE>()?;
220        Ok(terrain)
221    }
222
223    pub fn write_to<W: Write>(&self, output: &mut W) -> Result<()> {
224        output.write_i32::<LE>(self.percent)?;
225        output.write_i32::<LE>(self.terrain_type)?;
226        output.write_i32::<LE>(self.clumps)?;
227        output.write_i32::<LE>(self.spacing)?;
228        output.write_i32::<LE>(self.base_terrain_type)?;
229        output.write_i32::<LE>(self.clumpiness_factor)?;
230        Ok(())
231    }
232}
233
234#[derive(Debug, Default, Clone)]
235pub struct RandomMapObject {
236    unit_type: UnitTypeID,
237    terrain_type: i32,
238    group_flag: i8,
239    scale_flag: i8,
240    group_size: i32,
241    group_size_variance: i32,
242    group_count: i32,
243    group_area: i32,
244    player_id: i32,
245    land_id: i32,
246    min_distance_to_players: i32,
247    max_distance_to_players: i32,
248}
249
250impl RandomMapObject {
251    pub fn read_from<R: Read>(input: &mut R) -> Result<Self> {
252        let mut object = Self::default();
253        object.unit_type = input.read_u32::<LE>()?.try_into().unwrap();
254        object.terrain_type = input.read_i32::<LE>()?;
255        object.group_flag = input.read_i8()?;
256        object.scale_flag = input.read_i8()?;
257        let _padding = input.read_u16::<LE>()?;
258        object.group_size = input.read_i32::<LE>()?;
259        object.group_size_variance = input.read_i32::<LE>()?;
260        object.group_count = input.read_i32::<LE>()?;
261        object.group_area = input.read_i32::<LE>()?;
262        object.player_id = input.read_i32::<LE>()?;
263        object.land_id = input.read_i32::<LE>()?;
264        object.min_distance_to_players = input.read_i32::<LE>()?;
265        object.max_distance_to_players = input.read_i32::<LE>()?;
266        Ok(object)
267    }
268
269    pub fn write_to<W: Write>(&self, output: &mut W) -> Result<()> {
270        output.write_u32::<LE>(self.unit_type.try_into().unwrap())?;
271        output.write_i32::<LE>(self.terrain_type)?;
272        output.write_i8(self.group_flag)?;
273        output.write_i8(self.scale_flag)?;
274        output.write_u16::<LE>(0)?;
275        output.write_i32::<LE>(self.group_size)?;
276        output.write_i32::<LE>(self.group_size_variance)?;
277        output.write_i32::<LE>(self.group_count)?;
278        output.write_i32::<LE>(self.group_area)?;
279        output.write_i32::<LE>(self.player_id)?;
280        output.write_i32::<LE>(self.land_id)?;
281        output.write_i32::<LE>(self.min_distance_to_players)?;
282        output.write_i32::<LE>(self.max_distance_to_players)?;
283        Ok(())
284    }
285}
286
287#[derive(Debug, Default, Clone)]
288pub struct RandomMapElevation {
289    percent: i32,
290    height: i32,
291    clumps: i32,
292    spacing: i32,
293    base_terrain_type: i32,
294    base_elevation_type: i32,
295}
296
297impl RandomMapElevation {
298    pub fn read_from<R: Read>(input: &mut R) -> Result<Self> {
299        let mut elevation = Self::default();
300        elevation.percent = input.read_u32::<LE>()?.try_into().unwrap();
301        elevation.height = input.read_i32::<LE>()?;
302        elevation.clumps = input.read_i32::<LE>()?;
303        elevation.spacing = input.read_i32::<LE>()?;
304        elevation.base_terrain_type = input.read_i32::<LE>()?;
305        elevation.base_elevation_type = input.read_i32::<LE>()?;
306        Ok(elevation)
307    }
308
309    pub fn write_to<W: Write>(&self, output: &mut W) -> Result<()> {
310        output.write_i32::<LE>(self.percent)?;
311        output.write_i32::<LE>(self.height)?;
312        output.write_i32::<LE>(self.clumps)?;
313        output.write_i32::<LE>(self.spacing)?;
314        output.write_i32::<LE>(self.base_terrain_type)?;
315        output.write_i32::<LE>(self.base_elevation_type)?;
316        Ok(())
317    }
318}