brickrust 1.11.2+brickrust-001

A library which allows Brick Rigs modding
#![allow(nonstandard_style)]


use brickworks::br_print;
use brickworks::set_module_name;
set_module_name!("coreuobject");

use crate::ue::fframe::FFrame;
use crate::ue::fstring::FString;

use super::fname::*;
use super::uclass::*;

pub(crate) static mut StaticConstructObject_Internal: Option<StaticConstructObject_t> = None;
pub(crate) type StaticConstructObject_t = unsafe extern "C" fn ( params: FStaticConstructObjectParameters) -> *mut UObjectBase;

pub(crate) type fnProcessInternal = unsafe extern "C" fn(obj: *mut UObject, stack: *mut FFrame, result: *mut ());
pub(crate) static mut ProcessInternal_ptr: Option<fnProcessInternal> = None;
pub(crate) static mut ProcessInternal_hook: Option<fnProcessInternal> = None;

pub(crate) type fnStaticLoadObject = unsafe extern "C" fn
( class: *mut UClass, in_outer: *mut UObject, inname: *const u16, filename: *const u16, flags: u32, reconciliation: bool ) -> *mut UObject;
pub(crate) static mut StaticLoadObject_ptr: Option<fnStaticLoadObject> = None;

pub(crate) static mut UCLASS: *mut UClass = core::ptr::null_mut();
pub unsafe fn default_uclass() -> *mut UClass
{
    UCLASS
}

pub unsafe fn StaticLoadObject(
    class: *mut UClass,
    in_outer: *mut UObject,
    inname: *const u16,
    filename: *const u16,
    flags: u32,
    reconciliation: bool
) -> *mut UObject
{
    (StaticLoadObject_ptr.unwrap())(class, in_outer, inname, filename, flags, reconciliation)
}

#[repr(C)]
#[derive(Debug)]
pub struct FUObjectItem
{
    pub object: *mut UObject,
    pub flags: i32,
    pub cluster_root_index: i32,
    pub serial: i32,

}

#[repr(C)]
#[derive(Debug)]
pub struct FChunkedFixedUObjectArray
{
    objects: *mut *mut FUObjectItem,
    pre_allocated_objects: *mut FUObjectItem,
    max_elements: i32,
    num_elements: i32,
    max_chunks: i32,
    num_chunks: i32,
}
impl FChunkedFixedUObjectArray
{
    pub unsafe fn Count(&self) -> i32
    {
        self.num_elements
    }
    pub unsafe fn Get(&self, idx: i32) -> *mut FUObjectItem
    {
        let elements_per_chunk = self.max_elements / self.max_chunks;
        let chunk = idx / elements_per_chunk;
        let within = idx % elements_per_chunk;
        let chunk = *self.objects.add(chunk as usize);
        return chunk.add(within as usize);
    }
}

#[repr(C)]
#[derive(Debug)]
pub struct FUObjectArray
{
    first_gc_index: i32,
    last_non_gc_index: i32,
    max_not_considered_gc: i32,
    open_disregard: i32,
    pub array: FChunkedFixedUObjectArray
}

pub(crate) static mut GOBJECTS_PTR: *mut FUObjectArray = core::ptr::null_mut();

pub unsafe fn GObjects() -> &'static mut FUObjectArray
{
    return &mut *GOBJECTS_PTR;
}

#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct FStaticConstructObjectParameters
{
    pub class: *const UClass,
    pub outer: *const UObjectBase,
    pub name: FName,
    pub set_flags: u32,
    pub internal_flags: u32,
    pub copy_transients: bool,
    pub archetype: bool,
    pub template: *const UObjectBase,
    pub instance_graph: *const (),
    pub external_package: *const (),
}

#[repr(C)]
#[derive(Debug, Copy , Clone)]
pub enum EObjectFlags {
    RF_NoFlags = 0x0000,
    RF_Public = 0x0001,
    RF_Standalone = 0x0002,
    RF_MarkAsNative = 0x0004,
    RF_Transactional = 0x0008,
    RF_ClassDefaultObject = 0x0010,
    RF_ArchetypeObject = 0x0020,
    RF_Transient = 0x0040,
    RF_MarkAsRootSet = 0x0080,
    RF_TagGarbageTemp = 0x0100,
    RF_NeedInitialization = 0x0200,
    RF_NeedLoad = 0x0400,
    RF_KeepForCooker = 0x0800,
    RF_NeedPostLoad = 0x1000,
    RF_NeedPostLoadSubobjects = 0x2000,
    RF_NewerVersionExists = 0x4000,
    RF_BeginDestroyed = 0x8000,
    RF_FinishDestroyed = 0x00010000,
    RF_BeingRegenerated = 0x00020000,
    RF_DefaultSubObject = 0x00040000,
    RF_WasLoaded = 0x00080000,
    RF_TextExportTransient = 0x00100000,
    RF_LoadCompleted = 0x00200000,
    RF_InheritableComponentTemplate = 0x00400000,
    RF_DuplicateTransient = 0x00800000,
    RF_StrongRefOnFrame = 0x01000000,
    RF_NonPIEDuplicateTransient = 0x02000000,
    RF_Dynamic = 0x04000000,
    RF_WillBeLoaded = 0x08000000,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct UObjectBaseVTable
{
    pub Destructor: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_1: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_2: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_3: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_4: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_5: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_6: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_7: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_8: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_9: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_10: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_11: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_12: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_13: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_14: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_15: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_16: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_17: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_18: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_19: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_20: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_21: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_22: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_23: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_24: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_25: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_26: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_27: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_28: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_29: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_30: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_31: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_32: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_33: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_34: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_35: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_36: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_37: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_38: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_39: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_40: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_41: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_42: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_43: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_44: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_45: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_46: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_47: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_48: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_49: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_50: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_51: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_52: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_53: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_54: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_55: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_56: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_57: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_58: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_59: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_60: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_61: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_62: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_63: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_64: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_65: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_66: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_67: unsafe extern "C" fn( brick: *mut UObject ),
    pub process_event: unsafe extern "C" fn( obj: *mut UObject, f: *mut UFunction, params: *mut () ),
    pub _a_69: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_70: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_71: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_72: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_73: unsafe extern "C" fn( brick: *mut UObject ),
    pub _a_74: unsafe extern "C" fn( brick: *mut UObject ),
}

#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct UObjectBase {
    pub vtable: *mut usize,
    pub object_flags: EObjectFlags,
    pub internal_index: i32,
    pub class_private: *const UClass,
    pub name_private: FName,
    pub outer_private: *const UObject,
}


pub type UObject = UObjectBase;

pub trait StaticClass {
    unsafe fn StaticClass() -> *const UStruct;
}
impl UObject
{
    pub unsafe fn CallFunction<T>(&mut self, name: &'static str, params: *mut T )
    {
        let class = self.class_private;
        let f = (*class).FindFunctionByName(name, true);
        ((*(self.vtable as *mut UObjectBaseVTable)).process_event)(self, f, params as *mut _);

    }
    pub unsafe fn IsExact(&self, s: &'static str) -> bool
    {
        let mut name = String::new();

        let (ptr, count) = self.name_private.as_sptr(); 
        for i in 0..count
        {
            name.push(*ptr.add(i as usize) as char);
        }

        let mut cls = self.class_private;
        loop 
        {
            let (ptr, count) =(*cls).ustruct.ufield.uobject.name_private.as_sptr(); 
            name.push('.');
            for i in 0..count
            {
                name.push(*ptr.add(i as usize) as char);
            }

            cls = (*cls).ustruct.super_struct as *const UClass;
            if cls.is_null() { break; }
        }
        br_print!("{}", name);

        name == s
    }
    pub unsafe fn IsOuterExact(&self, s: &'static str) -> bool
    {
        let name = self.name_private; 
        let s = FString::from_fname(name);
        br_print!("+  {}", s);
        let mut cls = self.outer_private;
        loop 
        {
            if cls.is_null() { break; }

            let s = FString::from_fname((*cls).name_private);
            br_print!("{}", s);
            cls = (*cls).outer_private;
        }
        false
    }

    pub unsafe fn IsA(&self, s: &'static str) -> bool
    {
        let trimmed = &s[1..];
        let fname = FName::search_str(trimmed);
        let mut cls = self.class_private;
        loop 
        {
            if (*cls).ustruct.ufield.uobject.name_private.comparison_index == fname.comparison_index
            {
                return true;
            }

            cls = (*cls).ustruct.super_struct as *const UClass;
            if cls.is_null() { break; }
        }
        false
    }
    pub unsafe fn IsOuterA(&self, s: &'static str) -> bool
    {
        let trimmed = &s[1..];
        let fname = FName::search_str(trimmed);
        let mut cls = self.outer_private;
        loop 
        {
            if cls.is_null() { break; }
            if (*cls).name_private.comparison_index == fname.comparison_index
            {
                return true;
            }

            cls = (*cls).outer_private;
        }
        false
    }
}