Skip to main content

nya_ecs/
world.rs

1use indexmap::{IndexMap, IndexSet};
2
3use crate::{
4    Entity,
5    component::{Bundle, Component, ComponentBox, ComponentKey},
6};
7
8/// The [World] contains all entities and components, it is queryable using [Queryable](crate::query::Queryable)
9pub struct World {
10    pub(crate) entities: IndexSet<Entity>,
11    pub(crate) components: IndexMap<Entity, IndexMap<ComponentKey, ComponentBox>>,
12    pub(crate) resources: IndexMap<ComponentKey, ComponentBox>,
13}
14
15impl World {
16    /// Create a new [World]
17    pub fn new() -> Self {
18        let entities = 100;
19        Self {
20            entities: IndexSet::with_capacity(entities),
21            components: IndexMap::with_capacity(entities),
22            resources: IndexMap::with_capacity(5),
23        }
24    }
25
26    /// Create an entity
27    pub fn spawn(&mut self) -> Entity {
28        let id = self.entities.len();
29        self.entities.insert(id);
30        self.components.insert(id, IndexMap::with_capacity(1000));
31        id
32    }
33
34    /// Destroy an entity
35    pub fn despawn(&mut self, entity: Entity) {
36        self.entities.swap_remove(&entity);
37        self.components.swap_remove(&entity);
38    }
39
40    /// Add a component to an entity
41    pub fn add<B: Bundle>(&mut self, entity: Entity, bundle: B) {
42        let boxes = bundle.into_boxes();
43
44        for (key, boxed) in boxes {
45            if !self.has_key(entity, &key) {
46                self.components
47                    .entry(entity)
48                    .or_default()
49                    .insert(key, boxed);
50            }
51        }
52    }
53
54    /// Check if `entity` has component `C`
55    pub fn has<C: Component>(&self, entity: Entity) -> bool {
56        self.has_key(entity, &ComponentKey::of::<C>())
57    }
58
59    /// Same as [Self::has] but uses a [ComponentKey]
60    pub fn has_key(&self, entity: Entity, key: &ComponentKey) -> bool {
61        let Some(components) = self.components.get(&entity) else {
62            return false;
63        };
64        components.contains_key(key)
65    }
66
67    /// Get a reference to the component of an entity
68    pub fn get<C: Component>(&self, entity: Entity) -> Option<&C> {
69        let c = self
70            .components
71            .get(&entity)?
72            .get(&ComponentKey::of::<C>())?;
73        c.downcast_ref::<C>()
74    }
75
76    /// Get a mutable reference to the component of an entity
77    pub fn get_mut<C: Component>(&mut self, entity: Entity) -> Option<&mut C> {
78        let c = self
79            .components
80            .get_mut(&entity)?
81            .get_mut(&ComponentKey::of::<C>())?;
82        c.downcast_mut::<C>()
83    }
84
85    /// Remove a component from an entity
86    pub fn del<C: Component>(&mut self, entity: Entity) -> Option<Box<C>> {
87        let c = self
88            .components
89            .get_mut(&entity)?
90            .swap_remove(&ComponentKey::of::<C>())?;
91        c.downcast().ok()
92    }
93
94    /// Add a global resource
95    ///
96    /// A resource is like a component but it behaves like a singleton.
97    /// There can only be one type of a resource at a time.
98    ///
99    /// Anything that implements [Component] can be used as a resource.
100    ///
101    /// You cannot overwrite a resource, if you must, delete one using [Self::delete_res]
102    pub fn add_res<C: Component>(&mut self, resource: C) {
103        if !self.has_res::<C>() {
104            self.resources
105                .insert(ComponentKey::of::<C>(), Box::new(resource));
106        }
107    }
108
109    /// Similar to [Self::has] but for resources
110    pub fn has_res<C: Component>(&self) -> bool {
111        self.has_res_key(&ComponentKey::of::<C>())
112    }
113
114    /// Same as [Self::has_res] but uses a [ComponentKey]
115    pub fn has_res_key(&self, key: &ComponentKey) -> bool {
116        self.resources.contains_key(key)
117    }
118
119    /// Get a reference to a global resource
120    ///
121    /// For more on resources see [Self::add_res]
122    pub fn get_res<C: Component>(&self) -> Option<&C> {
123        self.resources.get(&ComponentKey::of::<C>())?.downcast_ref()
124    }
125
126    /// Get a mutable reference to a global resource
127    ///
128    /// For more on resources see [Self::add_res]
129    pub fn get_res_mut<C: Component>(&mut self) -> Option<&mut C> {
130        self.resources
131            .get_mut(&ComponentKey::of::<C>())?
132            .downcast_mut()
133    }
134
135    /// Remove a global resource
136    pub fn del_res<C: Component>(&mut self) -> Option<Box<C>> {
137        self.resources
138            .swap_remove(&ComponentKey::of::<C>())
139            .map(|c| c.downcast().ok())
140            .flatten()
141    }
142}
143
144impl Default for World {
145    fn default() -> Self {
146        World::new()
147    }
148}