assembly_maps/luz/paths/
parser.rs

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);