Skip to main content

rusteal_core/
world.rs

1use rusteal_ffi::{FNameHandle, UClassHandle, UObjectHandle, UStructHandle};
2
3use crate::error::{RustealError, RustealResult, check_ffi};
4use crate::ffi_dispatch;
5
6#[track_caller]
7pub fn spawn_actor_raw(
8    world: UObjectHandle,
9    class: UClassHandle,
10    transform_buf: &[u8],
11    owner: UObjectHandle,
12) -> RustealResult<UObjectHandle> {
13    let result = unsafe {
14        ffi_dispatch::world_spawn_actor(
15            world,
16            class,
17            transform_buf.as_ptr(),
18            transform_buf.len() as u32,
19            owner,
20        )
21    };
22
23    if result.is_null() {
24        Err(RustealError::invalid_operation("spawn_actor returned null"))
25    } else {
26        Ok(result)
27    }
28}
29
30#[track_caller]
31pub fn find_object_raw(class: UClassHandle, path: &str) -> RustealResult<UObjectHandle> {
32    let result =
33        unsafe { ffi_dispatch::world_find_object(class, path.as_ptr(), path.len() as u32) };
34
35    if result.is_null() {
36        Err(RustealError::invalid_operation(format!(
37            "find_object: not found: {path}"
38        )))
39    } else {
40        Ok(result)
41    }
42}
43
44#[track_caller]
45pub fn load_object_raw(class: UClassHandle, path: &str) -> RustealResult<UObjectHandle> {
46    let result =
47        unsafe { ffi_dispatch::world_load_object(class, path.as_ptr(), path.len() as u32) };
48
49    if result.is_null() {
50        Err(RustealError::invalid_operation(format!(
51            "load_object: failed to load: {path}"
52        )))
53    } else {
54        Ok(result)
55    }
56}
57
58#[track_caller]
59pub fn new_object_raw(outer: UObjectHandle, class: UClassHandle) -> RustealResult<UObjectHandle> {
60    let result = unsafe { ffi_dispatch::world_new_object(outer, class) };
61
62    if result.is_null() {
63        Err(RustealError::invalid_operation("new_object returned null"))
64    } else {
65        Ok(result)
66    }
67}
68
69#[track_caller]
70pub fn spawn_actor_deferred_raw(
71    world: UObjectHandle,
72    class: UClassHandle,
73    transform_buf: &[u8],
74    owner: UObjectHandle,
75    instigator: UObjectHandle,
76    collision_method: u8,
77) -> RustealResult<UObjectHandle> {
78    let result = unsafe {
79        ffi_dispatch::world_spawn_actor_deferred(
80            world,
81            class,
82            transform_buf.as_ptr(),
83            transform_buf.len() as u32,
84            owner,
85            instigator,
86            collision_method,
87        )
88    };
89
90    if result.is_null() {
91        Err(RustealError::invalid_operation(
92            "spawn_actor_deferred returned null",
93        ))
94    } else {
95        Ok(result)
96    }
97}
98
99#[track_caller]
100pub fn finish_spawning_raw(actor: UObjectHandle, transform_buf: &[u8]) -> RustealResult<()> {
101    check_ffi(unsafe {
102        ffi_dispatch::world_finish_spawning(
103            actor,
104            transform_buf.as_ptr(),
105            transform_buf.len() as u32,
106        )
107    })
108}
109
110#[track_caller]
111pub fn get_world_raw(object: UObjectHandle) -> RustealResult<UObjectHandle> {
112    let result = unsafe { ffi_dispatch::world_get_world(object) };
113
114    if result.is_null() {
115        Err(RustealError::invalid_operation("get_world returned null"))
116    } else {
117        Ok(result)
118    }
119}
120
121#[track_caller]
122pub fn get_all_actors_of_class_raw(
123    world: UObjectHandle,
124    class: UClassHandle,
125) -> RustealResult<Vec<UObjectHandle>> {
126    let handle_size = core::mem::size_of::<UObjectHandle>() as u32;
127
128    let mut count: u32 = 0;
129
130    check_ffi(unsafe {
131        ffi_dispatch::world_get_all_actors_of_class(
132            world,
133            class,
134            std::ptr::null_mut(),
135            0,
136            &mut count,
137        )
138    })?;
139
140    if count == 0 {
141        return Ok(Vec::new());
142    }
143
144    let byte_size = count * handle_size;
145    let mut buf = vec![0u8; byte_size as usize];
146    let mut actual_count: u32 = 0;
147
148    check_ffi(unsafe {
149        ffi_dispatch::world_get_all_actors_of_class(
150            world,
151            class,
152            buf.as_mut_ptr(),
153            byte_size,
154            &mut actual_count,
155        )
156    })?;
157
158    let handles = buf
159        .chunks_exact(handle_size as usize)
160        .take(actual_count as usize)
161        .map(|chunk| {
162            let bytes: [u8; 8] = chunk.try_into().expect("handle is 8 bytes");
163            let ptr = usize::from_ne_bytes(bytes) as *mut std::ffi::c_void;
164
165            UObjectHandle(ptr)
166        })
167        .collect();
168
169    Ok(handles)
170}
171
172pub fn find_data_table_row_raw(
173    table: UObjectHandle,
174    row_name: FNameHandle,
175    row_struct: UStructHandle,
176) -> Option<*mut u8> {
177    let row = unsafe { ffi_dispatch::world_find_data_table_row(table, row_name, row_struct) };
178    (!row.is_null()).then_some(row)
179}