1#![allow(clippy::missing_safety_doc)]
2
3pub use rusteal_core as runtime;
4pub use rusteal_ffi as ffi;
5pub use rusteal_macros::{uclass, uclass_impl, ustruct};
6pub use rusteal_ue_flags as ue_flags;
7
8#[doc(hidden)]
9pub extern crate inventory as __inventory;
10
11pub mod prelude;
12
13pub use glam;
14
15extern "C" fn real_drop_rust_instance(
16 handle: ffi::UObjectHandle,
17 type_id: u64,
18 _rust_data: *mut u8,
19) {
20 runtime::ffi_boundary((), || {
21 runtime::reify_registry::drop_instance(handle, type_id);
22 });
23}
24
25extern "C" fn real_invoke_rust_function(
26 callback_id: u64,
27 obj: ffi::UObjectHandle,
28 params: *mut u8,
29) {
30 runtime::ffi_boundary((), || {
31 runtime::reify_registry::invoke_function(callback_id, obj, params);
32 });
33}
34
35extern "C" fn real_invoke_delegate_callback(callback_id: u64, params: *mut u8) {
36 runtime::ffi_boundary((), || {
37 runtime::delegate_registry::invoke(callback_id, params);
38 });
39}
40
41extern "C" fn real_construct_rust_instance(obj: ffi::UObjectHandle, type_id: u64, _is_cdo: bool) {
42 runtime::ffi_boundary((), || {
43 runtime::reify_registry::construct_instance(obj, type_id);
44 });
45}
46
47extern "C" fn real_on_shutdown() {
48 runtime::ffi_boundary((), || {
49 runtime::task::shutdown();
50 runtime::reify_registry::clear_all();
51 runtime::delegate_registry::clear_all();
52 runtime::pinned::clear_all();
53 });
54}
55
56extern "C" fn real_notify_pinned_destroyed(handle: ffi::UObjectHandle) {
57 runtime::ffi_boundary((), || {
58 runtime::pinned::notify_pinned_destroyed(handle);
59 });
60}
61
62extern "C" fn real_on_tick(delta_seconds: f32) {
63 runtime::ffi_boundary((), || {
64 runtime::task::tick(delta_seconds);
65 });
66}
67
68#[doc(hidden)]
69pub static __CALLBACKS: ffi::RustealRustCallbacks = ffi::RustealRustCallbacks {
70 drop_rust_instance: real_drop_rust_instance,
71 invoke_rust_function: real_invoke_rust_function,
72 invoke_delegate_callback: real_invoke_delegate_callback,
73 on_shutdown: real_on_shutdown,
74 construct_rust_instance: real_construct_rust_instance,
75 notify_pinned_destroyed: real_notify_pinned_destroyed,
76 on_tick: real_on_tick,
77};
78
79pub unsafe fn init(api_table: *const ffi::RustealApiTable) -> *const ffi::RustealRustCallbacks {
80 std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
81 if api_table.is_null() {
82 return std::ptr::null();
83 }
84
85 if unsafe { (*api_table).version } != ffi::RUSTEAL_VERSION {
86 return std::ptr::null();
87 }
88
89 runtime::init_api(api_table);
90 runtime::task::mark_game_thread();
91
92 log_greeting();
93 register_all_classes();
94 run_load_hooks();
95
96 &__CALLBACKS as *const ffi::RustealRustCallbacks
97 }))
98 .unwrap_or(std::ptr::null())
99}
100
101fn log_greeting() {
102 let msg = "[Rusteal] Rust side initialized";
103 let bytes = msg.as_bytes();
104
105 unsafe {
106 runtime::ffi_dispatch::logging_log(0, bytes.as_ptr(), bytes.len() as u32);
107 }
108}
109
110fn register_all_classes() {
111 runtime::reify_registry::register_all_from_inventory();
112}
113
114#[doc(hidden)]
115pub struct LoadHook(pub fn());
116inventory::collect!(LoadHook);
117
118fn run_load_hooks() {
119 for hook in inventory::iter::<LoadHook> {
120 (hook.0)();
121 }
122}
123
124#[macro_export]
125macro_rules! on_load {
126 ($function:path) => {
127 $crate::__inventory::submit! { $crate::LoadHook($function) }
128 };
129}
130
131pub fn shutdown() {
132 let _ = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
133 (__CALLBACKS.on_shutdown)();
134 }));
135}
136
137#[macro_export]
138macro_rules! entry {
139 () => {
140 mod __rusteal_native_entry {
141 #[unsafe(no_mangle)]
142 pub extern "C" fn rusteal_init(
143 api_table: *const $crate::ffi::RustealApiTable,
144 ) -> *const $crate::ffi::RustealRustCallbacks {
145 unsafe { $crate::init(api_table) }
146 }
147
148 #[unsafe(no_mangle)]
149 pub extern "C" fn rusteal_shutdown() {
150 $crate::shutdown()
151 }
152
153 #[unsafe(no_mangle)]
154 pub extern "C" fn rusteal_version() -> u32 {
155 $crate::ffi::RUSTEAL_VERSION
156 }
157
158 #[unsafe(no_mangle)]
159 pub extern "C" fn rusteal_callbacks() -> *const $crate::ffi::RustealRustCallbacks {
160 &$crate::__CALLBACKS
161 }
162 }
163 };
164}