From 7f5a02355042581ade2b7d235c7adaedd6466c6a Mon Sep 17 00:00:00 2001 From: Anarelion Date: Mon, 6 Nov 2023 22:28:35 +0000 Subject: [PATCH] Refactor into what I expect is more ergonomic --- Cargo.lock | 15 +- Cargo.toml | 4 +- src/lib.rs | 13 +- src/pfs/block.rs | 10 +- src/pfs/entry.rs | 8 +- src/pfs/header.rs | 10 +- src/pfs/mod.rs | 27 +-- src/utils.rs | 7 +- src/wld/fragments/mod.rs | 67 ++++++- src/wld/fragments/t16_skeleton.rs | 23 +-- src/wld/fragments/t17_skeleton_ref.rs | 22 ++- src/wld/fragments/t18_track_def.rs | 17 +- src/wld/fragments/t19_track.rs | 24 +-- src/wld/fragments/t20_model.rs | 34 ++-- src/wld/fragments/t3_texture_name.rs | 13 +- src/wld/fragments/t45_dm_sprite_ref.rs | 15 +- src/wld/fragments/t48_material.rs | 14 +- src/wld/fragments/t49_material_list.rs | 13 +- src/wld/fragments/t4_texture.rs | 12 +- src/wld/fragments/t54_mesh.rs | 16 +- src/wld/fragments/t5_texture_list_wrapper.rs | 12 +- src/wld/header.rs | 12 +- src/wld/mod.rs | 183 +++++++------------ src/wld/names.rs | 24 ++- src/wld/raw_fragment.rs | 29 ++- 25 files changed, 323 insertions(+), 301 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 21f66dd..0a60938 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -63,6 +63,7 @@ dependencies = [ "bitbybit", "bytes", "compress", + "lazy_static", "thiserror", "tracing", ] @@ -78,11 +79,17 @@ dependencies = [ "wasi", ] +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + [[package]] name = "libc" -version = "0.2.149" +version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" [[package]] name = "log" @@ -245,9 +252,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.38" +version = "2.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 2ccecfa..d1722f0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" [dependencies] bitbybit = "1.2" bytes = "1.0" +compress = "0.2" +lazy_static = "1.4" thiserror = "1.0" tracing = "0.1" -compress = "0.2" - diff --git a/src/lib.rs b/src/lib.rs index 7f16e97..811be3e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,11 +3,13 @@ mod utils; mod wld; use std::string::FromUtf8Error; +use std::sync::Arc; pub use crate::pfs::PackFile; pub use crate::wld::fragments::*; pub use crate::wld::WldFile; use bytes::Bytes; +use lazy_static::lazy_static; use thiserror::Error; #[derive(Debug, Error)] @@ -22,10 +24,15 @@ pub enum EQFilesError { ErrorDecodingString(#[from] FromUtf8Error), } -pub trait Decoder { - type Settings; +#[derive(Default)] +pub struct EmptySettings; - fn new(input: &mut Bytes, settings: Self::Settings) -> Result +lazy_static! { + pub static ref EMPTY_SETTINGS: Arc = Arc::new(EmptySettings); +} + +pub trait Decoder { + fn new(input: &mut Bytes, settings: Arc) -> Result where Self: Sized; } diff --git a/src/pfs/block.rs b/src/pfs/block.rs index ed9e53c..af9f5c9 100644 --- a/src/pfs/block.rs +++ b/src/pfs/block.rs @@ -1,5 +1,9 @@ +use std::sync::Arc; + use bytes::{Buf, Bytes}; +use crate::{EmptySettings, Decoder}; + #[derive(Clone, PartialEq)] pub struct PackFileBlock { pub compressed_size: u32, @@ -7,10 +11,8 @@ pub struct PackFileBlock { pub data: Bytes, } -impl crate::Decoder for PackFileBlock { - type Settings = (); - - fn new(input: &mut Bytes, _: Self::Settings) -> Result +impl Decoder for PackFileBlock { + fn new(input: &mut Bytes, _: Arc) -> Result where Self: Sized, { diff --git a/src/pfs/entry.rs b/src/pfs/entry.rs index 7d25ab6..b3ee1c6 100644 --- a/src/pfs/entry.rs +++ b/src/pfs/entry.rs @@ -1,6 +1,8 @@ use std::io::Read; +use std::sync::Arc; use crate::pfs::block::PackFileBlock; +use crate::EmptySettings; use bytes::{Buf, Bytes}; use compress::zlib; @@ -12,10 +14,8 @@ pub struct PackFileEntry { pub blocks: Option>, } -impl crate::Decoder for PackFileEntry { - type Settings = (); - - fn new(input: &mut Bytes, _: Self::Settings) -> Result +impl crate::Decoder for PackFileEntry { + fn new(input: &mut Bytes, _: Arc) -> Result where Self: Sized, { diff --git a/src/pfs/header.rs b/src/pfs/header.rs index f34af75..a131b30 100644 --- a/src/pfs/header.rs +++ b/src/pfs/header.rs @@ -1,5 +1,9 @@ +use std::sync::Arc; + use bytes::{Buf, Bytes}; +use crate::EmptySettings; + #[derive(Clone)] pub struct PackFileHeader { pub(crate) directory_offset: u32, @@ -7,10 +11,8 @@ pub struct PackFileHeader { pub version: u32, } -impl crate::Decoder for PackFileHeader { - type Settings = (); - - fn new(input: &mut Bytes, _: Self::Settings) -> Result +impl crate::Decoder for PackFileHeader { + fn new(input: &mut Bytes, _: Arc ) -> Result where Self: Sized, { diff --git a/src/pfs/mod.rs b/src/pfs/mod.rs index d230b76..bba5b5b 100644 --- a/src/pfs/mod.rs +++ b/src/pfs/mod.rs @@ -3,10 +3,11 @@ mod entry; mod header; use std::path::PathBuf; +use std::sync::Arc; use bytes::{Buf, Bytes}; -use crate::utils::*; +use crate::{utils::*, EMPTY_SETTINGS, EmptySettings}; use crate::{Decoder, EQFilesError}; #[derive(Clone)] @@ -18,17 +19,20 @@ pub struct PackFile { // footer: PackFileFooter, } -impl Decoder for PackFile { - type Settings = PathBuf; - - fn new(input: &mut Bytes, settings: Self::Settings) -> Result +impl Decoder for PackFile { + fn new(input: &mut Bytes, settings: Arc) -> Result where Self: Sized, { - let header = header::PackFileHeader::new(input, ())?; + let header = header::PackFileHeader::new(input, EMPTY_SETTINGS.clone())?; let block_contents = take(input, header.directory_offset as usize - 12); let entry_count = input.get_u32_le() as usize; - let mut entries = count(input, entry_count, (), entry::PackFileEntry::new)?; + let mut entries = count( + input, + entry_count, + EMPTY_SETTINGS.clone(), + entry::PackFileEntry::new, + )?; // let footer = footer(input)?; entries.sort_by_key(|a| a.pointer); @@ -43,7 +47,8 @@ impl Decoder for PackFile { while bytes_remaining > 0 { let mut temp_block = block_contents.clone(); temp_block.advance(offset); - let block = block::PackFileBlock::new(&mut temp_block, ()).unwrap(); + let block = + block::PackFileBlock::new(&mut temp_block, EMPTY_SETTINGS.clone()).unwrap(); offset += (block.compressed_size + 8) as usize; bytes_remaining -= block.uncompressed_size; blocks.push(block); @@ -53,7 +58,7 @@ impl Decoder for PackFile { }) .collect(); Ok(PackFile { - path: settings, + path: settings.clone().to_path_buf(), header, entry_count, entries, @@ -65,7 +70,7 @@ impl Decoder for PackFile { } } -fn directory_string(input: &mut Bytes, _: ()) -> Result { +fn directory_string(input: &mut Bytes, _: Arc) -> Result { let length = input.get_u32_le(); match string(input, length as usize) { Ok(s) => Ok(s), @@ -75,7 +80,7 @@ fn directory_string(input: &mut Bytes, _: ()) -> Result { pub fn directory(input: &mut Bytes) -> Result, EQFilesError> { let file_count = input.get_u32_le(); - Ok(count(input, file_count as usize, (), directory_string)?) + Ok(count(input, file_count as usize, EMPTY_SETTINGS.clone(), directory_string)?) } impl PackFile { diff --git a/src/utils.rs b/src/utils.rs index 6c436e1..8490422 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,4 +1,5 @@ use std::string::FromUtf8Error; +use std::sync::Arc; use bytes::{Buf, Bytes}; @@ -6,11 +7,11 @@ use crate::EQFilesError; pub(crate) const HASH_KEY: [u8; 8] = [0x95u8, 0x3A, 0xC5, 0x2A, 0x95, 0x7A, 0x95, 0x6A]; -pub fn count( +pub fn count( input: &mut Bytes, count: usize, - settings: S, - f: fn(&mut Bytes, S) -> Result, + settings: Arc, + f: fn(&mut Bytes, Arc) -> Result, ) -> Result, E> { let mut temp = Vec::new(); for _ in 0..count { diff --git a/src/wld/fragments/mod.rs b/src/wld/fragments/mod.rs index 171dace..67beb29 100644 --- a/src/wld/fragments/mod.rs +++ b/src/wld/fragments/mod.rs @@ -1,25 +1,80 @@ +mod t16_skeleton; +mod t17_skeleton_ref; mod t18_track_def; mod t19_track; mod t20_model; mod t3_texture_name; +mod t45_dm_sprite_ref; mod t48_material; mod t49_material_list; mod t4_texture; mod t54_mesh; mod t5_texture_list_wrapper; -mod t45_dm_sprite_ref; -mod t17_skeleton_ref; -mod t16_skeleton; +use std::sync::Arc; + +pub use t16_skeleton::WldSkeleton; +pub use t17_skeleton_ref::WldSkeletonRef; pub use t18_track_def::WldTrackDef; pub use t19_track::WldTrack; pub use t20_model::WldModel; pub use t3_texture_name::WldTextureFilename; +pub use t45_dm_sprite_ref::WldDmSpriteRef; pub use t48_material::WldMaterial; pub use t49_material_list::WldMaterialList; pub use t4_texture::WldTextureList; pub use t54_mesh::WldMesh; pub use t5_texture_list_wrapper::WldTextureRef; -pub use t45_dm_sprite_ref::WldDmSpriteRef; -pub use t17_skeleton_ref::WldSkeletonRef; -pub use t16_skeleton::WldSkeleton; + +use crate::Decoder; + +use super::{header::WldHeader, names::WldNames, raw_fragment::WldRawFragment}; + +#[derive(Debug)] +pub struct BaseSettings { + header: Arc, + names: Arc, +} + +impl BaseSettings { + pub fn new(header: Arc, names: Arc) -> Self { + Self { header, names } + } + + pub fn make_settings(&self, fragment: Arc) -> Arc { + Arc::new(Settings { + header: self.header.clone(), + names: self.names.clone(), + fragment, + }) + } +} + +#[derive(Debug)] +pub struct Settings { + header: Arc, + names: Arc, + fragment: Arc, +} + +impl Settings { + pub fn get_name_ref(&self) -> i32 { + self.fragment.name_ref + } + + pub fn get_name(&self) -> Option { + self.fragment.name.clone() + } + + pub fn get_from_name_ref(&self, index: i32) -> Option { + self.names.get_name(index) + } + + pub fn is_old_world(&self) -> bool { + self.header.is_old_world + } +} + +pub trait WldFragment: Decoder { + const TYPE: u32; +} diff --git a/src/wld/fragments/t16_skeleton.rs b/src/wld/fragments/t16_skeleton.rs index 0c2052c..301e446 100644 --- a/src/wld/fragments/t16_skeleton.rs +++ b/src/wld/fragments/t16_skeleton.rs @@ -1,12 +1,10 @@ use bitbybit::bitfield; use bytes::{Buf, Bytes}; use std::fmt::{Debug, Formatter}; -use std::rc::Rc; -use tracing::info; +use std::sync::Arc; -use crate::utils::count; -use crate::wld::names::WldNames; use crate::Decoder; +use crate::{utils::count, Settings}; #[derive(Clone, Debug)] pub struct WldSkeleton { @@ -42,14 +40,12 @@ pub struct WldSkeletonDag { pub sub_dags: Vec, } -impl Decoder for WldSkeleton { - type Settings = Rc; - - fn new(input: &mut Bytes, settings: Self::Settings) -> Result +impl Decoder for WldSkeleton { + fn new(input: &mut Bytes, settings: Arc) -> Result where Self: Sized, { - let name = settings.get_name(input); + let name = settings.get_name().clone(); let flags = WldSkeletonFlags::new_with_raw_value(input.get_u32_le()); let num_dags = input.get_u32_le(); let collision_volume_reference = input.get_u32_le(); @@ -99,14 +95,13 @@ impl Decoder for WldSkeleton { } } -impl Decoder for WldSkeletonDag { - type Settings = Rc; - - fn new(input: &mut Bytes, settings: Self::Settings) -> Result +impl Decoder for WldSkeletonDag { + fn new(input: &mut Bytes, settings: Arc) -> Result where Self: Sized, { - let name = settings.get_name(input); + let name_ref = input.get_i32_le(); + let name = settings.get_from_name_ref(name_ref); let flags = input.get_u32_le(); let track_ref = input.get_u32_le(); diff --git a/src/wld/fragments/t17_skeleton_ref.rs b/src/wld/fragments/t17_skeleton_ref.rs index 65aa9d9..e6d3d9a 100644 --- a/src/wld/fragments/t17_skeleton_ref.rs +++ b/src/wld/fragments/t17_skeleton_ref.rs @@ -1,30 +1,32 @@ -use std::rc::Rc; +use std::sync::Arc; -use bytes::{Bytes, Buf}; +use bytes::{Buf, Bytes}; +use tracing::info; -use crate::wld::names::WldNames; use crate::Decoder; +use crate::Settings; #[derive(Clone, Debug)] pub struct WldSkeletonRef { + pub name_ref: i32, pub name: Option, - pub reference : u32, + pub reference: u32, pub params1: u32, } -impl Decoder for WldSkeletonRef { - type Settings = Rc; - - fn new(input: &mut Bytes, settings: Self::Settings) -> Result +impl Decoder for WldSkeletonRef { + fn new(input: &mut Bytes, settings: Arc) -> Result where Self: Sized, { - let name = settings.get_name(input); let reference = input.get_u32_le(); let params1 = input.get_u32_le(); + info!("Remaining t17: {:?}", input); + Ok(Self { - name, + name_ref: settings.get_name_ref(), + name: settings.get_name(), reference, params1, }) diff --git a/src/wld/fragments/t18_track_def.rs b/src/wld/fragments/t18_track_def.rs index 0b97bf3..eb5f163 100644 --- a/src/wld/fragments/t18_track_def.rs +++ b/src/wld/fragments/t18_track_def.rs @@ -1,28 +1,25 @@ -use std::rc::Rc; +use std::sync::Arc; use bytes::Bytes; -use crate::wld::names::WldNames; -use crate::Decoder; +use crate::{Decoder, Settings}; #[derive(Clone, Debug)] pub struct WldTrackDef { pub name: Option, - pub remainder: Bytes, + // pub remainder: Bytes, } -impl Decoder for WldTrackDef { - type Settings = Rc; - - fn new(input: &mut Bytes, settings: Self::Settings) -> Result +impl Decoder for WldTrackDef { + fn new(input: &mut Bytes, settings: Arc) -> Result where Self: Sized, { - let name = settings.get_name(input); + let name = settings.get_name(); Ok(Self { name, - remainder: input.clone(), + // remainder: input.clone(), }) } } diff --git a/src/wld/fragments/t19_track.rs b/src/wld/fragments/t19_track.rs index 248b838..0b49d62 100644 --- a/src/wld/fragments/t19_track.rs +++ b/src/wld/fragments/t19_track.rs @@ -1,12 +1,11 @@ -use std::rc::Rc; -use std::fmt::{Debug, Formatter}; use bitbybit::bitfield; -use bytes::{Bytes, Buf}; +use bytes::{Buf, Bytes}; +use std::fmt::{Debug, Formatter}; +use std::sync::Arc; -use crate::wld::names::WldNames; -use crate::Decoder; +use crate::{Decoder, Settings}; -#[derive(Clone, Debug)] +#[derive(Clone, Debug, )] pub struct WldTrack { pub name: Option, pub reference: u32, @@ -14,8 +13,8 @@ pub struct WldTrack { pub sleep: Option, } - #[bitfield(u32)] +#[derive()] pub struct WldTrackFlags { #[bit(0, r)] pub has_sleep: bool, // 0x01 @@ -25,14 +24,12 @@ pub struct WldTrackFlags { pub interpolate: bool, // 0x04 } -impl Decoder for WldTrack { - type Settings = Rc; - - fn new(input: &mut Bytes, settings: Self::Settings) -> Result +impl Decoder for WldTrack { + fn new(input: &mut Bytes, settings: Arc) -> Result where Self: Sized, { - let name = settings.get_name(input); + let name = settings.get_name(); let reference = input.get_u32_le(); let flags = WldTrackFlags::new_with_raw_value(input.get_u32_le()); let sleep = if flags.has_sleep() { @@ -50,7 +47,6 @@ impl Decoder for WldTrack { } } - impl Debug for WldTrackFlags { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_struct("WldSkeletonFlags") @@ -59,4 +55,4 @@ impl Debug for WldTrackFlags { .field("interpolate", &self.interpolate()) .finish() } -} \ No newline at end of file +} diff --git a/src/wld/fragments/t20_model.rs b/src/wld/fragments/t20_model.rs index 9427de3..94a8871 100644 --- a/src/wld/fragments/t20_model.rs +++ b/src/wld/fragments/t20_model.rs @@ -1,15 +1,18 @@ -use std::rc::Rc; + +use std::sync::Arc; use bytes::{Buf, Bytes}; +use tracing::info; -use crate::wld::names::WldNames; -use crate::Decoder; +use crate::{Decoder, Settings}; -#[derive(Clone, Debug)] +#[derive(Clone, Debug, )] pub struct WldModel { + pub name_ref: i32, pub name: Option, pub flags: u32, - pub callback_name_ref: Option, + pub callback_name_ref: i32, + pub callback_name: Option, pub action_count: u32, pub fragment_count: u32, pub bounds_ref: u32, @@ -17,25 +20,26 @@ pub struct WldModel { pub offset_rotation: Option<((f32, f32, f32), (f32, f32, f32), u32)>, pub actions: Vec, pub fragments: Vec, + pub some_other_count: u32, } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, )] pub struct WldModelAction { pub lod_count: u32, pub unk1: u32, pub lod: Vec, } -impl Decoder for WldModel { - type Settings = Rc; - - fn new(input: &mut Bytes, settings: Self::Settings) -> Result +impl Decoder for WldModel { + fn new(input: &mut Bytes, settings: Arc) -> Result where Self: Sized, { - let name = settings.get_name(input); + let name_ref =settings.get_name_ref(); + let name = settings.get_name(); let flags = input.get_u32_le(); - let callback_name_ref = settings.get_name(input); + let callback_name_ref = input.get_i32_le(); + let callback_name = settings.get_from_name_ref(callback_name_ref); let action_count = input.get_u32_le(); let fragment_count = input.get_u32_le(); let bounds_ref = input.get_u32_le(); @@ -75,10 +79,15 @@ impl Decoder for WldModel { fragments.push(input.get_u32_le()); } + let some_other_count = input.get_u32_le(); + info!("Remaining t20: {:?}", input); + Ok(Self { + name_ref, name, flags, callback_name_ref, + callback_name, action_count, fragment_count, bounds_ref, @@ -86,6 +95,7 @@ impl Decoder for WldModel { offset_rotation, actions, fragments, + some_other_count, }) } } diff --git a/src/wld/fragments/t3_texture_name.rs b/src/wld/fragments/t3_texture_name.rs index e262219..d66103d 100644 --- a/src/wld/fragments/t3_texture_name.rs +++ b/src/wld/fragments/t3_texture_name.rs @@ -1,10 +1,9 @@ -use std::rc::Rc; +use std::sync::Arc; use bytes::{Buf, Bytes}; use crate::utils::decode_string; -use crate::wld::names::WldNames; -use crate::Decoder; +use crate::{Decoder, Settings}; #[derive(Clone, Debug)] pub struct WldTextureFilename { @@ -12,14 +11,12 @@ pub struct WldTextureFilename { pub textures: Vec, } -impl Decoder for WldTextureFilename { - type Settings = Rc; - - fn new(input: &mut Bytes, settings: Self::Settings) -> Result +impl Decoder for WldTextureFilename { + fn new(input: &mut Bytes, settings: Arc) -> Result where Self: Sized, { - let name = settings.get_name(input); + let name = settings.get_name(); let textures = (0..(input.get_i32_le() + 1)) .map(|_| { let name_length = input.get_u16_le(); diff --git a/src/wld/fragments/t45_dm_sprite_ref.rs b/src/wld/fragments/t45_dm_sprite_ref.rs index 11c7c01..856e615 100644 --- a/src/wld/fragments/t45_dm_sprite_ref.rs +++ b/src/wld/fragments/t45_dm_sprite_ref.rs @@ -1,9 +1,8 @@ -use std::rc::Rc; +use std::sync::Arc; -use bytes::{Bytes, Buf}; +use bytes::{Buf, Bytes}; -use crate::wld::names::WldNames; -use crate::Decoder; +use crate::{Decoder, Settings}; #[derive(Clone, Debug)] pub struct WldDmSpriteRef { @@ -12,14 +11,12 @@ pub struct WldDmSpriteRef { pub params: u32, } -impl Decoder for WldDmSpriteRef { - type Settings = Rc; - - fn new(input: &mut Bytes, settings: Self::Settings) -> Result +impl Decoder for WldDmSpriteRef { + fn new(input: &mut Bytes, settings: Arc) -> Result where Self: Sized, { - let name = settings.get_name(input); + let name = settings.get_name(); Ok(Self { name, diff --git a/src/wld/fragments/t48_material.rs b/src/wld/fragments/t48_material.rs index 54c7d29..4d1b546 100644 --- a/src/wld/fragments/t48_material.rs +++ b/src/wld/fragments/t48_material.rs @@ -1,10 +1,8 @@ -use std::rc::Rc; +use std::sync::Arc; +use crate::{Decoder, Settings}; use bytes::{Buf, Bytes}; -use crate::wld::names::WldNames; -use crate::Decoder; - #[derive(Clone, Debug)] pub struct WldMaterial { pub name: Option, @@ -17,14 +15,12 @@ pub struct WldMaterial { pub pairs: Option<(u32, u32)>, } -impl Decoder for WldMaterial { - type Settings = Rc; - - fn new(input: &mut Bytes, settings: Self::Settings) -> Result +impl Decoder for WldMaterial { + fn new(input: &mut Bytes, settings: Arc) -> Result where Self: Sized, { - let name = settings.get_name(input); + let name = settings.get_name(); let flags = input.get_u32_le(); let render_method = input.get_u32_le(); diff --git a/src/wld/fragments/t49_material_list.rs b/src/wld/fragments/t49_material_list.rs index 2bf3421..e6a1c7b 100644 --- a/src/wld/fragments/t49_material_list.rs +++ b/src/wld/fragments/t49_material_list.rs @@ -1,9 +1,8 @@ -use std::rc::Rc; +use std::sync::Arc; use bytes::{Buf, Bytes}; -use crate::wld::names::WldNames; -use crate::Decoder; +use crate::{Decoder, Settings}; #[derive(Clone, Debug)] pub struct WldMaterialList { @@ -12,14 +11,12 @@ pub struct WldMaterialList { pub material_refs: Vec, } -impl Decoder for WldMaterialList { - type Settings = Rc; - - fn new(input: &mut Bytes, settings: Self::Settings) -> Result +impl Decoder for WldMaterialList { + fn new(input: &mut Bytes, settings: Arc) -> Result where Self: Sized, { - let name = settings.get_name(input); + let name = settings.get_name(); let flags = input.get_u32_le(); let count = input.get_u32_le(); let mut refs = Vec::new(); diff --git a/src/wld/fragments/t4_texture.rs b/src/wld/fragments/t4_texture.rs index 2cacef7..0b108c6 100644 --- a/src/wld/fragments/t4_texture.rs +++ b/src/wld/fragments/t4_texture.rs @@ -1,9 +1,9 @@ -use std::rc::Rc; +use std::sync::Arc; use bytes::{Buf, Bytes}; -use crate::wld::names::WldNames; use crate::Decoder; +use crate::Settings; use tracing::info; #[derive(Clone, Debug)] @@ -15,14 +15,12 @@ pub struct WldTextureList { pub texture_list: Vec, } -impl Decoder for WldTextureList { - type Settings = Rc; - - fn new(input: &mut Bytes, settings: Self::Settings) -> Result +impl Decoder for WldTextureList { + fn new(input: &mut Bytes, settings: Arc) -> Result where Self: Sized, { - let name = settings.get_name(input); + let name = settings.get_name(); let flags = input.get_u32_le(); let texture_count = input.get_i32_le(); diff --git a/src/wld/fragments/t54_mesh.rs b/src/wld/fragments/t54_mesh.rs index 8bbee91..71356d5 100644 --- a/src/wld/fragments/t54_mesh.rs +++ b/src/wld/fragments/t54_mesh.rs @@ -1,10 +1,8 @@ -use std::rc::Rc; +use std::sync::Arc; use bytes::{Buf, Bytes}; -use crate::wld::names::WldNames; -use crate::Decoder; -use tracing::info; +use crate::{Decoder, Settings}; #[derive(Clone, Debug)] pub struct WldMesh { @@ -42,14 +40,12 @@ pub struct WldMesh { pub vertex_texture: Vec<[u16; 2]>, } -impl Decoder for WldMesh { - type Settings = (bool, Rc); - - fn new(input: &mut Bytes, settings: Self::Settings) -> Result +impl Decoder for WldMesh { + fn new(input: &mut Bytes, settings: Arc) -> Result where Self: Sized, { - let name = settings.1.get_name(input); + let name = settings.get_name().clone(); let flags = input.get_u32_le(); let material_list_ref = input.get_u32_le(); let animation_ref = input.get_u32_le(); @@ -84,7 +80,7 @@ impl Decoder for WldMesh { let mut uv = Vec::new(); for _ in 0..uv_count { - if settings.0 { + if settings.is_old_world() { uv.push([ (input.get_i16_le() as f32) / 256f32, (input.get_i16_le() as f32) / 256f32, diff --git a/src/wld/fragments/t5_texture_list_wrapper.rs b/src/wld/fragments/t5_texture_list_wrapper.rs index 4f8ad81..a14cb37 100644 --- a/src/wld/fragments/t5_texture_list_wrapper.rs +++ b/src/wld/fragments/t5_texture_list_wrapper.rs @@ -1,9 +1,9 @@ -use std::rc::Rc; +use std::sync::Arc; use bytes::{Buf, Bytes}; -use crate::wld::names::WldNames; use crate::Decoder; +use crate::Settings; #[derive(Clone, Debug)] pub struct WldTextureRef { @@ -12,14 +12,12 @@ pub struct WldTextureRef { pub texture_ref: u16, } -impl Decoder for WldTextureRef { - type Settings = Rc; - - fn new(input: &mut Bytes, settings: Self::Settings) -> Result +impl Decoder for WldTextureRef { + fn new(input: &mut Bytes, settings: Arc) -> Result where Self: Sized, { - let name = settings.get_name(input); + let name = settings.get_name(); let texture_ref = input.get_u16_le(); let flags = input.get_u32_le(); diff --git a/src/wld/header.rs b/src/wld/header.rs index dbb2caf..6d59340 100644 --- a/src/wld/header.rs +++ b/src/wld/header.rs @@ -1,8 +1,10 @@ +use std::sync::Arc; + use bytes::{Buf, Bytes}; -use crate::{Decoder, EQFilesError}; +use crate::{Decoder, EQFilesError, EmptySettings}; -#[derive(Debug, Default)] +#[derive(Clone, Debug, Default)] pub struct WldHeader { pub magic_number: u32, pub is_old_world: bool, @@ -13,10 +15,8 @@ pub struct WldHeader { pub unk3: u32, } -impl Decoder for WldHeader { - type Settings = (); - - fn new(input: &mut Bytes, _: Self::Settings) -> Result +impl Decoder for WldHeader { + fn new(input: &mut Bytes, settings: Arc) -> Result where Self: Sized, { diff --git a/src/wld/mod.rs b/src/wld/mod.rs index 6b506c5..e844bc1 100644 --- a/src/wld/mod.rs +++ b/src/wld/mod.rs @@ -3,161 +3,114 @@ mod header; mod names; mod raw_fragment; -use std::rc::Rc; +use std::sync::Arc; use bytes::Bytes; -use std::collections::{HashMap, HashSet}; -use tracing::info; +use std::collections::BTreeMap; -use crate::utils::*; +use crate::{utils::*, EmptySettings}; use crate::{Decoder, EQFilesError}; use fragments::*; use header::WldHeader; use names::WldNames; use raw_fragment::WldRawFragment; -#[derive(Debug, Default)] +#[derive(Debug)] pub struct WldFile { - pub header: WldHeader, - pub names: WldNames, - pub raw_fragments: HashMap, - pub t3: HashMap, - pub t4: HashMap, - pub t5: HashMap, - pub t16: HashMap, - pub t17: HashMap, - pub t18: HashMap, - pub t19: HashMap, - pub t20: HashMap, - pub t45: HashMap, - pub t48: HashMap, - pub t49: HashMap, - pub t54: HashMap, + pub header: Arc, + pub names: Arc, + pub raw_fragments: BTreeMap>, + base_settings: BaseSettings, } -impl Decoder for WldFile { - type Settings = (); - - fn new(input: &mut Bytes, _settings: Self::Settings) -> Result +impl Decoder for WldFile { + fn new(input: &mut Bytes, settings: Arc) -> Result where Self: Sized, { - let header = WldHeader::new(input, ())?; - let names = WldNames::new(input, header.hash_size)?; - let raw_fragments: HashMap = count( + let header = Arc::new(WldHeader::new(input, settings.clone())?); + let names = Arc::new(WldNames::new(input, Arc::new(header.hash_size))?); + + let raw_fragments: BTreeMap> = count( input, header.fragment_count as usize, - (), + names.clone(), WldRawFragment::new, )? .iter() .enumerate() - .map(|(i, v)| ((i + 1) as u32, v.clone())) + .map(|(i, v)| ((i + 1) as u32, Arc::new(v.clone()))) .collect(); - let names = Rc::new(names); - - let t3 = extract_fragments(&raw_fragments, 3, names.clone()); - let t4 = extract_fragments(&raw_fragments, 4, names.clone()); - let t5 = extract_fragments(&raw_fragments, 5, names.clone()); - let t16 = extract_fragments(&raw_fragments, 16, names.clone()); - let t17 = extract_fragments(&raw_fragments, 17, names.clone()); - let t18 = extract_fragments(&raw_fragments, 18, names.clone()); - let t19 = extract_fragments(&raw_fragments, 19, names.clone()); - let t20 = extract_fragments(&raw_fragments, 20, names.clone()); - let t45 = extract_fragments(&raw_fragments, 45, names.clone()); - let t48 = extract_fragments(&raw_fragments, 48, names.clone()); - let t49 = extract_fragments(&raw_fragments, 49, names.clone()); - let t54 = extract_fragments(&raw_fragments, 54, (header.is_old_world, names.clone())); - let remaining: HashSet = raw_fragments - .iter() - .map(|(_, frag)| frag.0) - .filter(|a| ![3, 4, 5, 16, 17, 18, 19, 20, 45, 48, 49, 54].contains(a)) - .collect(); - if !remaining.is_empty() { - info!("{:?}", remaining); - } Ok(WldFile { - header, - names: Rc::into_inner(names).unwrap(), + header: header.clone(), + names: names.clone(), raw_fragments, - t3, - t4, - t5, - t16, - t17, - t18, - t19, - t20, - t45, - t48, - t49, - t54, + base_settings: BaseSettings::new(header, names), }) } } -fn extract_fragments>( - raw_fragments: &HashMap, - code: u32, - settings: S, -) -> HashMap -where - S: Clone, -{ - raw_fragments - .iter() - .filter(|f| f.1 .0 == code) - .map(|(k, v)| (*k, T::new(&mut v.1.clone(), settings.clone()).unwrap())) - .collect() -} - impl WldFile { - pub fn materials(&self) -> Vec { - self.t48.clone().into_values().collect() + pub fn fragment_by_index(&self, index: u32) -> Option + where + T: WldFragment, + { + let fragment = self.raw_fragments.get(&index)?.clone(); + assert_eq!(fragment.fragment_type, T::TYPE); + let mut raw = fragment.contents.clone(); + + T::new( + &mut raw, + self.base_settings.make_settings(fragment), + ) + .ok() } + // pub fn models(&self) -> Vec { + // self.t20.clone().into_values().collect() + // } - pub fn meshes(&self) -> Vec { - self.t54.clone().into_values().collect() - } + // pub fn materials(&self) -> Vec { + // self.t48.clone().into_values().collect() + // } - pub fn models(&self) -> Vec { - self.t20.clone().into_values().collect() - } + // pub fn meshes(&self) -> Vec { + // self.t54.clone().into_values().collect() + // } - pub fn get_texture_filename(&self, index: u32) -> WldTextureFilename { - self.t3.get(&index).unwrap().clone() - } + // pub fn get_texture_filename(&self, index: u32) -> WldTextureFilename { + // self.t3.get(&index).unwrap().clone() + // } - pub fn get_texture_list(&self, index: u32) -> WldTextureList { - self.t4.get(&index).unwrap().clone() - } + // pub fn get_texture_list(&self, index: u32) -> WldTextureList { + // self.t4.get(&index).unwrap().clone() + // } - pub fn get_texture_list_ref(&self, index: u32) -> WldTextureRef { - self.t5.get(&index).unwrap().clone() - } + // pub fn get_texture_list_ref(&self, index: u32) -> WldTextureRef { + // self.t5.get(&index).unwrap().clone() + // } - pub fn get_mesh(&self, index: u32) -> WldMesh { - self.t54.get(&index).unwrap().clone() - } + // pub fn get_skeleton(&self, index: u32) -> WldSkeleton { + // self.t16.get(&index).unwrap().clone() + // } - pub fn get_skeleton_ref(&self, index: u32) -> WldSkeletonRef { - self.t17.get(&index).unwrap().clone() - } + // pub fn get_skeleton_ref(&self, index: u32) -> WldSkeletonRef { + // self.t17.get(&index).unwrap().clone() + // } - pub fn get_skeleton(&self, index: u32) -> WldSkeleton { - self.t16.get(&index).unwrap().clone() - } + // pub fn get_track(&self, index: u32) -> WldTrack { + // self.t19.get(&index).unwrap().clone() + // } - pub fn get_track(&self, index: u32) -> WldTrack { - self.t19.get(&index).unwrap().clone() - } + // pub fn get_dm_sprite_ref(&self, index: u32) -> WldDmSpriteRef { + // self.t45.get(&index).unwrap().clone() + // } - pub fn get_dm_sprite_ref(&self, index: u32) -> WldDmSpriteRef { - self.t45.get(&index).unwrap().clone() - } + // pub fn get_mesh(&self, index: u32) -> WldMesh { + // self.t54.get(&index).unwrap().clone() + // } - pub fn get_fragment_type(&self, index: u32) -> u32 { - self.raw_fragments.get(&index).unwrap().0 - } + // pub fn get_fragment_type(&self, index: u32) -> u32 { + // self.raw_fragments.get(&index).unwrap().0 + // } } diff --git a/src/wld/names.rs b/src/wld/names.rs index a0e77d7..074f638 100644 --- a/src/wld/names.rs +++ b/src/wld/names.rs @@ -1,23 +1,22 @@ use bytes::{Buf, Bytes}; -use std::collections::HashMap; +use std::collections::BTreeMap; +use std::sync::Arc; use crate::utils::HASH_KEY; use crate::{Decoder, EQFilesError}; -#[derive(Debug, Default)] -pub struct WldNames(HashMap); +#[derive(Clone, Debug, Default)] +pub struct WldNames(BTreeMap); -impl Decoder for WldNames { - type Settings = u32; - - fn new(input: &mut Bytes, size: Self::Settings) -> Result +impl Decoder for WldNames { + fn new(input: &mut Bytes, size: Arc) -> Result where Self: Sized, { let mut last_offset = 0; let mut temp = Vec::new(); - let mut res = HashMap::new(); - for i in 0..size { + let mut res = BTreeMap::new(); + for i in 0..*size { let c = input.get_u8() ^ HASH_KEY.get((i % 8) as usize).unwrap(); if c == 0 { let name = @@ -34,12 +33,11 @@ impl Decoder for WldNames { } impl WldNames { - pub fn get_name(&self, input: &mut Bytes) -> Option { - let ref_id = input.get_u32_le(); - match ref_id { + pub fn get_name(&self, index: i32) -> Option { + match index { 0 => None, _ => { - let name_ref = (!ref_id) as u32; + let name_ref = (!index) as u32; Some( self.0 .get(&name_ref) diff --git a/src/wld/raw_fragment.rs b/src/wld/raw_fragment.rs index 1424c8b..4036f61 100644 --- a/src/wld/raw_fragment.rs +++ b/src/wld/raw_fragment.rs @@ -1,23 +1,36 @@ +use std::sync::Arc; + use bytes::{Buf, Bytes}; use crate::utils::take; use crate::{Decoder, EQFilesError}; -#[derive(Clone, Debug)] -pub struct WldRawFragment(pub u32, pub Bytes); +use super::names::WldNames; -impl Decoder for WldRawFragment { - type Settings = (); +#[derive(Clone, Debug)] +pub struct WldRawFragment { + pub fragment_size: u32, + pub fragment_type: u32, + pub name_ref: i32, + pub name: Option, + pub contents: Bytes, +} - fn new(input: &mut Bytes, _: Self::Settings) -> Result +impl Decoder for WldRawFragment { + fn new(input: &mut Bytes, names: Arc) -> Result where Self: Sized, { let fragment_size = input.get_u32_le(); let fragment_type = input.get_u32_le(); - Ok(WldRawFragment( + let name_ref = input.get_i32_le(); + let name = names.get_name(name_ref); + Ok(WldRawFragment { + fragment_size, fragment_type, - take(input, fragment_size as usize), - )) + name_ref, + name, + contents: take(input, (fragment_size - 4) as usize), + }) } }