handle possibility of missing static class (UMapProperty)

This commit is contained in:
Janis 2023-04-20 20:48:54 +02:00
parent 674a54afb9
commit 99a3effc4c

View file

@ -170,10 +170,34 @@ macro_rules! define_utypes {
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct $ty(NonNull<UnsafeCell<()>>); pub struct $ty(NonNull<UnsafeCell<()>>);
impl $ty { impl traits::StaticClass for $ty {
pub const fn static_class_name() -> &'static str { fn static_class_name() -> &'static str {
concat!("Class CoreUObject.", $name) concat!("Class CoreUObject.", $name)
} }
fn static_class() -> Option<UClass> {
use crate::global_tables::objects::{FindClass, GOBJECTS};
use once_cell::sync::OnceCell;
// this is something that we always do in C/C++ but unfortinately requires a blanket impl Sync + Send on all UObject types..
static CLASS: OnceCell<Option<UClass>> = OnceCell::new();
*CLASS.get_or_init(|| {
let class = match GOBJECTS
.read()
.unwrap()
.as_objects()
.unwrap()
.find_class(Self::static_class_name()) {
Some(class) => {Some(class)},
None => {
log::error!("static class \"{}\" not found!", Self::static_class_name());
None
}
};
log::info!("class for {} is {:?}", Self::static_class_name(), class);
class
})
}
} }
impl_asuobject!($ty); impl_asuobject!($ty);
@ -192,6 +216,30 @@ macro_rules! define_utypes {
fn static_class_name() -> &'static str { fn static_class_name() -> &'static str {
concat!("Class CoreUObject.", $name) concat!("Class CoreUObject.", $name)
} }
fn static_class() -> Option<UClass> {
use crate::global_tables::objects::{FindClass, GOBJECTS};
use once_cell::sync::OnceCell;
// this is something that we always do in C/C++ but unfortinately requires a blanket impl Sync + Send on all UObject types..
static CLASS: OnceCell<Option<UClass>> = OnceCell::new();
*CLASS.get_or_init(|| {
let class = match GOBJECTS
.read()
.unwrap()
.as_objects()
.unwrap()
.find_class(Self::static_class_name()) {
Some(class) => {Some(class)},
None => {
log::error!("static class \"{}\" not found!", Self::static_class_name());
None
}
};
log::info!("class for {} is {:?}", Self::static_class_name(), class);
class
})
}
} }
impl_asuobject!($ty); impl_asuobject!($ty);
@ -453,15 +501,19 @@ impl UAnyType {
// remember to order this from most specialized to least. // remember to order this from most specialized to least.
// specifically: a UClass is also a UStruct, so check for UClass first, // specifically: a UClass is also a UStruct, so check for UClass first,
// then for any other subtypes of UStruct, then for UStruct // then for any other subtypes of UStruct, then for UStruct
if uobject.is_a(&UEnum::static_class()) { if uobject.is_a_maybe(&UClass::static_class()) {
Self::UEnum(unsafe { uobject.cast() })
} else if uobject.is_a(&UClass::static_class()) {
Self::UClass(unsafe { uobject.cast() }) Self::UClass(unsafe { uobject.cast() })
} else if uobject.is_a(&UScriptStruct::static_class()) { } else if uobject.is_a_maybe(&UProperty::static_class()) {
Self::UProperty(unsafe { uobject.cast() })
} else if uobject.is_a_maybe(&UFunction::static_class()) {
Self::UFunction(unsafe { uobject.cast() })
} else if uobject.is_a_maybe(&UScriptStruct::static_class()) {
Self::UScriptStruct(unsafe { uobject.cast() }) Self::UScriptStruct(unsafe { uobject.cast() })
} else if uobject.is_a(&UStruct::static_class()) { } else if uobject.is_a_maybe(&UEnum::static_class()) {
Self::UEnum(unsafe { uobject.cast() })
} else if uobject.is_a_maybe(&UStruct::static_class()) {
Self::UStruct(unsafe { uobject.cast() }) Self::UStruct(unsafe { uobject.cast() })
} else if uobject.is_a(&UField::static_class()) { } else if uobject.is_a_maybe(&UField::static_class()) {
Self::UField(unsafe { uobject.cast() }) Self::UField(unsafe { uobject.cast() })
} else { } else {
Self::UObject(uobject) Self::UObject(uobject)
@ -497,30 +549,15 @@ pub mod traits {
use anyhow::Context; use anyhow::Context;
use itertools::Itertools; use itertools::Itertools;
use once_cell::sync::OnceCell;
use crate::fname::FName; use crate::fname::FName;
use crate::global_tables::objects::{FindClass, GOBJECTS};
use crate::tarray::{FString, TArray}; use crate::tarray::{FString, TArray};
use super::{EObjectFlags, VTbl}; use super::{EObjectFlags, VTbl};
pub trait StaticClass { pub trait StaticClass {
fn static_class_name() -> &'static str; fn static_class_name() -> &'static str;
fn static_class() -> super::UClass { fn static_class() -> Option<super::UClass>;
// this is something that we always do in C/C++ but unfortinately requires a blanket impl Sync + Send on all UObject types..
static CLASS: OnceCell<super::UClass> = OnceCell::new();
*CLASS.get_or_init(|| {
GOBJECTS
.read()
.unwrap()
.as_objects()
.unwrap()
.find_class(Self::static_class_name())
.expect("static class not found!")
})
}
} }
#[const_trait] #[const_trait]
@ -601,6 +638,13 @@ pub mod traits {
.map(|class| class.iter_super_classes().contains(other)) .map(|class| class.iter_super_classes().contains(other))
.unwrap_or(false) .unwrap_or(false)
} }
fn is_a_maybe(&self, other: &Option<super::UClass>) -> bool {
other
.as_ref()
.map(|class| self.is_a(class))
.unwrap_or(false)
}
} }
impl<T> UObjectNonConst for T where T: UObjectTrait {} impl<T> UObjectNonConst for T where T: UObjectTrait {}