1use super::core::*;
2use assembly_core::nom::{
3 call, cond, do_parse, fold_many_m_n, length_count, map_opt, map_res, named, named_args,
4 number::complete::{le_f32, le_u32, le_u8},
5 pair, switch, value, IResult,
6};
7use assembly_core::parser::{
8 parse_object_id, parse_object_template, parse_quat, parse_quat_wxyz, parse_u32_wstring,
9 parse_u8_bool, parse_u8_wstring, parse_vec3f, parse_world_id,
10};
11use num_traits::FromPrimitive;
12use std::collections::HashMap;
13use std::convert::TryFrom;
14
15named!(pub parse_zone_paths_version<ZonePathsVersion>,
16 map_opt!(le_u32, ZonePathsVersion::from_u32)
17);
18
19named!(pub parse_path_version<PathVersion>,
20 map_opt!(le_u32, PathVersion::from_u32)
21);
22
23named!(pub parse_path_type<PathType>,
24 map_opt!(le_u32, PathType::from_u32)
25);
26
27named!(pub parse_path_composition<PathComposition>,
28 map_opt!(le_u32, PathComposition::from_u32)
29);
30
31named!(pub parse_path_data_movement<PathDataMovement>,
32 value!(PathDataMovement{})
33);
34
35named_args!(pub parse_path_data_moving_platform(version: PathVersion)<PathDataMovingPlatform>,
36 do_parse!(
37 a: cond!(version.min(18), call!(le_u8)) >>
38 b: cond!(version.min(13) && !version.min(18), call!(parse_u8_wstring)) >>
39 (PathDataMovingPlatform{
40 something: a,
41 platform_travel_sound: b,
42 })
43 )
44);
45
46named!(pub parse_property_rental_time_unit<PropertyRentalTimeUnit>,
47 map_opt!(le_u32, PropertyRentalTimeUnit::from_u32)
48);
49
50named!(pub parse_property_achievement_required<PropertyAchievementRequired>,
51 map_opt!(le_u32, PropertyAchievementRequired::from_u32)
52);
53
54named!(pub parse_path_data_property<PathDataProperty>,
55 do_parse!(
56 value_1: le_u32 >>
57 price: le_u32 >>
58 rental_time: le_u32 >>
59 associated_map: parse_world_id >>
60 value_2: le_u32 >>
61 display_name: parse_u8_wstring >>
62 display_description: parse_u32_wstring >>
63 value_3: le_u32 >>
64 clone_limit: le_u32 >>
65 reputation_multiplier: le_f32 >>
66 rental_time_unit: parse_property_rental_time_unit >>
67 achievement_required: parse_property_achievement_required >>
68 player_zone_coordinate: parse_vec3f >>
69 max_build_height: le_f32 >>
70 (PathDataProperty {
71 value_1,
72 price, rental_time, associated_map,
73 value_2,
74 display_name, display_description,
75 value_3,
76 clone_limit, reputation_multiplier,
77 rental_time_unit, achievement_required,
78 player_zone_coordinate, max_build_height,
79 })
80 )
81);
82
83named_args!(pub parse_path_data_camera(version: PathVersion)<PathDataCamera>,
84 do_parse!(
85 next_path: parse_u8_wstring >>
86 value_1: cond!(version.min(14), le_u8) >>
87 (PathDataCamera{next_path, value_1})
88 )
89);
90
91named!(pub parse_path_data_spawner<PathDataSpawner>,
92 do_parse!(
93 spawned_lot: parse_object_template >>
94 respawn_time: le_u32 >>
95 max_to_spawn: le_u32 >>
96 min_to_spawn: le_u32 >>
97 spawner_obj_id: parse_object_id >>
98 activate_network_on_load: parse_u8_bool >>
99 (PathDataSpawner{
100 spawned_lot,
101 respawn_time,
102 max_to_spawn,
103 min_to_spawn,
104 spawner_obj_id,
105 activate_network_on_load,
106 })
107 )
108);
109
110named!(pub parse_path_data_showcase<PathDataShowcase>,
111 value!(PathDataShowcase{})
112);
113
114named!(pub parse_path_data_race<PathDataRace>,
115 value!(PathDataRace{})
116);
117
118named!(pub parse_path_data_rail<PathDataRail>,
119 value!(PathDataRail{})
120);
121
122named!(pub parse_path_waypoint_data_movement<PathWaypointDataMovement>,
123 do_parse!(
124 config: parse_waypoint_config >>
125 (PathWaypointDataMovement{config})
126 )
127);
128
129named!(pub parse_path_waypoint_data_moving_platform_sounds<PathWaypointDataMovingPlatformSounds>,
130 do_parse!(
131 depart_sound: parse_u8_wstring >>
132 arrive_sound: parse_u8_wstring >>
133 (PathWaypointDataMovingPlatformSounds{ depart_sound, arrive_sound })
134 )
135);
136
137named_args!(pub parse_path_waypoint_data_moving_platform(version: PathVersion)<PathWaypointDataMovingPlatform>,
138 do_parse!(
139 rotation: parse_quat >>
140 lock_player: parse_u8_bool >>
141 speed: le_f32 >>
142 wait: le_f32 >>
143 sounds: cond!(version.min(13), call!(parse_path_waypoint_data_moving_platform_sounds)) >>
144 (PathWaypointDataMovingPlatform {
145 rotation, lock_player, speed, wait, sounds
146 })
147 )
148);
149
150named!(pub parse_path_waypoint_data_property<PathWaypointDataProperty>,
151 value!(PathWaypointDataProperty{})
152);
153
154named!(pub parse_path_waypoint_data_camera<PathWaypointDataCamera>,
155 do_parse!(
156 rotation: parse_quat >>
157 time: le_f32 >>
158 value_5: le_f32 >>
159 tension: le_f32 >>
160 continuity: le_f32 >>
161 bias: le_f32 >>
162 (PathWaypointDataCamera {
163 rotation, time, value_5,
164 tension, continuity, bias,
165 })
166 )
167);
168
169named!(pub parse_path_waypoint_data_spawner<PathWaypointDataSpawner>,
170 do_parse!(
171 rotation: parse_quat >>
172 config: parse_waypoint_config >>
173 (PathWaypointDataSpawner{ rotation, config })
174 )
175);
176
177named!(pub parse_path_waypoint_data_showcase<PathWaypointDataShowcase>,
178 value!(PathWaypointDataShowcase{})
179);
180
181named!(pub parse_path_waypoint_data_race<PathWaypointDataRace>,
182 do_parse!(
183 rotation: parse_quat >>
184 value_1: le_u8 >>
185 value_2: le_u8 >>
186 value_3: le_f32 >>
187 value_4: le_f32 >>
188 value_5: le_f32 >>
189 (PathWaypointDataRace{ rotation, value_1, value_2, value_3, value_4, value_5 })
190 )
191);
192
193named!(
194 parse_path_waypoint_variant_movement<PathWaypointVariantMovement>,
195 do_parse!(
196 position: parse_vec3f
197 >> data: parse_path_waypoint_data_movement
198 >> (PathWaypointVariantMovement { position, data })
199 )
200);
201
202named_args!(parse_path_variant_movement(header: PathHeader)<PathVariantMovement>,
203 do_parse!(
204 path_data: parse_path_data_movement >>
205 waypoints: length_count!(le_u32, parse_path_waypoint_variant_movement) >>
206 (PathVariantMovement {
207 header, path_data, waypoints,
208 })
209 )
210);
211
212named_args!(parse_path_waypoint_variant_moving_platform(version: PathVersion)<PathWaypointVariantMovingPlatform>,
213 do_parse!(
214 position: parse_vec3f >>
215 data: call!(parse_path_waypoint_data_moving_platform, version) >>
216 (PathWaypointVariantMovingPlatform{position, data})
217 )
218);
219
220named_args!(parse_path_variant_moving_platform(header: PathHeader)<PathVariantMovingPlatform>,
221 do_parse!(
222 path_data: call!(parse_path_data_moving_platform, header.version) >>
223 waypoints: length_count!(le_u32, call!(parse_path_waypoint_variant_moving_platform, header.version)) >>
224 (PathVariantMovingPlatform {
225 header, path_data, waypoints,
226 })
227 )
228);
229
230named!(
231 parse_path_waypoint_variant_property<PathWaypointVariantProperty>,
232 do_parse!(
233 position: parse_vec3f
234 >> data: parse_path_waypoint_data_property
235 >> (PathWaypointVariantProperty { position, data })
236 )
237);
238
239named_args!(parse_path_variant_property(header: PathHeader)<PathVariantProperty>,
240 do_parse!(
241 path_data: parse_path_data_property >>
242 waypoints: length_count!(le_u32, parse_path_waypoint_variant_property) >>
243 (PathVariantProperty {
244 header, path_data, waypoints,
245 })
246 )
247);
248
249named!(
250 parse_path_waypoint_variant_camera<PathWaypointVariantCamera>,
251 do_parse!(
252 position: parse_vec3f
253 >> data: parse_path_waypoint_data_camera
254 >> (PathWaypointVariantCamera { position, data })
255 )
256);
257
258named_args!(parse_path_variant_camera(header: PathHeader)<PathVariantCamera>,
259 do_parse!(
260 path_data: call!(parse_path_data_camera, header.version) >>
261 waypoints: length_count!(le_u32, parse_path_waypoint_variant_camera) >>
262 (PathVariantCamera {
263 header, path_data, waypoints,
264 })
265 )
266);
267
268named!(
269 parse_path_waypoint_variant_spawner<PathWaypointVariantSpawner>,
270 do_parse!(
271 position: parse_vec3f
272 >> data: parse_path_waypoint_data_spawner
273 >> (PathWaypointVariantSpawner { position, data })
274 )
275);
276
277named_args!(parse_path_variant_spawner(header: PathHeader)<PathVariantSpawner>,
278 do_parse!(
279 path_data: parse_path_data_spawner >>
280 waypoints: length_count!(le_u32, parse_path_waypoint_variant_spawner) >>
281 (PathVariantSpawner {
282 header, path_data, waypoints,
283 })
284 )
285);
286
287named!(
288 parse_path_waypoint_variant_showcase<PathWaypointVariantShowcase>,
289 do_parse!(
290 position: parse_vec3f
291 >> data: parse_path_waypoint_data_showcase
292 >> (PathWaypointVariantShowcase { position, data })
293 )
294);
295
296named_args!(parse_path_variant_showcase(header: PathHeader)<PathVariantShowcase>,
297 do_parse!(
298 path_data: parse_path_data_showcase >>
299 waypoints: length_count!(le_u32, parse_path_waypoint_variant_showcase) >>
300 (PathVariantShowcase {
301 header, path_data, waypoints,
302 })
303 )
304);
305
306named!(
307 parse_path_waypoint_variant_race<PathWaypointVariantRace>,
308 do_parse!(
309 position: parse_vec3f
310 >> data: parse_path_waypoint_data_race
311 >> (PathWaypointVariantRace { position, data })
312 )
313);
314
315named_args!(parse_path_variant_race(header: PathHeader)<PathVariantRace>,
316 do_parse!(
317 path_data: parse_path_data_race >>
318 waypoints: length_count!(le_u32, parse_path_waypoint_variant_race) >>
319 (PathVariantRace {
320 header, path_data, waypoints,
321 })
322 )
323);
324
325named!(
326 parse_path_waypoint_variant_rail<PathWaypointVariantRail>,
327 do_parse!(
328 position: parse_vec3f
329 >> rotation: parse_quat_wxyz
330 >> config: parse_waypoint_config
331 >> (PathWaypointVariantRail {
332 position,
333 data: PathWaypointDataRail {
334 rotation,
335 speed: None,
336 config
337 }
338 })
339 )
340);
341
342named!(
343 parse_path_waypoint_variant_rail_17<PathWaypointVariantRail>,
344 do_parse!(
345 position: parse_vec3f
346 >> rotation: parse_quat_wxyz
347 >> speed: le_f32
348 >> config: parse_waypoint_config
349 >> (PathWaypointVariantRail {
350 position,
351 data: PathWaypointDataRail {
352 rotation,
353 speed: Some(speed),
354 config
355 }
356 })
357 )
358);
359
360fn parse_path_variant_rail(i: &[u8], header: PathHeader) -> IResult<&[u8], PathVariantRail> {
361 let version = header.version;
362 do_parse!(
363 i,
364 path_data: parse_path_data_rail
365 >> waypoints:
366 switch!(value!(version.min(17)),
367 true => length_count!(le_u32, parse_path_waypoint_variant_rail_17) |
368 false => length_count!(le_u32, parse_path_waypoint_variant_rail)
369 )
370 >> (PathVariantRail {
371 header,
372 path_data,
373 waypoints,
374 })
375 )
376}
377
378fn parse_path_data(inp: &[u8], path_type: PathType, header: PathHeader) -> IResult<&[u8], Path> {
379 match path_type {
380 PathType::Movement => {
381 let (inp, var) = parse_path_variant_movement(inp, header)?;
382 Ok((inp, Path::Movement(var)))
383 }
384 PathType::MovingPlatform => {
385 let (inp, var) = parse_path_variant_moving_platform(inp, header)?;
386 Ok((inp, Path::MovingPlatform(var)))
387 }
388 PathType::Property => {
389 let (inp, var) = parse_path_variant_property(inp, header)?;
390 Ok((inp, Path::Property(var)))
391 }
392 PathType::Camera => {
393 let (inp, var) = parse_path_variant_camera(inp, header)?;
394 Ok((inp, Path::Camera(var)))
395 }
396 PathType::Spawner => {
397 let (inp, var) = parse_path_variant_spawner(inp, header)?;
398 Ok((inp, Path::Spawner(var)))
399 }
400 PathType::Showcase => {
401 let (inp, var) = parse_path_variant_showcase(inp, header)?;
402 Ok((inp, Path::Showcase(var)))
403 }
404 PathType::Race => {
405 let (inp, var) = parse_path_variant_race(inp, header)?;
406 Ok((inp, Path::Race(var)))
407 }
408 PathType::Rail => {
409 let (inp, var) = parse_path_variant_rail(inp, header)?;
410 Ok((inp, Path::Rail(var)))
411 }
412 }
413}
414
415named!(pub parse_path<Path>,
416 do_parse!(
417 version: parse_path_version >>
418 path_name: parse_u8_wstring >>
419 path_type: parse_path_type >>
420 value_1: le_u32 >>
421 path_composition: parse_path_composition >>
422 header: value!(PathHeader{version, path_name, value_1, path_composition}) >>
423 path: call!(parse_path_data, path_type, header) >>
424 (path)
425 )
426);
427
428named!(pub parse_waypoint_config_entry<(String, String)>,
429 pair!(parse_u8_wstring, parse_u8_wstring)
430);
431
432fn extend_config_map(
433 mut map: HashMap<String, String>,
434 entry: (String, String),
435) -> HashMap<String, String> {
436 map.insert(entry.0, entry.1);
437 map
438}
439
440named!(pub parse_waypoint_config<WaypointConfig>,
441 do_parse!(
442 count: map_res!(le_u32, usize::try_from) >>
443 map: fold_many_m_n!(count, count, parse_waypoint_config_entry, HashMap::new(), extend_config_map) >>
444 (map)
445 )
446);
447
448named!(pub parse_zone_paths<ZonePaths>,
449 do_parse!(
450 version: parse_zone_paths_version >>
451 paths: length_count!(le_u32, parse_path) >>
452 (ZonePaths{version,paths})
453 )
454);