rusteal_core/
script_interface.rs1use 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}