goud_engine/sdk/
entity.rs1use super::GoudGame;
10use crate::ecs::Entity;
11
12impl GoudGame {
15 pub fn ffi_entity_spawn_empty(&mut self) -> u64 {
19 self.world_mut().spawn_empty().to_bits()
20 }
21
22 pub unsafe fn ffi_entity_spawn_batch(&mut self, count: u32, out_entities: *mut u64) -> u32 {
32 if out_entities.is_null() || count == 0 {
33 return 0;
34 }
35 let entities = self.world_mut().spawn_batch(count as usize);
36 let out_slice = std::slice::from_raw_parts_mut(out_entities, count as usize);
38 for (i, entity) in entities.iter().enumerate() {
39 out_slice[i] = entity.to_bits();
40 }
41 entities.len() as u32
42 }
43
44 pub fn ffi_entity_despawn(&mut self, entity_id: u64) -> bool {
48 let entity = Entity::from_bits(entity_id);
49 self.world_mut().despawn(entity)
50 }
51
52 pub unsafe fn ffi_entity_despawn_batch(&mut self, entity_ids: *const u64, count: u32) -> u32 {
61 if entity_ids.is_null() || count == 0 {
62 return 0;
63 }
64 let entity_slice = std::slice::from_raw_parts(entity_ids, count as usize);
66 let entities: Vec<Entity> = entity_slice
67 .iter()
68 .map(|&bits| Entity::from_bits(bits))
69 .collect();
70 self.world_mut().despawn_batch(&entities) as u32
71 }
72
73 pub fn ffi_entity_is_alive(&self, entity_id: u64) -> bool {
75 let entity = Entity::from_bits(entity_id);
76 self.world().is_alive(entity)
77 }
78
79 pub fn ffi_entity_count(&self) -> u32 {
81 self.world().entity_count() as u32
82 }
83
84 pub unsafe fn ffi_entity_is_alive_batch(
96 &self,
97 entity_ids: *const u64,
98 count: u32,
99 out_results: *mut u8,
100 ) -> u32 {
101 if entity_ids.is_null() || out_results.is_null() || count == 0 {
102 return 0;
103 }
104 let entity_slice = std::slice::from_raw_parts(entity_ids, count as usize);
106 let results_slice = std::slice::from_raw_parts_mut(out_results, count as usize);
107 for (i, &entity_bits) in entity_slice.iter().enumerate() {
108 let entity = Entity::from_bits(entity_bits);
109 results_slice[i] = if self.world().is_alive(entity) { 1 } else { 0 };
110 }
111 count
112 }
113}
114
115#[cfg(test)]
116mod tests {
117 use super::*;
118 use crate::sdk::GameConfig;
119
120 #[test]
121 fn test_ffi_entity_spawn_empty() {
122 let mut game = GoudGame::new(GameConfig::default()).unwrap();
123 let bits = game.ffi_entity_spawn_empty();
124 assert_ne!(bits, u64::MAX);
125 assert!(game.ffi_entity_is_alive(bits));
126 }
127
128 #[test]
129 fn test_ffi_entity_despawn() {
130 let mut game = GoudGame::new(GameConfig::default()).unwrap();
131 let bits = game.ffi_entity_spawn_empty();
132 assert!(game.ffi_entity_despawn(bits));
133 assert!(!game.ffi_entity_is_alive(bits));
134 }
135
136 #[test]
137 fn test_ffi_entity_count() {
138 let mut game = GoudGame::new(GameConfig::default()).unwrap();
139 assert_eq!(game.ffi_entity_count(), 0);
140 game.ffi_entity_spawn_empty();
141 assert_eq!(game.ffi_entity_count(), 1);
142 game.ffi_entity_spawn_empty();
143 assert_eq!(game.ffi_entity_count(), 2);
144 }
145
146 #[test]
147 fn test_ffi_entity_spawn_batch() {
148 let mut game = GoudGame::new(GameConfig::default()).unwrap();
149 let mut out = vec![0u64; 5];
150 let count = unsafe { game.ffi_entity_spawn_batch(5, out.as_mut_ptr()) };
152 assert_eq!(count, 5);
153 for &bits in &out {
154 assert!(game.ffi_entity_is_alive(bits));
155 }
156 }
157
158 #[test]
159 fn test_ffi_entity_despawn_batch() {
160 let mut game = GoudGame::new(GameConfig::default()).unwrap();
161 let mut out = vec![0u64; 3];
162 unsafe { game.ffi_entity_spawn_batch(3, out.as_mut_ptr()) };
164 assert_eq!(game.ffi_entity_count(), 3);
165
166 let count = unsafe { game.ffi_entity_despawn_batch(out.as_ptr(), 3) };
168 assert_eq!(count, 3);
169 assert_eq!(game.ffi_entity_count(), 0);
170 }
171
172 #[test]
173 fn test_ffi_entity_is_alive_batch() {
174 let mut game = GoudGame::new(GameConfig::default()).unwrap();
175 let mut entities = vec![0u64; 3];
176 unsafe { game.ffi_entity_spawn_batch(3, entities.as_mut_ptr()) };
178
179 game.ffi_entity_despawn(entities[1]);
181
182 let mut results = vec![0u8; 3];
183 let count =
185 unsafe { game.ffi_entity_is_alive_batch(entities.as_ptr(), 3, results.as_mut_ptr()) };
186 assert_eq!(count, 3);
187 assert_eq!(results[0], 1);
188 assert_eq!(results[1], 0);
189 assert_eq!(results[2], 1);
190 }
191}