diff --git a/src/fot/decoder.rs b/src/fot/decoder.rs index d996928..0610243 100644 --- a/src/fot/decoder.rs +++ b/src/fot/decoder.rs @@ -8,9 +8,9 @@ pub trait Decoder: Sized { fn get_enc_size(&self) -> usize; } -pub trait DecoderCtx: Sized { - fn decode(raw: &Raw, offset: usize, size: usize, ctx: Ctx) -> Result; - fn encode(&self, ctx: Ctx) -> Result; +pub trait DecoderCtx: Sized { + fn decode(raw: &Raw, offset: usize, size: usize, ctx: DCtx) -> Result; + fn encode(&self, ctx: ECtx) -> Result; fn get_enc_size(&self) -> usize; } diff --git a/src/fot/entity.rs b/src/fot/entity.rs index 24e2c4b..c0cfc54 100644 --- a/src/fot/entity.rs +++ b/src/fot/entity.rs @@ -14,7 +14,7 @@ pub struct Entity { enc_size: usize, } -impl DecoderCtx<&mut EntityList> for Entity { +impl DecoderCtx<&mut EntityList, &EntityList> for Entity { fn decode(raw: &Raw, offset: usize, _: usize, ctx: &mut EntityList) -> Result { let mut rd = ReadStream::new(raw, offset); Ok(match ctx.get_entity_encoding() { @@ -45,11 +45,10 @@ impl DecoderCtx<&mut EntityList> for Entity { }) } - fn encode(&self, ctx: &mut EntityList) -> Result { + fn encode(&self, ctx: &EntityList) -> Result { let mut wd = WriteStream::new(self.get_enc_size()); match ctx.get_entity_encoding() { EntityEncoding::File => { - wd.write(ctx.get_entity_tag())?; wd.write(ctx.get_type_name(self.type_idx))?; wd.write(&self.esh)?; } diff --git a/src/fot/entitylist.rs b/src/fot/entitylist.rs index 703ef3d..06017b8 100644 --- a/src/fot/entitylist.rs +++ b/src/fot/entitylist.rs @@ -21,8 +21,8 @@ pub struct EntityList { unk1: u32, enc_size: usize, - types: Vec, - entities: Vec + pub types: Vec, + pub entities: Vec } impl EntityList { @@ -51,7 +51,7 @@ impl EntityList { } } -impl DecoderCtx for EntityList { +impl DecoderCtx for EntityList { fn decode(raw: &Raw, offset: usize, size: usize, ctx: EntityEncoding) -> Result { let mut rd = ReadStream::new(raw, offset); let mut ent_list = EntityList { @@ -84,15 +84,16 @@ impl DecoderCtx for EntityList { EntityEncoding::World => { ent_list.entity_file_tag = Some(rd.read(0)?); - let n = rd.read_u32()?; - for _ in 0..n { + let type_count = rd.read_u32()?; + for _ in 0..type_count { ent_list.types.push(rd.read(0)?); } - let m = rd.read_u16()?; + let ent_count = rd.read_u16()?; ent_list.unk1 = rd.read_u32()?; - for _ in 0..m { + for i in 1..ent_count { let ent: Entity = rd.read_opt(0, &mut ent_list)?; + println!("ok read {}", i); ent_list.entities.push(ent); } @@ -103,7 +104,30 @@ impl DecoderCtx for EntityList { } fn encode(&self, ctx: EntityEncoding) -> Result { - todo!(); + let mut wd = WriteStream::new(self.get_enc_size()); + match ctx { + EntityEncoding::File => { + for ent in self.entities.iter() { + wd.write(self.get_entity_tag())?; + wd.write_opt(ent, &self)?; + } + }, + EntityEncoding::World => { + wd.write(self.entity_file_tag.as_ref().unwrap())?; + wd.write_u32(self.types.len() as u32)?; + for type_name in self.types.iter() { + wd.write(type_name)?; + } + + wd.write_u16(self.entities.len() as u16)?; + wd.write_u32(self.unk1)?; + for ent in self.entities.iter() { + wd.write_opt(ent, &self)?; + } + } + } + + Ok(wd.into_raw(0, 0)) } fn get_enc_size(&self) -> usize { diff --git a/src/fot/save.rs b/src/fot/save.rs index 192adbf..8a2ce50 100644 --- a/src/fot/save.rs +++ b/src/fot/save.rs @@ -7,7 +7,6 @@ use byteorder::{ByteOrder, LittleEndian}; use std::path::Path; use std::str; -#[derive(Debug)] pub struct Save { pub raw: Raw, pub world: World, diff --git a/src/fot/stream.rs b/src/fot/stream.rs index bfb1d5d..4064fac 100644 --- a/src/fot/stream.rs +++ b/src/fot/stream.rs @@ -46,7 +46,7 @@ impl<'a> ReadStream<'a> { // read_opt - decode with optional paramters. required for complex structure // with different origins (save / entfile) like entities - pub fn read_opt, Ctx>(&mut self, size: usize, ctx: Ctx) -> Result { + pub fn read_opt, DCtx, ECtx>(&mut self, size: usize, ctx: DCtx) -> Result { let val = T::decode(&self.raw, self.offset(), size, ctx)?; self.skip(val.get_enc_size()); Ok(val) @@ -112,6 +112,13 @@ impl WriteStream { self.buf.get_mut().extend(bytes.iter()); } + pub fn write_opt, DCtx, ECtx>(&mut self, val: &T, ctx: ECtx) -> Result<()> { + let mut raw = val.encode(ctx)?; + self.skip(raw.mem.len()); + self.buf.get_mut().append(&mut raw.mem); + Ok(()) + } + pub fn write(&mut self, val: &T) -> Result<()> { let mut raw = val.encode()?; self.skip(raw.mem.len()); diff --git a/src/fot/world.rs b/src/fot/world.rs index a5bff36..4be5126 100644 --- a/src/fot/world.rs +++ b/src/fot/world.rs @@ -1,6 +1,6 @@ use super::decoder::Decoder; -use super::esh::ESH; use super::fstring::FString; +use super::entitylist::{EntityList, EntityEncoding}; use super::raw::Raw; use super::sgd::SGD; use super::ssg::SSG; @@ -13,7 +13,6 @@ use deflate::deflate_bytes_zlib; use inflate::inflate_bytes_zlib; use std::io::Cursor; -#[derive(Debug)] pub struct World { pub tag: Tag, pub uncompressed_size: u32, @@ -23,6 +22,8 @@ pub struct World { pub mission: FString, pub sgd: SGD, pub ssg: SSG, + + pub ents: EntityList } impl World { @@ -30,37 +31,7 @@ impl World { const WORLD_HDR_LEN: usize = 0x13; pub fn test(&self) -> Result<()> { - let mut rd = ReadStream::new(&self.data, 0x1038); - let _: Tag = rd.read(0)?; - - let n = rd.read_u32()? as usize; - let mut types: Vec = Vec::with_capacity(n); - for i in 0..n { - let ent_type: FString = rd.read(0)?; - println!("{}\t{}", i, &ent_type); - types.push(ent_type); - } - - let esh_count = rd.read_u16()?; - let unk1 = rd.read_u32()?; - dbg!(esh_count); - for i in 1..esh_count { - let unk2 = rd.read_u32()?; - let type_idx = rd.read_u16()?; - if type_idx == 0xFFFF { - continue; - } - - let name = &types[type_idx as usize]; - println!( - "offset {:x} idx {} unk1 {} name {}", - rd.offset(), - i, - unk2, - name - ); - let _: ESH = rd.read(0)?; - } + println!("read {} ents", self.ents.entities.len()); Ok(()) } @@ -88,6 +59,8 @@ impl Decoder for World { let sgd: SGD = rd.read(0)?; let ssg: SSG = rd.read(0)?; + let ents: EntityList = rd.read_opt(0, EntityEncoding::World)?; + Ok(World { tag, uncompressed_size, @@ -95,6 +68,7 @@ impl Decoder for World { mission, sgd, ssg, + ents }) }