1use crate::prelude::*;
4
5#[derive(Clone)]
13pub struct World {
14 pub resources: Resources,
16 pub components: ComponentStores,
18}
19impl std::fmt::Debug for World {
20 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21 f.debug_struct("World").finish()
22 }
23}
24
25impl Default for World {
26 fn default() -> Self {
27 let resources = Resources::new();
28
29 resources.insert(Entities::default());
31
32 Self {
33 resources,
34 components: Default::default(),
35 }
36 }
37}
38
39impl World {
40 pub fn new() -> Self {
42 Self::default()
43 }
44
45 pub fn with_entities(entities: AtomicResource<Entities>) -> Self {
49 let resources = Resources::new();
50 resources
51 .untyped()
52 .insert_cell(entities.into_untyped())
53 .unwrap();
54 World {
55 resources,
56 components: default(),
57 }
58 }
59
60 pub fn maintain(&self) {
67 let mut entities = self.resource_mut::<Entities>();
68 for components in self.components.components.read_only_view().values() {
69 let mut components = components.borrow_mut();
70 let killed = entities.killed();
71 for &entity in killed {
72 unsafe {
75 components.remove_raw(entity, None);
76 }
77 }
78 }
79 entities.clear_killed();
80 }
81
82 pub fn run_system<'system, R, In, Out, S>(&self, system: S, input: In) -> Out
86 where
87 In: 'system,
88 Out: 'system,
89 S: IntoSystem<R, In, Out>,
90 S::Sys: 'system,
91 {
92 let mut s = system.system();
93 s.run(self, input)
94 }
95
96 pub fn entity_components<Q: QueryItem>(
102 &self,
103 entity: Entity,
104 query: Q,
105 ) -> <Q::Iter as Iterator>::Item {
106 self.get_entity_components(entity, query).unwrap()
107 }
108
109 pub fn get_entity_components<Q: QueryItem>(
111 &self,
112 entity: Entity,
113 query: Q,
114 ) -> Option<<Q::Iter as Iterator>::Item> {
115 let mut bitset = BitSetVec::default();
116 if self.resource::<Entities>().bitset().contains(entity) {
117 bitset.set(entity);
118 }
119 query.apply_bitset(&mut bitset);
120 match query.get_single_with_bitset(bitset.into()) {
121 Ok(components) => Some(components),
122 Err(QuerySingleError::NoEntities) => None,
123 Err(QuerySingleError::MultipleEntities) => {
124 panic!(
125 "Query returned a MultipleEntities error for a bitset that \
126 contains at most one enabled bit"
127 )
128 }
129 }
130 }
131
132 pub fn init_resource<R: HasSchema + FromWorld>(&mut self) -> RefMut<'_, R> {
134 if unlikely(!self.resources.contains::<R>()) {
135 let value = R::from_world(self);
136 self.resources.insert(value);
137 }
138 self.resource_mut()
139 }
140
141 pub fn insert_resource<R: HasSchema>(&self, resource: R) -> Option<R> {
143 self.resources.insert(resource)
144 }
145
146 #[track_caller]
150 pub fn resource<T: HasSchema>(&self) -> Ref<'_, T> {
151 match self.resources.get::<T>() {
152 Some(r) => r,
153 None => panic!(
154 "Requested resource {} does not exist in the `World`. \
155 Did you forget to add it using `world.insert_resource` / `world.init_resource`?",
156 std::any::type_name::<T>()
157 ),
158 }
159 }
160
161 #[track_caller]
165 pub fn resource_mut<T: HasSchema>(&self) -> RefMut<'_, T> {
166 match self.resources.get_mut::<T>() {
167 Some(r) => r,
168 None => panic!(
169 "Requested resource {} does not exist in the `World`. \
170 Did you forget to add it using `world.insert_resource` / `world.init_resource`?",
171 std::any::type_name::<T>()
172 ),
173 }
174 }
175
176 pub fn get_resource<T: HasSchema>(&self) -> Option<Ref<'_, T>> {
178 self.resources.get()
179 }
180
181 pub fn get_resource_mut<T: HasSchema>(&self) -> Option<RefMut<'_, T>> {
183 self.resources.get_mut()
184 }
185
186 #[track_caller]
190 pub fn component<T: HasSchema>(&self) -> Ref<'_, ComponentStore<T>> {
191 self.components.get::<T>().borrow()
192 }
193
194 #[track_caller]
198 pub fn component_mut<T: HasSchema>(&self) -> RefMut<'_, ComponentStore<T>> {
199 self.components.get::<T>().borrow_mut()
200 }
201
202 pub fn load_snapshot(&mut self, snapshot: World) {
204 self.components = snapshot.components;
205 self.resources = snapshot.resources;
206 }
207}
208
209pub trait FromWorld {
214 fn from_world(world: &World) -> Self;
216}
217
218impl<T: Default> FromWorld for T {
219 fn from_world(_world: &World) -> Self {
220 T::default()
221 }
222}
223
224#[cfg(test)]
225mod tests {
226 use crate::prelude::*;
227
228 use super::FromWorld;
229
230 #[derive(Clone, Copy, HasSchema, Debug, Eq, PartialEq, Default)]
231 #[repr(C)]
232 struct C(u32);
233
234 #[derive(Clone, HasSchema, Debug, Eq, PartialEq, Default)]
235 #[repr(C)]
236 struct Pos(i32, i32);
237
238 #[derive(Clone, HasSchema, Debug, Eq, PartialEq, Default)]
239 #[repr(C)]
240 struct Vel(i32, i32);
241
242 #[derive(Clone, HasSchema, Debug, Eq, PartialEq, Default)]
243 struct Marker;
244
245 fn setup_world(
247 mut entities: ResMut<Entities>,
248 mut pos_comps: CompMut<Pos>,
249 mut vel_comps: CompMut<Vel>,
250 mut marker_comps: CompMut<Marker>,
251 ) {
252 let ent1 = entities.create();
253 pos_comps.insert(ent1, Pos(0, 100));
254 vel_comps.insert(ent1, Vel(0, -1));
255
256 let ent2 = entities.create();
257 pos_comps.insert(ent2, Pos(0, 0));
258 vel_comps.insert(ent2, Vel(1, 1));
259 marker_comps.insert(ent2, Marker);
260 }
261
262 fn pos_vel_system(entities: Res<Entities>, mut pos: CompMut<Pos>, vel: Comp<Vel>) {
264 for (_, (pos, vel)) in entities.iter_with((&mut pos, &vel)) {
265 pos.0 += vel.0;
266 pos.1 += vel.1;
267 }
268 }
269
270 fn test_after_setup_state(
272 entities: Res<Entities>,
273 pos: Comp<Pos>,
274 vel: Comp<Vel>,
275 marker: Comp<Marker>,
276 ) {
277 let mut i = 0;
278 for (entity, (pos, vel)) in entities.iter_with((&pos, &vel)) {
279 let marker = marker.get(entity);
280 match (i, pos, vel, marker) {
281 (0, Pos(0, 100), Vel(0, -1), None) | (1, Pos(0, 0), Vel(1, 1), Some(Marker)) => (),
282 x => unreachable!("{:?}", x),
283 }
284 i += 1;
285 }
286 assert_eq!(i, 2);
287 }
288
289 fn test_pos_vel_1_run(
292 entities: Res<Entities>,
293 pos: Comp<Pos>,
294 vel: Comp<Vel>,
295 marker: Comp<Marker>,
296 ) {
297 let mut i = 0;
298 for (entity, (pos, vel)) in entities.iter_with((&pos, &vel)) {
299 let marker = marker.get(entity);
300 match (i, pos, vel, marker) {
301 (0, Pos(0, 99), Vel(0, -1), None) | (1, Pos(1, 1), Vel(1, 1), Some(Marker)) => (),
302 x => unreachable!("{:?}", x),
303 }
304 i += 1;
305 }
306 assert_eq!(i, 2);
307 }
308
309 #[test]
310 fn sanity_check() {
311 let world = World::new();
312
313 world.run_system(setup_world, ());
314
315 let test = || {};
317 world.run_system(test, ());
318
319 world.run_system(pos_vel_system, ());
321
322 world.run_system(test_pos_vel_1_run, ());
324 }
325
326 #[test]
327 fn snapshot() {
328 let world1 = World::new();
329 world1.run_system(setup_world, ());
330
331 let snap = world1.clone();
333
334 snap.run_system(test_after_setup_state, ());
336
337 world1.run_system(pos_vel_system, ());
339
340 world1.run_system(test_pos_vel_1_run, ());
342
343 snap.run_system(test_after_setup_state, ());
345
346 snap.run_system(pos_vel_system, ());
348
349 world1.run_system(test_pos_vel_1_run, ());
351 }
352
353 #[test]
354 fn world_is_send() {
355 fn send<T: Send>(_: T) {}
356 send(World::new())
357 }
358
359 #[test]
360 fn get_entity_components() {
361 let w = World::default();
362
363 let (e1, e2) = {
364 let mut entities = w.resource_mut::<Entities>();
365 (entities.create(), entities.create())
366 };
367
368 let state = w.components.get::<C>();
369 let mut comp = state.borrow_mut();
370
371 let c2 = C(2);
372 comp.insert(e2, c2);
373
374 assert_eq!(w.get_entity_components(e1, &comp), None);
375 assert_eq!(w.get_entity_components(e2, &comp), Some(&c2));
376 }
377
378 #[derive(Clone, HasSchema, Default)]
383 struct TestResource(u32);
384
385 #[derive(Clone, HasSchema)]
386 #[schema(opaque, no_default)]
387 struct TestFromWorld(u32);
388 impl FromWorld for TestFromWorld {
389 fn from_world(world: &World) -> Self {
390 let b = world.resource::<TestResource>();
391 Self(b.0)
392 }
393 }
394
395 #[test]
396 fn init_resource_does_not_overwrite() {
397 let mut w = World::default();
398 w.insert_resource(TestResource(0));
399 w.init_resource::<TestFromWorld>();
400 w.insert_resource(TestResource(1));
401
402 let resource = w.resource::<TestFromWorld>();
403 assert_eq!(resource.0, 0);
404 }
405}