use super::paths::core::ZonePaths;
use crate::luz::paths::parser::parse_zone_paths;
use assembly_core::{
nom::{error::ErrorKind, Finish, Offset},
types::{Placement3D, Vector3f, WorldID},
};
#[cfg(feature = "serde-derives")]
use serde::Serialize;
#[derive(Debug, Clone, Copy)]
#[cfg_attr(feature = "serde-derives", derive(Serialize))]
pub struct FileVersion(u32);
impl FileVersion {
pub fn id(&self) -> u32 {
self.0
}
pub fn min(&self, val: u32) -> bool {
self.0 >= val
}
}
impl From<u32> for FileVersion {
fn from(val: u32) -> Self {
FileVersion(val)
}
}
#[derive(Debug)]
#[cfg_attr(feature = "serde-derives", derive(Serialize))]
pub struct SceneRef {
pub file_name: String,
pub id: u32,
pub layer: u32,
pub name: String,
}
#[derive(Copy, Clone, Debug)]
#[cfg_attr(feature = "serde-derives", derive(Serialize))]
pub struct SceneTransitionPoint {
pub scene_id: u64,
pub point: Vector3f,
}
#[derive(Debug)]
#[cfg_attr(feature = "serde-derives", derive(Serialize))]
pub enum SceneTransitionInfo {
Point2([SceneTransitionPoint; 2]),
Point5([SceneTransitionPoint; 5]),
}
impl From<[SceneTransitionPoint; 2]> for SceneTransitionInfo {
fn from(val: [SceneTransitionPoint; 2]) -> Self {
SceneTransitionInfo::Point2(val)
}
}
impl From<[SceneTransitionPoint; 5]> for SceneTransitionInfo {
fn from(val: [SceneTransitionPoint; 5]) -> Self {
SceneTransitionInfo::Point5(val)
}
}
#[derive(Debug)]
#[cfg_attr(feature = "serde-derives", derive(Serialize))]
pub struct SceneTransition {
pub name: Option<String>,
pub points: SceneTransitionInfo,
}
pub trait PathData {}
impl PathData for Vec<u8> {}
impl PathData for ZonePaths {}
#[derive(Debug)]
#[cfg_attr(feature = "serde-derives", derive(Serialize))]
pub struct ZoneFile<P: PathData> {
pub file_version: FileVersion,
pub file_revision: Option<u32>,
pub world_id: WorldID,
pub spawn_point: Option<Placement3D>,
pub scene_refs: Vec<SceneRef>,
pub something: String,
pub map_filename: String,
pub map_name: String,
pub map_description: String,
pub scene_transitions: Option<Vec<SceneTransition>>,
pub path_data: Option<P>,
}
impl<P: PathData> ZoneFile<P> {
fn set_path_data<N: PathData>(self, new: Option<N>) -> ZoneFile<N> {
ZoneFile {
file_version: self.file_version,
file_revision: self.file_revision,
world_id: self.world_id,
spawn_point: self.spawn_point,
scene_refs: self.scene_refs,
something: self.something,
map_filename: self.map_filename,
map_name: self.map_name,
map_description: self.map_description,
scene_transitions: self.scene_transitions,
path_data: new,
}
}
}
pub type ParsePathErr = Box<(ZoneFile<Vec<u8>>, (usize, ErrorKind))>;
impl ZoneFile<Vec<u8>> {
pub fn parse_paths(self) -> Result<ZoneFile<ZonePaths>, ParsePathErr> {
if let Some(path_data) = &self.path_data {
match parse_zone_paths(path_data).finish() {
Ok((_rest, path_data)) => Ok(self.set_path_data(Some(path_data))),
Err(e) => {
let len = path_data.offset(e.input);
let code = e.code;
Err(Box::new((self, (len, code))))
}
}
} else {
Ok(self.set_path_data(None))
}
}
}