Skip to content

Commit

Permalink
Refactor into what I expect is more ergonomic
Browse files Browse the repository at this point in the history
  • Loading branch information
anarelion committed Nov 6, 2023
1 parent dab91db commit 7f5a023
Show file tree
Hide file tree
Showing 25 changed files with 323 additions and 301 deletions.
15 changes: 11 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"

13 changes: 10 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand All @@ -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<Self, EQFilesError>
lazy_static! {
pub static ref EMPTY_SETTINGS: Arc<EmptySettings> = Arc::new(EmptySettings);
}

pub trait Decoder<S> {
fn new(input: &mut Bytes, settings: Arc<S>) -> Result<Self, EQFilesError>
where
Self: Sized;
}
10 changes: 6 additions & 4 deletions src/pfs/block.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
use std::sync::Arc;

use bytes::{Buf, Bytes};

use crate::{EmptySettings, Decoder};

#[derive(Clone, PartialEq)]
pub struct PackFileBlock {
pub compressed_size: u32,
pub uncompressed_size: u32,
pub data: Bytes,
}

impl crate::Decoder for PackFileBlock {
type Settings = ();

fn new(input: &mut Bytes, _: Self::Settings) -> Result<Self, crate::EQFilesError>
impl Decoder<EmptySettings> for PackFileBlock {
fn new(input: &mut Bytes, _: Arc<EmptySettings>) -> Result<Self, crate::EQFilesError>
where
Self: Sized,
{
Expand Down
8 changes: 4 additions & 4 deletions src/pfs/entry.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -12,10 +14,8 @@ pub struct PackFileEntry {
pub blocks: Option<Vec<PackFileBlock>>,
}

impl crate::Decoder for PackFileEntry {
type Settings = ();

fn new(input: &mut Bytes, _: Self::Settings) -> Result<Self, crate::EQFilesError>
impl crate::Decoder<EmptySettings> for PackFileEntry {
fn new(input: &mut Bytes, _: Arc<EmptySettings>) -> Result<Self, crate::EQFilesError>
where
Self: Sized,
{
Expand Down
10 changes: 6 additions & 4 deletions src/pfs/header.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
use std::sync::Arc;

use bytes::{Buf, Bytes};

use crate::EmptySettings;

#[derive(Clone)]
pub struct PackFileHeader {
pub(crate) directory_offset: u32,
pub magic_number: u32,
pub version: u32,
}

impl crate::Decoder for PackFileHeader {
type Settings = ();

fn new(input: &mut Bytes, _: Self::Settings) -> Result<Self, crate::EQFilesError>
impl crate::Decoder<EmptySettings> for PackFileHeader {
fn new(input: &mut Bytes, _: Arc<EmptySettings> ) -> Result<Self, crate::EQFilesError>
where
Self: Sized,
{
Expand Down
27 changes: 16 additions & 11 deletions src/pfs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand All @@ -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<Self, EQFilesError>
impl Decoder<PathBuf> for PackFile {
fn new(input: &mut Bytes, settings: Arc<PathBuf>) -> Result<Self, EQFilesError>
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);
Expand All @@ -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);
Expand All @@ -53,7 +58,7 @@ impl Decoder for PackFile {
})
.collect();
Ok(PackFile {
path: settings,
path: settings.clone().to_path_buf(),
header,
entry_count,
entries,
Expand All @@ -65,7 +70,7 @@ impl Decoder for PackFile {
}
}

fn directory_string(input: &mut Bytes, _: ()) -> Result<String, EQFilesError> {
fn directory_string(input: &mut Bytes, _: Arc<EmptySettings>) -> Result<String, EQFilesError> {
let length = input.get_u32_le();
match string(input, length as usize) {
Ok(s) => Ok(s),
Expand All @@ -75,7 +80,7 @@ fn directory_string(input: &mut Bytes, _: ()) -> Result<String, EQFilesError> {

pub fn directory(input: &mut Bytes) -> Result<Vec<String>, 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 {
Expand Down
7 changes: 4 additions & 3 deletions src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
use std::string::FromUtf8Error;
use std::sync::Arc;

use bytes::{Buf, Bytes};

use crate::EQFilesError;

pub(crate) const HASH_KEY: [u8; 8] = [0x95u8, 0x3A, 0xC5, 0x2A, 0x95, 0x7A, 0x95, 0x6A];

pub fn count<T, E, S: Clone>(
pub fn count<T, E, S>(
input: &mut Bytes,
count: usize,
settings: S,
f: fn(&mut Bytes, S) -> Result<T, E>,
settings: Arc<S>,
f: fn(&mut Bytes, Arc<S>) -> Result<T, E>,
) -> Result<Vec<T>, E> {
let mut temp = Vec::new();
for _ in 0..count {
Expand Down
67 changes: 61 additions & 6 deletions src/wld/fragments/mod.rs
Original file line number Diff line number Diff line change
@@ -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<WldHeader>,
names: Arc<WldNames>,
}

impl BaseSettings {
pub fn new(header: Arc<WldHeader>, names: Arc<WldNames>) -> Self {
Self { header, names }
}

pub fn make_settings(&self, fragment: Arc<WldRawFragment>) -> Arc<Settings> {
Arc::new(Settings {
header: self.header.clone(),
names: self.names.clone(),
fragment,
})
}
}

#[derive(Debug)]
pub struct Settings {
header: Arc<WldHeader>,
names: Arc<WldNames>,
fragment: Arc<WldRawFragment>,
}

impl Settings {
pub fn get_name_ref(&self) -> i32 {
self.fragment.name_ref
}

pub fn get_name(&self) -> Option<String> {
self.fragment.name.clone()
}

pub fn get_from_name_ref(&self, index: i32) -> Option<String> {
self.names.get_name(index)
}

pub fn is_old_world(&self) -> bool {
self.header.is_old_world
}
}

pub trait WldFragment: Decoder<Settings> {
const TYPE: u32;
}
23 changes: 9 additions & 14 deletions src/wld/fragments/t16_skeleton.rs
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down Expand Up @@ -42,14 +40,12 @@ pub struct WldSkeletonDag {
pub sub_dags: Vec<u32>,
}

impl Decoder for WldSkeleton {
type Settings = Rc<WldNames>;

fn new(input: &mut Bytes, settings: Self::Settings) -> Result<Self, crate::EQFilesError>
impl Decoder<Settings> for WldSkeleton {
fn new(input: &mut Bytes, settings: Arc<Settings>) -> Result<Self, crate::EQFilesError>
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();
Expand Down Expand Up @@ -99,14 +95,13 @@ impl Decoder for WldSkeleton {
}
}

impl Decoder for WldSkeletonDag {
type Settings = Rc<WldNames>;

fn new(input: &mut Bytes, settings: Self::Settings) -> Result<Self, crate::EQFilesError>
impl Decoder<Settings> for WldSkeletonDag {
fn new(input: &mut Bytes, settings: Arc<Settings>) -> Result<Self, crate::EQFilesError>
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();
Expand Down
Loading

0 comments on commit 7f5a023

Please sign in to comment.