1use crate::arch::{ArchetypeId, ArchRowId};
2use crate::component::FlagId;
3
4pub type EntityId = u32;
5
6pub(crate) struct Entity {
7 pub(crate) arch_id: ArchetypeId,
8 pub(crate) arch_row: ArchRowId,
9}
10
11pub(crate) struct EntityStore {
12 next_id: EntityId,
13 dead: Vec<u8>,
14 entities: Vec<Entity>,
15 flags: Vec<Vec<u8>>,
17 available_ids: Vec<EntityId>
18}
19
20impl EntityStore {
21 pub(crate) fn new() -> Self {
22 Self {
23 next_id: 0,
24 dead: Vec::new(),
25 entities: Vec::new(),
26 flags: Vec::new(),
27 available_ids: Vec::new()
28 }
29 }
30
31 #[inline]
33 pub(crate) fn new_id(&mut self) -> EntityId {
34 if let Some(id) = self.available_ids.pop() {
35 let idx = id / 8;
37 let idx2 = id % 8;
38 self.flags.iter_mut().for_each(|flag_bitmap| {
39 if let Some(bitmap) = flag_bitmap.get_mut(idx as usize) {
40 *bitmap &= !(1 << idx2);
41 }
42 });
43
44 return id;
45 } else {
46 let entity_id = self.next_id;
47 self.next_id += 1;
48 return entity_id;
49 }
50
51 }
52
53 #[inline]
55 pub(crate) fn spawn_with_id(&mut self, ent_id: EntityId, arch_id: ArchetypeId, arch_row: ArchRowId) {
56 if self.entities.len() <= ent_id as usize {
57 self.entities.resize_with(ent_id as usize + 1, || Entity { arch_id, arch_row });
58 } else {
59 self.entities[ent_id as usize] = Entity { arch_id, arch_row };
60 }
61 }
62
63 #[inline]
65 pub(crate) fn kill_and_keep(&mut self, ent: EntityId) {
66 let idx = ent / 8;
67 let idx2 = ent % 8;
68 if self.dead.len() <= ent as usize {
69 self.dead.resize(ent as usize + 1, 0);
70 }
71 let dead_map = &mut self.dead[idx as usize];
72 *dead_map |= 1 << idx2
73 }
74
75 #[inline]
76 pub(crate) fn kill(&mut self, ent: EntityId) {
77 self.kill_and_keep(ent);
78 self.free_id(ent);
79 }
80
81 #[inline]
82 pub(crate) fn free_id(&mut self, ent: EntityId) {
83 self.available_ids.push(ent);
84 }
85
86 #[inline]
87 pub(crate) fn is_alive(&self, ent: EntityId) -> bool {
88 let idx = ent / 8;
89 let idx2 = ent % 8;
90 match self.dead.get(idx as usize) {
91 Some(bitmap) => {
92 return bitmap & (1 << idx2) != (1 << idx2);
93 }
94 None => {
95 return true;
96 }
97 }
98 }
99
100 #[inline]
101 pub(crate) fn entity_count(&self) -> usize {
102 (0..(self.entities.len() as u32))
103 .filter(|ent_id| self.is_alive(*ent_id))
104 .count()
105 }
106
107 #[inline]
108 pub(crate) fn entities(&self) -> &Vec<Entity> {
109 &self.entities
110 }
111
112 #[inline]
113 pub(crate) fn has_flag(&self, ent: EntityId, flag: FlagId) -> bool {
114 let idx = ent / 8;
115 let idx2 = ent % 8;
116
117 match self.flags.get(flag as usize) {
118 Some(bitmaps) => {
119 match bitmaps.get(idx as usize) {
120 Some(bitmap) => {
121 return bitmap & (1 << idx2) == (1 << idx2);
122 }
123 None => {
124 return false;
125 }
126 }
127 }
128 None => {
129 return false;
130 }
131 }
132 }
133
134 #[inline]
135 pub(crate) fn set_flag(&mut self, ent: EntityId, flag: FlagId) {
136 let idx = ent / 8;
137 let idx2 = ent % 8;
138
139 if self.flags.len() <= flag as usize {
140 self.flags.resize_with(flag as usize + 1, Vec::new);
141 }
142
143 if self.flags[flag as usize].len() <= idx as usize {
144 self.flags[flag as usize].resize_with(idx as usize + 1, || 0);
145 }
146
147 self.flags[flag as usize][idx as usize] |= 1 << idx2;
148 }
149
150 #[inline]
151 pub(crate) fn unset_flag(&mut self, ent: EntityId, flag: FlagId) {
152 let idx = ent / 8;
153 let idx2 = ent % 8;
154
155 if self.flags.len() <= flag as usize {
156 return;
158 }
159
160 if self.flags[flag as usize].len() <= idx as usize {
161 return;
162 }
163
164 self.flags[flag as usize][idx as usize] &= !(1 << idx2);
165 }
166}
167
168#[cfg(test)]
169mod tests {
170 use crate::entity::EntityStore;
171
172 #[test]
173 fn new_entity_id() {
174 let mut ent_store = EntityStore::new();
175 let id1 = ent_store.new_id();
176 let id2 = ent_store.new_id();
177
178 assert_eq!(id1, 0);
179 assert_eq!(id2, 1);
180 }
181
182 #[test]
183 fn kill_entity() {
184 let mut ent_store = EntityStore::new();
185 let id1 = ent_store.new_id();
186 assert!(ent_store.is_alive(id1));
187 let id2 = ent_store.new_id();
188 assert!(ent_store.is_alive(id2));
189 ent_store.kill(id2);
190
191 assert!(ent_store.is_alive(id1));
192 assert!(!ent_store.is_alive(id2));
193 }
194}