Reorganize the entire project
This commit is contained in:
parent
53aba498d1
commit
3b26da6b57
44 changed files with 424 additions and 359 deletions
|
@ -40,8 +40,8 @@ pub fn serialized_struct(_metadata: TokenStream, input: TokenStream)
|
||||||
field_names.push(our_custom_name.clone());
|
field_names.push(our_custom_name.clone());
|
||||||
let field_tokens = field.to_token_stream();
|
let field_tokens = field.to_token_stream();
|
||||||
let new_field_token_stream = quote! {
|
let new_field_token_stream = quote! {
|
||||||
#[br(parse_with = crate::structs::read_struct_field, args(#our_custom_name))]
|
#[br(parse_with = crate::structure::read_struct_field, args(#our_custom_name))]
|
||||||
#[bw(write_with = crate::structs::write_struct_field, args(#our_custom_name))]
|
#[bw(write_with = crate::structure::write_struct_field, args(#our_custom_name))]
|
||||||
#field_tokens
|
#field_tokens
|
||||||
};
|
};
|
||||||
let buffer = ::syn::parse::Parser::parse2(
|
let buffer = ::syn::parse::Parser::parse2(
|
||||||
|
@ -54,8 +54,8 @@ pub fn serialized_struct(_metadata: TokenStream, input: TokenStream)
|
||||||
// Add "None" field
|
// Add "None" field
|
||||||
let none_field_stream = quote! {
|
let none_field_stream = quote! {
|
||||||
#[br(temp)]
|
#[br(temp)]
|
||||||
#[bw(calc = crate::structs::GenericProperty { property_name: "None".to_string(), type_name: "".to_string(), key: None } )]
|
#[bw(calc = crate::property::generic_property::GenericProperty { property_name: "None".to_string(), type_name: "".to_string(), key: None } )]
|
||||||
none_field: crate::structs::GenericProperty
|
none_field: crate::property::generic_property::GenericProperty
|
||||||
};
|
};
|
||||||
let buffer = ::syn::parse::Parser::parse2(
|
let buffer = ::syn::parse::Parser::parse2(
|
||||||
syn::Field::parse_named,
|
syn::Field::parse_named,
|
||||||
|
@ -75,7 +75,7 @@ pub fn serialized_struct(_metadata: TokenStream, input: TokenStream)
|
||||||
#input
|
#input
|
||||||
|
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl crate::structs::PropertyBase for #id {
|
impl crate::property::PropertyBase for #id {
|
||||||
fn type_name() -> &'static str {
|
fn type_name() -> &'static str {
|
||||||
return "StructProperty";
|
return "StructProperty";
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,7 @@ pub fn serialized_struct(_metadata: TokenStream, input: TokenStream)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn size_in_bytes(&self) -> u32 {
|
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
|
#( #field_types::size_in_bytes(&self.#field_idents) )+* + #( (crate::structure::calc_struct_field_prelude_byte_size(stringify!(#field_types), #field_names, #field_types::struct_name()) ) )+* + 9 // for "none" field
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use binrw::BinRead;
|
use binrw::BinRead;
|
||||||
use ireko::{CompressedSaveFile, GenericTaggedObject};
|
use ireko::CompressedSaveFile;
|
||||||
|
use ireko::save_object::generic::GenericTaggedObject;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
|
||||||
|
|
146
src/lib.rs
146
src/lib.rs
|
@ -1,155 +1,15 @@
|
||||||
pub mod array_property;
|
|
||||||
pub mod bool_property;
|
|
||||||
mod build_data;
|
|
||||||
mod common;
|
mod common;
|
||||||
mod da_assemble_id_data;
|
pub mod property;
|
||||||
mod da_customize_asset_id;
|
pub mod save_object;
|
||||||
mod da_humanoid_coloring_data;
|
pub mod structure;
|
||||||
mod da_humanoid_figure_data;
|
|
||||||
mod da_load_option;
|
|
||||||
mod da_machine_coloring_data;
|
|
||||||
mod da_module_color;
|
|
||||||
mod da_module_item_data;
|
|
||||||
mod da_trigger_data;
|
|
||||||
mod da_tuning_data;
|
|
||||||
mod da_tuning_point_data;
|
|
||||||
mod datetime;
|
|
||||||
mod enum_property;
|
|
||||||
pub mod float_property;
|
|
||||||
mod guid;
|
|
||||||
pub mod int_property;
|
|
||||||
mod linear_color;
|
|
||||||
mod localprofile;
|
|
||||||
pub mod map_property;
|
|
||||||
mod name_property;
|
|
||||||
mod persistent;
|
|
||||||
mod primary_asset_id;
|
|
||||||
mod primary_asset_type;
|
|
||||||
mod quat;
|
|
||||||
mod save_slot_info;
|
|
||||||
pub mod set_property;
|
|
||||||
mod slot;
|
|
||||||
pub mod str_property;
|
|
||||||
pub mod struct_property;
|
|
||||||
mod structs;
|
|
||||||
mod transform;
|
|
||||||
mod vector;
|
|
||||||
|
|
||||||
use binrw::helpers::until_eof;
|
use binrw::helpers::until_eof;
|
||||||
use std::fs::write;
|
use std::fs::write;
|
||||||
use std::io::{Cursor, Read};
|
use std::io::{Cursor, Read};
|
||||||
|
|
||||||
use crate::array_property::ArrayProperty;
|
|
||||||
use crate::bool_property::BoolProperty;
|
|
||||||
use crate::common::{read_string_with_length, write_string_with_length};
|
|
||||||
use crate::float_property::FloatProperty;
|
|
||||||
use crate::int_property::IntProperty;
|
|
||||||
use crate::map_property::MapProperty;
|
|
||||||
use crate::name_property::NameProperty;
|
|
||||||
use crate::set_property::SetProperty;
|
|
||||||
use crate::str_property::StrProperty;
|
|
||||||
use crate::struct_property::StructProperty;
|
|
||||||
use binrw::{BinRead, BinResult, BinWrite, binrw};
|
use binrw::{BinRead, BinResult, BinWrite, binrw};
|
||||||
use flate2::bufread::ZlibDecoder;
|
use flate2::bufread::ZlibDecoder;
|
||||||
|
|
||||||
// Used in ArrayProperty exclusively, but could be used instead of magic above
|
|
||||||
#[binrw]
|
|
||||||
#[derive(Debug)]
|
|
||||||
#[br(import { magic: &str, name: &str })]
|
|
||||||
pub enum Property {
|
|
||||||
#[br(pre_assert("NameProperty" == magic))]
|
|
||||||
Name(NameProperty),
|
|
||||||
#[br(pre_assert("StructProperty" == magic))]
|
|
||||||
Struct(StructProperty),
|
|
||||||
#[br(pre_assert("FloatProperty" == magic))]
|
|
||||||
Float(FloatProperty),
|
|
||||||
#[br(pre_assert("StrProperty" == magic))]
|
|
||||||
String(StrProperty),
|
|
||||||
#[br(pre_assert("BoolProperty" == magic))]
|
|
||||||
Bool(BoolProperty),
|
|
||||||
#[br(pre_assert("IntProperty" == magic))]
|
|
||||||
Int(IntProperty),
|
|
||||||
#[br(pre_assert("ArrayProperty" == magic))]
|
|
||||||
Array(ArrayProperty),
|
|
||||||
#[br(pre_assert("MapProperty" == magic))]
|
|
||||||
Map(MapProperty),
|
|
||||||
#[br(pre_assert("SetProperty" == magic))]
|
|
||||||
Set(SetProperty),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[binrw]
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Entry {
|
|
||||||
#[br(parse_with = read_string_with_length)]
|
|
||||||
#[bw(write_with = write_string_with_length)]
|
|
||||||
pub name: String,
|
|
||||||
|
|
||||||
#[br(parse_with = read_string_with_length)]
|
|
||||||
#[bw(write_with = write_string_with_length)]
|
|
||||||
#[br(if(name != "None"))]
|
|
||||||
pub type_name: String,
|
|
||||||
|
|
||||||
#[br(if(name != "None"), args { magic: &type_name, name: &name })]
|
|
||||||
pub r#type: Option<Property>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[binrw::parser(reader, endian)]
|
|
||||||
fn custom_tagged_object_parser(size_in_bytes: u32) -> BinResult<Vec<Entry>> {
|
|
||||||
let mut result = Vec::<Entry>::new();
|
|
||||||
|
|
||||||
let mut current = reader.stream_position()?;
|
|
||||||
let end = current + size_in_bytes as u64 - 4; // for the size bits
|
|
||||||
|
|
||||||
while current < end {
|
|
||||||
let entry = Entry::read_options(reader, endian, ())?;
|
|
||||||
if entry.name == "None" {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
result.push(entry);
|
|
||||||
current = reader.stream_position()?;
|
|
||||||
}
|
|
||||||
Ok(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[binrw::writer(writer, endian)]
|
|
||||||
fn custom_tagged_object_writer(entries: &Vec<Entry>) -> BinResult<()> {
|
|
||||||
for entry in entries {
|
|
||||||
entry.write_options(writer, endian, ())?
|
|
||||||
}
|
|
||||||
// Write "none" entry at the end
|
|
||||||
let none_entry = Entry {
|
|
||||||
name: "None".to_string(),
|
|
||||||
type_name: "".to_string(),
|
|
||||||
r#type: None,
|
|
||||||
};
|
|
||||||
none_entry.write_options(writer, endian, ())?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[binrw]
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct GenericTaggedObject {
|
|
||||||
pub size_in_bytes: u32,
|
|
||||||
#[br(parse_with = custom_tagged_object_parser, args(size_in_bytes))]
|
|
||||||
#[bw(write_with = custom_tagged_object_writer)]
|
|
||||||
pub entries: Vec<Entry>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[binrw]
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct PersistentObject {
|
|
||||||
pub size_in_bytes: u32,
|
|
||||||
#[br(pad_after = 4)]
|
|
||||||
pub profile: persistent::Persistent,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GenericTaggedObject {
|
|
||||||
pub fn entry(&self, key: &str) -> Option<&Entry> {
|
|
||||||
let entries: Vec<&Entry> = self.entries.iter().filter(|e| e.name == key).collect();
|
|
||||||
entries.first().copied()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[binrw]
|
#[binrw]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct TaggedSerialization<T>
|
pub struct TaggedSerialization<T>
|
||||||
|
|
|
@ -1,8 +1,15 @@
|
||||||
use crate::common::{read_string_with_length, write_string_with_length};
|
|
||||||
use crate::map_property::{KeyType, StringMapKey};
|
|
||||||
use crate::struct_property::Struct;
|
|
||||||
use binrw::{BinRead, BinResult, binrw};
|
use binrw::{BinRead, BinResult, binrw};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
common::{read_string_with_length, write_string_with_length},
|
||||||
|
structure::Struct,
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
PropertyBase,
|
||||||
|
map_property::{KeyType, StringMapKey},
|
||||||
|
};
|
||||||
|
|
||||||
fn calculate_header_size(key_name: &str, array_key_data: &ArrayKeyData) -> u64 {
|
fn calculate_header_size(key_name: &str, array_key_data: &ArrayKeyData) -> u64 {
|
||||||
// TODO: blah, needs to take into account everything before the first item
|
// TODO: blah, needs to take into account everything before the first item
|
||||||
match array_key_data {
|
match array_key_data {
|
||||||
|
@ -19,7 +26,7 @@ fn calculate_header_size(key_name: &str, array_key_data: &ArrayKeyData) -> u64 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl crate::structs::PropertyBase for ArrayProperty {
|
impl PropertyBase for ArrayProperty {
|
||||||
fn type_name() -> &'static str {
|
fn type_name() -> &'static str {
|
||||||
"ArrayProperty"
|
"ArrayProperty"
|
||||||
}
|
}
|
||||||
|
@ -83,7 +90,7 @@ fn calc_size_in_bytes(prop: &ArrayProperty) -> u32 {
|
||||||
|
|
||||||
for entry in &prop.entries {
|
for entry in &prop.entries {
|
||||||
size += match &entry.key {
|
size += match &entry.key {
|
||||||
ArrayValue::Struct { r#struct } => crate::struct_property::calc_size_in_bytes(r#struct),
|
ArrayValue::Struct { r#struct } => crate::structure::calc_size_in_bytes(r#struct),
|
||||||
ArrayValue::String(string_map_key) => {
|
ArrayValue::String(string_map_key) => {
|
||||||
crate::common::size_of_string_with_length(&string_map_key.value)
|
crate::common::size_of_string_with_length(&string_map_key.value)
|
||||||
}
|
}
|
||||||
|
@ -158,7 +165,6 @@ pub struct ArrayProperty {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::map_property::StringMapKey;
|
|
||||||
use binrw::{BinRead, BinWrite};
|
use binrw::{BinRead, BinWrite};
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
use crate::common::{read_bool_from, write_bool_as};
|
use crate::common::{read_bool_from, write_bool_as};
|
||||||
use binrw::binrw;
|
use binrw::binrw;
|
||||||
|
|
||||||
|
use super::PropertyBase;
|
||||||
|
|
||||||
#[binrw]
|
#[binrw]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct BoolProperty {
|
pub struct BoolProperty {
|
||||||
|
@ -10,7 +12,7 @@ pub struct BoolProperty {
|
||||||
pub value: bool,
|
pub value: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl crate::structs::PropertyBase for BoolProperty {
|
impl PropertyBase for BoolProperty {
|
||||||
fn type_name() -> &'static str {
|
fn type_name() -> &'static str {
|
||||||
"IntProperty"
|
"IntProperty"
|
||||||
}
|
}
|
|
@ -1,6 +1,8 @@
|
||||||
use crate::common::{read_string_with_length, write_string_with_length};
|
use crate::common::{read_string_with_length, write_string_with_length};
|
||||||
use binrw::binrw;
|
use binrw::binrw;
|
||||||
|
|
||||||
|
use super::PropertyBase;
|
||||||
|
|
||||||
#[binrw]
|
#[binrw]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct EnumProperty {
|
pub struct EnumProperty {
|
||||||
|
@ -15,7 +17,7 @@ pub struct EnumProperty {
|
||||||
pub value: String,
|
pub value: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl crate::structs::PropertyBase for EnumProperty {
|
impl PropertyBase for EnumProperty {
|
||||||
fn type_name() -> &'static str {
|
fn type_name() -> &'static str {
|
||||||
"EnumProperty"
|
"EnumProperty"
|
||||||
}
|
}
|
|
@ -1,5 +1,7 @@
|
||||||
use binrw::binrw;
|
use binrw::binrw;
|
||||||
|
|
||||||
|
use super::PropertyBase;
|
||||||
|
|
||||||
#[binrw]
|
#[binrw]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct FloatProperty {
|
pub struct FloatProperty {
|
||||||
|
@ -9,7 +11,7 @@ pub struct FloatProperty {
|
||||||
pub value: f32,
|
pub value: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl crate::structs::PropertyBase for FloatProperty {
|
impl PropertyBase for FloatProperty {
|
||||||
fn type_name() -> &'static str {
|
fn type_name() -> &'static str {
|
||||||
"FloatProperty"
|
"FloatProperty"
|
||||||
}
|
}
|
23
src/property/generic_property.rs
Normal file
23
src/property/generic_property.rs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
use binrw::binrw;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
common::{read_string_with_length, write_string_with_length},
|
||||||
|
save_object::generic::Property,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[binrw]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct GenericProperty {
|
||||||
|
#[br(parse_with = read_string_with_length)]
|
||||||
|
#[bw(write_with = write_string_with_length)]
|
||||||
|
pub property_name: String,
|
||||||
|
|
||||||
|
#[br(parse_with = read_string_with_length)]
|
||||||
|
#[bw(write_with = write_string_with_length)]
|
||||||
|
#[br(if(property_name != "None"))]
|
||||||
|
pub type_name: String,
|
||||||
|
|
||||||
|
#[br(if(property_name != "None"))]
|
||||||
|
#[br(args { magic: &type_name, name: &property_name})]
|
||||||
|
pub key: Option<Box<Property>>,
|
||||||
|
}
|
|
@ -1,5 +1,7 @@
|
||||||
use binrw::binrw;
|
use binrw::binrw;
|
||||||
|
|
||||||
|
use super::PropertyBase;
|
||||||
|
|
||||||
#[binrw]
|
#[binrw]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct IntProperty {
|
pub struct IntProperty {
|
||||||
|
@ -9,7 +11,7 @@ pub struct IntProperty {
|
||||||
pub value: u32,
|
pub value: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl crate::structs::PropertyBase for IntProperty {
|
impl PropertyBase for IntProperty {
|
||||||
fn type_name() -> &'static str {
|
fn type_name() -> &'static str {
|
||||||
"IntProperty"
|
"IntProperty"
|
||||||
}
|
}
|
|
@ -1,11 +1,12 @@
|
||||||
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::{GenericProperty, PropertyBase};
|
|
||||||
use binrw::{BinRead, BinResult, binrw};
|
use binrw::{BinRead, BinResult, binrw};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
common::{read_bool_from, read_string_with_length, write_bool_as, write_string_with_length},
|
||||||
|
structure::{Struct, guid::Guid},
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::{PropertyBase, generic_property::GenericProperty};
|
||||||
|
|
||||||
// parse until we can't parse no more. kind of a hack for how we run into the end of Persistent.Sav
|
// parse until we can't parse no more. kind of a hack for how we run into the end of Persistent.Sav
|
||||||
#[binrw::parser(reader, endian)]
|
#[binrw::parser(reader, endian)]
|
||||||
fn cc() -> BinResult<Vec<GenericProperty>> {
|
fn cc() -> BinResult<Vec<GenericProperty>> {
|
||||||
|
@ -225,7 +226,7 @@ fn calc_entry_size_in_bytes(prop: &MapProperty) -> u32 {
|
||||||
+ crate::common::size_of_string_with_length(&struct_maybe_key.unk_type)
|
+ crate::common::size_of_string_with_length(&struct_maybe_key.unk_type)
|
||||||
+ crate::common::size_of_string_with_length(&struct_maybe_key.struct_name)
|
+ crate::common::size_of_string_with_length(&struct_maybe_key.struct_name)
|
||||||
+ 17
|
+ 17
|
||||||
+ crate::struct_property::calc_size_in_bytes(&struct_maybe_key.r#struct)
|
+ crate::structure::calc_size_in_bytes(&struct_maybe_key.r#struct)
|
||||||
}
|
}
|
||||||
MapKeyProperty::Enum(map_sub_enum_property) => {
|
MapKeyProperty::Enum(map_sub_enum_property) => {
|
||||||
crate::common::size_of_string_with_length(&map_sub_enum_property.value)
|
crate::common::size_of_string_with_length(&map_sub_enum_property.value)
|
||||||
|
@ -242,7 +243,7 @@ fn calc_entry_size_in_bytes(prop: &MapProperty) -> u32 {
|
||||||
+ crate::common::size_of_string_with_length(&struct_maybe_key.unk_type)
|
+ crate::common::size_of_string_with_length(&struct_maybe_key.unk_type)
|
||||||
+ crate::common::size_of_string_with_length(&struct_maybe_key.struct_name)
|
+ crate::common::size_of_string_with_length(&struct_maybe_key.struct_name)
|
||||||
+ 17
|
+ 17
|
||||||
+ crate::struct_property::calc_size_in_bytes(&struct_maybe_key.r#struct)
|
+ crate::structure::calc_size_in_bytes(&struct_maybe_key.r#struct)
|
||||||
}
|
}
|
||||||
MapKeyProperty::SomeID3(guid) => guid.size_in_bytes(),
|
MapKeyProperty::SomeID3(guid) => guid.size_in_bytes(),
|
||||||
MapKeyProperty::SoftObjectProperty(string_map_key) => {
|
MapKeyProperty::SoftObjectProperty(string_map_key) => {
|
||||||
|
@ -292,7 +293,7 @@ pub struct MapProperty {
|
||||||
pub entries: Vec<MapEntry>,
|
pub entries: Vec<MapEntry>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl crate::structs::PropertyBase for MapProperty {
|
impl PropertyBase for MapProperty {
|
||||||
fn type_name() -> &'static str {
|
fn type_name() -> &'static str {
|
||||||
"MapProperty"
|
"MapProperty"
|
||||||
}
|
}
|
||||||
|
@ -310,7 +311,6 @@ impl crate::structs::PropertyBase for MapProperty {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::map_property::MabSubProperty::{Int, String};
|
|
||||||
use binrw::{BinRead, BinWrite};
|
use binrw::{BinRead, BinWrite};
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
|
||||||
|
@ -333,7 +333,7 @@ mod tests {
|
||||||
let MapKeyProperty::String(key_property) = &decoded.entries.first().unwrap().key else {
|
let MapKeyProperty::String(key_property) = &decoded.entries.first().unwrap().key else {
|
||||||
panic!("StrProperty!")
|
panic!("StrProperty!")
|
||||||
};
|
};
|
||||||
let String(value_property) = &decoded.entries.first().unwrap().value else {
|
let MabSubProperty::String(value_property) = &decoded.entries.first().unwrap().value else {
|
||||||
panic!("StrProperty!")
|
panic!("StrProperty!")
|
||||||
};
|
};
|
||||||
assert_eq!(key_property.value, "AR0XJGFWA6HNIQ1AAUJ9UR828");
|
assert_eq!(key_property.value, "AR0XJGFWA6HNIQ1AAUJ9UR828");
|
||||||
|
@ -359,7 +359,7 @@ mod tests {
|
||||||
key: MapKeyProperty::String(StringMapKey {
|
key: MapKeyProperty::String(StringMapKey {
|
||||||
value: "AR0XJGFWA6HNIQ1AAUJ9UR828".to_string(),
|
value: "AR0XJGFWA6HNIQ1AAUJ9UR828".to_string(),
|
||||||
}),
|
}),
|
||||||
value: String(MapSubStrProperty {
|
value: MabSubProperty::String(MapSubStrProperty {
|
||||||
value: "NAME 1".to_string(),
|
value: "NAME 1".to_string(),
|
||||||
}),
|
}),
|
||||||
}],
|
}],
|
||||||
|
@ -403,7 +403,7 @@ mod tests {
|
||||||
let MapKeyProperty::Enum(key_property) = &decoded.entries.first().unwrap().key else {
|
let MapKeyProperty::Enum(key_property) = &decoded.entries.first().unwrap().key else {
|
||||||
panic!("Name!")
|
panic!("Name!")
|
||||||
};
|
};
|
||||||
let Int(value_property) = &decoded.entries.first().unwrap().value else {
|
let MabSubProperty::Int(value_property) = &decoded.entries.first().unwrap().value else {
|
||||||
panic!("Int!")
|
panic!("Int!")
|
||||||
};
|
};
|
||||||
assert_eq!(key_property.value, "SelectedMachine");
|
assert_eq!(key_property.value, "SelectedMachine");
|
22
src/property/mod.rs
Normal file
22
src/property/mod.rs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
pub mod array_property;
|
||||||
|
pub mod bool_property;
|
||||||
|
pub mod enum_property;
|
||||||
|
pub mod float_property;
|
||||||
|
pub mod generic_property;
|
||||||
|
pub mod int_property;
|
||||||
|
pub mod map_property;
|
||||||
|
pub mod name_property;
|
||||||
|
pub mod set_property;
|
||||||
|
pub mod str_property;
|
||||||
|
pub mod struct_property;
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,8 @@
|
||||||
use crate::common::{read_string_with_length, write_string_with_length};
|
use crate::common::{read_string_with_length, write_string_with_length};
|
||||||
use binrw::binrw;
|
use binrw::binrw;
|
||||||
|
|
||||||
|
use super::PropertyBase;
|
||||||
|
|
||||||
#[binrw]
|
#[binrw]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct NameProperty {
|
pub struct NameProperty {
|
||||||
|
@ -14,7 +16,7 @@ pub struct NameProperty {
|
||||||
pub value: String,
|
pub value: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl crate::structs::PropertyBase for NameProperty {
|
impl PropertyBase for NameProperty {
|
||||||
fn type_name() -> &'static str {
|
fn type_name() -> &'static str {
|
||||||
"NameProperty"
|
"NameProperty"
|
||||||
}
|
}
|
|
@ -1,8 +1,12 @@
|
||||||
use crate::common::{read_string_with_length, write_string_with_length};
|
use crate::common::{read_string_with_length, write_string_with_length};
|
||||||
use crate::map_property::{KeyType, MapSubStrProperty};
|
|
||||||
use crate::structs::GenericProperty;
|
|
||||||
use binrw::{BinRead, BinResult, binrw};
|
use binrw::{BinRead, BinResult, binrw};
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
PropertyBase,
|
||||||
|
generic_property::GenericProperty,
|
||||||
|
map_property::{KeyType, MapSubStrProperty},
|
||||||
|
};
|
||||||
|
|
||||||
// hack, we should be checking for "none" instead
|
// hack, we should be checking for "none" instead
|
||||||
#[binrw::parser(reader, endian)]
|
#[binrw::parser(reader, endian)]
|
||||||
fn cc() -> BinResult<Vec<GenericProperty>> {
|
fn cc() -> BinResult<Vec<GenericProperty>> {
|
||||||
|
@ -88,7 +92,7 @@ pub struct SetProperty {
|
||||||
pub entries: Vec<SetEntry>,
|
pub entries: Vec<SetEntry>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl crate::structs::PropertyBase for SetProperty {
|
impl PropertyBase for SetProperty {
|
||||||
fn type_name() -> &'static str {
|
fn type_name() -> &'static str {
|
||||||
"SetProperty"
|
"SetProperty"
|
||||||
}
|
}
|
|
@ -1,6 +1,8 @@
|
||||||
use crate::common::{read_string_with_length, write_string_with_length};
|
use crate::common::{read_string_with_length, write_string_with_length};
|
||||||
use binrw::binrw;
|
use binrw::binrw;
|
||||||
|
|
||||||
|
use super::PropertyBase;
|
||||||
|
|
||||||
#[binrw]
|
#[binrw]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct StrProperty {
|
pub struct StrProperty {
|
||||||
|
@ -14,7 +16,7 @@ pub struct StrProperty {
|
||||||
pub value: String,
|
pub value: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl crate::structs::PropertyBase for StrProperty {
|
impl PropertyBase for StrProperty {
|
||||||
fn type_name() -> &'static str {
|
fn type_name() -> &'static str {
|
||||||
"StrProperty"
|
"StrProperty"
|
||||||
}
|
}
|
18
src/property/struct_property.rs
Normal file
18
src/property/struct_property.rs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
use crate::{
|
||||||
|
common::{read_string_with_length, write_string_with_length},
|
||||||
|
structure::Struct,
|
||||||
|
};
|
||||||
|
use binrw::binrw;
|
||||||
|
|
||||||
|
#[binrw]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct StructProperty {
|
||||||
|
pub unk: u32,
|
||||||
|
#[brw(pad_before = 4)]
|
||||||
|
#[br(parse_with = read_string_with_length)]
|
||||||
|
#[bw(write_with = write_string_with_length)]
|
||||||
|
pub struct_name: String,
|
||||||
|
#[br(args { magic: &struct_name })]
|
||||||
|
#[brw(pad_before = 17)]
|
||||||
|
pub r#struct: Struct,
|
||||||
|
}
|
100
src/save_object/generic.rs
Normal file
100
src/save_object/generic.rs
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
use binrw::{BinRead, BinResult, BinWrite, binrw};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
common::{read_string_with_length, write_string_with_length},
|
||||||
|
property::{
|
||||||
|
array_property::ArrayProperty, bool_property::BoolProperty, float_property::FloatProperty,
|
||||||
|
int_property::IntProperty, map_property::MapProperty, name_property::NameProperty,
|
||||||
|
set_property::SetProperty, str_property::StrProperty, struct_property::StructProperty,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Used in ArrayProperty exclusively, but could be used instead of magic above
|
||||||
|
#[binrw]
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[br(import { magic: &str, name: &str })]
|
||||||
|
pub enum Property {
|
||||||
|
#[br(pre_assert("NameProperty" == magic))]
|
||||||
|
Name(NameProperty),
|
||||||
|
#[br(pre_assert("StructProperty" == magic))]
|
||||||
|
Struct(StructProperty),
|
||||||
|
#[br(pre_assert("FloatProperty" == magic))]
|
||||||
|
Float(FloatProperty),
|
||||||
|
#[br(pre_assert("StrProperty" == magic))]
|
||||||
|
String(StrProperty),
|
||||||
|
#[br(pre_assert("BoolProperty" == magic))]
|
||||||
|
Bool(BoolProperty),
|
||||||
|
#[br(pre_assert("IntProperty" == magic))]
|
||||||
|
Int(IntProperty),
|
||||||
|
#[br(pre_assert("ArrayProperty" == magic))]
|
||||||
|
Array(ArrayProperty),
|
||||||
|
#[br(pre_assert("MapProperty" == magic))]
|
||||||
|
Map(MapProperty),
|
||||||
|
#[br(pre_assert("SetProperty" == magic))]
|
||||||
|
Set(SetProperty),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[binrw]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Entry {
|
||||||
|
#[br(parse_with = read_string_with_length)]
|
||||||
|
#[bw(write_with = write_string_with_length)]
|
||||||
|
pub name: String,
|
||||||
|
|
||||||
|
#[br(parse_with = read_string_with_length)]
|
||||||
|
#[bw(write_with = write_string_with_length)]
|
||||||
|
#[br(if(name != "None"))]
|
||||||
|
pub type_name: String,
|
||||||
|
|
||||||
|
#[br(if(name != "None"), args { magic: &type_name, name: &name })]
|
||||||
|
pub r#type: Option<Property>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[binrw::parser(reader, endian)]
|
||||||
|
fn custom_tagged_object_parser(size_in_bytes: u32) -> BinResult<Vec<Entry>> {
|
||||||
|
let mut result = Vec::<Entry>::new();
|
||||||
|
|
||||||
|
let mut current = reader.stream_position()?;
|
||||||
|
let end = current + size_in_bytes as u64 - 4; // for the size bits
|
||||||
|
|
||||||
|
while current < end {
|
||||||
|
let entry = Entry::read_options(reader, endian, ())?;
|
||||||
|
if entry.name == "None" {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
result.push(entry);
|
||||||
|
current = reader.stream_position()?;
|
||||||
|
}
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[binrw::writer(writer, endian)]
|
||||||
|
fn custom_tagged_object_writer(entries: &Vec<Entry>) -> BinResult<()> {
|
||||||
|
for entry in entries {
|
||||||
|
entry.write_options(writer, endian, ())?
|
||||||
|
}
|
||||||
|
// Write "none" entry at the end
|
||||||
|
let none_entry = Entry {
|
||||||
|
name: "None".to_string(),
|
||||||
|
type_name: "".to_string(),
|
||||||
|
r#type: None,
|
||||||
|
};
|
||||||
|
none_entry.write_options(writer, endian, ())?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[binrw]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct GenericTaggedObject {
|
||||||
|
pub size_in_bytes: u32,
|
||||||
|
#[br(parse_with = custom_tagged_object_parser, args(size_in_bytes))]
|
||||||
|
#[bw(write_with = custom_tagged_object_writer)]
|
||||||
|
pub entries: Vec<Entry>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GenericTaggedObject {
|
||||||
|
pub fn entry(&self, key: &str) -> Option<&Entry> {
|
||||||
|
let entries: Vec<&Entry> = self.entries.iter().filter(|e| e.name == key).collect();
|
||||||
|
entries.first().copied()
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{
|
use crate::property::{
|
||||||
bool_property::BoolProperty, int_property::IntProperty, map_property::MapProperty,
|
bool_property::BoolProperty, int_property::IntProperty, map_property::MapProperty,
|
||||||
str_property::StrProperty,
|
str_property::StrProperty,
|
||||||
};
|
};
|
4
src/save_object/mod.rs
Normal file
4
src/save_object/mod.rs
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
pub mod generic;
|
||||||
|
pub mod localprofile;
|
||||||
|
pub mod persistent;
|
||||||
|
pub mod slot;
|
|
@ -1,7 +1,15 @@
|
||||||
|
use binrw::binrw;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
array_property::ArrayProperty, bool_property::BoolProperty, build_data::DABuildDataStruct, da_tuning_point_data::DATuningPointData, int_property::IntProperty,
|
property::{
|
||||||
map_property::MapProperty, name_property::NameProperty,
|
array_property::ArrayProperty, bool_property::BoolProperty, int_property::IntProperty,
|
||||||
set_property::SetProperty, str_property::StrProperty, transform::TransformStruct,
|
map_property::MapProperty, name_property::NameProperty, set_property::SetProperty,
|
||||||
|
str_property::StrProperty,
|
||||||
|
},
|
||||||
|
structure::{
|
||||||
|
build_data::DABuildDataStruct, da_tuning_point_data::DATuningPointData,
|
||||||
|
transform::TransformStruct,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[paramacro::serialized_struct("Transform")]
|
#[paramacro::serialized_struct("Transform")]
|
||||||
|
@ -97,3 +105,11 @@ pub struct Persistent {
|
||||||
#[paramacro::serialized_field = "bUseSaveSlot"]
|
#[paramacro::serialized_field = "bUseSaveSlot"]
|
||||||
use_save_slot: BoolProperty,
|
use_save_slot: BoolProperty,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[binrw]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct PersistentObject {
|
||||||
|
pub size_in_bytes: u32,
|
||||||
|
#[br(pad_after = 4)]
|
||||||
|
pub profile: Persistent,
|
||||||
|
}
|
|
@ -1,7 +1,12 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
bool_property::BoolProperty, da_load_option::DALoadOptionStruct, datetime::DateTimeStruct,
|
property::{
|
||||||
float_property::FloatProperty, int_property::IntProperty,
|
bool_property::BoolProperty, float_property::FloatProperty, int_property::IntProperty,
|
||||||
name_property::NameProperty, save_slot_info::SaveSlotInfoStruct, str_property::StrProperty,
|
name_property::NameProperty, str_property::StrProperty,
|
||||||
|
},
|
||||||
|
structure::{
|
||||||
|
da_load_option::DALoadOptionStruct, datetime::DateTimeStruct,
|
||||||
|
save_slot_info::SaveSlotInfoStruct,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[paramacro::serialized_struct("Transform")]
|
#[paramacro::serialized_struct("Transform")]
|
116
src/structs.rs
116
src/structs.rs
|
@ -1,116 +0,0 @@
|
||||||
use crate::Property;
|
|
||||||
use crate::common::{read_string_with_length, write_string_with_length};
|
|
||||||
use binrw::{BinRead, BinResult, BinWrite, binrw};
|
|
||||||
use std::fmt::Debug;
|
|
||||||
|
|
||||||
#[binrw]
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct GenericProperty {
|
|
||||||
#[br(parse_with = read_string_with_length)]
|
|
||||||
#[bw(write_with = write_string_with_length)]
|
|
||||||
pub property_name: String,
|
|
||||||
|
|
||||||
#[br(parse_with = read_string_with_length)]
|
|
||||||
#[bw(write_with = write_string_with_length)]
|
|
||||||
#[br(if(property_name != "None"))]
|
|
||||||
pub type_name: String,
|
|
||||||
|
|
||||||
#[br(if(property_name != "None"))]
|
|
||||||
#[br(args { magic: &type_name, name: &property_name})]
|
|
||||||
pub key: Option<Box<Property>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[binrw]
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct StructFieldPrelude {
|
|
||||||
#[br(parse_with = read_string_with_length)]
|
|
||||||
#[bw(write_with = write_string_with_length)]
|
|
||||||
pub property_name: String,
|
|
||||||
|
|
||||||
#[br(parse_with = read_string_with_length)]
|
|
||||||
#[bw(write_with = write_string_with_length)]
|
|
||||||
pub type_name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[binrw]
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct StructPrelude {
|
|
||||||
pub size_in_bytes: u32,
|
|
||||||
#[brw(pad_before = 4)]
|
|
||||||
#[br(parse_with = read_string_with_length)]
|
|
||||||
#[bw(write_with = write_string_with_length)]
|
|
||||||
#[brw(pad_after = 17)]
|
|
||||||
pub struct_name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[binrw::parser(reader, endian)]
|
|
||||||
pub(crate) fn read_struct_field<T: BinRead<Args<'static> = ()> + Debug>(
|
|
||||||
name: &str,
|
|
||||||
) -> BinResult<T> {
|
|
||||||
let prelude = StructFieldPrelude::read_le(reader)?;
|
|
||||||
if prelude.property_name != name {
|
|
||||||
panic!(
|
|
||||||
"Property name doesn't match! Is supposed to be {} but is actually {}",
|
|
||||||
name, prelude.property_name
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// TODO: type check with type_name()
|
|
||||||
if prelude.type_name == "StructProperty" {
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[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
|
|
||||||
}
|
|
|
@ -1,10 +1,13 @@
|
||||||
use crate::da_assemble_id_data::DAAssembleIdDataStruct;
|
|
||||||
use crate::da_customize_asset_id::DACustomizeAssetIdDataStruct;
|
|
||||||
use crate::da_trigger_data::DATriggerDataStruct;
|
|
||||||
use crate::da_tuning_data::DATuningDataStruct;
|
|
||||||
use crate::str_property::StrProperty;
|
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
|
use crate::property::str_property::StrProperty;
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
da_assemble_id_data::DAAssembleIdDataStruct,
|
||||||
|
da_customize_asset_id::DACustomizeAssetIdDataStruct, da_trigger_data::DATriggerDataStruct,
|
||||||
|
da_tuning_data::DATuningDataStruct,
|
||||||
|
};
|
||||||
|
|
||||||
#[paramacro::serialized_struct("DABuildData")]
|
#[paramacro::serialized_struct("DABuildData")]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct DABuildDataStruct {
|
pub struct DABuildDataStruct {
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{da_machine_coloring_data::DAMachineColoringDataStruct, guid::Guid};
|
use super::{da_machine_coloring_data::DAMachineColoringDataStruct, guid::Guid};
|
||||||
|
|
||||||
#[paramacro::serialized_struct("DAAssembleIdData")]
|
#[paramacro::serialized_struct("DAAssembleIdData")]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
|
@ -1,5 +1,7 @@
|
||||||
use crate::{
|
use crate::property::bool_property::BoolProperty;
|
||||||
bool_property::BoolProperty, da_humanoid_coloring_data::DAHumanoidColoringDataStruct,
|
|
||||||
|
use super::{
|
||||||
|
da_humanoid_coloring_data::DAHumanoidColoringDataStruct,
|
||||||
da_humanoid_figure_data::DAHumanoidFigureData, primary_asset_id::PrimaryAssetIdStruct,
|
da_humanoid_figure_data::DAHumanoidFigureData, primary_asset_id::PrimaryAssetIdStruct,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::linear_color::LinearColorStruct;
|
use super::linear_color::LinearColorStruct;
|
||||||
|
|
||||||
#[paramacro::serialized_struct("DAHumanoidColoringData")]
|
#[paramacro::serialized_struct("DAHumanoidColoringData")]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::float_property::FloatProperty;
|
use crate::property::float_property::FloatProperty;
|
||||||
|
|
||||||
#[paramacro::serialized_struct("DAHumanoidFigureData")]
|
#[paramacro::serialized_struct("DAHumanoidFigureData")]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::int_property::IntProperty;
|
use crate::property::int_property::IntProperty;
|
||||||
|
|
||||||
#[paramacro::serialized_struct("DALoadOption")]
|
#[paramacro::serialized_struct("DALoadOption")]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::da_module_color::DAModuleColorStruct;
|
use super::da_module_color::DAModuleColorStruct;
|
||||||
|
|
||||||
#[paramacro::serialized_struct("DAMachineColoringData")]
|
#[paramacro::serialized_struct("DAMachineColoringData")]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::linear_color::LinearColorStruct;
|
use super::linear_color::LinearColorStruct;
|
||||||
|
|
||||||
#[paramacro::serialized_struct("DAModuleColor")]
|
#[paramacro::serialized_struct("DAModuleColor")]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::int_property::IntProperty;
|
use crate::property::int_property::IntProperty;
|
||||||
|
|
||||||
#[paramacro::serialized_struct("DAModuleItemData")]
|
#[paramacro::serialized_struct("DAModuleItemData")]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::enum_property::EnumProperty;
|
use crate::property::enum_property::EnumProperty;
|
||||||
|
|
||||||
#[paramacro::serialized_struct("DATriggerData")]
|
#[paramacro::serialized_struct("DATriggerData")]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::map_property::MapProperty;
|
use crate::property::map_property::MapProperty;
|
||||||
|
|
||||||
#[paramacro::serialized_struct("DATuningData")]
|
#[paramacro::serialized_struct("DATuningData")]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::int_property::IntProperty;
|
use crate::property::int_property::IntProperty;
|
||||||
|
|
||||||
#[paramacro::serialized_struct("DATuningPointData")]
|
#[paramacro::serialized_struct("DATuningPointData")]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
|
@ -1,6 +1,6 @@
|
||||||
use binrw::binrw;
|
use binrw::binrw;
|
||||||
|
|
||||||
use crate::structs::PropertyBase;
|
use crate::property::PropertyBase;
|
||||||
|
|
||||||
#[binrw]
|
#[binrw]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
|
@ -1,6 +1,8 @@
|
||||||
use binrw::binrw;
|
use binrw::binrw;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
use crate::property::PropertyBase;
|
||||||
|
|
||||||
// See https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Core/Misc/FGuid
|
// See https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Core/Misc/FGuid
|
||||||
#[binrw]
|
#[binrw]
|
||||||
pub struct Guid {
|
pub struct Guid {
|
||||||
|
@ -10,7 +12,7 @@ pub struct Guid {
|
||||||
pub d: u32,
|
pub d: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl crate::structs::PropertyBase for Guid {
|
impl PropertyBase for Guid {
|
||||||
fn type_name() -> &'static str {
|
fn type_name() -> &'static str {
|
||||||
"StructProperty"
|
"StructProperty"
|
||||||
}
|
}
|
|
@ -1,5 +1,7 @@
|
||||||
use binrw::binrw;
|
use binrw::binrw;
|
||||||
|
|
||||||
|
use crate::property::PropertyBase;
|
||||||
|
|
||||||
#[binrw]
|
#[binrw]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct LinearColorStruct {
|
pub struct LinearColorStruct {
|
||||||
|
@ -9,7 +11,7 @@ pub struct LinearColorStruct {
|
||||||
pub a: f32,
|
pub a: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl crate::structs::PropertyBase for LinearColorStruct {
|
impl PropertyBase for LinearColorStruct {
|
||||||
fn type_name() -> &'static str {
|
fn type_name() -> &'static str {
|
||||||
"StructProperty"
|
"StructProperty"
|
||||||
}
|
}
|
|
@ -1,27 +1,53 @@
|
||||||
use crate::build_data::DABuildDataStruct;
|
use binrw::{BinRead, BinResult, BinWrite, binrw};
|
||||||
use crate::common::{read_string_with_length, write_string_with_length};
|
use build_data::DABuildDataStruct;
|
||||||
use crate::da_assemble_id_data::DAAssembleIdDataStruct;
|
use da_assemble_id_data::DAAssembleIdDataStruct;
|
||||||
use crate::da_customize_asset_id::DACustomizeAssetIdDataStruct;
|
use da_customize_asset_id::DACustomizeAssetIdDataStruct;
|
||||||
use crate::da_humanoid_coloring_data::DAHumanoidColoringDataStruct;
|
use da_humanoid_coloring_data::DAHumanoidColoringDataStruct;
|
||||||
use crate::da_humanoid_figure_data::DAHumanoidFigureData;
|
use da_humanoid_figure_data::DAHumanoidFigureData;
|
||||||
use crate::da_load_option::DALoadOptionStruct;
|
use da_load_option::DALoadOptionStruct;
|
||||||
use crate::da_machine_coloring_data::DAMachineColoringDataStruct;
|
use da_machine_coloring_data::DAMachineColoringDataStruct;
|
||||||
use crate::da_module_color::DAModuleColorStruct;
|
use da_module_color::DAModuleColorStruct;
|
||||||
use crate::da_module_item_data::DAModuleItemDataStruct;
|
use da_module_item_data::DAModuleItemDataStruct;
|
||||||
use crate::da_trigger_data::DATriggerDataStruct;
|
use da_trigger_data::DATriggerDataStruct;
|
||||||
use crate::da_tuning_data::DATuningDataStruct;
|
use da_tuning_data::DATuningDataStruct;
|
||||||
use crate::da_tuning_point_data::DATuningPointData;
|
use da_tuning_point_data::DATuningPointData;
|
||||||
use crate::datetime::DateTimeStruct;
|
use datetime::DateTimeStruct;
|
||||||
use crate::guid::Guid;
|
use guid::Guid;
|
||||||
use crate::linear_color::LinearColorStruct;
|
use linear_color::LinearColorStruct;
|
||||||
use crate::primary_asset_id::PrimaryAssetIdStruct;
|
use primary_asset_id::PrimaryAssetIdStruct;
|
||||||
use crate::primary_asset_type::PrimaryAssetTypeStruct;
|
use primary_asset_type::PrimaryAssetTypeStruct;
|
||||||
use crate::quat::QuatStruct;
|
use quat::QuatStruct;
|
||||||
use crate::save_slot_info::SaveSlotInfoStruct;
|
use save_slot_info::SaveSlotInfoStruct;
|
||||||
use crate::structs::PropertyBase;
|
use std::fmt::Debug;
|
||||||
use crate::transform::TransformStruct;
|
use transform::TransformStruct;
|
||||||
use crate::vector::VectorStruct;
|
use vector::VectorStruct;
|
||||||
use binrw::binrw;
|
|
||||||
|
use crate::{
|
||||||
|
common::{read_string_with_length, write_string_with_length},
|
||||||
|
property::PropertyBase,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub mod build_data;
|
||||||
|
pub mod da_assemble_id_data;
|
||||||
|
pub mod da_customize_asset_id;
|
||||||
|
pub mod da_humanoid_coloring_data;
|
||||||
|
pub mod da_humanoid_figure_data;
|
||||||
|
pub mod da_load_option;
|
||||||
|
pub mod da_machine_coloring_data;
|
||||||
|
pub mod da_module_color;
|
||||||
|
pub mod da_module_item_data;
|
||||||
|
pub mod da_trigger_data;
|
||||||
|
pub mod da_tuning_data;
|
||||||
|
pub mod da_tuning_point_data;
|
||||||
|
pub mod datetime;
|
||||||
|
pub mod guid;
|
||||||
|
pub mod linear_color;
|
||||||
|
pub mod primary_asset_id;
|
||||||
|
pub mod primary_asset_type;
|
||||||
|
pub mod quat;
|
||||||
|
pub mod save_slot_info;
|
||||||
|
pub mod transform;
|
||||||
|
pub mod vector;
|
||||||
|
|
||||||
#[binrw]
|
#[binrw]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -114,13 +140,84 @@ pub(crate) fn calc_size_in_bytes(r#struct: &Struct) -> u32 {
|
||||||
|
|
||||||
#[binrw]
|
#[binrw]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct StructProperty {
|
pub struct StructFieldPrelude {
|
||||||
pub unk: u32,
|
#[br(parse_with = read_string_with_length)]
|
||||||
|
#[bw(write_with = write_string_with_length)]
|
||||||
|
pub property_name: String,
|
||||||
|
|
||||||
|
#[br(parse_with = read_string_with_length)]
|
||||||
|
#[bw(write_with = write_string_with_length)]
|
||||||
|
pub type_name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[binrw]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct StructPrelude {
|
||||||
|
pub size_in_bytes: u32,
|
||||||
#[brw(pad_before = 4)]
|
#[brw(pad_before = 4)]
|
||||||
#[br(parse_with = read_string_with_length)]
|
#[br(parse_with = read_string_with_length)]
|
||||||
#[bw(write_with = write_string_with_length)]
|
#[bw(write_with = write_string_with_length)]
|
||||||
|
#[brw(pad_after = 17)]
|
||||||
pub struct_name: String,
|
pub struct_name: String,
|
||||||
#[br(args { magic: &struct_name })]
|
}
|
||||||
#[brw(pad_before = 17)]
|
|
||||||
pub r#struct: Struct,
|
#[binrw::parser(reader, endian)]
|
||||||
|
pub(crate) fn read_struct_field<T: BinRead<Args<'static> = ()> + Debug>(
|
||||||
|
name: &str,
|
||||||
|
) -> BinResult<T> {
|
||||||
|
let prelude = StructFieldPrelude::read_le(reader)?;
|
||||||
|
if prelude.property_name != name {
|
||||||
|
panic!(
|
||||||
|
"Property name doesn't match! Is supposed to be {} but is actually {}",
|
||||||
|
name, prelude.property_name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// TODO: type check with type_name()
|
||||||
|
if prelude.type_name == "StructProperty" {
|
||||||
|
StructPrelude::read_le(reader)?;
|
||||||
|
}
|
||||||
|
let val = T::read_options(reader, endian, ())?;
|
||||||
|
Ok(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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
|
||||||
}
|
}
|
|
@ -1,4 +1,6 @@
|
||||||
use crate::{name_property::NameProperty, primary_asset_type::PrimaryAssetTypeStruct};
|
use crate::property::name_property::NameProperty;
|
||||||
|
|
||||||
|
use super::primary_asset_type::PrimaryAssetTypeStruct;
|
||||||
|
|
||||||
#[paramacro::serialized_struct("PrimaryAssetId")]
|
#[paramacro::serialized_struct("PrimaryAssetId")]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::name_property::NameProperty;
|
use crate::property::name_property::NameProperty;
|
||||||
|
|
||||||
#[paramacro::serialized_struct("PrimaryAssetType")]
|
#[paramacro::serialized_struct("PrimaryAssetType")]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
|
@ -1,6 +1,6 @@
|
||||||
use binrw::binrw;
|
use binrw::binrw;
|
||||||
|
|
||||||
use crate::structs::PropertyBase;
|
use crate::property::PropertyBase;
|
||||||
|
|
||||||
#[binrw]
|
#[binrw]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
|
@ -1,8 +1,9 @@
|
||||||
use crate::{
|
use crate::property::{
|
||||||
array_property::ArrayProperty, datetime::DateTimeStruct, name_property::NameProperty,
|
array_property::ArrayProperty, name_property::NameProperty, str_property::StrProperty,
|
||||||
str_property::StrProperty,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use super::datetime::DateTimeStruct;
|
||||||
|
|
||||||
#[paramacro::serialized_struct("SaveSlotInfo")]
|
#[paramacro::serialized_struct("SaveSlotInfo")]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SaveSlotInfoStruct {
|
pub struct SaveSlotInfoStruct {
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{quat::QuatStruct, vector::VectorStruct};
|
use super::{quat::QuatStruct, vector::VectorStruct};
|
||||||
|
|
||||||
#[paramacro::serialized_struct("Transform")]
|
#[paramacro::serialized_struct("Transform")]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
|
@ -1,6 +1,6 @@
|
||||||
use binrw::binrw;
|
use binrw::binrw;
|
||||||
|
|
||||||
use crate::structs::PropertyBase;
|
use crate::property::PropertyBase;
|
||||||
|
|
||||||
#[binrw]
|
#[binrw]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
|
@ -1,5 +1,6 @@
|
||||||
use binrw::{BinRead, BinWrite};
|
use binrw::{BinRead, BinWrite};
|
||||||
use ireko::{GenericTaggedObject, TaggedSerialization};
|
use ireko::TaggedSerialization;
|
||||||
|
use ireko::save_object::generic::GenericTaggedObject;
|
||||||
use std::fs::read;
|
use std::fs::read;
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
Loading…
Add table
Reference in a new issue