Add new PropertyBase trait, implement more things needed for writing
The biggest change is that structs and properties now provide their own name, which is needed when we want to write everything back to a file. Also a bunch of reorganization of stuff I didn't understand before.
This commit is contained in:
parent
08ac990c15
commit
4801c2678a
19 changed files with 502 additions and 145 deletions
|
@ -12,8 +12,15 @@ use syn::{parse_macro_input, Expr, Fields, Item, Lit};
|
|||
pub fn serialized_struct(_metadata: TokenStream, input: TokenStream)
|
||||
-> TokenStream {
|
||||
let mut input = syn::parse_macro_input!(input as syn::ItemStruct);
|
||||
let Lit::Str(struct_name) = syn::parse_macro_input!(_metadata as syn::Lit) else {
|
||||
panic!("This must be given a name!")
|
||||
};
|
||||
|
||||
for mut field in &mut input.fields {
|
||||
let mut field_types = vec![];
|
||||
let mut field_idents = vec![];
|
||||
let mut field_names = vec![];
|
||||
|
||||
for field in &mut input.fields {
|
||||
let our_custom = &field.attrs[0];
|
||||
let our_custom_name = our_custom.meta.require_name_value().unwrap();
|
||||
let our_custom_name = match &our_custom_name.value {
|
||||
|
@ -28,9 +35,13 @@ pub fn serialized_struct(_metadata: TokenStream, input: TokenStream)
|
|||
_ => None
|
||||
}.unwrap();
|
||||
field.attrs.clear();
|
||||
field_types.push(field.ty.clone());
|
||||
field_idents.push(field.ident.clone());
|
||||
field_names.push(our_custom_name.clone());
|
||||
let field_tokens = field.to_token_stream();
|
||||
let new_field_token_stream = quote! {
|
||||
#[br(parse_with = crate::structs::read_struct_field, args(#our_custom_name))]
|
||||
#[bw(write_with = crate::structs::write_struct_field, args(#our_custom_name))]
|
||||
#field_tokens
|
||||
};
|
||||
let buffer = ::syn::parse::Parser::parse2(
|
||||
|
@ -43,7 +54,7 @@ pub fn serialized_struct(_metadata: TokenStream, input: TokenStream)
|
|||
// Add "None" field
|
||||
let none_field_stream = quote! {
|
||||
#[br(temp)]
|
||||
#[bw(ignore)]
|
||||
#[bw(calc = crate::structs::PrimaryAssetNameProperty { property_name: "None".to_string(), type_name: "".to_string(), key: None } )]
|
||||
none_field: crate::structs::PrimaryAssetNameProperty
|
||||
};
|
||||
let buffer = ::syn::parse::Parser::parse2(
|
||||
|
@ -57,9 +68,26 @@ pub fn serialized_struct(_metadata: TokenStream, input: TokenStream)
|
|||
_ => {}
|
||||
}
|
||||
|
||||
let id = &input.ident;
|
||||
|
||||
let output = quote! {
|
||||
#[binrw]
|
||||
#input
|
||||
|
||||
#[automatically_derived]
|
||||
impl crate::structs::PropertyBase for #id {
|
||||
fn type_name() -> &'static str {
|
||||
return "StructProperty";
|
||||
}
|
||||
|
||||
fn struct_name() -> Option<&'static str> {
|
||||
return Some(#struct_name);
|
||||
}
|
||||
|
||||
fn size_in_bytes(&self) -> u32 {
|
||||
#( #field_types::size_in_bytes(&self.#field_idents) )+* + #( (crate::structs::calc_struct_field_prelude_byte_size(stringify!(#field_types), #field_names, #field_types::struct_name()) ) )+* + 9 // for "none" field
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
output.into_token_stream().into()
|
||||
|
|
|
@ -19,6 +19,20 @@ fn calculate_header_size(key_name: &str, array_key_data: &ArrayKeyData) -> u64 {
|
|||
}
|
||||
}
|
||||
|
||||
impl crate::structs::PropertyBase for ArrayProperty {
|
||||
fn type_name() -> &'static str {
|
||||
return "ArrayProperty";
|
||||
}
|
||||
|
||||
fn size_in_bytes(&self) -> u32 {
|
||||
// todo
|
||||
4 + 8
|
||||
+ crate::common::size_of_string_with_length(&self.key_name)
|
||||
+ calc_key_data_size_in_bytes(&self.key_data)
|
||||
+ calc_size_in_bytes(&self)
|
||||
}
|
||||
}
|
||||
|
||||
#[binrw::parser(reader, endian)]
|
||||
fn custom_parser(
|
||||
size_in_bytes: u32,
|
||||
|
@ -63,9 +77,22 @@ pub struct ArrayEntry {
|
|||
pub key: ArrayValue,
|
||||
}
|
||||
|
||||
fn calc_size_in_bytes(entries: &Vec<ArrayEntry>) -> u32 {
|
||||
// TODO: stub
|
||||
18
|
||||
fn calc_size_in_bytes(prop: &ArrayProperty) -> u32 {
|
||||
// TODO: complete guesswork still
|
||||
let mut size = 4;
|
||||
|
||||
for entry in &prop.entries {
|
||||
size += match &entry.key {
|
||||
ArrayValue::Struct { r#struct } => {
|
||||
crate::struct_property::calc_size_in_bytes(&r#struct)
|
||||
}
|
||||
ArrayValue::String(string_map_key) => {
|
||||
crate::common::size_of_string_with_length(&string_map_key.value)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
size
|
||||
}
|
||||
|
||||
#[binrw]
|
||||
|
@ -86,16 +113,33 @@ pub enum ArrayKeyData {
|
|||
|
||||
#[br(parse_with = read_string_with_length)]
|
||||
#[bw(write_with = write_string_with_length)]
|
||||
#[br(pad_before = 8)] // idk
|
||||
#[br(pad_after = 17)] // super idk
|
||||
#[brw(pad_before = 8)] // idk
|
||||
#[brw(pad_after = 17)] // super idk
|
||||
struct_name: String,
|
||||
},
|
||||
}
|
||||
|
||||
fn calc_key_data_size_in_bytes(key_data: &ArrayKeyData) -> u32 {
|
||||
return match key_data {
|
||||
ArrayKeyData::String() => 0,
|
||||
ArrayKeyData::Struct {
|
||||
name,
|
||||
type_name,
|
||||
struct_name,
|
||||
} => {
|
||||
crate::common::size_of_string_with_length(&name)
|
||||
+ crate::common::size_of_string_with_length(&type_name)
|
||||
+ crate::common::size_of_string_with_length(&struct_name)
|
||||
+ 8
|
||||
+ 17
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[binrw]
|
||||
#[derive(Debug)]
|
||||
pub struct ArrayProperty {
|
||||
#[bw(calc = calc_size_in_bytes(entries))]
|
||||
#[bw(calc = calc_size_in_bytes(self))]
|
||||
pub size_in_bytes: u32,
|
||||
|
||||
#[brw(pad_before = 4)]
|
||||
|
|
|
@ -10,6 +10,16 @@ pub struct BoolProperty {
|
|||
pub value: bool,
|
||||
}
|
||||
|
||||
impl crate::structs::PropertyBase for BoolProperty {
|
||||
fn type_name() -> &'static str {
|
||||
return "IntProperty";
|
||||
}
|
||||
|
||||
fn size_in_bytes(&self) -> u32 {
|
||||
10
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
use crate::common::{read_string_with_length, write_string_with_length};
|
||||
use crate::str_property::StrProperty;
|
||||
use crate::structs::PropertyBase;
|
||||
use crate::structs::{
|
||||
DAAssembleIdDataStruct, DACustomizeAssetIdDataStruct, DATriggerDataStruct, DATuningDataStruct,
|
||||
};
|
||||
use binrw::{binrw};
|
||||
use binrw::binrw;
|
||||
use std::fmt::Debug;
|
||||
|
||||
#[paramacro::serialized_struct]
|
||||
#[paramacro::serialized_struct("DABuildData")]
|
||||
#[derive(Debug)]
|
||||
pub struct DABuildDataStruct {
|
||||
#[paramacro::serialized_field = "Name"]
|
||||
|
@ -28,8 +29,8 @@ pub struct DABuildDataStruct {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use binrw::BinRead;
|
||||
use std::io::Cursor;
|
||||
use binrw::{BinRead, BinWrite};
|
||||
use std::{fs::write, io::Cursor};
|
||||
|
||||
#[test]
|
||||
fn read_build_data() {
|
||||
|
|
|
@ -48,6 +48,10 @@ pub(crate) fn write_string_with_length(string: &String) -> BinResult<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn size_of_string_with_length(string: &str) -> u32 {
|
||||
4 + string.len() as u32 + 1
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use binrw::binrw;
|
||||
use crate::common::{read_string_with_length, write_string_with_length};
|
||||
use binrw::binrw;
|
||||
|
||||
#[binrw]
|
||||
#[derive(Debug)]
|
||||
|
@ -15,6 +15,18 @@ pub struct EnumProperty {
|
|||
pub value: String,
|
||||
}
|
||||
|
||||
impl crate::structs::PropertyBase for EnumProperty {
|
||||
fn type_name() -> &'static str {
|
||||
return "EnumProperty";
|
||||
}
|
||||
|
||||
fn size_in_bytes(&self) -> u32 {
|
||||
8 + crate::common::size_of_string_with_length(&self.enum_type)
|
||||
+ 1
|
||||
+ crate::common::size_of_string_with_length(&self.value)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
@ -25,32 +37,12 @@ mod tests {
|
|||
fn read_enum() {
|
||||
// Persistent.sav
|
||||
let data = [
|
||||
0x29, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x18,
|
||||
0x00, 0x00, 0x00,
|
||||
0x45, 0x44, 0x41,
|
||||
0x57, 0x65, 0x61,
|
||||
0x70, 0x6f, 0x6e,
|
||||
0x4d, 0x6f, 0x64,
|
||||
0x75, 0x6c, 0x65,
|
||||
0x50, 0x6f, 0x73,
|
||||
0x69, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x00,
|
||||
0x00, 0x25, 0x00,
|
||||
0x00, 0x00, 0x45,
|
||||
0x44, 0x41, 0x57,
|
||||
0x65, 0x61, 0x70,
|
||||
0x6f, 0x6e, 0x4d,
|
||||
0x6f, 0x64, 0x75,
|
||||
0x6c, 0x65, 0x50,
|
||||
0x6f, 0x73, 0x69,
|
||||
0x74, 0x69, 0x6f,
|
||||
0x6e, 0x3a, 0x3a,
|
||||
0x46, 0x72, 0x6f,
|
||||
0x6e, 0x74, 0x57,
|
||||
0x65, 0x61, 0x70,
|
||||
0x6f, 0x6e, 0x00
|
||||
0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x45, 0x44,
|
||||
0x41, 0x57, 0x65, 0x61, 0x70, 0x6f, 0x6e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x50,
|
||||
0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x45,
|
||||
0x44, 0x41, 0x57, 0x65, 0x61, 0x70, 0x6f, 0x6e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65,
|
||||
0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x3a, 0x46, 0x72, 0x6f, 0x6e,
|
||||
0x74, 0x57, 0x65, 0x61, 0x70, 0x6f, 0x6e, 0x00,
|
||||
];
|
||||
let mut cursor = Cursor::new(data);
|
||||
let decoded = EnumProperty::read_le(&mut cursor).unwrap();
|
||||
|
|
|
@ -9,6 +9,16 @@ pub struct FloatProperty {
|
|||
pub value: f32,
|
||||
}
|
||||
|
||||
impl crate::structs::PropertyBase for FloatProperty {
|
||||
fn type_name() -> &'static str {
|
||||
return "FloatProperty";
|
||||
}
|
||||
|
||||
fn size_in_bytes(&self) -> u32 {
|
||||
4 + 5 + 4
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
14
src/guid.rs
14
src/guid.rs
|
@ -10,6 +10,20 @@ pub struct Guid {
|
|||
pub d: u32,
|
||||
}
|
||||
|
||||
impl crate::structs::PropertyBase for Guid {
|
||||
fn type_name() -> &'static str {
|
||||
return "StructProperty";
|
||||
}
|
||||
|
||||
fn struct_name() -> Option<&'static str> {
|
||||
return Some("Guid");
|
||||
}
|
||||
|
||||
fn size_in_bytes(&self) -> u32 {
|
||||
16
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Guid {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str(&format!(
|
||||
|
|
|
@ -9,6 +9,16 @@ pub struct IntProperty {
|
|||
pub value: u32,
|
||||
}
|
||||
|
||||
impl crate::structs::PropertyBase for IntProperty {
|
||||
fn type_name() -> &'static str {
|
||||
return "IntProperty";
|
||||
}
|
||||
|
||||
fn size_in_bytes(&self) -> u32 {
|
||||
4 + 5 + 4
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
@ -2,6 +2,7 @@ pub mod array_property;
|
|||
pub mod bool_property;
|
||||
mod build_data;
|
||||
mod common;
|
||||
mod enum_property;
|
||||
pub mod float_property;
|
||||
mod guid;
|
||||
pub mod int_property;
|
||||
|
@ -14,7 +15,6 @@ pub mod set_property;
|
|||
pub mod str_property;
|
||||
pub mod struct_property;
|
||||
mod structs;
|
||||
mod enum_property;
|
||||
|
||||
use binrw::helpers::until_eof;
|
||||
use std::fs::write;
|
||||
|
@ -30,7 +30,7 @@ use crate::name_property::NameProperty;
|
|||
use crate::set_property::SetProperty;
|
||||
use crate::str_property::StrProperty;
|
||||
use crate::struct_property::StructProperty;
|
||||
use binrw::{BinRead, BinResult, binrw, BinWrite};
|
||||
use binrw::{BinRead, BinResult, BinWrite, binrw};
|
||||
use flate2::bufread::ZlibDecoder;
|
||||
|
||||
// Used in ArrayProperty exclusively, but could be used instead of magic above
|
||||
|
|
|
@ -9,6 +9,20 @@ pub struct LinearColorStruct {
|
|||
pub a: f32,
|
||||
}
|
||||
|
||||
impl crate::structs::PropertyBase for LinearColorStruct {
|
||||
fn type_name() -> &'static str {
|
||||
return "StructProperty";
|
||||
}
|
||||
|
||||
fn struct_name() -> Option<&'static str> {
|
||||
return Some("LinearColor");
|
||||
}
|
||||
|
||||
fn size_in_bytes(&self) -> u32 {
|
||||
16
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
@ -2,8 +2,8 @@ use crate::common::{
|
|||
read_bool_from, read_string_with_length, write_bool_as, write_string_with_length,
|
||||
};
|
||||
use crate::guid::Guid;
|
||||
use crate::struct_property::Struct;
|
||||
use crate::structs::PrimaryAssetNameProperty;
|
||||
use crate::struct_property::{Struct, calc_size_in_bytes};
|
||||
use crate::structs::{PrimaryAssetNameProperty, PropertyBase};
|
||||
use binrw::{BinRead, BinResult, binrw};
|
||||
|
||||
// parse until we can't parse no more. kind of a hack for how we run into the end of Persistent.Sav
|
||||
|
@ -203,15 +203,69 @@ fn custom_parser(
|
|||
Ok(result)
|
||||
}
|
||||
|
||||
fn calc_size_in_bytes(entries: &Vec<MapEntry>) -> u32 {
|
||||
// TODO: stub
|
||||
49
|
||||
fn calc_entry_size_in_bytes(prop: &MapProperty) -> u32 {
|
||||
// TODO: complete guesswork still
|
||||
let mut size = 4;
|
||||
|
||||
for entry in &prop.entries {
|
||||
size += match &entry.key {
|
||||
MapKeyProperty::String(string_map_key) => {
|
||||
crate::common::size_of_string_with_length(&string_map_key.value)
|
||||
}
|
||||
MapKeyProperty::StructMaybe(struct_maybe_key) => {
|
||||
crate::common::size_of_string_with_length(&struct_maybe_key.unk_name)
|
||||
+ 8
|
||||
+ crate::common::size_of_string_with_length(&struct_maybe_key.unk_type)
|
||||
+ crate::common::size_of_string_with_length(&struct_maybe_key.struct_name)
|
||||
+ 17
|
||||
+ crate::struct_property::calc_size_in_bytes(&struct_maybe_key.r#struct)
|
||||
}
|
||||
MapKeyProperty::Enum(map_sub_enum_property) => {
|
||||
crate::common::size_of_string_with_length(&map_sub_enum_property.value)
|
||||
}
|
||||
MapKeyProperty::EnumAgain(map_sub_enum_property) => {
|
||||
crate::common::size_of_string_with_length(&map_sub_enum_property.value)
|
||||
}
|
||||
MapKeyProperty::GUID(guid) => guid.size_in_bytes(),
|
||||
MapKeyProperty::SomeID(guid) => guid.size_in_bytes(),
|
||||
MapKeyProperty::SomeID2(guid) => guid.size_in_bytes(),
|
||||
MapKeyProperty::ArrayStruct(struct_maybe_key) => {
|
||||
crate::common::size_of_string_with_length(&struct_maybe_key.unk_name)
|
||||
+ 8
|
||||
+ crate::common::size_of_string_with_length(&struct_maybe_key.unk_type)
|
||||
+ crate::common::size_of_string_with_length(&struct_maybe_key.struct_name)
|
||||
+ 17
|
||||
+ crate::struct_property::calc_size_in_bytes(&struct_maybe_key.r#struct)
|
||||
}
|
||||
MapKeyProperty::SomeID3(guid) => guid.size_in_bytes(),
|
||||
MapKeyProperty::SoftObjectProperty(string_map_key) => {
|
||||
crate::common::size_of_string_with_length(&string_map_key.value)
|
||||
}
|
||||
};
|
||||
size += match &entry.value {
|
||||
MabSubProperty::Name(map_sub_name_property) => {
|
||||
crate::common::size_of_string_with_length(&map_sub_name_property.value)
|
||||
}
|
||||
MabSubProperty::Struct(map_sub_struct_property) => 0,
|
||||
MabSubProperty::Float(map_sub_float_property) => 4,
|
||||
MabSubProperty::String(map_sub_str_property) => {
|
||||
crate::common::size_of_string_with_length(&map_sub_str_property.value)
|
||||
}
|
||||
MabSubProperty::Bool(map_sub_bool_property) => 1,
|
||||
MabSubProperty::Int(map_sub_int_property) => 4,
|
||||
MabSubProperty::Enum(map_sub_enum_property) => {
|
||||
crate::common::size_of_string_with_length(&map_sub_enum_property.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size
|
||||
}
|
||||
|
||||
#[binrw]
|
||||
#[derive(Debug)]
|
||||
pub struct MapProperty {
|
||||
#[bw(calc = calc_size_in_bytes(entries))]
|
||||
#[bw(calc = calc_entry_size_in_bytes(&self))]
|
||||
pub size_in_bytes: u32,
|
||||
|
||||
#[brw(pad_before = 4)]
|
||||
|
@ -231,6 +285,21 @@ pub struct MapProperty {
|
|||
pub entries: Vec<MapEntry>,
|
||||
}
|
||||
|
||||
impl crate::structs::PropertyBase for MapProperty {
|
||||
fn type_name() -> &'static str {
|
||||
return "MapProperty";
|
||||
}
|
||||
|
||||
fn size_in_bytes(&self) -> u32 {
|
||||
4 + 4
|
||||
+ crate::common::size_of_string_with_length(&self.key_name)
|
||||
+ crate::common::size_of_string_with_length(&self.value_name)
|
||||
+ 5
|
||||
+ 4
|
||||
+ calc_entry_size_in_bytes(&self)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
@ -13,3 +13,13 @@ pub struct NameProperty {
|
|||
#[bw(write_with = write_string_with_length)]
|
||||
pub value: String,
|
||||
}
|
||||
|
||||
impl crate::structs::PropertyBase for NameProperty {
|
||||
fn type_name() -> &'static str {
|
||||
return "NameProperty";
|
||||
}
|
||||
|
||||
fn size_in_bytes(&self) -> u32 {
|
||||
5 + 4 + crate::common::size_of_string_with_length(&self.value)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
use crate::structs::StructField;
|
||||
use crate::{
|
||||
name_property::NameProperty, primary_asset_type::PrimaryAssetTypeStruct, structs::StructField,
|
||||
};
|
||||
use binrw::binrw;
|
||||
|
||||
#[binrw]
|
||||
#[paramacro::serialized_struct("PrimaryAssetId")]
|
||||
#[derive(Debug)]
|
||||
pub struct PrimaryAssetIdStruct {
|
||||
//#[brw(pad_before = 17)]
|
||||
//#[br(pad_after = 9)] // "None"
|
||||
#[br(args {name: "PrimaryAssetType", r#type: "StructProperty" })]
|
||||
primary_asset_type: StructField,
|
||||
#[paramacro::serialized_field = "PrimaryAssetType"]
|
||||
pub primary_asset_type: PrimaryAssetTypeStruct,
|
||||
|
||||
#[paramacro::serialized_field = "PrimaryAssetName"]
|
||||
pub primary_asset_name: NameProperty,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -19,21 +22,23 @@ mod tests {
|
|||
#[test]
|
||||
fn read_id() {
|
||||
let data = [
|
||||
0x11, 0x00, 0x00, 0x00, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x41, 0x73, 0x73, 0x65, 0x74,
|
||||
0x54, 0x79, 0x70, 0x65, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x50,
|
||||
0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x00, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x11, 0x00, 0x00, 0x00, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x41, 0x73, 0x73, 0x65, 0x74,
|
||||
0x54, 0x79, 0x70, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x4e, 0x61, 0x6d, 0x65, 0x00, 0x0d,
|
||||
0x00, 0x00, 0x00, 0x4e, 0x61, 0x6d, 0x65, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x00,
|
||||
0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x50, 0x6f, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x00, 0x05, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x6e, 0x65, 0x00, 0x11, 0x00, 0x00,
|
||||
0x00, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4e, 0x61, 0x6d,
|
||||
0x65, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x4e, 0x61, 0x6d, 0x65, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72,
|
||||
0x74, 0x79, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
|
||||
0x49, 0x74, 0x65, 0x6d, 0x5f, 0x50, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x48, 0x65, 0x61, 0x6c,
|
||||
0x74, 0x68, 0x50, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x05, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x6e,
|
||||
0x65, 0x00
|
||||
0x11, 0x00, 0x00, 0x00, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x41, 0x73, 0x73,
|
||||
0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x53, 0x74, 0x72,
|
||||
0x75, 0x63, 0x74, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x00, 0x37, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x50, 0x72, 0x69, 0x6d,
|
||||
0x61, 0x72, 0x79, 0x41, 0x73, 0x73, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x4e, 0x61, 0x6d, 0x65, 0x00, 0x0d, 0x00, 0x00,
|
||||
0x00, 0x4e, 0x61, 0x6d, 0x65, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x00,
|
||||
0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x50,
|
||||
0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x05, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x6e, 0x65,
|
||||
0x00, 0x11, 0x00, 0x00, 0x00, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x41, 0x73,
|
||||
0x73, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x4e, 0x61,
|
||||
0x6d, 0x65, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x00, 0x1d, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x49, 0x74, 0x65, 0x6d,
|
||||
0x5f, 0x50, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68,
|
||||
0x50, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x05, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x6e,
|
||||
0x65, 0x00,
|
||||
];
|
||||
let mut cursor = Cursor::new(data);
|
||||
let decoded = PrimaryAssetIdStruct::read_le(&mut cursor).unwrap();
|
||||
|
|
|
@ -1,16 +1,11 @@
|
|||
use crate::structs::StructField;
|
||||
use crate::{name_property::NameProperty, structs::StructField};
|
||||
use binrw::binrw;
|
||||
|
||||
// TODO: im pretty sure everything about this + PrimaryAssetId is wrong. i think primary_asset_name needs to belong in PrimaryAssetId
|
||||
#[binrw]
|
||||
#[paramacro::serialized_struct("PrimaryAssetType")]
|
||||
#[derive(Debug)]
|
||||
pub struct PrimaryAssetTypeStruct {
|
||||
#[brw(pad_after = 9)]
|
||||
#[br(args { name: "Name", r#type: "NameProperty" })]
|
||||
name: StructField,
|
||||
#[brw(pad_after = 9)]
|
||||
#[br(args { name: "PrimaryAssetName", r#type: "NameProperty" })]
|
||||
primary_asset_name: StructField,
|
||||
#[paramacro::serialized_field = "Name"]
|
||||
pub name: NameProperty,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -22,15 +17,16 @@ mod tests {
|
|||
#[test]
|
||||
fn read_id() {
|
||||
let data = [
|
||||
0x05, 0x00, 0x00, 0x00, 0x4e, 0x61, 0x6d, 0x65, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x4e, 0x61, 0x6d,
|
||||
0x65, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x50, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x05, 0x00,
|
||||
0x00, 0x00, 0x4e, 0x6f, 0x6e, 0x65, 0x00, 0x11, 0x00, 0x00, 0x00, 0x50, 0x72, 0x69, 0x6d, 0x61,
|
||||
0x72, 0x79, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x00, 0x0d, 0x00, 0x00, 0x00,
|
||||
0x4e, 0x61, 0x6d, 0x65, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x00, 0x1d, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x49, 0x74, 0x65, 0x6d, 0x5f, 0x50,
|
||||
0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x50, 0x6f, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x00, 0x05, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x6e, 0x65, 0x00
|
||||
0x05, 0x00, 0x00, 0x00, 0x4e, 0x61, 0x6d, 0x65, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x4e,
|
||||
0x61, 0x6d, 0x65, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x00, 0x0b, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x50, 0x6f, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x00, 0x05, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x6e, 0x65, 0x00, 0x11,
|
||||
0x00, 0x00, 0x00, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x41, 0x73, 0x73, 0x65,
|
||||
0x74, 0x4e, 0x61, 0x6d, 0x65, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x4e, 0x61, 0x6d, 0x65,
|
||||
0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x49, 0x74, 0x65, 0x6d, 0x5f, 0x50,
|
||||
0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x50, 0x6f,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x00, 0x05, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x6e, 0x65, 0x00,
|
||||
];
|
||||
let mut cursor = Cursor::new(data);
|
||||
let decoded = PrimaryAssetTypeStruct::read_le(&mut cursor).unwrap();
|
||||
|
|
|
@ -1,8 +1,24 @@
|
|||
use crate::common::{read_string_with_length, write_string_with_length};
|
||||
use crate::map_property::{KeyType, MapSubStrProperty};
|
||||
use crate::struct_property::Struct;
|
||||
use crate::structs::PrimaryAssetNameProperty;
|
||||
use binrw::{BinRead, BinResult, binrw};
|
||||
|
||||
// hack, we should be checking for "none" instead
|
||||
#[binrw::parser(reader, endian)]
|
||||
fn cc() -> BinResult<Vec<PrimaryAssetNameProperty>> {
|
||||
let mut result = Vec::<PrimaryAssetNameProperty>::new();
|
||||
|
||||
loop {
|
||||
if let Ok(str) = PrimaryAssetNameProperty::read_options(reader, endian, ()) {
|
||||
result.push(str);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
#[binrw]
|
||||
#[derive(Debug)]
|
||||
#[br(import { magic: &str, name: &str })]
|
||||
|
@ -10,19 +26,8 @@ pub enum SetValue {
|
|||
// NOTE: the name checking is just a temporary workaround
|
||||
#[br(pre_assert("StructProperty" == magic && name != "OpenedStrongBoxIds" && name != "AcquiredItemBoxIds"))]
|
||||
Struct {
|
||||
#[br(parse_with = read_string_with_length)]
|
||||
#[bw(write_with = write_string_with_length)]
|
||||
struct_type: String,
|
||||
#[br(parse_with = read_string_with_length)]
|
||||
#[bw(write_with = write_string_with_length)]
|
||||
r#type: String,
|
||||
#[br(parse_with = read_string_with_length)]
|
||||
#[bw(write_with = write_string_with_length)]
|
||||
#[br(pad_before = 8)]
|
||||
struct_type_for_some_reason_again: String,
|
||||
#[br(args { magic: &struct_type_for_some_reason_again })]
|
||||
#[brw(pad_before = 17)]
|
||||
r#struct: Struct,
|
||||
#[br(parse_with = cc)]
|
||||
fields: Vec<PrimaryAssetNameProperty>,
|
||||
},
|
||||
#[br(pre_assert("StringProperty" == magic || "NameProperty" == magic))]
|
||||
String(MapSubStrProperty),
|
||||
|
|
|
@ -14,6 +14,16 @@ pub struct StrProperty {
|
|||
pub value: String,
|
||||
}
|
||||
|
||||
impl crate::structs::PropertyBase for StrProperty {
|
||||
fn type_name() -> &'static str {
|
||||
return "StrProperty";
|
||||
}
|
||||
|
||||
fn size_in_bytes(&self) -> u32 {
|
||||
5 + 4 + crate::common::size_of_string_with_length(&self.value)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
@ -5,11 +5,10 @@ use crate::linear_color::LinearColorStruct;
|
|||
use crate::primary_asset_id::PrimaryAssetIdStruct;
|
||||
use crate::primary_asset_type::PrimaryAssetTypeStruct;
|
||||
use crate::structs::{
|
||||
DAAssembleIdDataStruct, DACustomizeAssetIdDataStruct,
|
||||
DAHumanoidColoringDataStruct, DAHumanoidFigureData, DALoadOptionStruct,
|
||||
DAMachineColoringDataStruct, DAModuleColorStruct, DAModuleItemDataStruct, DATriggerDataStruct,
|
||||
DATuningDataStruct, DATuningPointData, DateTimeStruct, QuatStruct, SaveSlotInfoStruct,
|
||||
TransformStruct, VectorStruct,
|
||||
DAAssembleIdDataStruct, DACustomizeAssetIdDataStruct, DAHumanoidColoringDataStruct,
|
||||
DAHumanoidFigureData, DALoadOptionStruct, DAMachineColoringDataStruct, DAModuleColorStruct,
|
||||
DAModuleItemDataStruct, DATriggerDataStruct, DATuningDataStruct, DATuningPointData,
|
||||
DateTimeStruct, PropertyBase, QuatStruct, SaveSlotInfoStruct, TransformStruct, VectorStruct,
|
||||
};
|
||||
use binrw::binrw;
|
||||
|
||||
|
@ -17,50 +16,91 @@ use binrw::binrw;
|
|||
#[derive(Debug)]
|
||||
#[br(import { magic: &str })]
|
||||
pub enum Struct {
|
||||
#[br(pre_assert(magic == "DateTime"))]
|
||||
#[br(pre_assert(magic == DateTimeStruct::struct_name().unwrap()))]
|
||||
DateTime(DateTimeStruct),
|
||||
#[br(pre_assert(magic == "DALoadOption"))]
|
||||
#[br(pre_assert(magic == DALoadOptionStruct::struct_name().unwrap()))]
|
||||
DALoadOption(DALoadOptionStruct),
|
||||
#[br(pre_assert(magic == "SaveSlotInfo"))]
|
||||
#[br(pre_assert(magic == SaveSlotInfoStruct::struct_name().unwrap()))]
|
||||
SaveSlotInfo(SaveSlotInfoStruct),
|
||||
#[br(pre_assert(magic == "PrimaryAssetType"))]
|
||||
#[br(pre_assert(magic == PrimaryAssetTypeStruct::struct_name().unwrap()))]
|
||||
PrimaryAssetType(PrimaryAssetTypeStruct),
|
||||
#[br(pre_assert(magic == "PrimaryAssetId"))]
|
||||
#[br(pre_assert(magic == PrimaryAssetIdStruct::struct_name().unwrap()))]
|
||||
PrimaryAssetId(PrimaryAssetIdStruct),
|
||||
#[br(pre_assert(magic == "DAModuleItemData"))]
|
||||
#[br(pre_assert(magic == DAModuleItemDataStruct::struct_name().unwrap()))]
|
||||
DAModuleItemData(DAModuleItemDataStruct),
|
||||
#[br(pre_assert(magic == "DABuildData"))]
|
||||
#[br(pre_assert(magic == DABuildDataStruct::struct_name().unwrap()))]
|
||||
DABuildData(DABuildDataStruct),
|
||||
#[br(pre_assert(magic == "DAAssembleIdData"))]
|
||||
#[br(pre_assert(magic == DAAssembleIdDataStruct::struct_name().unwrap()))]
|
||||
DAAssembleIdData(DAAssembleIdDataStruct),
|
||||
#[br(pre_assert(magic == "Guid"))]
|
||||
#[br(pre_assert(magic == Guid::struct_name().unwrap()))]
|
||||
Guid(Guid),
|
||||
#[br(pre_assert(magic == "DAMachineColoringData"))]
|
||||
#[br(pre_assert(magic == DAMachineColoringDataStruct::struct_name().unwrap()))]
|
||||
DAMachineColoringData(DAMachineColoringDataStruct),
|
||||
#[br(pre_assert(magic == "DAModuleColor"))]
|
||||
#[br(pre_assert(magic == DAModuleColorStruct::struct_name().unwrap()))]
|
||||
DAModuleColor(DAModuleColorStruct),
|
||||
#[br(pre_assert(magic == "LinearColor"))]
|
||||
#[br(pre_assert(magic == LinearColorStruct::struct_name().unwrap()))]
|
||||
LinearColor(LinearColorStruct),
|
||||
#[br(pre_assert(magic == "DATriggerData"))]
|
||||
#[br(pre_assert(magic == DATriggerDataStruct::struct_name().unwrap()))]
|
||||
DATriggerData(DATriggerDataStruct),
|
||||
#[br(pre_assert(magic == "DACustomizeAssetIdData"))]
|
||||
#[br(pre_assert(magic == DACustomizeAssetIdDataStruct::struct_name().unwrap()))]
|
||||
DACustomizeAssetIdData(DACustomizeAssetIdDataStruct),
|
||||
#[br(pre_assert(magic == "DATuningData"))]
|
||||
#[br(pre_assert(magic == DATuningDataStruct::struct_name().unwrap()))]
|
||||
DATuningData(DATuningDataStruct),
|
||||
#[br(pre_assert(magic == "DAHumanoidColoringData"))]
|
||||
#[br(pre_assert(magic == DAHumanoidColoringDataStruct::struct_name().unwrap()))]
|
||||
DAHumanoidColoringData(DAHumanoidColoringDataStruct),
|
||||
#[br(pre_assert(magic == "DAHumanoidFigureData"))]
|
||||
#[br(pre_assert(magic == DAHumanoidFigureData::struct_name().unwrap()))]
|
||||
DAHumanoidFigureData(DAHumanoidFigureData),
|
||||
#[br(pre_assert(magic == "DATuningPointData"))]
|
||||
#[br(pre_assert(magic == DATuningPointData::struct_name().unwrap()))]
|
||||
DATuningPointData(DATuningPointData),
|
||||
#[br(pre_assert(magic == "Transform"))]
|
||||
#[br(pre_assert(magic == TransformStruct::struct_name().unwrap()))]
|
||||
Transform(TransformStruct),
|
||||
#[br(pre_assert(magic == "Quat"))]
|
||||
#[br(pre_assert(magic == QuatStruct::struct_name().unwrap()))]
|
||||
Quat(QuatStruct),
|
||||
#[br(pre_assert(magic == "Vector"))]
|
||||
#[br(pre_assert(magic == VectorStruct::struct_name().unwrap()))]
|
||||
Vector(VectorStruct),
|
||||
}
|
||||
|
||||
pub(crate) fn calc_size_in_bytes(r#struct: &Struct) -> u32 {
|
||||
// todo
|
||||
return match r#struct {
|
||||
Struct::DateTime(date_time_struct) => date_time_struct.size_in_bytes(),
|
||||
Struct::DALoadOption(daload_option_struct) => daload_option_struct.size_in_bytes(),
|
||||
Struct::SaveSlotInfo(save_slot_info_struct) => save_slot_info_struct.size_in_bytes(),
|
||||
Struct::PrimaryAssetType(primary_asset_type_struct) => {
|
||||
primary_asset_type_struct.size_in_bytes()
|
||||
}
|
||||
Struct::PrimaryAssetId(primary_asset_id_struct) => primary_asset_id_struct.size_in_bytes(),
|
||||
Struct::DAModuleItemData(damodule_item_data_struct) => {
|
||||
damodule_item_data_struct.size_in_bytes()
|
||||
}
|
||||
Struct::DABuildData(dabuild_data_struct) => dabuild_data_struct.size_in_bytes(),
|
||||
Struct::DAAssembleIdData(daassemble_id_data_struct) => {
|
||||
daassemble_id_data_struct.size_in_bytes()
|
||||
}
|
||||
Struct::Guid(guid) => guid.size_in_bytes(),
|
||||
Struct::DAMachineColoringData(damachine_coloring_data_struct) => {
|
||||
damachine_coloring_data_struct.size_in_bytes()
|
||||
}
|
||||
Struct::DAModuleColor(damodule_color_struct) => damodule_color_struct.size_in_bytes(),
|
||||
Struct::LinearColor(linear_color_struct) => linear_color_struct.size_in_bytes(),
|
||||
Struct::DATriggerData(datrigger_data_struct) => datrigger_data_struct.size_in_bytes(),
|
||||
Struct::DACustomizeAssetIdData(dacustomize_asset_id_data_struct) => {
|
||||
dacustomize_asset_id_data_struct.size_in_bytes()
|
||||
}
|
||||
Struct::DATuningData(datuning_data_struct) => datuning_data_struct.size_in_bytes(),
|
||||
Struct::DAHumanoidColoringData(dahumanoid_coloring_data_struct) => {
|
||||
dahumanoid_coloring_data_struct.size_in_bytes()
|
||||
}
|
||||
Struct::DAHumanoidFigureData(dahumanoid_figure_data) => {
|
||||
dahumanoid_figure_data.size_in_bytes()
|
||||
}
|
||||
Struct::DATuningPointData(datuning_point_data) => datuning_point_data.size_in_bytes(),
|
||||
Struct::Transform(transform_struct) => transform_struct.size_in_bytes(),
|
||||
Struct::Quat(quat_struct) => quat_struct.size_in_bytes(),
|
||||
Struct::Vector(vector_struct) => vector_struct.size_in_bytes(),
|
||||
};
|
||||
}
|
||||
|
||||
#[binrw]
|
||||
#[derive(Debug)]
|
||||
pub struct StructProperty {
|
||||
|
@ -70,6 +110,6 @@ pub struct StructProperty {
|
|||
#[bw(write_with = write_string_with_length)]
|
||||
pub struct_name: String,
|
||||
#[br(args { magic: &struct_name })]
|
||||
#[br(pad_before = 17)]
|
||||
#[brw(pad_before = 17)]
|
||||
pub r#struct: Struct,
|
||||
}
|
||||
|
|
133
src/structs.rs
133
src/structs.rs
|
@ -3,6 +3,7 @@ use crate::array_property::ArrayProperty;
|
|||
use crate::bool_property::BoolProperty;
|
||||
use crate::build_data::DABuildDataStruct;
|
||||
use crate::common::{read_string_with_length, write_string_with_length};
|
||||
use crate::enum_property::EnumProperty;
|
||||
use crate::float_property::FloatProperty;
|
||||
use crate::guid::Guid;
|
||||
use crate::int_property::IntProperty;
|
||||
|
@ -12,9 +13,8 @@ use crate::name_property::NameProperty;
|
|||
use crate::primary_asset_id::PrimaryAssetIdStruct;
|
||||
use crate::primary_asset_type::PrimaryAssetTypeStruct;
|
||||
use crate::str_property::StrProperty;
|
||||
use binrw::{BinRead, BinResult, binrw};
|
||||
use binrw::{BinRead, BinResult, BinWrite, binrw};
|
||||
use std::fmt::Debug;
|
||||
use crate::enum_property::EnumProperty;
|
||||
|
||||
#[binrw]
|
||||
#[derive(Debug)]
|
||||
|
@ -22,14 +22,14 @@ pub struct DateTimeStruct {
|
|||
pub unk: [u8; 8],
|
||||
}
|
||||
|
||||
#[paramacro::serialized_struct]
|
||||
#[paramacro::serialized_struct("DALoadOption")]
|
||||
#[derive(Debug)]
|
||||
pub struct DALoadOptionStruct {
|
||||
#[paramacro::serialized_field = "LoadTypes"]
|
||||
pub load_types: IntProperty,
|
||||
}
|
||||
|
||||
#[paramacro::serialized_struct]
|
||||
#[paramacro::serialized_struct("SaveSlotInfo")]
|
||||
#[derive(Debug)]
|
||||
pub struct SaveSlotInfoStruct {
|
||||
#[paramacro::serialized_field = "Name"]
|
||||
|
@ -83,14 +83,14 @@ pub struct StructField {
|
|||
pub key: Option<Box<Property>>,
|
||||
}
|
||||
|
||||
#[paramacro::serialized_struct]
|
||||
#[paramacro::serialized_struct("DAModuleItemData")]
|
||||
#[derive(Debug)]
|
||||
pub struct DAModuleItemDataStruct {
|
||||
#[paramacro::serialized_field = "ModuleLevel"]
|
||||
pub module_level: IntProperty,
|
||||
}
|
||||
|
||||
#[paramacro::serialized_struct]
|
||||
#[paramacro::serialized_struct("DAAssembleIdData")]
|
||||
#[derive(Debug)]
|
||||
pub struct DAAssembleIdDataStruct {
|
||||
#[paramacro::serialized_field = "Hanger"]
|
||||
|
@ -124,7 +124,7 @@ pub struct DAAssembleIdDataStruct {
|
|||
pub coloring_data: DAMachineColoringDataStruct,
|
||||
}
|
||||
|
||||
#[paramacro::serialized_struct]
|
||||
#[paramacro::serialized_struct("DAMachineColoringData")]
|
||||
#[derive(Debug)]
|
||||
pub struct DAMachineColoringDataStruct {
|
||||
#[paramacro::serialized_field = "Hanger"]
|
||||
|
@ -155,7 +155,7 @@ pub struct DAMachineColoringDataStruct {
|
|||
pub right_rear_weapon: DAModuleColorStruct,
|
||||
}
|
||||
|
||||
#[paramacro::serialized_struct]
|
||||
#[paramacro::serialized_struct("DAHumanoidColoringData")]
|
||||
#[derive(Debug)]
|
||||
pub struct DAHumanoidColoringDataStruct {
|
||||
#[paramacro::serialized_field = "Skin"]
|
||||
|
@ -192,7 +192,7 @@ pub struct DAHumanoidColoringDataStruct {
|
|||
pub body_sub3: LinearColorStruct,
|
||||
}
|
||||
|
||||
#[paramacro::serialized_struct]
|
||||
#[paramacro::serialized_struct("DAModuleColor")]
|
||||
#[derive(Debug)]
|
||||
pub struct DAModuleColorStruct {
|
||||
#[paramacro::serialized_field = "Main"]
|
||||
|
@ -208,7 +208,7 @@ pub struct DAModuleColorStruct {
|
|||
pub glow: LinearColorStruct,
|
||||
}
|
||||
|
||||
#[paramacro::serialized_struct]
|
||||
#[paramacro::serialized_struct("DATriggerData")]
|
||||
#[derive(Debug)]
|
||||
pub struct DATriggerDataStruct {
|
||||
#[paramacro::serialized_field = "A"]
|
||||
|
@ -221,7 +221,7 @@ pub struct DATriggerDataStruct {
|
|||
pub c: EnumProperty,
|
||||
}
|
||||
|
||||
#[paramacro::serialized_struct]
|
||||
#[paramacro::serialized_struct("DACustomizeAssetIdData")]
|
||||
#[derive(Debug)]
|
||||
pub struct DACustomizeAssetIdDataStruct {
|
||||
#[paramacro::serialized_field = "Body"]
|
||||
|
@ -252,7 +252,7 @@ pub struct DACustomizeAssetIdDataStruct {
|
|||
pub inverse_back_hair_mesh: BoolProperty,
|
||||
}
|
||||
|
||||
#[paramacro::serialized_struct]
|
||||
#[paramacro::serialized_struct("DAHumanoidFigureData")]
|
||||
#[derive(Debug)]
|
||||
pub struct DAHumanoidFigureData {
|
||||
#[paramacro::serialized_field = "BustUp"]
|
||||
|
@ -271,7 +271,7 @@ pub struct DAHumanoidFigureData {
|
|||
pub waist_up: FloatProperty,
|
||||
}
|
||||
|
||||
#[paramacro::serialized_struct]
|
||||
#[paramacro::serialized_struct("DATuningData")]
|
||||
#[derive(Debug)]
|
||||
pub struct DATuningDataStruct {
|
||||
#[paramacro::serialized_field = "GrantedTuningPointList"]
|
||||
|
@ -284,7 +284,7 @@ pub struct SavedBuildData {
|
|||
pub build_data: DABuildDataStruct,
|
||||
}
|
||||
|
||||
#[paramacro::serialized_struct]
|
||||
#[paramacro::serialized_struct("DATuningPointData")]
|
||||
#[derive(Debug)]
|
||||
pub struct DATuningPointData {
|
||||
#[paramacro::serialized_field = "TuningPoint"]
|
||||
|
@ -294,7 +294,7 @@ pub struct DATuningPointData {
|
|||
max_tuning_point: IntProperty,
|
||||
}
|
||||
|
||||
#[paramacro::serialized_struct]
|
||||
#[paramacro::serialized_struct("Transform")]
|
||||
#[derive(Debug)]
|
||||
pub struct TransformStruct {
|
||||
#[paramacro::serialized_field = "Rotation"]
|
||||
|
@ -340,11 +340,11 @@ pub struct StructFieldPrelude {
|
|||
#[binrw]
|
||||
#[derive(Debug)]
|
||||
pub struct StructPrelude {
|
||||
pub unk: u32,
|
||||
pub size_in_bytes: u32,
|
||||
#[brw(pad_before = 4)]
|
||||
#[br(parse_with = read_string_with_length)]
|
||||
#[bw(write_with = write_string_with_length)]
|
||||
#[br(pad_after = 17)]
|
||||
#[brw(pad_after = 17)]
|
||||
pub struct_name: String,
|
||||
}
|
||||
|
||||
|
@ -359,10 +359,105 @@ pub(crate) fn read_struct_field<T: BinRead<Args<'static> = ()> + Debug>(
|
|||
name, prelude.property_name
|
||||
);
|
||||
}
|
||||
println!("{:#?}", prelude);
|
||||
// TODO: type check with type_name()
|
||||
if prelude.type_name == "StructProperty" {
|
||||
println!("{:#?}", StructPrelude::read_le(reader)?);
|
||||
StructPrelude::read_le(reader)?;
|
||||
}
|
||||
let val = T::read_options(reader, endian, ())?;
|
||||
Ok(val)
|
||||
}
|
||||
|
||||
pub(crate) trait PropertyBase {
|
||||
fn type_name() -> &'static str;
|
||||
fn size_in_bytes(&self) -> u32;
|
||||
|
||||
// these are only relevant for structs:
|
||||
// FIXME: this isn't great'
|
||||
fn struct_name() -> Option<&'static str> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl PropertyBase for DateTimeStruct {
|
||||
fn type_name() -> &'static str {
|
||||
return "StructProperty";
|
||||
}
|
||||
|
||||
fn struct_name() -> Option<&'static str> {
|
||||
return Some("DateTime");
|
||||
}
|
||||
|
||||
fn size_in_bytes(&self) -> u32 {
|
||||
8
|
||||
}
|
||||
}
|
||||
|
||||
impl PropertyBase for VectorStruct {
|
||||
fn type_name() -> &'static str {
|
||||
return "StructProperty";
|
||||
}
|
||||
|
||||
fn struct_name() -> Option<&'static str> {
|
||||
return Some("Vector");
|
||||
}
|
||||
|
||||
fn size_in_bytes(&self) -> u32 {
|
||||
16
|
||||
}
|
||||
}
|
||||
|
||||
impl PropertyBase for QuatStruct {
|
||||
fn type_name() -> &'static str {
|
||||
return "StructProperty";
|
||||
}
|
||||
|
||||
fn struct_name() -> Option<&'static str> {
|
||||
return Some("Quat");
|
||||
}
|
||||
|
||||
fn size_in_bytes(&self) -> u32 {
|
||||
16
|
||||
}
|
||||
}
|
||||
|
||||
#[binrw::writer(writer, endian)]
|
||||
pub(crate) fn write_struct_field<T: PropertyBase + BinWrite<Args<'static> = ()> + Debug>(
|
||||
structure: &T,
|
||||
name: &str,
|
||||
) -> BinResult<()> {
|
||||
let prelude = StructFieldPrelude {
|
||||
property_name: name.to_string(),
|
||||
type_name: T::type_name().to_string(),
|
||||
};
|
||||
prelude.write_le(writer)?;
|
||||
if T::type_name() == "StructProperty" {
|
||||
let struct_prelude = StructPrelude {
|
||||
size_in_bytes: T::size_in_bytes(structure),
|
||||
struct_name: T::struct_name().unwrap().to_string(),
|
||||
};
|
||||
struct_prelude.write_le(writer)?;
|
||||
}
|
||||
structure.write_options(writer, endian, ())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn calc_struct_field_prelude_byte_size(
|
||||
type_name: &str,
|
||||
field_name: &str,
|
||||
struct_name: Option<&str>,
|
||||
) -> u32 {
|
||||
let mut base_size = crate::common::size_of_string_with_length(field_name);
|
||||
|
||||
// This is an easy way to detect properties that are actually structs
|
||||
if struct_name.is_some() {
|
||||
base_size += crate::common::size_of_string_with_length("StructProperty")
|
||||
+ crate::common::size_of_string_with_length(struct_name.unwrap())
|
||||
+ 4
|
||||
+ 17
|
||||
+ 4; // see struct prelude
|
||||
} else {
|
||||
base_size += crate::common::size_of_string_with_length(type_name);
|
||||
}
|
||||
|
||||
base_size
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue