use super::core::*;
use assembly_core::nom::{
call, cond, do_parse, fold_many_m_n, length_count, map_opt, map_res, named, named_args,
number::complete::{le_f32, le_u32, le_u8},
pair, switch, value, IResult,
};
use assembly_core::parser::{
parse_object_id, parse_object_template, parse_quat, parse_quat_wxyz, parse_u32_wstring,
parse_u8_bool, parse_u8_wstring, parse_vec3f, parse_world_id,
};
use num_traits::FromPrimitive;
use std::collections::HashMap;
use std::convert::TryFrom;
named!(pub parse_zone_paths_version<ZonePathsVersion>,
map_opt!(le_u32, ZonePathsVersion::from_u32)
);
named!(pub parse_path_version<PathVersion>,
map_opt!(le_u32, PathVersion::from_u32)
);
named!(pub parse_path_type<PathType>,
map_opt!(le_u32, PathType::from_u32)
);
named!(pub parse_path_composition<PathComposition>,
map_opt!(le_u32, PathComposition::from_u32)
);
named!(pub parse_path_data_movement<PathDataMovement>,
value!(PathDataMovement{})
);
named_args!(pub parse_path_data_moving_platform(version: PathVersion)<PathDataMovingPlatform>,
do_parse!(
a: cond!(version.min(18), call!(le_u8)) >>
b: cond!(version.min(13) && !version.min(18), call!(parse_u8_wstring)) >>
(PathDataMovingPlatform{
something: a,
platform_travel_sound: b,
})
)
);
named!(pub parse_property_rental_time_unit<PropertyRentalTimeUnit>,
map_opt!(le_u32, PropertyRentalTimeUnit::from_u32)
);
named!(pub parse_property_achievement_required<PropertyAchievementRequired>,
map_opt!(le_u32, PropertyAchievementRequired::from_u32)
);
named!(pub parse_path_data_property<PathDataProperty>,
do_parse!(
value_1: le_u32 >>
price: le_u32 >>
rental_time: le_u32 >>
associated_map: parse_world_id >>
value_2: le_u32 >>
display_name: parse_u8_wstring >>
display_description: parse_u32_wstring >>
value_3: le_u32 >>
clone_limit: le_u32 >>
reputation_multiplier: le_f32 >>
rental_time_unit: parse_property_rental_time_unit >>
achievement_required: parse_property_achievement_required >>
player_zone_coordinate: parse_vec3f >>
max_build_height: le_f32 >>
(PathDataProperty {
value_1,
price, rental_time, associated_map,
value_2,
display_name, display_description,
value_3,
clone_limit, reputation_multiplier,
rental_time_unit, achievement_required,
player_zone_coordinate, max_build_height,
})
)
);
named_args!(pub parse_path_data_camera(version: PathVersion)<PathDataCamera>,
do_parse!(
next_path: parse_u8_wstring >>
value_1: cond!(version.min(14), le_u8) >>
(PathDataCamera{next_path, value_1})
)
);
named!(pub parse_path_data_spawner<PathDataSpawner>,
do_parse!(
spawned_lot: parse_object_template >>
respawn_time: le_u32 >>
max_to_spawn: le_u32 >>
min_to_spawn: le_u32 >>
spawner_obj_id: parse_object_id >>
activate_network_on_load: parse_u8_bool >>
(PathDataSpawner{
spawned_lot,
respawn_time,
max_to_spawn,
min_to_spawn,
spawner_obj_id,
activate_network_on_load,
})
)
);
named!(pub parse_path_data_showcase<PathDataShowcase>,
value!(PathDataShowcase{})
);
named!(pub parse_path_data_race<PathDataRace>,
value!(PathDataRace{})
);
named!(pub parse_path_data_rail<PathDataRail>,
value!(PathDataRail{})
);
named!(pub parse_path_waypoint_data_movement<PathWaypointDataMovement>,
do_parse!(
config: parse_waypoint_config >>
(PathWaypointDataMovement{config})
)
);
named!(pub parse_path_waypoint_data_moving_platform_sounds<PathWaypointDataMovingPlatformSounds>,
do_parse!(
depart_sound: parse_u8_wstring >>
arrive_sound: parse_u8_wstring >>
(PathWaypointDataMovingPlatformSounds{ depart_sound, arrive_sound })
)
);
named_args!(pub parse_path_waypoint_data_moving_platform(version: PathVersion)<PathWaypointDataMovingPlatform>,
do_parse!(
rotation: parse_quat >>
lock_player: parse_u8_bool >>
speed: le_f32 >>
wait: le_f32 >>
sounds: cond!(version.min(13), call!(parse_path_waypoint_data_moving_platform_sounds)) >>
(PathWaypointDataMovingPlatform {
rotation, lock_player, speed, wait, sounds
})
)
);
named!(pub parse_path_waypoint_data_property<PathWaypointDataProperty>,
value!(PathWaypointDataProperty{})
);
named!(pub parse_path_waypoint_data_camera<PathWaypointDataCamera>,
do_parse!(
rotation: parse_quat >>
time: le_f32 >>
value_5: le_f32 >>
tension: le_f32 >>
continuity: le_f32 >>
bias: le_f32 >>
(PathWaypointDataCamera {
rotation, time, value_5,
tension, continuity, bias,
})
)
);
named!(pub parse_path_waypoint_data_spawner<PathWaypointDataSpawner>,
do_parse!(
rotation: parse_quat >>
config: parse_waypoint_config >>
(PathWaypointDataSpawner{ rotation, config })
)
);
named!(pub parse_path_waypoint_data_showcase<PathWaypointDataShowcase>,
value!(PathWaypointDataShowcase{})
);
named!(pub parse_path_waypoint_data_race<PathWaypointDataRace>,
do_parse!(
rotation: parse_quat >>
value_1: le_u8 >>
value_2: le_u8 >>
value_3: le_f32 >>
value_4: le_f32 >>
value_5: le_f32 >>
(PathWaypointDataRace{ rotation, value_1, value_2, value_3, value_4, value_5 })
)
);
named!(
parse_path_waypoint_variant_movement<PathWaypointVariantMovement>,
do_parse!(
position: parse_vec3f
>> data: parse_path_waypoint_data_movement
>> (PathWaypointVariantMovement { position, data })
)
);
named_args!(parse_path_variant_movement(header: PathHeader)<PathVariantMovement>,
do_parse!(
path_data: parse_path_data_movement >>
waypoints: length_count!(le_u32, parse_path_waypoint_variant_movement) >>
(PathVariantMovement {
header, path_data, waypoints,
})
)
);
named_args!(parse_path_waypoint_variant_moving_platform(version: PathVersion)<PathWaypointVariantMovingPlatform>,
do_parse!(
position: parse_vec3f >>
data: call!(parse_path_waypoint_data_moving_platform, version) >>
(PathWaypointVariantMovingPlatform{position, data})
)
);
named_args!(parse_path_variant_moving_platform(header: PathHeader)<PathVariantMovingPlatform>,
do_parse!(
path_data: call!(parse_path_data_moving_platform, header.version) >>
waypoints: length_count!(le_u32, call!(parse_path_waypoint_variant_moving_platform, header.version)) >>
(PathVariantMovingPlatform {
header, path_data, waypoints,
})
)
);
named!(
parse_path_waypoint_variant_property<PathWaypointVariantProperty>,
do_parse!(
position: parse_vec3f
>> data: parse_path_waypoint_data_property
>> (PathWaypointVariantProperty { position, data })
)
);
named_args!(parse_path_variant_property(header: PathHeader)<PathVariantProperty>,
do_parse!(
path_data: parse_path_data_property >>
waypoints: length_count!(le_u32, parse_path_waypoint_variant_property) >>
(PathVariantProperty {
header, path_data, waypoints,
})
)
);
named!(
parse_path_waypoint_variant_camera<PathWaypointVariantCamera>,
do_parse!(
position: parse_vec3f
>> data: parse_path_waypoint_data_camera
>> (PathWaypointVariantCamera { position, data })
)
);
named_args!(parse_path_variant_camera(header: PathHeader)<PathVariantCamera>,
do_parse!(
path_data: call!(parse_path_data_camera, header.version) >>
waypoints: length_count!(le_u32, parse_path_waypoint_variant_camera) >>
(PathVariantCamera {
header, path_data, waypoints,
})
)
);
named!(
parse_path_waypoint_variant_spawner<PathWaypointVariantSpawner>,
do_parse!(
position: parse_vec3f
>> data: parse_path_waypoint_data_spawner
>> (PathWaypointVariantSpawner { position, data })
)
);
named_args!(parse_path_variant_spawner(header: PathHeader)<PathVariantSpawner>,
do_parse!(
path_data: parse_path_data_spawner >>
waypoints: length_count!(le_u32, parse_path_waypoint_variant_spawner) >>
(PathVariantSpawner {
header, path_data, waypoints,
})
)
);
named!(
parse_path_waypoint_variant_showcase<PathWaypointVariantShowcase>,
do_parse!(
position: parse_vec3f
>> data: parse_path_waypoint_data_showcase
>> (PathWaypointVariantShowcase { position, data })
)
);
named_args!(parse_path_variant_showcase(header: PathHeader)<PathVariantShowcase>,
do_parse!(
path_data: parse_path_data_showcase >>
waypoints: length_count!(le_u32, parse_path_waypoint_variant_showcase) >>
(PathVariantShowcase {
header, path_data, waypoints,
})
)
);
named!(
parse_path_waypoint_variant_race<PathWaypointVariantRace>,
do_parse!(
position: parse_vec3f
>> data: parse_path_waypoint_data_race
>> (PathWaypointVariantRace { position, data })
)
);
named_args!(parse_path_variant_race(header: PathHeader)<PathVariantRace>,
do_parse!(
path_data: parse_path_data_race >>
waypoints: length_count!(le_u32, parse_path_waypoint_variant_race) >>
(PathVariantRace {
header, path_data, waypoints,
})
)
);
named!(
parse_path_waypoint_variant_rail<PathWaypointVariantRail>,
do_parse!(
position: parse_vec3f
>> rotation: parse_quat_wxyz
>> config: parse_waypoint_config
>> (PathWaypointVariantRail {
position,
data: PathWaypointDataRail {
rotation,
speed: None,
config
}
})
)
);
named!(
parse_path_waypoint_variant_rail_17<PathWaypointVariantRail>,
do_parse!(
position: parse_vec3f
>> rotation: parse_quat_wxyz
>> speed: le_f32
>> config: parse_waypoint_config
>> (PathWaypointVariantRail {
position,
data: PathWaypointDataRail {
rotation,
speed: Some(speed),
config
}
})
)
);
fn parse_path_variant_rail(i: &[u8], header: PathHeader) -> IResult<&[u8], PathVariantRail> {
let version = header.version;
do_parse!(
i,
path_data: parse_path_data_rail
>> waypoints:
switch!(value!(version.min(17)),
true => length_count!(le_u32, parse_path_waypoint_variant_rail_17) |
false => length_count!(le_u32, parse_path_waypoint_variant_rail)
)
>> (PathVariantRail {
header,
path_data,
waypoints,
})
)
}
fn parse_path_data(inp: &[u8], path_type: PathType, header: PathHeader) -> IResult<&[u8], Path> {
match path_type {
PathType::Movement => {
let (inp, var) = parse_path_variant_movement(inp, header)?;
Ok((inp, Path::Movement(var)))
}
PathType::MovingPlatform => {
let (inp, var) = parse_path_variant_moving_platform(inp, header)?;
Ok((inp, Path::MovingPlatform(var)))
}
PathType::Property => {
let (inp, var) = parse_path_variant_property(inp, header)?;
Ok((inp, Path::Property(var)))
}
PathType::Camera => {
let (inp, var) = parse_path_variant_camera(inp, header)?;
Ok((inp, Path::Camera(var)))
}
PathType::Spawner => {
let (inp, var) = parse_path_variant_spawner(inp, header)?;
Ok((inp, Path::Spawner(var)))
}
PathType::Showcase => {
let (inp, var) = parse_path_variant_showcase(inp, header)?;
Ok((inp, Path::Showcase(var)))
}
PathType::Race => {
let (inp, var) = parse_path_variant_race(inp, header)?;
Ok((inp, Path::Race(var)))
}
PathType::Rail => {
let (inp, var) = parse_path_variant_rail(inp, header)?;
Ok((inp, Path::Rail(var)))
}
}
}
named!(pub parse_path<Path>,
do_parse!(
version: parse_path_version >>
path_name: parse_u8_wstring >>
path_type: parse_path_type >>
value_1: le_u32 >>
path_composition: parse_path_composition >>
header: value!(PathHeader{version, path_name, value_1, path_composition}) >>
path: call!(parse_path_data, path_type, header) >>
(path)
)
);
named!(pub parse_waypoint_config_entry<(String, String)>,
pair!(parse_u8_wstring, parse_u8_wstring)
);
fn extend_config_map(
mut map: HashMap<String, String>,
entry: (String, String),
) -> HashMap<String, String> {
map.insert(entry.0, entry.1);
map
}
named!(pub parse_waypoint_config<WaypointConfig>,
do_parse!(
count: map_res!(le_u32, usize::try_from) >>
map: fold_many_m_n!(count, count, parse_waypoint_config_entry, HashMap::new(), extend_config_map) >>
(map)
)
);
named!(pub parse_zone_paths<ZonePaths>,
do_parse!(
version: parse_zone_paths_version >>
paths: length_count!(le_u32, parse_path) >>
(ZonePaths{version,paths})
)
);