1#![allow(dead_code)]
26
27use std::{any::{Any, TypeId}, collections::HashMap};
28
29pub trait Component: 'static + Send + Sync + Clone {}
36
37#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
46pub struct Entity {
47 pub index: u32,
49 pub generation: u32,
51}
52
53impl Entity {
54 #[inline] pub fn from_raw(index: u32, generation: u32) -> Self { Self { index, generation } }
56 #[inline] pub fn null() -> Self { Self { index: u32::MAX, generation: u32::MAX } }
58 #[inline] pub fn is_null(self) -> bool { self.index == u32::MAX }
60}
61
62impl std::fmt::Display for Entity {
63 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
64 write!(f, "Entity({}v{})", self.index, self.generation)
65 }
66}
67
68#[derive(Debug, Clone)]
73struct EntityRecord { generation: u32, location: Option<EntityLocation> }
74
75#[derive(Debug, Clone, Copy)]
76struct EntityLocation { archetype_id: ArchetypeId, row: usize }
77
78#[derive(Debug, Default)]
79struct EntityAllocator { records: Vec<EntityRecord>, free: Vec<u32> }
80
81impl EntityAllocator {
82 fn alloc(&mut self) -> Entity {
83 if let Some(idx) = self.free.pop() {
84 let gen = self.records[idx as usize].generation;
85 Entity { index: idx, generation: gen }
86 } else {
87 let idx = self.records.len() as u32;
88 self.records.push(EntityRecord { generation: 0, location: None });
89 Entity { index: idx, generation: 0 }
90 }
91 }
92 fn free(&mut self, e: Entity) {
93 let r = &mut self.records[e.index as usize];
94 r.generation = r.generation.wrapping_add(1);
95 r.location = None;
96 self.free.push(e.index);
97 }
98 fn is_alive(&self, e: Entity) -> bool {
99 self.records.get(e.index as usize)
100 .map(|r| r.generation == e.generation && r.location.is_some())
101 .unwrap_or(false)
102 }
103 fn location(&self, e: Entity) -> Option<EntityLocation> {
104 self.records.get(e.index as usize)
105 .filter(|r| r.generation == e.generation)
106 .and_then(|r| r.location)
107 }
108 fn set_location(&mut self, e: Entity, loc: EntityLocation) {
109 if let Some(r) = self.records.get_mut(e.index as usize) {
110 if r.generation == e.generation { r.location = Some(loc); }
111 }
112 }
113}
114
115struct AnyVec {
120 type_id: TypeId,
121 len: usize,
122 data: Vec<u8>,
123 element_size: usize,
124 drop_fn: unsafe fn(*mut u8),
125 clone_fn: unsafe fn(*const u8, *mut u8),
126}
127unsafe impl Send for AnyVec {}
128unsafe impl Sync for AnyVec {}
129
130impl AnyVec {
131 fn new<T: Component>() -> Self {
132 Self {
133 type_id: TypeId::of::<T>(),
134 len: 0,
135 data: Vec::new(),
136 element_size: std::mem::size_of::<T>(),
137 drop_fn: |p| unsafe { std::ptr::drop_in_place(p as *mut T) },
138 clone_fn: |s, d| unsafe { std::ptr::write(d as *mut T, (*(s as *const T)).clone()) },
139 }
140 }
141
142 fn reserve_one(&mut self) {
143 let sz = self.element_size;
144 if sz == 0 { return; }
145 let need = (self.len + 1) * sz;
146 if self.data.len() < need {
147 self.data.resize(need.max(self.data.len() * 2).max(sz * 4), 0);
148 }
149 }
150
151 fn push<T: Component>(&mut self, v: T) {
152 self.reserve_one();
153 unsafe { std::ptr::write(self.data.as_mut_ptr().add(self.len * self.element_size) as *mut T, v); }
154 self.len += 1;
155 }
156
157 fn get<T: Component>(&self, row: usize) -> &T {
158 unsafe { &*(self.data.as_ptr().add(row * self.element_size) as *const T) }
159 }
160
161 fn get_mut<T: Component>(&mut self, row: usize) -> &mut T {
162 unsafe { &mut *(self.data.as_mut_ptr().add(row * self.element_size) as *mut T) }
163 }
164
165 fn get_ptr(&self, row: usize) -> *const u8 {
166 unsafe { self.data.as_ptr().add(row * self.element_size) }
167 }
168
169 fn swap_remove_raw(&mut self, row: usize) {
170 let last = self.len - 1;
171 let sz = self.element_size;
172 unsafe {
173 let dst = self.data.as_mut_ptr().add(row * sz);
174 (self.drop_fn)(dst);
175 if row != last {
176 let src = self.data.as_ptr().add(last * sz);
177 std::ptr::copy_nonoverlapping(src, dst, sz);
178 }
179 }
180 self.len -= 1;
181 }
182}
183
184impl Drop for AnyVec {
185 fn drop(&mut self) {
186 for i in 0..self.len {
187 unsafe { (self.drop_fn)(self.data.as_mut_ptr().add(i * self.element_size)); }
188 }
189 }
190}
191
192struct ComponentStorage {
197 column: AnyVec,
198 added_ticks: Vec<u32>,
199 changed_ticks: Vec<u32>,
200}
201
202impl ComponentStorage {
203 fn new<T: Component>() -> Self {
204 Self { column: AnyVec::new::<T>(), added_ticks: Vec::new(), changed_ticks: Vec::new() }
205 }
206
207 fn push<T: Component>(&mut self, v: T, tick: u32) {
208 self.column.push(v);
209 self.added_ticks.push(tick);
210 self.changed_ticks.push(tick);
211 }
212
213 fn swap_remove(&mut self, row: usize) {
214 self.column.swap_remove_raw(row);
215 let last = self.added_ticks.len() - 1;
216 self.added_ticks.swap(row, last); self.added_ticks.pop();
217 let last = self.changed_ticks.len() - 1;
218 self.changed_ticks.swap(row, last); self.changed_ticks.pop();
219 }
220
221 fn clone_row_into(&self, row: usize, dst: &mut ComponentStorage, tick: u32) {
223 let sz = self.column.element_size;
224 let need = (dst.column.len + 1) * sz;
225 if dst.column.data.len() < need {
226 dst.column.data.resize(need.max(dst.column.data.len() * 2).max(sz * 4), 0);
227 }
228 unsafe {
229 let s = self.column.data.as_ptr().add(row * sz);
230 let d = dst.column.data.as_mut_ptr().add(dst.column.len * sz);
231 (self.column.clone_fn)(s, d);
232 }
233 dst.column.len += 1;
234 dst.added_ticks.push(self.added_ticks[row]);
235 dst.changed_ticks.push(tick);
236 }
237}
238
239#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
245pub struct ArchetypeId(pub u32);
246
247pub struct Archetype {
249 pub id: ArchetypeId,
251 pub component_types: Vec<TypeId>,
253 columns: HashMap<TypeId, ComponentStorage>,
254 pub entities: Vec<Entity>,
256}
257
258impl Archetype {
259 fn new(id: ArchetypeId, types: Vec<TypeId>) -> Self {
260 Self { id, component_types: types, columns: HashMap::new(), entities: Vec::new() }
261 }
262
263 fn register_column<T: Component>(&mut self) {
264 self.columns.entry(TypeId::of::<T>()).or_insert_with(ComponentStorage::new::<T>);
265 }
266
267 pub fn contains(&self, tid: TypeId) -> bool { self.columns.contains_key(&tid) }
269
270 pub fn len(&self) -> usize { self.entities.len() }
272
273 pub fn is_empty(&self) -> bool { self.entities.is_empty() }
275
276 fn swap_remove(&mut self, row: usize) -> Option<Entity> {
278 let last = self.entities.len() - 1;
279 for col in self.columns.values_mut() { col.swap_remove(row); }
280 self.entities.swap(row, last);
281 self.entities.pop();
282 if row < self.entities.len() { Some(self.entities[row]) } else { None }
283 }
284}
285
286pub trait Bundle: 'static + Send + Sync {
292 fn type_ids() -> Vec<TypeId>;
294 fn register_columns(arch: &mut Archetype);
296 fn insert_into(self, arch: &mut Archetype, tick: u32);
298}
299
300impl<C: Component> Bundle for C {
301 fn type_ids() -> Vec<TypeId> { vec![TypeId::of::<C>()] }
302 fn register_columns(a: &mut Archetype) { a.register_column::<C>(); }
303 fn insert_into(self, a: &mut Archetype, tick: u32) {
304 a.columns.get_mut(&TypeId::of::<C>()).expect("col missing").push(self, tick);
305 }
306}
307
308macro_rules! impl_bundle {
309 ($($C:ident),+) => {
310 #[allow(non_snake_case)]
311 impl<$($C: Component),+> Bundle for ($($C,)+) {
312 fn type_ids() -> Vec<TypeId> {
313 let mut v = vec![$(TypeId::of::<$C>()),+]; v.sort(); v.dedup(); v
314 }
315 fn register_columns(a: &mut Archetype) { $(a.register_column::<$C>();)+ }
316 fn insert_into(self, a: &mut Archetype, tick: u32) {
317 let ($($C,)+) = self;
318 $(a.columns.get_mut(&TypeId::of::<$C>()).expect("col missing").push($C, tick);)+
319 }
320 }
321 };
322}
323impl_bundle!(A, B);
324impl_bundle!(A, B, C);
325impl_bundle!(A, B, C, D);
326impl_bundle!(A, B, C, D, E);
327impl_bundle!(A, B, C, D, E, F);
328impl_bundle!(A, B, C, D, E, F, G);
329impl_bundle!(A, B, C, D, E, F, G, H);
330
331#[derive(Default)]
337pub struct Resources {
338 map: HashMap<TypeId, Box<dyn Any + Send + Sync>>,
339}
340
341impl Resources {
342 pub fn new() -> Self { Self::default() }
344 pub fn insert<T: 'static + Send + Sync>(&mut self, v: T) {
346 self.map.insert(TypeId::of::<T>(), Box::new(v));
347 }
348 pub fn get<T: 'static + Send + Sync>(&self) -> Option<&T> {
350 self.map.get(&TypeId::of::<T>())?.downcast_ref()
351 }
352 pub fn get_mut<T: 'static + Send + Sync>(&mut self) -> Option<&mut T> {
354 self.map.get_mut(&TypeId::of::<T>())?.downcast_mut()
355 }
356 pub fn remove<T: 'static + Send + Sync>(&mut self) -> Option<T> {
358 self.map.remove(&TypeId::of::<T>())
359 .and_then(|b| b.downcast::<T>().ok()).map(|b| *b)
360 }
361 pub fn contains<T: 'static + Send + Sync>(&self) -> bool {
363 self.map.contains_key(&TypeId::of::<T>())
364 }
365}
366
367pub struct Res<'a, T: 'static + Send + Sync> { inner: &'a T }
373impl<'a, T: 'static + Send + Sync> Res<'a, T> {
374 pub fn new(inner: &'a T) -> Self { Self { inner } }
376}
377impl<'a, T: 'static + Send + Sync> std::ops::Deref for Res<'a, T> {
378 type Target = T; fn deref(&self) -> &T { self.inner }
379}
380
381pub struct ResMut<'a, T: 'static + Send + Sync> { inner: &'a mut T }
383impl<'a, T: 'static + Send + Sync> ResMut<'a, T> {
384 pub fn new(inner: &'a mut T) -> Self { Self { inner } }
386}
387impl<'a, T: 'static + Send + Sync> std::ops::Deref for ResMut<'a, T> {
388 type Target = T; fn deref(&self) -> &T { self.inner }
389}
390impl<'a, T: 'static + Send + Sync> std::ops::DerefMut for ResMut<'a, T> {
391 fn deref_mut(&mut self) -> &mut T { self.inner }
392}
393
394pub struct Local<T: Default + 'static> { value: T }
400impl<T: Default + 'static> Local<T> {
401 pub fn new(value: T) -> Self { Self { value } }
403 pub fn default_value() -> Self { Self { value: T::default() } }
405}
406impl<T: Default + 'static> std::ops::Deref for Local<T> {
407 type Target = T; fn deref(&self) -> &T { &self.value }
408}
409impl<T: Default + 'static> std::ops::DerefMut for Local<T> {
410 fn deref_mut(&mut self) -> &mut T { &mut self.value }
411}
412
413pub struct Events<E: 'static + Send + Sync> {
419 buffers: [Vec<E>; 2],
420 current: usize,
421 event_count: usize,
422 start_event_count: usize,
423}
424
425impl<E: 'static + Send + Sync> Default for Events<E> {
426 fn default() -> Self {
427 Self { buffers: [Vec::new(), Vec::new()], current: 0, event_count: 0, start_event_count: 0 }
428 }
429}
430
431impl<E: 'static + Send + Sync> Events<E> {
432 pub fn new() -> Self { Self::default() }
434 pub fn send(&mut self, e: E) { self.buffers[self.current].push(e); self.event_count += 1; }
436 pub fn update(&mut self) {
438 let next = 1 - self.current;
439 self.buffers[next].clear();
440 self.start_event_count = self.event_count - self.buffers[self.current].len();
441 self.current = next;
442 }
443 pub fn get_reader(&self) -> EventCursor { EventCursor { last: self.event_count } }
445 pub fn get_reader_current(&self) -> EventCursor { EventCursor { last: self.start_event_count } }
447 pub fn read<'a>(&'a self, cursor: &mut EventCursor) -> impl Iterator<Item = &'a E> {
449 let start = cursor.last;
450 cursor.last = self.event_count;
451 let old = &self.buffers[1 - self.current];
452 let new = &self.buffers[self.current];
453 let base = self.start_event_count;
454 let sk0 = start.saturating_sub(base);
455 let tk0 = old.len().saturating_sub(sk0);
456 let sk1 = start.saturating_sub(base + old.len());
457 let tk1 = new.len().saturating_sub(sk1);
458 old.iter().skip(sk0).take(tk0).chain(new.iter().skip(sk1).take(tk1))
459 }
460 pub fn len(&self) -> usize { self.event_count }
462 pub fn is_empty(&self) -> bool { self.buffers[0].is_empty() && self.buffers[1].is_empty() }
464 pub fn clear(&mut self) { self.buffers[0].clear(); self.buffers[1].clear(); }
466}
467
468#[derive(Debug, Clone, Default)]
470pub struct EventCursor { last: usize }
471
472pub struct EventWriter<'a, E: 'static + Send + Sync> { events: &'a mut Events<E> }
474impl<'a, E: 'static + Send + Sync> EventWriter<'a, E> {
475 pub fn new(events: &'a mut Events<E>) -> Self { Self { events } }
477 pub fn send(&mut self, e: E) { self.events.send(e); }
479 pub fn send_batch(&mut self, it: impl IntoIterator<Item = E>) { for e in it { self.events.send(e); } }
481}
482
483pub struct EventReader<'a, E: 'static + Send + Sync> { events: &'a Events<E>, cursor: EventCursor }
485impl<'a, E: 'static + Send + Sync> EventReader<'a, E> {
486 pub fn new(events: &'a Events<E>) -> Self { Self { cursor: events.get_reader(), events } }
488 pub fn new_current(events: &'a Events<E>) -> Self { Self { cursor: events.get_reader_current(), events } }
490 pub fn read(&mut self) -> impl Iterator<Item = &E> { self.events.read(&mut self.cursor) }
492}
493
494enum Cmd {
499 Spawn(Box<dyn FnOnce(&mut World) + Send + Sync>),
500 Despawn(Entity),
501 Insert(Box<dyn FnOnce(&mut World) + Send + Sync>),
502 Remove(Entity, TypeId),
503 InsertRes(Box<dyn FnOnce(&mut World) + Send + Sync>),
504 RemoveRes(TypeId),
505}
506
507pub struct Commands { queue: Vec<Cmd> }
509impl Commands {
510 pub fn new() -> Self { Self { queue: Vec::new() } }
512 pub fn spawn<B: Bundle>(&mut self, b: B) {
514 self.queue.push(Cmd::Spawn(Box::new(move |w| { w.spawn(b); })));
515 }
516 pub fn despawn(&mut self, e: Entity) { self.queue.push(Cmd::Despawn(e)); }
518 pub fn insert<C: Component>(&mut self, e: Entity, c: C) {
520 self.queue.push(Cmd::Insert(Box::new(move |w| w.insert(e, c))));
521 }
522 pub fn remove<C: Component>(&mut self, e: Entity) {
524 self.queue.push(Cmd::Remove(e, TypeId::of::<C>()));
525 }
526 pub fn insert_resource<T: 'static + Send + Sync>(&mut self, v: T) {
528 self.queue.push(Cmd::InsertRes(Box::new(move |w| w.resources.insert(v))));
529 }
530 pub fn remove_resource<T: 'static + Send + Sync>(&mut self) {
532 self.queue.push(Cmd::RemoveRes(TypeId::of::<T>()));
533 }
534 pub fn apply(&mut self, world: &mut World) {
536 for cmd in self.queue.drain(..) {
537 match cmd {
538 Cmd::Spawn(f) => f(world),
539 Cmd::Despawn(e) => { world.despawn(e); }
540 Cmd::Insert(f) => f(world),
541 Cmd::Remove(e, tid) => world.remove_by_type_id(e, tid),
542 Cmd::InsertRes(f) => f(world),
543 Cmd::RemoveRes(tid) => { world.resources.map.remove(&tid); }
544 }
545 }
546 }
547 pub fn is_empty(&self) -> bool { self.queue.is_empty() }
549}
550impl Default for Commands { fn default() -> Self { Self::new() } }
551
552pub struct With<T: Component>(std::marker::PhantomData<T>);
558pub struct Without<T: Component>(std::marker::PhantomData<T>);
560pub struct Added<T: Component>(std::marker::PhantomData<T>);
562pub struct Changed<T: Component>(std::marker::PhantomData<T>);
564
565pub trait QueryFilter {
567 fn matches_archetype(arch: &Archetype) -> bool;
569}
570impl QueryFilter for () { fn matches_archetype(_: &Archetype) -> bool { true } }
571impl<T: Component> QueryFilter for With<T> {
572 fn matches_archetype(a: &Archetype) -> bool { a.contains(TypeId::of::<T>()) }
573}
574impl<T: Component> QueryFilter for Without<T> {
575 fn matches_archetype(a: &Archetype) -> bool { !a.contains(TypeId::of::<T>()) }
576}
577impl<A: QueryFilter, B: QueryFilter> QueryFilter for (A, B) {
578 fn matches_archetype(a: &Archetype) -> bool { A::matches_archetype(a) && B::matches_archetype(a) }
579}
580impl<A: QueryFilter, B: QueryFilter, C: QueryFilter> QueryFilter for (A, B, C) {
581 fn matches_archetype(a: &Archetype) -> bool {
582 A::matches_archetype(a) && B::matches_archetype(a) && C::matches_archetype(a)
583 }
584}
585
586pub struct Read<T: Component>(std::marker::PhantomData<T>);
592pub struct Write<T: Component>(std::marker::PhantomData<T>);
594pub struct OptionRead<T: Component>(std::marker::PhantomData<T>);
596
597pub trait WorldQuery: 'static {
599 type Item<'w>;
601 fn required_types() -> Vec<TypeId>;
603 fn matches(arch: &Archetype) -> bool;
605 unsafe fn fetch<'w>(arch: &'w Archetype, row: usize) -> Self::Item<'w>;
610}
611
612impl<T: Component> WorldQuery for Read<T> {
613 type Item<'w> = &'w T;
614 fn required_types() -> Vec<TypeId> { vec![TypeId::of::<T>()] }
615 fn matches(a: &Archetype) -> bool { a.contains(TypeId::of::<T>()) }
616 unsafe fn fetch<'w>(a: &'w Archetype, row: usize) -> &'w T {
617 a.columns[&TypeId::of::<T>()].column.get::<T>(row)
618 }
619}
620
621impl<T: Component> WorldQuery for Write<T> {
622 type Item<'w> = &'w mut T;
623 fn required_types() -> Vec<TypeId> { vec![TypeId::of::<T>()] }
624 fn matches(a: &Archetype) -> bool { a.contains(TypeId::of::<T>()) }
625 unsafe fn fetch<'w>(a: &'w Archetype, row: usize) -> &'w mut T {
626 let ptr = a.columns.get(&TypeId::of::<T>()).unwrap().column.get_ptr(row) as *mut T;
627 &mut *ptr
628 }
629}
630
631impl<T: Component> WorldQuery for OptionRead<T> {
632 type Item<'w> = Option<&'w T>;
633 fn required_types() -> Vec<TypeId> { vec![] }
634 fn matches(_: &Archetype) -> bool { true }
635 unsafe fn fetch<'w>(a: &'w Archetype, row: usize) -> Option<&'w T> {
636 a.columns.get(&TypeId::of::<T>()).map(|c| c.column.get::<T>(row))
637 }
638}
639
640impl WorldQuery for Entity {
641 type Item<'w> = Entity;
642 fn required_types() -> Vec<TypeId> { vec![] }
643 fn matches(_: &Archetype) -> bool { true }
644 unsafe fn fetch<'w>(a: &'w Archetype, row: usize) -> Entity { a.entities[row] }
645}
646
647macro_rules! impl_wq_tuple {
648 ($($Q:ident),+) => {
649 #[allow(non_snake_case)]
650 impl<$($Q: WorldQuery),+> WorldQuery for ($($Q,)+) {
651 type Item<'w> = ($($Q::Item<'w>,)+);
652 fn required_types() -> Vec<TypeId> {
653 let mut v = Vec::new(); $(v.extend($Q::required_types());)+ v.sort(); v.dedup(); v
654 }
655 fn matches(a: &Archetype) -> bool { $($Q::matches(a))&&+ }
656 unsafe fn fetch<'w>(a: &'w Archetype, row: usize) -> ($($Q::Item<'w>,)+) {
657 ($($Q::fetch(a, row),)+)
658 }
659 }
660 };
661}
662impl_wq_tuple!(A);
663impl_wq_tuple!(A, B);
664impl_wq_tuple!(A, B, C);
665impl_wq_tuple!(A, B, C, D);
666impl_wq_tuple!(A, B, C, D, E);
667impl_wq_tuple!(A, B, C, D, E, F);
668impl_wq_tuple!(A, B, C, D, E, F, G);
669impl_wq_tuple!(A, B, C, D, E, F, G, H);
670
671pub struct QueryIter<'w, Q: WorldQuery, F: QueryFilter> {
677 archetypes: &'w [Archetype],
678 arch_index: usize,
679 row: usize,
680 _q: std::marker::PhantomData<Q>,
681 _f: std::marker::PhantomData<F>,
682}
683impl<'w, Q: WorldQuery, F: QueryFilter> QueryIter<'w, Q, F> {
684 fn new(archetypes: &'w [Archetype]) -> Self {
685 Self { archetypes, arch_index: 0, row: 0, _q: std::marker::PhantomData, _f: std::marker::PhantomData }
686 }
687}
688impl<'w, Q: WorldQuery, F: QueryFilter> Iterator for QueryIter<'w, Q, F> {
689 type Item = Q::Item<'w>;
690 fn next(&mut self) -> Option<Self::Item> {
691 loop {
692 let arch = self.archetypes.get(self.arch_index)?;
693 if !Q::matches(arch) || !F::matches_archetype(arch) {
694 self.arch_index += 1; self.row = 0; continue;
695 }
696 if self.row >= arch.len() {
697 self.arch_index += 1; self.row = 0; continue;
698 }
699 let row = self.row; self.row += 1;
700 return Some(unsafe { Q::fetch(arch, row) });
701 }
702 }
703}
704
705pub struct EntityRef<'w> { arch: &'w Archetype, row: usize }
711impl<'w> EntityRef<'w> {
712 fn new(arch: &'w Archetype, row: usize) -> Self { Self { arch, row } }
713 pub fn entity(&self) -> Entity { self.arch.entities[self.row] }
715 pub fn get<T: Component>(&self) -> Option<&T> {
717 self.arch.columns.get(&TypeId::of::<T>()).map(|c| c.column.get::<T>(self.row))
718 }
719 pub fn has<T: Component>(&self) -> bool { self.arch.contains(TypeId::of::<T>()) }
721 pub fn component_types(&self) -> &[TypeId] { &self.arch.component_types }
723}
724
725pub struct EntityMut<'w> { arch: &'w mut Archetype, row: usize }
727impl<'w> EntityMut<'w> {
728 fn new(arch: &'w mut Archetype, row: usize) -> Self { Self { arch, row } }
729 pub fn entity(&self) -> Entity { self.arch.entities[self.row] }
731 pub fn get<T: Component>(&self) -> Option<&T> {
733 self.arch.columns.get(&TypeId::of::<T>()).map(|c| c.column.get::<T>(self.row))
734 }
735 pub fn get_mut<T: Component>(&mut self) -> Option<&mut T> {
737 self.arch.columns.get_mut(&TypeId::of::<T>()).map(|c| c.column.get_mut::<T>(self.row))
738 }
739 pub fn has<T: Component>(&self) -> bool { self.arch.contains(TypeId::of::<T>()) }
741}
742
743pub struct World {
749 archetypes: Vec<Archetype>,
750 archetype_index: HashMap<Vec<TypeId>, usize>,
751 entities: EntityAllocator,
752 pub resources: Resources,
754 events: HashMap<TypeId, Box<dyn Any + Send + Sync>>,
755 tick: u32,
756}
757
758impl World {
759 pub fn new() -> Self {
761 Self {
762 archetypes: Vec::new(),
763 archetype_index: HashMap::new(),
764 entities: EntityAllocator::default(),
765 resources: Resources::new(),
766 events: HashMap::new(),
767 tick: 0,
768 }
769 }
770
771 pub fn tick(&self) -> u32 { self.tick }
773 pub fn increment_tick(&mut self) { self.tick = self.tick.wrapping_add(1); }
775
776 fn get_or_create_archetype(&mut self, mut types: Vec<TypeId>) -> usize {
779 types.sort(); types.dedup();
780 if let Some(&i) = self.archetype_index.get(&types) { return i; }
781 let id = ArchetypeId(self.archetypes.len() as u32);
782 let arch = Archetype::new(id, types.clone());
783 let i = self.archetypes.len();
784 self.archetypes.push(arch);
785 self.archetype_index.insert(types, i);
786 i
787 }
788
789 pub fn spawn<B: Bundle>(&mut self, bundle: B) -> Entity {
793 let types = B::type_ids();
794 let ai = self.get_or_create_archetype(types);
795 let entity = self.entities.alloc();
796 let tick = self.tick;
797 let arch = &mut self.archetypes[ai];
798 B::register_columns(arch);
799 let row = arch.entities.len();
800 arch.entities.push(entity);
801 bundle.insert_into(arch, tick);
802 self.entities.set_location(entity, EntityLocation { archetype_id: ArchetypeId(ai as u32), row });
803 entity
804 }
805
806 pub fn despawn(&mut self, entity: Entity) -> bool {
808 let loc = match self.entities.location(entity) { Some(l) => l, None => return false };
809 let ai = loc.archetype_id.0 as usize;
810 let swapped = self.archetypes[ai].swap_remove(loc.row);
811 self.entities.free(entity);
812 if let Some(se) = swapped {
813 self.entities.set_location(se, EntityLocation { archetype_id: loc.archetype_id, row: loc.row });
814 }
815 true
816 }
817
818 pub fn is_alive(&self, entity: Entity) -> bool { self.entities.is_alive(entity) }
820
821 pub fn insert<C: Component>(&mut self, entity: Entity, component: C) {
825 let loc = match self.entities.location(entity) { Some(l) => l, None => return };
826 let ai = loc.archetype_id.0 as usize;
827 if self.archetypes[ai].contains(TypeId::of::<C>()) {
829 let tick = self.tick;
830 let col = self.archetypes[ai].columns.get_mut(&TypeId::of::<C>()).unwrap();
831 *col.column.get_mut::<C>(loc.row) = component;
832 col.changed_ticks[loc.row] = tick;
833 return;
834 }
835 let mut new_types = self.archetypes[ai].component_types.clone();
837 new_types.push(TypeId::of::<C>());
838 let new_ai = self.get_or_create_archetype(new_types);
839 let tick = self.tick;
840 self.migrate_add::<C>(entity, loc, new_ai, component, tick);
841 }
842
843 fn migrate_add<C: Component>(
844 &mut self, entity: Entity, loc: EntityLocation, new_ai: usize, extra: C, tick: u32,
845 ) {
846 let old_ai = loc.archetype_id.0 as usize;
847 let row = loc.row;
848 let old_types: Vec<TypeId> = self.archetypes[old_ai].component_types.clone();
849 self.ensure_cols(old_ai, new_ai, &old_types);
851 if !self.archetypes[new_ai].columns.contains_key(&TypeId::of::<C>()) {
852 self.archetypes[new_ai].register_column::<C>();
853 }
854 let new_row = self.archetypes[new_ai].entities.len();
855 for &tid in &old_types {
856 Self::copy_row(&mut self.archetypes, old_ai, new_ai, tid, row, tick);
857 }
858 self.archetypes[new_ai].columns.get_mut(&TypeId::of::<C>()).unwrap().push(extra, tick);
859 self.archetypes[new_ai].entities.push(entity);
860 let swapped = self.archetypes[old_ai].swap_remove(row);
861 self.entities.set_location(entity, EntityLocation { archetype_id: ArchetypeId(new_ai as u32), row: new_row });
862 if let Some(se) = swapped {
863 self.entities.set_location(se, EntityLocation { archetype_id: loc.archetype_id, row });
864 }
865 }
866
867 fn ensure_cols(&mut self, src: usize, dst: usize, types: &[TypeId]) {
868 for &tid in types {
869 if self.archetypes[dst].columns.contains_key(&tid) { continue; }
870 let s = &self.archetypes[src].columns[&tid];
871 let nc = ComponentStorage {
872 column: AnyVec {
873 type_id: s.column.type_id, len: 0, data: Vec::new(),
874 element_size: s.column.element_size,
875 drop_fn: s.column.drop_fn, clone_fn: s.column.clone_fn,
876 },
877 added_ticks: Vec::new(), changed_ticks: Vec::new(),
878 };
879 self.archetypes[dst].columns.insert(tid, nc);
880 }
881 }
882
883 fn copy_row(archetypes: &mut Vec<Archetype>, src: usize, dst: usize, tid: TypeId, row: usize, tick: u32) {
884 let (sa, da) = if src < dst {
885 let (l, r) = archetypes.split_at_mut(dst); (&l[src], &mut r[0])
886 } else {
887 let (l, r) = archetypes.split_at_mut(src); (&r[0], &mut l[dst])
888 };
889 if let (Some(sc), Some(dc)) = (sa.columns.get(&tid), da.columns.get_mut(&tid)) {
890 sc.clone_row_into(row, dc, tick);
891 }
892 }
893
894 pub fn remove<C: Component>(&mut self, entity: Entity) {
896 self.remove_by_type_id(entity, TypeId::of::<C>());
897 }
898
899 pub(crate) fn remove_by_type_id(&mut self, entity: Entity, tid: TypeId) {
901 let loc = match self.entities.location(entity) { Some(l) => l, None => return };
902 let old_ai = loc.archetype_id.0 as usize;
903 if !self.archetypes[old_ai].contains(tid) { return; }
904 let row = loc.row;
905 let new_types: Vec<TypeId> = self.archetypes[old_ai].component_types.iter()
906 .copied().filter(|&t| t != tid).collect();
907 let new_ai = self.get_or_create_archetype(new_types.clone());
908 let tick = self.tick;
909 let old_types: Vec<TypeId> = self.archetypes[old_ai].component_types.clone();
910 self.ensure_cols(old_ai, new_ai, &old_types);
911 let new_row = self.archetypes[new_ai].entities.len();
912 for &t in &old_types {
913 if t == tid { continue; }
914 Self::copy_row(&mut self.archetypes, old_ai, new_ai, t, row, tick);
915 }
916 self.archetypes[new_ai].entities.push(entity);
917 let swapped = self.archetypes[old_ai].swap_remove(row);
918 self.entities.set_location(entity, EntityLocation { archetype_id: ArchetypeId(new_ai as u32), row: new_row });
919 if let Some(se) = swapped {
920 self.entities.set_location(se, EntityLocation { archetype_id: loc.archetype_id, row });
921 }
922 }
923
924 pub fn get<C: Component>(&self, entity: Entity) -> Option<&C> {
928 let loc = self.entities.location(entity)?;
929 self.archetypes[loc.archetype_id.0 as usize]
930 .columns.get(&TypeId::of::<C>()).map(|c| c.column.get::<C>(loc.row))
931 }
932
933 pub fn get_mut<C: Component>(&mut self, entity: Entity) -> Option<&mut C> {
935 let loc = self.entities.location(entity)?;
936 let tick = self.tick;
937 let arch = &mut self.archetypes[loc.archetype_id.0 as usize];
938 arch.columns.get_mut(&TypeId::of::<C>()).map(|c| {
939 c.changed_ticks[loc.row] = tick;
940 c.column.get_mut::<C>(loc.row)
941 })
942 }
943
944 pub fn entity_ref(&self, entity: Entity) -> Option<EntityRef<'_>> {
946 let loc = self.entities.location(entity)?;
947 Some(EntityRef::new(&self.archetypes[loc.archetype_id.0 as usize], loc.row))
948 }
949
950 pub fn entity_mut(&mut self, entity: Entity) -> Option<EntityMut<'_>> {
952 let loc = self.entities.location(entity)?;
953 let ai = loc.archetype_id.0 as usize;
954 Some(EntityMut::new(&mut self.archetypes[ai], loc.row))
955 }
956
957 pub fn query<Q: WorldQuery, F: QueryFilter>(&self) -> QueryIter<'_, Q, F> {
961 QueryIter::new(&self.archetypes)
962 }
963
964 pub fn query_all<Q: WorldQuery>(&self) -> QueryIter<'_, Q, ()> {
966 QueryIter::new(&self.archetypes)
967 }
968
969 pub fn query_single<Q: WorldQuery>(&self) -> Option<Q::Item<'_>> {
971 let mut it = self.query::<Q, ()>();
972 let first = it.next()?;
973 if it.next().is_some() { return None; }
974 Some(first)
975 }
976
977 pub fn insert_resource<T: 'static + Send + Sync>(&mut self, v: T) { self.resources.insert(v); }
981 pub fn resource<T: 'static + Send + Sync>(&self) -> Option<Res<'_, T>> {
983 self.resources.get::<T>().map(Res::new)
984 }
985 pub fn resource_mut<T: 'static + Send + Sync>(&mut self) -> Option<ResMut<'_, T>> {
987 self.resources.get_mut::<T>().map(ResMut::new)
988 }
989 pub fn remove_resource<T: 'static + Send + Sync>(&mut self) -> Option<T> { self.resources.remove::<T>() }
991
992 pub fn add_event<E: 'static + Send + Sync>(&mut self) {
996 self.events.entry(TypeId::of::<Events<E>>())
997 .or_insert_with(|| Box::new(Events::<E>::new()));
998 }
999 pub fn events<E: 'static + Send + Sync>(&self) -> Option<&Events<E>> {
1001 self.events.get(&TypeId::of::<Events<E>>())?.downcast_ref()
1002 }
1003 pub fn events_mut<E: 'static + Send + Sync>(&mut self) -> Option<&mut Events<E>> {
1005 self.events.get_mut(&TypeId::of::<Events<E>>())?.downcast_mut()
1006 }
1007 pub fn send_event<E: 'static + Send + Sync>(&mut self, event: E) {
1009 self.events.entry(TypeId::of::<Events<E>>())
1010 .or_insert_with(|| Box::new(Events::<E>::new()))
1011 .downcast_mut::<Events<E>>().unwrap().send(event);
1012 }
1013
1014 pub fn entities(&self) -> impl Iterator<Item = Entity> + '_ {
1018 self.archetypes.iter().flat_map(|a| a.entities.iter().copied())
1019 }
1020 pub fn entity_count(&self) -> usize { self.archetypes.iter().map(|a| a.len()).sum() }
1022 pub fn archetype_count(&self) -> usize { self.archetypes.len() }
1024}
1025
1026impl Default for World { fn default() -> Self { Self::new() } }
1027
1028pub trait SystemParam: Sized {
1034 type State: Default + Send + Sync + 'static;
1036 fn init_state(world: &mut World) -> Self::State;
1038}
1039
1040pub trait System: Send + Sync + 'static {
1046 fn run(&mut self, world: &mut World);
1048 fn name(&self) -> &str;
1050}
1051
1052pub struct FunctionSystem<F: FnMut(&mut World) + Send + Sync + 'static> { f: F, name: String }
1054impl<F: FnMut(&mut World) + Send + Sync + 'static> FunctionSystem<F> {
1055 pub fn new(name: impl Into<String>, f: F) -> Self { Self { f, name: name.into() } }
1057}
1058impl<F: FnMut(&mut World) + Send + Sync + 'static> System for FunctionSystem<F> {
1059 fn run(&mut self, w: &mut World) { (self.f)(w); }
1060 fn name(&self) -> &str { &self.name }
1061}
1062
1063pub fn into_system(name: impl Into<String>, f: impl FnMut(&mut World) + Send + Sync + 'static) -> Box<dyn System> {
1065 Box::new(FunctionSystem::new(name, f))
1066}
1067
1068#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1074pub struct SystemLabel(pub String);
1075impl SystemLabel {
1076 pub fn new(s: impl Into<String>) -> Self { Self(s.into()) }
1078}
1079impl<S: Into<String>> From<S> for SystemLabel { fn from(s: S) -> Self { Self(s.into()) } }
1080
1081pub type RunCondition = Box<dyn Fn(&World) -> bool + Send + Sync>;
1083
1084struct SystemEntry { system: Box<dyn System>, label: Option<SystemLabel>, run_if: Option<RunCondition> }
1085
1086pub struct Schedule { systems: Vec<SystemEntry> }
1088impl Schedule {
1089 pub fn new() -> Self { Self { systems: Vec::new() } }
1091 pub fn add_system(&mut self, s: Box<dyn System>) -> &mut Self {
1093 self.systems.push(SystemEntry { system: s, label: None, run_if: None }); self
1094 }
1095 pub fn add_system_with_label(&mut self, s: Box<dyn System>, label: impl Into<SystemLabel>) -> &mut Self {
1097 self.systems.push(SystemEntry { system: s, label: Some(label.into()), run_if: None }); self
1098 }
1099 pub fn add_system_with_condition(
1101 &mut self, s: Box<dyn System>,
1102 cond: impl Fn(&World) -> bool + Send + Sync + 'static,
1103 ) -> &mut Self {
1104 self.systems.push(SystemEntry { system: s, label: None, run_if: Some(Box::new(cond)) }); self
1105 }
1106 pub fn add_system_full(
1108 &mut self, s: Box<dyn System>, label: impl Into<SystemLabel>,
1109 cond: impl Fn(&World) -> bool + Send + Sync + 'static,
1110 ) -> &mut Self {
1111 self.systems.push(SystemEntry { system: s, label: Some(label.into()), run_if: Some(Box::new(cond)) }); self
1112 }
1113 pub fn remove_system(&mut self, label: &SystemLabel) {
1115 self.systems.retain(|e| e.label.as_ref() != Some(label));
1116 }
1117 pub fn system_count(&self) -> usize { self.systems.len() }
1119 pub fn run(&mut self, world: &mut World) {
1121 world.increment_tick();
1122 for e in &mut self.systems {
1123 if e.run_if.as_ref().map(|c| c(world)).unwrap_or(true) { e.system.run(world); }
1124 }
1125 }
1126 pub fn labels(&self) -> Vec<Option<&SystemLabel>> { self.systems.iter().map(|e| e.label.as_ref()).collect() }
1128}
1129impl Default for Schedule { fn default() -> Self { Self::new() } }
1130
1131pub fn was_added<C: Component>(w: &World, entity: Entity, since: u32) -> bool {
1137 let loc = match w.entities.location(entity) { Some(l) => l, None => return false };
1138 w.archetypes[loc.archetype_id.0 as usize].columns
1139 .get(&TypeId::of::<C>()).map(|c| c.added_ticks[loc.row] > since).unwrap_or(false)
1140}
1141
1142pub fn was_changed<C: Component>(w: &World, entity: Entity, since: u32) -> bool {
1144 let loc = match w.entities.location(entity) { Some(l) => l, None => return false };
1145 w.archetypes[loc.archetype_id.0 as usize].columns
1146 .get(&TypeId::of::<C>()).map(|c| c.changed_ticks[loc.row] > since).unwrap_or(false)
1147}
1148
1149pub fn query_added<C: Component>(w: &World, since: u32) -> impl Iterator<Item = Entity> + '_ {
1151 w.archetypes.iter().flat_map(move |arch| {
1152 if !arch.contains(TypeId::of::<C>()) { return vec![]; }
1153 let col = &arch.columns[&TypeId::of::<C>()];
1154 arch.entities.iter().enumerate()
1155 .filter(move |(r, _)| col.added_ticks[*r] > since)
1156 .map(|(_, &e)| e).collect::<Vec<_>>()
1157 })
1158}
1159
1160pub fn query_changed<C: Component>(w: &World, since: u32) -> impl Iterator<Item = Entity> + '_ {
1162 w.archetypes.iter().flat_map(move |arch| {
1163 if !arch.contains(TypeId::of::<C>()) { return vec![]; }
1164 let col = &arch.columns[&TypeId::of::<C>()];
1165 arch.entities.iter().enumerate()
1166 .filter(move |(r, _)| col.changed_ticks[*r] > since)
1167 .map(|(_, &e)| e).collect::<Vec<_>>()
1168 })
1169}
1170
1171pub mod prelude {
1177 pub use super::{
1178 Component, Entity, World, Bundle,
1179 Archetype, ArchetypeId, EntityRef, EntityMut,
1180 Resources, Res, ResMut, Local,
1181 Events, EventCursor, EventWriter, EventReader,
1182 Commands, With, Without, Added, Changed,
1183 Read, Write, OptionRead,
1184 WorldQuery, QueryFilter, QueryIter,
1185 System, SystemParam, FunctionSystem, into_system,
1186 Schedule, SystemLabel,
1187 was_added, was_changed, query_added, query_changed,
1188 };
1189}
1190
1191#[cfg(test)]
1196mod tests {
1197 use super::*;
1198
1199 #[derive(Debug, Clone, PartialEq)] struct Position { x: f32, y: f32 }
1200 impl Component for Position {}
1201
1202 #[derive(Debug, Clone, PartialEq)] struct Velocity { dx: f32, dy: f32 }
1203 impl Component for Velocity {}
1204
1205 #[derive(Debug, Clone, PartialEq)] struct Health(f32);
1206 impl Component for Health {}
1207
1208 #[derive(Debug, Clone)] struct Tag; impl Component for Tag {}
1209 #[derive(Debug, Clone)] struct Enemy; impl Component for Enemy {}
1210 #[derive(Debug, Clone)] struct Player; impl Component for Player {}
1211
1212 #[test] fn test_spawn_alive() {
1214 let mut w = World::new();
1215 let e = w.spawn(Position { x: 1.0, y: 2.0 });
1216 assert!(w.is_alive(e)); assert_eq!(w.entity_count(), 1);
1217 }
1218 #[test] fn test_despawn() {
1219 let mut w = World::new();
1220 let e = w.spawn(Position { x: 0.0, y: 0.0 });
1221 assert!(w.despawn(e)); assert!(!w.is_alive(e)); assert_eq!(w.entity_count(), 0);
1222 }
1223 #[test] fn test_despawn_nonexistent() {
1224 let mut w = World::new(); assert!(!w.despawn(Entity::from_raw(99, 99)));
1225 }
1226 #[test] fn test_null_entity() {
1227 assert!(Entity::null().is_null()); assert!(!Entity::from_raw(0,0).is_null());
1228 }
1229 #[test] fn test_generation_reuse() {
1230 let mut w = World::new();
1231 let e1 = w.spawn(Position { x: 0.0, y: 0.0 }); w.despawn(e1);
1232 let e2 = w.spawn(Position { x: 1.0, y: 0.0 });
1233 assert_eq!(e1.index, e2.index); assert_ne!(e1.generation, e2.generation);
1234 assert!(!w.is_alive(e1)); assert!(w.is_alive(e2));
1235 }
1236 #[test] fn test_entity_display() { assert_eq!(format!("{}", Entity::from_raw(5,2)), "Entity(5v2)"); }
1237
1238 #[test] fn test_get_component() {
1240 let mut w = World::new(); let e = w.spawn(Position { x: 3.0, y: 4.0 });
1241 assert_eq!(w.get::<Position>(e).unwrap().x, 3.0);
1242 }
1243 #[test] fn test_get_mut_component() {
1244 let mut w = World::new(); let e = w.spawn(Position { x: 0.0, y: 0.0 });
1245 w.get_mut::<Position>(e).unwrap().x = 10.0;
1246 assert_eq!(w.get::<Position>(e).unwrap().x, 10.0);
1247 }
1248 #[test] fn test_missing_component_none() {
1249 let mut w = World::new(); let e = w.spawn(Position { x: 0.0, y: 0.0 });
1250 assert!(w.get::<Velocity>(e).is_none());
1251 }
1252 #[test] fn test_entity_ref() {
1253 let mut w = World::new(); let e = w.spawn((Position { x: 1.0, y: 2.0 }, Health(100.0)));
1254 let er = w.entity_ref(e).unwrap();
1255 assert_eq!(er.get::<Position>().unwrap(), &Position { x: 1.0, y: 2.0 });
1256 assert!(er.has::<Position>()); assert!(!er.has::<Velocity>());
1257 }
1258 #[test] fn test_entity_mut() {
1259 let mut w = World::new(); let e = w.spawn(Health(50.0));
1260 w.entity_mut(e).unwrap().get_mut::<Health>().unwrap().0 = 75.0;
1261 assert_eq!(w.get::<Health>(e).unwrap().0, 75.0);
1262 }
1263
1264 #[test] fn test_spawn_tuple_bundle() {
1266 let mut w = World::new();
1267 let e = w.spawn((Position { x: 1.0, y: 0.0 }, Velocity { dx: 0.5, dy: 0.0 }, Health(100.0)));
1268 assert!(w.get::<Position>(e).is_some()); assert!(w.get::<Velocity>(e).is_some()); assert!(w.get::<Health>(e).is_some());
1269 }
1270 #[test] fn test_same_archetype() {
1271 let mut w = World::new();
1272 let e1 = w.spawn((Position { x: 0.0, y: 0.0 }, Velocity { dx: 1.0, dy: 0.0 }));
1273 let e2 = w.spawn((Position { x: 5.0, y: 5.0 }, Velocity { dx: -1.0, dy: 0.0 }));
1274 assert_eq!(w.archetype_count(), 1);
1275 assert_eq!(w.get::<Position>(e1).unwrap().x, 0.0);
1276 assert_eq!(w.get::<Position>(e2).unwrap().x, 5.0);
1277 }
1278
1279 #[test] fn test_insert_new_component() {
1281 let mut w = World::new(); let e = w.spawn(Position { x: 0.0, y: 0.0 });
1282 w.insert(e, Velocity { dx: 1.0, dy: 0.0 });
1283 assert!(w.get::<Velocity>(e).is_some()); assert!(w.get::<Position>(e).is_some());
1284 }
1285 #[test] fn test_insert_replaces() {
1286 let mut w = World::new(); let e = w.spawn(Health(100.0));
1287 w.insert(e, Health(50.0)); assert_eq!(w.get::<Health>(e).unwrap().0, 50.0);
1288 }
1289 #[test] fn test_remove_component() {
1290 let mut w = World::new();
1291 let e = w.spawn((Position { x: 0.0, y: 0.0 }, Velocity { dx: 1.0, dy: 0.0 }));
1292 w.remove::<Velocity>(e);
1293 assert!(w.get::<Velocity>(e).is_none()); assert!(w.get::<Position>(e).is_some());
1294 }
1295 #[test] fn test_remove_missing_noop() {
1296 let mut w = World::new(); let e = w.spawn(Position { x: 0.0, y: 0.0 });
1297 w.remove::<Velocity>(e); assert!(w.is_alive(e));
1298 }
1299 #[test] fn test_insert_remove_roundtrip() {
1300 let mut w = World::new(); let e = w.spawn(Position { x: 1.0, y: 2.0 });
1301 w.insert(e, Health(99.0)); assert_eq!(w.get::<Health>(e).unwrap().0, 99.0);
1302 w.remove::<Health>(e); assert!(w.get::<Health>(e).is_none());
1303 assert_eq!(w.get::<Position>(e).unwrap().x, 1.0);
1304 }
1305
1306 #[test] fn test_query_single_component() {
1308 let mut w = World::new();
1309 w.spawn(Position { x: 1.0, y: 0.0 }); w.spawn(Position { x: 2.0, y: 0.0 }); w.spawn(Position { x: 3.0, y: 0.0 });
1310 assert_eq!(w.query::<Read<Position>, ()>().count(), 3);
1311 }
1312 #[test] fn test_query_tuple() {
1313 let mut w = World::new();
1314 w.spawn((Position { x: 0.0, y: 0.0 }, Velocity { dx: 1.0, dy: 0.0 }));
1315 w.spawn(Position { x: 5.0, y: 0.0 });
1316 assert_eq!(w.query::<(Read<Position>, Read<Velocity>), ()>().count(), 1);
1317 }
1318 #[test] fn test_query_with_filter() {
1319 let mut w = World::new();
1320 w.spawn((Position { x: 0.0, y: 0.0 }, Tag)); w.spawn(Position { x: 1.0, y: 0.0 });
1321 assert_eq!(w.query::<Read<Position>, With<Tag>>().count(), 1);
1322 }
1323 #[test] fn test_query_without_filter() {
1324 let mut w = World::new();
1325 w.spawn((Position { x: 0.0, y: 0.0 }, Enemy));
1326 w.spawn((Position { x: 1.0, y: 0.0 }, Player));
1327 w.spawn(Position { x: 2.0, y: 0.0 });
1328 assert_eq!(w.query::<Read<Position>, Without<Enemy>>().count(), 2);
1329 }
1330 #[test] fn test_query_option_read() {
1331 let mut w = World::new();
1332 w.spawn((Position { x: 0.0, y: 0.0 }, Health(100.0))); w.spawn(Position { x: 1.0, y: 0.0 });
1333 let r: Vec<_> = w.query::<(Read<Position>, OptionRead<Health>), ()>().collect();
1334 assert_eq!(r.len(), 2); assert_eq!(r.iter().filter(|(_, h)| h.is_some()).count(), 1);
1335 }
1336 #[test] fn test_query_entity() {
1337 let mut w = World::new();
1338 let e1 = w.spawn(Position { x: 0.0, y: 0.0 }); let e2 = w.spawn(Position { x: 1.0, y: 0.0 });
1339 let es: Vec<Entity> = w.query::<Entity, ()>().collect();
1340 assert!(es.contains(&e1)); assert!(es.contains(&e2));
1341 }
1342 #[test] fn test_query_mutable() {
1343 let mut w = World::new();
1344 w.spawn(Position { x: 0.0, y: 0.0 }); w.spawn(Position { x: 1.0, y: 0.0 });
1345 for p in w.query::<Write<Position>, ()>() { p.x += 10.0; }
1346 assert!(w.query::<Read<Position>, ()>().all(|p| p.x >= 10.0));
1347 }
1348 #[test] fn test_query_single() {
1349 let mut w = World::new(); w.spawn(Player);
1350 assert!(w.query_single::<Read<Player>>().is_some());
1351 }
1352 #[test] fn test_query_single_none_multiple() {
1353 let mut w = World::new(); w.spawn(Player); w.spawn(Player);
1354 assert!(w.query_single::<Read<Player>>().is_none());
1355 }
1356
1357 #[test] fn test_resource_insert_get() {
1359 let mut w = World::new(); w.insert_resource(42u32);
1360 assert_eq!(*w.resource::<u32>().unwrap(), 42);
1361 }
1362 #[test] fn test_resource_mut() {
1363 let mut w = World::new(); w.insert_resource(0u32);
1364 *w.resource_mut::<u32>().unwrap() = 99;
1365 assert_eq!(*w.resource::<u32>().unwrap(), 99);
1366 }
1367 #[test] fn test_resource_remove() {
1368 let mut w = World::new(); w.insert_resource(42u32);
1369 assert_eq!(w.remove_resource::<u32>(), Some(42));
1370 assert!(w.resource::<u32>().is_none());
1371 }
1372 #[test] fn test_resources_standalone() {
1373 let mut r = Resources::new(); r.insert(42u32);
1374 assert!(r.contains::<u32>()); assert!(!r.contains::<i32>());
1375 r.remove::<u32>(); assert!(!r.contains::<u32>());
1376 }
1377
1378 #[test] fn test_commands_spawn() {
1380 let mut w = World::new(); let mut c = Commands::new();
1381 c.spawn(Position { x: 7.0, y: 8.0 }); c.apply(&mut w);
1382 assert_eq!(w.query_single::<Read<Position>>().unwrap().x, 7.0);
1383 }
1384 #[test] fn test_commands_despawn() {
1385 let mut w = World::new(); let e = w.spawn(Position { x: 0.0, y: 0.0 });
1386 let mut c = Commands::new(); c.despawn(e); c.apply(&mut w); assert!(!w.is_alive(e));
1387 }
1388 #[test] fn test_commands_insert() {
1389 let mut w = World::new(); let e = w.spawn(Position { x: 0.0, y: 0.0 });
1390 let mut c = Commands::new(); c.insert(e, Health(50.0)); c.apply(&mut w);
1391 assert_eq!(w.get::<Health>(e).unwrap().0, 50.0);
1392 }
1393 #[test] fn test_commands_remove() {
1394 let mut w = World::new(); let e = w.spawn((Position { x: 0.0, y: 0.0 }, Health(100.0)));
1395 let mut c = Commands::new(); c.remove::<Health>(e); c.apply(&mut w);
1396 assert!(w.get::<Health>(e).is_none());
1397 }
1398 #[test] fn test_commands_insert_resource() {
1399 let mut w = World::new(); let mut c = Commands::new();
1400 c.insert_resource(100i32); c.apply(&mut w);
1401 assert_eq!(*w.resource::<i32>().unwrap(), 100);
1402 }
1403
1404 #[derive(Debug, Clone, PartialEq)] struct Dmg { amount: f32 }
1406 #[test] fn test_events_send_read() {
1407 let mut ev: Events<Dmg> = Events::new(); let mut cur = ev.get_reader_current();
1408 ev.send(Dmg { amount: 10.0 }); ev.send(Dmg { amount: 20.0 });
1409 let r: Vec<_> = ev.read(&mut cur).collect();
1410 assert_eq!(r.len(), 2); assert_eq!(r[0].amount, 10.0);
1411 }
1412 #[test] fn test_events_update_clears() {
1413 let mut ev: Events<Dmg> = Events::new(); ev.send(Dmg { amount: 5.0 });
1414 ev.update(); ev.update(); assert!(ev.is_empty());
1415 }
1416 #[test] fn test_event_writer_reader() {
1417 let mut ev: Events<Dmg> = Events::new();
1418 EventWriter::new(&mut ev).send(Dmg { amount: 42.0 });
1419 let r: Vec<_> = EventReader::new_current(&ev).read().collect();
1420 assert_eq!(r.len(), 1); assert_eq!(r[0].amount, 42.0);
1421 }
1422 #[test] fn test_world_events() {
1423 let mut w = World::new(); w.add_event::<Dmg>();
1424 w.send_event(Dmg { amount: 99.0 }); assert!(!w.events::<Dmg>().unwrap().is_empty());
1425 }
1426
1427 #[test] fn test_schedule_runs_systems() {
1429 let mut w = World::new(); w.insert_resource(0u32);
1430 let mut s = Schedule::new();
1431 s.add_system(into_system("inc", |w| { *w.resource_mut::<u32>().unwrap() += 1; }));
1432 s.run(&mut w); s.run(&mut w); assert_eq!(*w.resource::<u32>().unwrap(), 2);
1433 }
1434 #[test] fn test_schedule_run_condition() {
1435 let mut w = World::new(); w.insert_resource(0u32); w.insert_resource(false);
1436 let mut s = Schedule::new();
1437 s.add_system_with_condition(
1438 into_system("g", |w| { *w.resource_mut::<u32>().unwrap() += 1; }),
1439 |w| *w.resource::<bool>().unwrap(),
1440 );
1441 s.run(&mut w); assert_eq!(*w.resource::<u32>().unwrap(), 0);
1442 *w.resource_mut::<bool>().unwrap() = true;
1443 s.run(&mut w); assert_eq!(*w.resource::<u32>().unwrap(), 1);
1444 }
1445 #[test] fn test_schedule_remove_label() {
1446 let mut s = Schedule::new();
1447 s.add_system_with_label(into_system("n", |_|{}), "lbl");
1448 assert_eq!(s.system_count(), 1);
1449 s.remove_system(&SystemLabel::new("lbl"));
1450 assert_eq!(s.system_count(), 0);
1451 }
1452 #[test] fn test_schedule_tick_increment() {
1453 let mut w = World::new(); let mut s = Schedule::new();
1454 s.run(&mut w); assert_eq!(w.tick(), 1); s.run(&mut w); assert_eq!(w.tick(), 2);
1455 }
1456
1457 #[test] fn test_was_added() {
1459 let mut w = World::new(); w.increment_tick();
1460 let e = w.spawn(Health(100.0));
1461 assert!(was_added::<Health>(&w, e, 0)); assert!(!was_added::<Health>(&w, e, 1));
1462 }
1463 #[test] fn test_was_changed() {
1464 let mut w = World::new(); w.increment_tick();
1465 let e = w.spawn(Health(100.0)); w.increment_tick();
1466 w.get_mut::<Health>(e).unwrap().0 = 50.0;
1467 assert!(was_changed::<Health>(&w, e, 1)); assert!(!was_changed::<Health>(&w, e, 2));
1468 }
1469 #[test] fn test_query_added() {
1470 let mut w = World::new(); w.increment_tick();
1471 let e1 = w.spawn(Health(100.0)); w.increment_tick(); let _e2 = w.spawn(Health(50.0));
1472 let added: Vec<_> = query_added::<Health>(&w, 1).collect();
1473 assert_eq!(added.len(), 1); assert!(!added.contains(&e1));
1474 }
1475
1476 #[test] fn test_local() {
1478 let mut l: Local<u32> = Local::default_value();
1479 assert_eq!(*l, 0); *l += 5; assert_eq!(*l, 5);
1480 }
1481
1482 #[test] fn test_swap_remove_updates_location() {
1484 let mut w = World::new();
1485 let e1 = w.spawn(Position { x: 1.0, y: 0.0 });
1486 let _e2 = w.spawn(Position { x: 2.0, y: 0.0 });
1487 let e3 = w.spawn(Position { x: 3.0, y: 0.0 });
1488 w.despawn(e1);
1489 assert!(w.is_alive(e3)); assert_eq!(w.get::<Position>(e3).unwrap().x, 3.0);
1490 }
1491 #[test] fn test_spawn_many() {
1492 let mut w = World::new();
1493 for i in 0..1000u32 { w.spawn(Position { x: i as f32, y: 0.0 }); }
1494 assert_eq!(w.entity_count(), 1000);
1495 assert_eq!(w.query::<Read<Position>, ()>().count(), 1000);
1496 }
1497 #[test] fn test_world_default() { let w = World::default(); assert_eq!(w.entity_count(), 0); }
1498 #[test] fn test_multiple_archetypes() {
1499 let mut w = World::new();
1500 w.spawn(Position { x: 0.0, y: 0.0 }); w.spawn(Health(100.0));
1501 w.spawn((Position { x: 1.0, y: 0.0 }, Health(50.0)));
1502 assert_eq!(w.archetype_count(), 3);
1503 assert_eq!(w.query::<Read<Position>, ()>().count(), 2);
1504 assert_eq!(w.query::<Read<Health>, ()>().count(), 2);
1505 assert_eq!(w.query::<(Read<Position>, Read<Health>), ()>().count(), 1);
1506 }
1507 #[test] fn test_entity_count_after_despawn() {
1508 let mut w = World::new();
1509 let es: Vec<Entity> = (0..10).map(|i| w.spawn(Health(i as f32))).collect();
1510 for &e in &es[..5] { w.despawn(e); }
1511 assert_eq!(w.entity_count(), 5);
1512 }
1513}