implemented EntityList decoding and encoding. But decoding has some bugs that needs to be fixed
This commit is contained in:
parent
4e8cc4a5e8
commit
5ea616cd44
6 changed files with 52 additions and 49 deletions
|
|
@ -8,9 +8,9 @@ pub trait Decoder: Sized {
|
|||
fn get_enc_size(&self) -> usize;
|
||||
}
|
||||
|
||||
pub trait DecoderCtx<Ctx>: Sized {
|
||||
fn decode(raw: &Raw, offset: usize, size: usize, ctx: Ctx) -> Result<Self>;
|
||||
fn encode(&self, ctx: Ctx) -> Result<Raw>;
|
||||
pub trait DecoderCtx<DCtx, ECtx>: Sized {
|
||||
fn decode(raw: &Raw, offset: usize, size: usize, ctx: DCtx) -> Result<Self>;
|
||||
fn encode(&self, ctx: ECtx) -> Result<Raw>;
|
||||
fn get_enc_size(&self) -> usize;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<Self> {
|
||||
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<Raw> {
|
||||
fn encode(&self, ctx: &EntityList) -> Result<Raw> {
|
||||
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)?;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ pub struct EntityList {
|
|||
unk1: u32,
|
||||
enc_size: usize,
|
||||
|
||||
types: Vec<FString>,
|
||||
entities: Vec<Entity>
|
||||
pub types: Vec<FString>,
|
||||
pub entities: Vec<Entity>
|
||||
}
|
||||
|
||||
impl EntityList {
|
||||
|
|
@ -51,7 +51,7 @@ impl EntityList {
|
|||
}
|
||||
}
|
||||
|
||||
impl DecoderCtx<EntityEncoding> for EntityList {
|
||||
impl DecoderCtx<EntityEncoding,EntityEncoding> for EntityList {
|
||||
fn decode(raw: &Raw, offset: usize, size: usize, ctx: EntityEncoding) -> Result<Self> {
|
||||
let mut rd = ReadStream::new(raw, offset);
|
||||
let mut ent_list = EntityList {
|
||||
|
|
@ -84,15 +84,16 @@ impl DecoderCtx<EntityEncoding> 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<EntityEncoding> for EntityList {
|
|||
}
|
||||
|
||||
fn encode(&self, ctx: EntityEncoding) -> Result<Raw> {
|
||||
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 {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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<T: DecoderCtx<Ctx>, Ctx>(&mut self, size: usize, ctx: Ctx) -> Result<T> {
|
||||
pub fn read_opt<T: DecoderCtx<DCtx, ECtx>, DCtx, ECtx>(&mut self, size: usize, ctx: DCtx) -> Result<T> {
|
||||
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<T: DecoderCtx<DCtx, ECtx>, 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<T: Decoder>(&mut self, val: &T) -> Result<()> {
|
||||
let mut raw = val.encode()?;
|
||||
self.skip(raw.mem.len());
|
||||
|
|
|
|||
|
|
@ -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<FString> = 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
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue