bones_ecs/
world.rs

1//! Contains the ECS [`World`].
2
3use crate::prelude::*;
4
5/// The [`World`] is simply a collection of [`Resources`], and [`ComponentStores`].
6///
7/// Also stored in the world is the [`Entities`], but it is stored as a resource.
8///
9/// [`World`] is designed to be trivially [`Clone`]ed to allow for snapshotting the world state. The
10/// is especially useful in the context of rollback networking, which requires the ability to
11/// snapshot and restore state.
12#[derive(Clone)]
13pub struct World {
14    /// Stores the world resources.
15    pub resources: Resources,
16    /// Stores the world components.
17    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        // Always initialize an Entities resource
30        resources.insert(Entities::default());
31
32        Self {
33            resources,
34            components: Default::default(),
35        }
36    }
37}
38
39impl World {
40    /// Create a new [`World`].
41    pub fn new() -> Self {
42        Self::default()
43    }
44
45    /// Create a new world that uses the provided entities resource.
46    ///
47    /// This allows multiple worlds to avoid allocating the same entity IDs.
48    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    /// Remove the component info for dead entities.
61    ///
62    /// This should be called every game frame to cleanup entities that have been killed.
63    ///
64    /// This will remove the component storage for all killed entities, and allow their slots to be
65    /// re-used for any new entities.
66    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                // Safe: We don't provide an out pointer, so it doesn't overlap the component's
73                // internal storage.
74                unsafe {
75                    components.remove_raw(entity, None);
76                }
77            }
78        }
79        entities.clear_killed();
80    }
81
82    /// Run a system once.
83    ///
84    /// This is good for initializing the world with setup systems.
85    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    /// Get an entity's components.
97    ///
98    /// # Panics
99    ///
100    /// Panics if the entity does not have the required components from the query.
101    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    /// Get an entity's components.
110    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    /// Initialize a resource of type `T` by inserting it's default value.
133    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    /// Insert a resource.
142    pub fn insert_resource<R: HasSchema>(&self, resource: R) -> Option<R> {
143        self.resources.insert(resource)
144    }
145
146    /// Borrow a resource from the world.
147    /// # Panics
148    /// Panics if the resource does not exist in the store.
149    #[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    /// Borrow a resource from the world.
162    /// # Panics
163    /// Panics if the resource does not exist in the store.
164    #[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    /// Borrow a resource from the world, if it exists.
177    pub fn get_resource<T: HasSchema>(&self) -> Option<Ref<'_, T>> {
178        self.resources.get()
179    }
180
181    /// Borrow a resource from the world, if it exists.
182    pub fn get_resource_mut<T: HasSchema>(&self) -> Option<RefMut<'_, T>> {
183        self.resources.get_mut()
184    }
185
186    /// Borrow a component store from the world.
187    /// # Panics
188    /// Panics if the component store does not exist in the world.
189    #[track_caller]
190    pub fn component<T: HasSchema>(&self) -> Ref<'_, ComponentStore<T>> {
191        self.components.get::<T>().borrow()
192    }
193
194    /// Mutably borrow a component store from the world.
195    /// # Panics
196    /// Panics if the component store does not exist in the world.
197    #[track_caller]
198    pub fn component_mut<T: HasSchema>(&self) -> RefMut<'_, ComponentStore<T>> {
199        self.components.get::<T>().borrow_mut()
200    }
201
202    /// Load snapshot of [`World`] into self.
203    pub fn load_snapshot(&mut self, snapshot: World) {
204        self.components = snapshot.components;
205        self.resources = snapshot.resources;
206    }
207}
208
209/// Creates an instance of the type this trait is implemented for
210/// using data from the supplied [`World`].
211///
212/// This can be helpful for complex initialization or context-aware defaults.
213pub trait FromWorld {
214    /// Creates `Self` using data from the given [`World`].
215    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    // Sets up the world with a couple entities.
246    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    /// Mutates the positions based on the velocities.
263    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    /// Tests that the world's components matches the state it should after running `setup_world`.
271    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    /// Tests that the worlds components matches the state it should after running the
290    /// pos_vel_system one time.
291    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        // Make sure our entities exist visit properly during iteration
316        let test = || {};
317        world.run_system(test, ());
318
319        // Mutate and read some components
320        world.run_system(pos_vel_system, ());
321
322        // Make sure the mutations were applied
323        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        // Snapshot world1
332        let snap = world1.clone();
333
334        // Make sure the snapshot represents world1's state
335        snap.run_system(test_after_setup_state, ());
336
337        // Run the pos_vel system on world1
338        world1.run_system(pos_vel_system, ());
339
340        // Make sure world1 has properly update
341        world1.run_system(test_pos_vel_1_run, ());
342
343        // Make sure the snapshot hasn't changed
344        snap.run_system(test_after_setup_state, ());
345
346        // Run the pos vel system once on the snapshot
347        snap.run_system(pos_vel_system, ());
348
349        // Make sure the snapshot has updated
350        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    // ============
379    //  From World
380    // ============
381
382    #[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}