Skip to main content

rusteal_core/
script_interface.rs

1use std::marker::PhantomData;
2
3use rusteal_ffi::UObjectHandle;
4
5use crate::dynamic_call::DynamicCall;
6use crate::error::{RustealError, RustealResult};
7use crate::ffi_dispatch;
8use crate::object_ref::UObjectRef;
9use crate::traits::{UeClass, UeInterface};
10
11#[repr(transparent)]
12pub struct ScriptInterface<I: UeInterface + ?Sized> {
13    handle: UObjectHandle,
14    _marker: PhantomData<*const I>,
15}
16
17impl<I: UeInterface + ?Sized> Clone for ScriptInterface<I> {
18    fn clone(&self) -> Self {
19        *self
20    }
21}
22
23impl<I: UeInterface + ?Sized> Copy for ScriptInterface<I> {}
24
25impl<I: UeInterface + ?Sized> PartialEq for ScriptInterface<I> {
26    fn eq(&self, other: &Self) -> bool {
27        self.handle == other.handle
28    }
29}
30
31impl<I: UeInterface + ?Sized> Eq for ScriptInterface<I> {}
32
33impl<I: UeInterface + ?Sized> std::fmt::Debug for ScriptInterface<I> {
34    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35        f.debug_struct("ScriptInterface")
36            .field("handle", &self.handle)
37            .finish()
38    }
39}
40
41unsafe impl<I: UeInterface + ?Sized> Send for ScriptInterface<I> {}
42
43impl<I: UeInterface + ?Sized> ScriptInterface<I> {
44    #[track_caller]
45    pub fn new(object: UObjectHandle) -> RustealResult<Self> {
46        if !unsafe { ffi_dispatch::core_is_valid(object) } {
47            return Err(RustealError::object_destroyed());
48        }
49
50        if !unsafe { ffi_dispatch::core_is_a(object, I::static_class()) } {
51            return Err(RustealError::invalid_cast_to(object, I::static_class()));
52        }
53
54        Ok(ScriptInterface {
55            handle: object,
56            _marker: PhantomData,
57        })
58    }
59
60    #[inline]
61    pub fn raw(&self) -> UObjectHandle {
62        self.handle
63    }
64
65    #[inline]
66    pub fn is_valid(&self) -> bool {
67        unsafe { ffi_dispatch::core_is_valid(self.handle) }
68    }
69
70    #[track_caller]
71    pub fn object<T: UeClass>(&self) -> RustealResult<UObjectRef<T>> {
72        unsafe { UObjectRef::<T>::from_raw(self.handle) }.cast()
73    }
74
75    #[track_caller]
76    pub fn call(&self, function: &str) -> RustealResult<DynamicCall> {
77        if !self.is_valid() {
78            return Err(RustealError::object_destroyed());
79        }
80
81        DynamicCall::on_object(self.handle, function)
82    }
83}