diff --git a/sdk-builder/src/main.rs b/sdk-builder/src/main.rs index e3dd0e0..b7a2eb4 100644 --- a/sdk-builder/src/main.rs +++ b/sdk-builder/src/main.rs @@ -411,13 +411,13 @@ pub mod rust { struct_name: &str, method: &ClassMethod, ) -> anyhow::Result<(TokenStream, TokenStream)> { - let method_name = canonicalize_name(&method.name); + let method_name = canonicalize_name(&method.unique_name()); let parameters = method .parameters .iter() .map(|parameter| { - let name = canonicalize_name(¶meter.name); + let name = canonicalize_name(¶meter.unique_name()); let type_name = self.type_name(¶meter.ty)?; anyhow::Ok((parameter, name, type_name)) @@ -611,7 +611,7 @@ pub mod rust { .fields .iter() .map(|field| { - let name = canonicalize_name(&field.name); + let name = canonicalize_name(&field.unique_name()); let ty = self.type_name(&field.ty)?; anyhow::Ok((field, name, ty)) diff --git a/unreal-sdk/src/sdk/process.rs b/unreal-sdk/src/sdk/process.rs index 258b1d9..c539ead 100644 --- a/unreal-sdk/src/sdk/process.rs +++ b/unreal-sdk/src/sdk/process.rs @@ -8,6 +8,7 @@ use ron::ser::PrettyConfig; use crate::global_tables::objects::GOBJECTS; use crate::sdk::repr::*; +use crate::util::DedupIter; use crate::v2_types::{ any_type::{self, AnyField, AnyObject, AnyProperty, AnyStruct}, traits::{ @@ -238,6 +239,28 @@ impl Class { }, ); + let fields = fields + .into_iter() + .dedup_with_by( + |n, field| ClassField { + override_name: Some(format!("{}{}", field.name, n)), + ..field + }, + |field: &ClassField| -> String { field.name.clone() }, + ) + .collect(); + + let methods = methods + .into_iter() + .dedup_with_by( + |n, field| ClassMethod { + override_name: Some(format!("{}{}", field.name, n)), + ..field + }, + |field: &ClassMethod| -> String { field.name.clone() }, + ) + .collect(); + (fields, methods) } @@ -257,14 +280,16 @@ impl Class { impl ClassField { pub fn from_uprop(prop: UProperty) -> anyhow::Result { + let name = prop + .name() + .get_name() + .context("failed to retrieve field name")?; Ok(Self { offset: *prop.offset() as u32, size: *prop.element_size() as u32, flags: *prop.property_flags(), - name: prop - .name() - .get_name() - .context("failed to retrieve field name")?, + override_name: None, + name, ty: resolve_type(prop).context("failed to get field type")?, }) } @@ -288,11 +313,21 @@ impl ClassMethod { _ => None, }) .map(|prop| ClassField::from_uprop(prop)) - .collect::>>()?; + .collect::>>()? + .into_iter() + .dedup_with_by( + |n, field| ClassField { + override_name: Some(format!("{}{}", field.name, n)), + ..field + }, + |field: &ClassField| -> String { field.name.clone() }, + ) + .collect(); Ok(ClassMethod { name, full_name, + override_name: None, flags: *func.function_flags(), parameters: params, }) @@ -359,6 +394,14 @@ impl Package { .context("not actually a package object")?, types, dependencies, + name: self + .package_object + .get_name() + .context("failed to get package object name.")?, + full_name: self + .package_object + .get_full_name() + .context("failed to get package object name.")?, }) } } diff --git a/unreal-sdk/src/sdk/repr.rs b/unreal-sdk/src/sdk/repr.rs index 8dc5c3d..d16d5a9 100644 --- a/unreal-sdk/src/sdk/repr.rs +++ b/unreal-sdk/src/sdk/repr.rs @@ -55,6 +55,8 @@ pub struct Package { pub struct ProcessedPackage { /// the package object ref. pub package_object: PackageRef, + pub name: String, + pub full_name: String, /// all types extracted from this package referenced by their `ObjectRef`. pub types: BTreeMap, /// All other packages that types in this package depend on directly. @@ -142,6 +144,7 @@ pub struct ClassField { pub offset: u32, pub size: u32, pub name: String, + pub override_name: Option, pub flags: EPropertyFlags, pub ty: Type, } @@ -166,11 +169,19 @@ impl ClassField { pub fn is_rep(&self) -> bool { !self.flags.contains(EPropertyFlags::RepSkip) } + + pub fn unique_name(&self) -> &str { + self.override_name + .as_ref() + .map(|s| s.as_str()) + .unwrap_or(self.name.as_str()) + } } #[derive(Debug, Serialize, Deserialize)] pub struct ClassMethod { pub name: String, + pub override_name: Option, pub full_name: String, pub flags: EFunctionFlags, pub parameters: Vec, @@ -180,13 +191,23 @@ impl ClassMethod { pub fn is_static(&self) -> bool { self.flags.contains(EFunctionFlags::Static) } + pub fn is_native(&self) -> bool { self.flags.contains(EFunctionFlags::Native) } + /// this function is replicated to the server, might be exploitable. pub fn is_net_server(&self) -> bool { self.flags.contains(EFunctionFlags::NetServer) } + + pub fn unique_name(&self) -> &str { + self.override_name + .as_ref() + .map(|s| s.as_str()) + .unwrap_or(self.name.as_str()) + } + pub fn out_params(&self) -> Vec<&ClassField> { self.parameters .iter()