diff --git a/src/any_type.rs b/src/any_type.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/fname.rs b/src/fname.rs index 5a48d75..4820d7e 100644 --- a/src/fname.rs +++ b/src/fname.rs @@ -5,7 +5,7 @@ use std::{ }; use anyhow::Context; -use once_cell::sync::{Lazy, OnceCell}; +use once_cell::sync::Lazy; use crate::global_tables::names::GNAMES; diff --git a/src/sdk/mod.rs b/src/sdk/mod.rs index 06df7b8..2f38ca9 100644 --- a/src/sdk/mod.rs +++ b/src/sdk/mod.rs @@ -25,7 +25,7 @@ use crate::{ UObjectPropertyBaseTrait, UObjectTrait, UPropertyTrait, UStructNonConst, UStructPropertyTrait, UStructTrait, }, - EFunctionFlags, EPropertyFlags, UBoolProperty, UClass, UEnum, UFunction, UObject, UStruct, + EFunctionFlags, EPropertyFlags, UClass, UEnum, UFunction, UObject, UStruct, }, }; @@ -186,15 +186,6 @@ impl Package { size: *strct.property_size() as u32, super_class: super_struct, fields, - min_alignment, - properties_size, - kind: if is_actor { - StructKind::Actor - } else if is_class { - StructKind::Object - } else { - StructKind::Struct - }, name, methods, full_name, @@ -353,7 +344,6 @@ impl Package { ClassField { offset: *prop.offset() as u32, size: *prop.element_size() as u32, - flags: *prop.property_flags(), name, ty, }); @@ -811,7 +801,6 @@ pub struct ClassField { pub offset: u32, pub size: u32, pub name: String, - pub flags: EPropertyFlags, pub ty: Type, } @@ -853,24 +842,13 @@ pub struct Class { pub name: String, pub full_name: String, pub super_class: Option, - pub properties_size: u32, - pub min_alignment: u32, - pub kind: StructKind, pub fields: Vec, pub methods: Vec, } impl Class { pub fn rust_name(&self) -> String { - format!( - "{}{}", - match self.kind { - StructKind::Object => "U", - StructKind::Actor => "A", - StructKind::Struct => "F", - }, - canonicalize_name(&self.name) - ) + format!("U{}", canonicalize_name(&self.name)) } pub fn referenced_types(&self) -> Vec { diff --git a/src/sdk/output/rust.rs b/src/sdk/output/rust.rs index 6062614..be9371c 100644 --- a/src/sdk/output/rust.rs +++ b/src/sdk/output/rust.rs @@ -12,7 +12,7 @@ use crate::{ Sdk, Type, Types, }, v2_types::{ - traits::{AsUObject, UBoolPropertyTrait, UObjectNonConst, UStructNonConst}, + traits::{AsUObject, UObjectNonConst, UStructNonConst}, UObject, }, }; @@ -87,7 +87,7 @@ impl RustType for Type { w, "{}", match ty { - PrimitiveType::Bool(_) => "bool", + PrimitiveType::Bool { .. } => "bool", PrimitiveType::U8 => "u8", PrimitiveType::U16 => "u16", PrimitiveType::U32 => "u32", @@ -298,13 +298,17 @@ pub fn generate_class_impl(class: &Class, sdk: &Sdk, w: &mut W) -> any // need to handle bools in a special way because they might be bitfields match field.ty { - Type::Primitive(PrimitiveType::Bool(prop)) if *prop.byte_mask() != 0xff => { + Type::Primitive(PrimitiveType::Bool { + byte_mask, + field_mask, + .. + }) if byte_mask != 0xff => { write!(w, "fn {}(&self) -> bool", field.name)?; writeln!( w, " {{unsafe {{ *self.as_ptr().offset({}) & (1u8 << {}u8) != 0 }} }}", field.offset, - prop.field_mask().trailing_zeros(), + field_mask.trailing_zeros(), )?; write!(w, "fn set_{0}(&mut self, {0}: bool", field.name)?; @@ -314,7 +318,7 @@ pub fn generate_class_impl(class: &Class, sdk: &Sdk, w: &mut W) -> any " {{unsafe {{ if {1} {{ *self.as_mut_ptr().offset({0}) |= ({1} as u8) << {2}u8; }} else {{ *self.as_mut_ptr().offset({0}) &= !(({1} as u8) << {2}u8); }} }} }}", field.offset, field.name, - prop.field_mask().trailing_zeros(), + field_mask.trailing_zeros(), )?; } _ => { diff --git a/src/sdk/process.rs b/src/sdk/process.rs index acea9ae..e6285d9 100644 --- a/src/sdk/process.rs +++ b/src/sdk/process.rs @@ -1,12 +1,17 @@ use std::collections::{btree_map::Entry, BTreeMap}; use anyhow::Context; +use itertools::Itertools; use rayon::prelude::{IntoParallelRefIterator, ParallelIterator}; +use crate::sdk::repr::*; use crate::v2_types::{ - any_type::{AnyField, AnyObject, AnyStruct}, - traits::{UEnumTrait, UObjectTrait, UPropertyTrait}, - UClass, UEnum, UFunction, UProperty, UScriptStruct, UStruct, + any_type::{self, AnyField, AnyObject, AnyProperty, AnyStruct}, + traits::{ + AsUObject, UArrayPropertyTrait, UBoolPropertyTrait, UEnumPropertyTrait, UEnumTrait, + UObjectNonConst, UObjectTrait, UPropertyTrait, UStructPropertyTrait, *, + }, + UClass, UEnum, UFunction, UProperty, UScriptStruct, }; use super::repr::{ @@ -50,16 +55,16 @@ impl Enum { if values.len() > 1 { acc.extend(values.into_iter().map(|i| (i as u32, format!("{name}{i}")))); } else { - acc.insert(values.into_iter().next().unwrap() as u32, name) + acc.insert(values.into_iter().next().unwrap() as u32, name); } acc }); - Ok(Enum { - name: value.name().get_name().context("could not get name")?, - full_name: value.name().get_full_name().context("could not get name")?, + Ok(UnrealType::Enum(Enum { + name: value.get_name().context("could not get name")?, + full_name: value.get_full_name().context("could not get full name")?, values, - }) + })) } } @@ -149,26 +154,36 @@ fn resolve_type(prop: UProperty) -> anyhow::Result { match object.as_any_object_base_property().unwrap() { any_type::AnyObjectBaseProperty::Object(obj) => Type::Class( obj.property_class() - .context("object property missing properry class")?, + .context("object property missing properry class")? + .as_uobject() + .object_ref(), ), any_type::AnyObjectBaseProperty::WeakObject(obj) => Type::WeakPtr( obj.property_class() - .context("weak ptr property missing property class.")?, + .context("weak ptr property missing property class.")? + .as_uobject() + .object_ref(), ), any_type::AnyObjectBaseProperty::LazyObject(obj) => Type::LazyPtr( obj.property_class() - .context("lazy ptr property missing property class.")?, + .context("lazy ptr property missing property class.")? + .as_uobject() + .object_ref(), ), any_type::AnyObjectBaseProperty::SoftObject(obj) => Type::SoftPtr( obj.property_class() - .context("soft ptr property missing property class.")?, + .context("soft ptr property missing property class.")? + .as_uobject() + .object_ref(), ), asset @ any_type::AnyObjectBaseProperty::AssetObject(_) => { match asset.as_any_asset_object_property().unwrap() { any_type::AnyAssetObjectProperty::Class(class) => Type::AssetPtr( class .property_class() - .context("asset object property missing properry class")?, + .context("asset object property missing properry class")? + .as_uobject() + .object_ref(), ), any_type::AnyAssetObjectProperty::Object(_) => { return Err(anyhow::anyhow!( @@ -182,13 +197,11 @@ fn resolve_type(prop: UProperty) -> anyhow::Result { } } } - AnyProperty::Array(array) => { - Type::Array(Box::new(Self::find_type(AnyProperty::from_prop( - array - .inner() - .context("array property inner type missing.")?, - ))?)) - } + AnyProperty::Array(array) => Type::Array(Box::new(resolve_type( + array + .inner() + .context("array property inner type missing.")?, + )?)), AnyProperty::Map(_) => unreachable!("not used in ARK"), AnyProperty::Str(_) => Type::String, AnyProperty::Text(_) => Type::Text, @@ -200,16 +213,22 @@ fn resolve_type(prop: UProperty) -> anyhow::Result { return Err(anyhow::anyhow!("skipping multicast delegates for now")); } AnyProperty::Enum(enm) => Type::Enum { - underlying: Box::new(Self::find_type(AnyProperty::from_prop( + underlying: Box::new(resolve_type( enm.underlying_type() .context("enum property was missing underlying type")?, - ))?), - enum_type: enm.uenum().context("enum property missing enum type")?, + )?), + enum_type: enm + .uenum() + .context("enum property missing enum type")? + .as_uobject() + .object_ref(), }, AnyProperty::Struct(class) => Type::Struct( class .ustruct() - .context("struct property had no inner struct")?, + .context("struct property had no inner struct")? + .as_uobject() + .object_ref(), ), AnyProperty::Other(_) => { return Err(anyhow::anyhow!("unhandled property.")); diff --git a/src/sdk/repr.rs b/src/sdk/repr.rs index c610cda..c2de6b4 100644 --- a/src/sdk/repr.rs +++ b/src/sdk/repr.rs @@ -1,4 +1,4 @@ -use std::collections::{BTreeMap, BTreeSet, HashMap}; +use std::collections::BTreeMap; use serde::{Deserialize, Serialize}; @@ -10,16 +10,16 @@ use crate::v2_types::{ impl UObject { pub fn object_ref(&self) -> ObjectRef { ObjectRef { - package: PackageRef(self.package_object().internal_index()), - object: self.internal_index(), + package: PackageRef(*self.package_object().internal_index()), + object: *self.internal_index(), } } } -#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)] +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Serialize, Deserialize)] pub struct PackageRef(u32); -#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)] +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Serialize, Deserialize)] pub struct ObjectRef { package: PackageRef, object: u32, @@ -43,17 +43,17 @@ pub struct Package { pub children: Vec, } -#[derive(Debug)] +#[derive(Debug, Serialize, Deserialize)] pub struct ProcessedPackage { - /// the package object. - pub package_object: UObject, + /// the package object ref. + pub package_object: PackageRef, /// all types extracted from this package referenced by their `ObjectRef`. pub types: BTreeMap, /// All other packages that types in this package depend on directly. pub dependencies: Vec, } -#[derive(Debug)] +#[derive(Debug, Serialize, Deserialize)] pub enum UnrealType { Class(Class), Struct(Class), @@ -85,7 +85,7 @@ pub struct Class { pub properties_size: u32, pub min_alignment: u32, pub fields: Vec, - pub methods: Vec, + pub methods: Vec, /// types this class depends on; includes super types, types of fields and /// types of function parameters. pub dependencies: Vec, @@ -104,15 +104,22 @@ impl ClassField { pub fn is_return_param(&self) -> bool { self.flags.contains(EPropertyFlags::ReturnParm) } + pub fn is_param(&self) -> bool { self.flags.contains(EPropertyFlags::Parm) } + pub fn is_const_param(&self) -> bool { self.flags.contains(EPropertyFlags::ConstParm) } + pub fn is_out_param(&self) -> bool { !self.is_const_param() && self.flags.contains(EPropertyFlags::OutParm) } + + pub fn is_rep(&self) -> bool { + !self.flags.contains(EPropertyFlags::RepSkip) + } } #[derive(Debug, Serialize, Deserialize)] @@ -121,7 +128,6 @@ pub struct ClassMethod { pub full_name: String, pub flags: EFunctionFlags, pub parameters: Vec, - pub return_param: Option, } impl ClassMethod { @@ -150,7 +156,7 @@ impl ClassMethod { } } -#[derive(Debug, Clone, Copy, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub enum PrimitiveType { Bool { byte_mask: u8, @@ -190,7 +196,7 @@ pub enum Type { Text, Enum { underlying: Box, - enum_type: UEnum, + enum_type: ObjectRef, }, Class(ObjectRef), Struct(ObjectRef), diff --git a/src/types.rs b/src/types.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/v2_types/mod.rs b/src/v2_types/mod.rs index ca0b18b..c7c59fc 100644 --- a/src/v2_types/mod.rs +++ b/src/v2_types/mod.rs @@ -359,7 +359,7 @@ define_utypes!( ); impl Hash for UObject { - fn hash(&self, state: &mut H) { + fn hash(&self, state: &mut H) { self.0.hash(state); } }