mewo_ecs/galaxy/
mod.rs

1use super::{
2    data::{ThreadLocal, ThreadLocalGuard},
3    ecs::{
4        ComponentGroupId, ComponentGroupPlanet, ComponentTypeId, ComponentTypePlanet, Entity,
5        EntityPlanet, EventId, EventModify, EventPlanet, QueryAccess, QueryAccessType,
6        QueryFilterType, QueryId, QueryLockType, QueryPlanet, ResourceId, ResourcePlanet,
7        ResourceTypeId, StorageModifyTransform, StoragePlanet, StorageTransform,
8    },
9};
10use parking_lot::RwLock;
11use std::sync::atomic::{AtomicBool, Ordering};
12
13mod access;
14mod component;
15mod entity;
16mod event;
17mod query;
18mod resource;
19
20#[cfg(test)]
21mod test;
22
23pub use access::{ComponentAccessOptional, ComponentAccessesNormal, ComponentAccessesOptional};
24pub use component::{CheapComponent, Component, GenericComponent, UniqueComponent};
25pub use entity::EntityGetter;
26pub use event::Event;
27pub use resource::{Resource, ResourceReadGuard, ResourceWriteGuard};
28
29pub struct Galaxy {
30    //  These RwLocks allow the galaxy to dynamically insert queries, components, etc during
31    //  runtime via `maybe_insert` functions. Based on their current usage, ABBA deadlocks
32    //  are not possible.
33    ep: RwLock<EntityPlanet>,
34    ctyp: RwLock<ComponentTypePlanet>,
35    cgp: RwLock<ComponentGroupPlanet>,
36    rcp: RwLock<ResourcePlanet>,
37    evp: RwLock<EventPlanet>,
38    qp: RwLock<QueryPlanet>,
39    sp: RwLock<StoragePlanet>,
40
41    ev_modify: ThreadLocal<EventModify>,
42    st_transforms: ThreadLocal<Vec<StorageTransform>>,
43
44    exit: AtomicBool,
45}
46
47impl Galaxy {
48    pub fn new() -> Self {
49        let mut cgp = ComponentGroupPlanet::new();
50        Galaxy {
51            sp: RwLock::new(StoragePlanet::new(&mut cgp).unwrap()),
52            cgp: RwLock::new(cgp),
53
54            rcp: RwLock::new(ResourcePlanet::new()),
55            evp: RwLock::new(EventPlanet::new()),
56            ctyp: RwLock::new(ComponentTypePlanet::new()),
57            qp: RwLock::new(QueryPlanet::new()),
58
59            ep: RwLock::new(EntityPlanet::new()),
60
61            ev_modify: ThreadLocal::new(),
62            st_transforms: ThreadLocal::new(),
63
64            exit: AtomicBool::new(false),
65        }
66    }
67
68    pub fn set_exit(&self) {
69        self.exit.store(true, Ordering::SeqCst);
70    }
71
72    pub fn update(&mut self) -> Option<()> {
73        if self.exit.load(Ordering::SeqCst) {
74            None?
75        }
76
77        let mut evp = self.evp.write();
78
79        let mut ep = self.ep.write();
80        let ctyp = self.ctyp.read();
81        let mut cgp = self.cgp.write();
82        let mut sp = self.sp.write();
83        let mut qp = self.qp.write();
84
85        let ev_modifies = unsafe { self.ev_modify.get_inner() };
86        for ev_modify in ev_modifies.iter_mut() {
87            evp.modify(ev_modify).unwrap();
88        }
89
90        let st_transforms = unsafe { self.st_transforms.get_inner() };
91        for st_trans in st_transforms.iter_mut() {
92            for trans in st_trans.iter_mut() {
93                //  Eh, it'll get cleared anyway.
94                let trans =
95                    std::mem::replace(trans, StorageTransform::Remove(Entity::from(0, 888)));
96                sp.transform(&mut ep, &ctyp, &mut cgp, &mut qp, trans)
97                    .unwrap();
98            }
99            st_trans.clear()
100        }
101
102        sp.update();
103
104        Some(())
105    }
106
107    fn get_event_modify(&self) -> ThreadLocalGuard<EventModify> {
108        self.ev_modify.get_or(EventModify::new)
109    }
110
111    fn get_storage_transforms(&self) -> ThreadLocalGuard<Vec<StorageTransform>> {
112        self.st_transforms.get_or(Vec::new)
113    }
114}
115
116impl Default for Galaxy {
117    fn default() -> Self {
118        Self::new()
119    }
120}