mod entity_ref; mod pointer; mod spawn_batch; mod world_cell; pub use entity_ref::*; pub use pointer::*; pub use spawn_batch::*; pub use world_cell::*; use crate::{ archetype::{ArchetypeComponentId, ArchetypeComponentInfo, ArchetypeId, Archetypes}, bundle::{Bundle, Bundles}, component::{ Component, ComponentDescriptor, ComponentId, ComponentTicks, Components, ComponentsError, StorageType, }, entity::{Entities, Entity}, query::{FilterFetch, QueryState, WorldQuery}, storage::{Column, SparseSet, Storages}, }; use std::{ any::TypeId, fmt, sync::atomic::{AtomicU32, Ordering}, }; #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub struct WorldId(u64); impl Default for WorldId { fn default() -> Self { WorldId(rand::random()) } } /// [World] stores and exposes operations on [entities](Entity), [components](Component), /// and their associated metadata. /// Each [Entity] has a set of components. Each component can have up to one instance of each /// component type. Entity components can be created, updated, removed, and queried using a given /// [World]. pub struct World { id: WorldId, pub(crate) entities: Entities, pub(crate) components: Components, pub(crate) archetypes: Archetypes, pub(crate) storages: Storages, pub(crate) bundles: Bundles, pub(crate) removed_components: SparseSet>, /// Access cache used by [WorldCell]. pub(crate) archetype_component_access: ArchetypeComponentAccess, main_thread_validator: MainThreadValidator, pub(crate) change_tick: AtomicU32, pub(crate) last_change_tick: u32, } impl Default for World { fn default() -> Self { Self { id: Default::default(), entities: Default::default(), components: Default::default(), archetypes: Default::default(), storages: Default::default(), bundles: Default::default(), removed_components: Default::default(), archetype_component_access: Default::default(), main_thread_validator: Default::default(), // Default value is `1`, and `last_change_tick`s default to `0`, such that changes // are detected on first system runs and for direct world queries. change_tick: AtomicU32::new(1), last_change_tick: 0, } } } impl World { /// Creates a new empty [World] #[inline] pub fn new() -> World { World::default() } /// Retrieves this world's unique ID #[inline] pub fn id(&self) -> WorldId { self.id } /// Retrieves this world's [Entities] collection #[inline] pub fn entities(&self) -> &Entities { &self.entities } /// Retrieves this world's [Archetypes] collection #[inline] pub fn archetypes(&self) -> &Archetypes { &self.archetypes } /// Retrieves this world's [Components] collection #[inline] pub fn components(&self) -> &Components { &self.components } /// Retrieves a mutable reference to this world's [Components] collection #[inline] pub fn components_mut(&mut self) -> &mut Components { &mut self.components } /// Retrieves this world's [Storages] collection #[inline] pub fn storages(&self) -> &Storages { &self.storages } /// Retrieves this world's [Bundles] collection #[inline] pub fn bundles(&self) -> &Bundles { &self.bundles } /// Retrieves a [WorldCell], which safely enables multiple mutable World accesses at the same /// time, provided those accesses do not conflict with each other. #[inline] pub fn cell(&mut self) -> WorldCell<'_> { WorldCell::new(self) } /// Registers a new component using the given [ComponentDescriptor]. Components do not need to /// be manually registered. This just provides a way to override default configuration. /// Attempting to register a component with a type that has already been used by [World] /// will result in an error. /// /// The default component storage type can be overridden like this: /// /// ``` /// use bevy_ecs::{component::{ComponentDescriptor, StorageType}, world::World}; /// /// struct Position { /// x: f32, /// y: f32, /// } /// /// let mut world = World::new(); /// world.register_component(ComponentDescriptor::new::(StorageType::SparseSet)).unwrap(); /// ``` pub fn register_component( &mut self, descriptor: ComponentDescriptor, ) -> Result { let storage_type = descriptor.storage_type(); let component_id = self.components.add(descriptor)?; // ensure sparse set is created for SparseSet components if storage_type == StorageType::SparseSet { // SAFE: just created let info = unsafe { self.components.get_info_unchecked(component_id) }; self.storages.sparse_sets.get_or_insert(info); } Ok(component_id) } /// Retrieves an [EntityRef] that exposes read-only operations for the given `entity`. /// This will panic if the `entity` does not exist. Use [World::get_entity] if you want /// to check for entity existence instead of implicitly panic-ing. /// /// ``` /// use bevy_ecs::world::World; /// /// struct Position { /// x: f32, /// y: f32, /// } /// /// let mut world = World::new(); /// let entity = world.spawn() /// .insert(Position { x: 0.0, y: 0.0 }) /// .id(); /// /// let position = world.entity(entity).get::().unwrap(); /// assert_eq!(position.x, 0.0); /// ``` #[inline] pub fn entity(&self, entity: Entity) -> EntityRef { self.get_entity(entity).expect("Entity does not exist") } /// Retrieves an [EntityMut] that exposes read and write operations for the given `entity`. /// This will panic if the `entity` does not exist. Use [World::get_entity_mut] if you want /// to check for entity existence instead of implicitly panic-ing. /// /// ``` /// use bevy_ecs::world::World; /// /// struct Position { /// x: f32, /// y: f32, /// } /// /// let mut world = World::new(); /// let entity = world.spawn() /// .insert(Position { x: 0.0, y: 0.0 }) /// .id(); /// /// let mut position = world.entity_mut(entity).get_mut::().unwrap(); /// position.x = 1.0; /// ``` #[inline] pub fn entity_mut(&mut self, entity: Entity) -> EntityMut { self.get_entity_mut(entity).expect("Entity does not exist") } /// Retrieves an [EntityRef] that exposes read-only operations for the given `entity`. /// Returns [None] if the `entity` does not exist. Use [World::entity] if you don't want /// to unwrap the [EntityRef] yourself. /// /// ``` /// use bevy_ecs::world::World; /// /// struct Position { /// x: f32, /// y: f32, /// } /// /// let mut world = World::new(); /// let entity = world.spawn() /// .insert(Position { x: 0.0, y: 0.0 }) /// .id(); /// /// let entity_ref = world.get_entity(entity).unwrap(); /// let position = entity_ref.get::().unwrap(); /// assert_eq!(position.x, 0.0); /// ``` #[inline] pub fn get_entity(&self, entity: Entity) -> Option { let location = self.entities.get(entity)?; Some(EntityRef::new(self, entity, location)) } /// Retrieves an [EntityMut] that exposes read and write operations for the given `entity`. /// Returns [None] if the `entity` does not exist. Use [World::entity_mut] if you don't want /// to unwrap the [EntityMut] yourself. /// /// ``` /// use bevy_ecs::world::World; /// /// struct Position { /// x: f32, /// y: f32, /// } /// /// let mut world = World::new(); /// let entity = world.spawn() /// .insert(Position { x: 0.0, y: 0.0 }) /// .id(); /// /// let mut entity_mut = world.get_entity_mut(entity).unwrap(); /// let mut position = entity_mut.get_mut::().unwrap(); /// position.x = 1.0; /// ``` #[inline] pub fn get_entity_mut(&mut self, entity: Entity) -> Option { let location = self.entities.get(entity)?; // SAFE: `entity` exists and `location` is that entity's location Some(unsafe { EntityMut::new(self, entity, location) }) } /// Spawns a new [Entity] and returns a corresponding [EntityMut], which can be used /// to add components to the entity or retrieve its id. /// /// ``` /// use bevy_ecs::world::World; /// /// struct Position { /// x: f32, /// y: f32, /// } /// /// let mut world = World::new(); /// let entity = world.spawn() /// .insert(Position { x: 0.0, y: 0.0 }) // add a single component /// .insert_bundle((1, 2.0, "hello")) // add a bundle of components /// .id(); /// /// let position = world.entity(entity).get::().unwrap(); /// assert_eq!(position.x, 0.0); /// ``` pub fn spawn(&mut self) -> EntityMut { self.flush(); let entity = self.entities.alloc(); let archetype = self.archetypes.empty_mut(); unsafe { // PERF: consider avoiding allocating entities in the empty archetype unless needed let table_row = self.storages.tables[archetype.table_id()].allocate(entity); // SAFE: no components are allocated by archetype.allocate() because the archetype is // empty let location = archetype.allocate(entity, table_row); // SAFE: entity index was just allocated self.entities .meta .get_unchecked_mut(entity.id() as usize) .location = location; EntityMut::new(self, entity, location) } } /// Spawns a batch of entities with the same component [Bundle] type. Takes a given [Bundle] /// iterator and returns a corresponding [Entity] iterator. /// This is more efficient than spawning entities and adding components to them individually, /// but it is limited to spawning entities with the same [Bundle] type, whereas spawning /// individually is more flexible. /// /// ``` /// use bevy_ecs::{entity::Entity, world::World}; /// /// let mut world = World::new(); /// let entities = world.spawn_batch(vec![ /// ("a", 0.0), // the first entity /// ("b", 1.0), // the second entity /// ]).collect::>(); /// /// assert_eq!(entities.len(), 2); /// ``` pub fn spawn_batch(&mut self, iter: I) -> SpawnBatchIter<'_, I::IntoIter> where I: IntoIterator, I::Item: Bundle, { SpawnBatchIter::new(self, iter.into_iter()) } /// Retrieves a reference to the given `entity`'s [Component] of the given type. /// Returns [None] if the `entity` does not have a [Component] of the given type. /// ``` /// use bevy_ecs::world::World; /// /// struct Position { /// x: f32, /// y: f32, /// } /// /// let mut world = World::new(); /// let entity = world.spawn() /// .insert(Position { x: 0.0, y: 0.0 }) /// .id(); /// let position = world.get::(entity).unwrap(); /// assert_eq!(position.x, 0.0); #[inline] pub fn get(&self, entity: Entity) -> Option<&T> { self.get_entity(entity)?.get() } /// Retrieves a mutable reference to the given `entity`'s [Component] of the given type. /// Returns [None] if the `entity` does not have a [Component] of the given type. /// ``` /// use bevy_ecs::world::World; /// /// struct Position { /// x: f32, /// y: f32, /// } /// /// let mut world = World::new(); /// let entity = world.spawn() /// .insert(Position { x: 0.0, y: 0.0 }) /// .id(); /// let mut position = world.get_mut::(entity).unwrap(); /// position.x = 1.0; #[inline] pub fn get_mut(&mut self, entity: Entity) -> Option> { self.get_entity_mut(entity)?.get_mut() } /// Despawns the given `entity`, if it exists. This will also remove all of the entity's /// [Component]s. Returns `true` if the `entity` is successfully despawned and `false` if /// the `entity` does not exist. /// ``` /// use bevy_ecs::world::World; /// /// struct Position { /// x: f32, /// y: f32, /// } /// /// let mut world = World::new(); /// let entity = world.spawn() /// .insert(Position { x: 0.0, y: 0.0 }) /// .id(); /// assert!(world.despawn(entity)); /// assert!(world.get_entity(entity).is_none()); /// assert!(world.get::(entity).is_none()); /// ``` #[inline] pub fn despawn(&mut self, entity: Entity) -> bool { self.get_entity_mut(entity) .map(|e| { e.despawn(); true }) .unwrap_or(false) } /// Clears component tracker state pub fn clear_trackers(&mut self) { for entities in self.removed_components.values_mut() { entities.clear(); } self.last_change_tick = self.increment_change_tick(); } /// Returns [QueryState] for the given [WorldQuery], which is used to efficiently /// run queries on the [World] by storing and reusing the [QueryState]. /// ``` /// use bevy_ecs::{entity::Entity, world::World}; /// /// #[derive(Debug, PartialEq)] /// struct Position { /// x: f32, /// y: f32, /// } /// /// struct Velocity { /// x: f32, /// y: f32, /// } /// /// let mut world = World::new(); /// let entities = world.spawn_batch(vec![ /// (Position { x: 0.0, y: 0.0}, Velocity { x: 1.0, y: 0.0 }), /// (Position { x: 0.0, y: 0.0}, Velocity { x: 0.0, y: 1.0 }), /// ]).collect::>(); /// /// let mut query = world.query::<(&mut Position, &Velocity)>(); /// for (mut position, velocity) in query.iter_mut(&mut world) { /// position.x += velocity.x; /// position.y += velocity.y; /// } /// /// assert_eq!(world.get::(entities[0]).unwrap(), &Position { x: 1.0, y: 0.0 }); /// assert_eq!(world.get::(entities[1]).unwrap(), &Position { x: 0.0, y: 1.0 }); /// ``` /// /// To iterate over entities in a deterministic order, /// sort the results of the query using the desired component as a key. /// Note that this requires fetching the whole result set from the query /// and allocation of a [Vec] to store it. /// /// ``` /// use bevy_ecs::{entity::Entity, world::World}; /// let mut world = World::new(); /// let a = world.spawn().insert_bundle((2, 4.0)).id(); /// let b = world.spawn().insert_bundle((3, 5.0)).id(); /// let c = world.spawn().insert_bundle((1, 6.0)).id(); /// let mut entities = world.query::<(Entity, &i32, &f64)>() /// .iter(&world) /// .collect::>(); /// // Sort the query results by their `i32` component before comparing /// // to expected results. Query iteration order should not be relied on. /// entities.sort_by_key(|e| e.1); /// assert_eq!(entities, vec![(c, &1, &6.0), (a, &2, &4.0), (b, &3, &5.0)]); /// ``` #[inline] pub fn query(&mut self) -> QueryState { QueryState::new(self) } /// Returns [QueryState] for the given filtered [WorldQuery], which is used to efficiently /// run queries on the [World] by storing and reusing the [QueryState]. /// ``` /// use bevy_ecs::{entity::Entity, world::World, query::With}; /// /// struct A; /// struct B; /// /// let mut world = World::new(); /// let e1 = world.spawn().insert(A).id(); /// let e2 = world.spawn().insert_bundle((A, B)).id(); /// /// let mut query = world.query_filtered::>(); /// let matching_entities = query.iter(&world).collect::>(); /// /// assert_eq!(matching_entities, vec![e2]); /// ``` #[inline] pub fn query_filtered(&mut self) -> QueryState where F::Fetch: FilterFetch, { QueryState::new(self) } /// Returns an iterator of entities that had components of type `T` removed /// since the last call to [World::clear_trackers]. pub fn removed(&self) -> std::iter::Cloned> { if let Some(component_id) = self.components.get_id(TypeId::of::()) { self.removed_with_id(component_id) } else { [].iter().cloned() } } /// Returns an iterator of entities that had components with the given `component_id` removed /// since the last call to [World::clear_trackers]. pub fn removed_with_id( &self, component_id: ComponentId, ) -> std::iter::Cloned> { if let Some(removed) = self.removed_components.get(component_id) { removed.iter().cloned() } else { [].iter().cloned() } } /// Inserts a new resource with the given `value`. /// Resources are "unique" data of a given type. #[inline] pub fn insert_resource(&mut self, value: T) { let component_id = self.components.get_or_insert_resource_id::(); // SAFE: component_id just initialized and corresponds to resource of type T unsafe { self.insert_resource_with_id(component_id, value) }; } /// Inserts a new non-send resource with the given `value`. /// Resources are "unique" data of a given type. #[inline] pub fn insert_non_send(&mut self, value: T) { self.validate_non_send_access::(); let component_id = self.components.get_or_insert_non_send_resource_id::(); // SAFE: component_id just initialized and corresponds to resource of type T unsafe { self.insert_resource_with_id(component_id, value) }; } /// Removes the resource of a given type and returns it, if it exists. Otherwise returns [None]. /// Resources are "unique" data of a given type. #[inline] pub fn remove_resource(&mut self) -> Option { // SAFE: T is Send + Sync unsafe { self.remove_resource_unchecked() } } #[inline] pub fn remove_non_send(&mut self) -> Option { self.validate_non_send_access::(); // SAFE: we are on main thread unsafe { self.remove_resource_unchecked() } } #[inline] /// # Safety /// make sure you're on main thread if T isn't Send + Sync #[allow(unused_unsafe)] pub unsafe fn remove_resource_unchecked(&mut self) -> Option { let component_id = self.components.get_resource_id(TypeId::of::())?; let resource_archetype = self.archetypes.resource_mut(); let unique_components = resource_archetype.unique_components_mut(); let column = unique_components.get_mut(component_id)?; if column.is_empty() { return None; } // SAFE: if a resource column exists, row 0 exists as well. caller takes ownership of the // ptr value / drop is called when T is dropped let (ptr, _) = unsafe { column.swap_remove_and_forget_unchecked(0) }; // SAFE: column is of type T Some(unsafe { ptr.cast::().read() }) } /// Returns `true` if a resource of type `T` exists. Otherwise returns `false`. #[inline] pub fn contains_resource(&self) -> bool { let component_id = if let Some(component_id) = self.components.get_resource_id(TypeId::of::()) { component_id } else { return false; }; self.get_populated_resource_column(component_id).is_some() } /// Gets a reference to the resource of the given type, if it exists. Otherwise returns [None] /// Resources are "unique" data of a given type. #[inline] pub fn get_resource(&self) -> Option<&T> { let component_id = self.components.get_resource_id(TypeId::of::())?; unsafe { self.get_resource_with_id(component_id) } } pub fn is_resource_added(&self) -> bool { let component_id = self.components.get_resource_id(TypeId::of::()).unwrap(); let column = self.get_populated_resource_column(component_id).unwrap(); let ticks = unsafe { &*column.get_ticks_mut_ptr() }; ticks.is_added(self.last_change_tick(), self.read_change_tick()) } pub fn is_resource_changed(&self) -> bool { let component_id = self.components.get_resource_id(TypeId::of::()).unwrap(); let column = self.get_populated_resource_column(component_id).unwrap(); let ticks = unsafe { &*column.get_ticks_mut_ptr() }; ticks.is_changed(self.last_change_tick(), self.read_change_tick()) } /// Gets a mutable reference to the resource of the given type, if it exists. Otherwise returns /// [None] Resources are "unique" data of a given type. #[inline] pub fn get_resource_mut(&mut self) -> Option> { // SAFE: unique world access unsafe { self.get_resource_unchecked_mut() } } // PERF: optimize this to avoid redundant lookups /// Gets a resource of type `T` if it exists, otherwise inserts the resource using the result of /// calling `func`. #[inline] pub fn get_resource_or_insert_with( &mut self, func: impl FnOnce() -> T, ) -> Mut<'_, T> { if !self.contains_resource::() { self.insert_resource(func()); } self.get_resource_mut().unwrap() } /// Gets a mutable reference to the resource of the given type, if it exists. Otherwise returns /// [None] Resources are "unique" data of a given type. /// /// # Safety /// This will allow aliased mutable access to the given resource type. The caller must ensure /// that only one mutable access exists at a time. #[inline] pub unsafe fn get_resource_unchecked_mut(&self) -> Option> { let component_id = self.components.get_resource_id(TypeId::of::())?; self.get_resource_unchecked_mut_with_id(component_id) } /// Gets a reference to the non-send resource of the given type, if it exists. Otherwise returns /// [None] Resources are "unique" data of a given type. #[inline] pub fn get_non_send_resource(&self) -> Option<&T> { let component_id = self.components.get_resource_id(TypeId::of::())?; // SAFE: component id matches type T unsafe { self.get_non_send_with_id(component_id) } } /// Gets a mutable reference to the non-send resource of the given type, if it exists. Otherwise /// returns [None] Resources are "unique" data of a given type. #[inline] pub fn get_non_send_resource_mut(&mut self) -> Option> { // SAFE: unique world access unsafe { self.get_non_send_resource_unchecked_mut() } } /// Gets a mutable reference to the non-send resource of the given type, if it exists. Otherwise /// returns [None] Resources are "unique" data of a given type. /// /// # Safety /// This will allow aliased mutable access to the given non-send resource type. The caller must /// ensure that only one mutable access exists at a time. #[inline] pub unsafe fn get_non_send_resource_unchecked_mut(&self) -> Option> { let component_id = self.components.get_resource_id(TypeId::of::())?; self.get_non_send_unchecked_mut_with_id(component_id) } /// Temporarily removes the requested resource from this [World], then re-adds it before /// returning. This enables safe mutable access to a resource while still providing mutable /// world access /// ``` /// use bevy_ecs::world::{World, Mut}; /// struct A(u32); /// struct B(u32); /// let mut world = World::new(); /// world.insert_resource(A(1)); /// let entity = world.spawn().insert(B(1)).id(); /// /// world.resource_scope(|world, mut a: Mut| { /// let b = world.get_mut::(entity).unwrap(); /// a.0 += b.0; /// }); /// assert_eq!(world.get_resource::().unwrap().0, 2); /// ``` pub fn resource_scope( &mut self, f: impl FnOnce(&mut World, Mut) -> U, ) -> U { let component_id = self .components .get_resource_id(TypeId::of::()) .unwrap_or_else(|| panic!("resource does not exist: {}", std::any::type_name::())); let (ptr, mut ticks) = { let resource_archetype = self.archetypes.resource_mut(); let unique_components = resource_archetype.unique_components_mut(); let column = unique_components.get_mut(component_id).unwrap_or_else(|| { panic!("resource does not exist: {}", std::any::type_name::()) }); if column.is_empty() { panic!("resource does not exist: {}", std::any::type_name::()); } // SAFE: if a resource column exists, row 0 exists as well. caller takes ownership of // the ptr value / drop is called when T is dropped unsafe { column.swap_remove_and_forget_unchecked(0) } }; // SAFE: pointer is of type T let value = Mut { value: unsafe { &mut *ptr.cast::() }, component_ticks: &mut ticks, last_change_tick: self.last_change_tick(), change_tick: self.change_tick(), }; let result = f(self, value); let resource_archetype = self.archetypes.resource_mut(); let unique_components = resource_archetype.unique_components_mut(); let column = unique_components .get_mut(component_id) .unwrap_or_else(|| panic!("resource does not exist: {}", std::any::type_name::())); // SAFE: new location is immediately written to below let row = unsafe { column.push_uninit() }; // SAFE: row was just allocated above unsafe { column.set_unchecked(row, ptr) }; // SAFE: row was just allocated above unsafe { *column.get_ticks_unchecked_mut(row) = ticks }; result } /// # Safety /// `component_id` must be assigned to a component of type T #[inline] pub(crate) unsafe fn get_resource_with_id( &self, component_id: ComponentId, ) -> Option<&T> { let column = self.get_populated_resource_column(component_id)?; Some(&*column.get_ptr().as_ptr().cast::()) } /// # Safety /// `component_id` must be assigned to a component of type T. /// Caller must ensure this doesn't violate Rust mutability rules for the given resource. #[inline] pub(crate) unsafe fn get_resource_unchecked_mut_with_id( &self, component_id: ComponentId, ) -> Option> { let column = self.get_populated_resource_column(component_id)?; Some(Mut { value: &mut *column.get_ptr().as_ptr().cast::(), component_ticks: &mut *column.get_ticks_mut_ptr(), last_change_tick: self.last_change_tick(), change_tick: self.read_change_tick(), }) } /// # Safety /// `component_id` must be assigned to a component of type T #[inline] pub(crate) unsafe fn get_non_send_with_id( &self, component_id: ComponentId, ) -> Option<&T> { self.validate_non_send_access::(); self.get_resource_with_id(component_id) } /// # Safety /// `component_id` must be assigned to a component of type T. /// Caller must ensure this doesn't violate Rust mutability rules for the given resource. #[inline] pub(crate) unsafe fn get_non_send_unchecked_mut_with_id( &self, component_id: ComponentId, ) -> Option> { self.validate_non_send_access::(); self.get_resource_unchecked_mut_with_id(component_id) } /// # Safety /// `component_id` must be valid and correspond to a resource component of type T #[inline] unsafe fn insert_resource_with_id(&mut self, component_id: ComponentId, mut value: T) { let change_tick = self.change_tick(); let column = self.initialize_resource_internal(component_id); if column.is_empty() { // SAFE: column is of type T and has been allocated above let data = (&mut value as *mut T).cast::(); // SAFE: new location is immediately written to below let row = column.push_uninit(); // SAFE: index was just allocated above column.set_unchecked(row, data); std::mem::forget(value); // SAFE: index was just allocated above *column.get_ticks_unchecked_mut(row) = ComponentTicks::new(change_tick); } else { // SAFE: column is of type T and has already been allocated *column.get_unchecked(0).cast::() = value; column.get_ticks_unchecked_mut(0).set_changed(change_tick); } } /// # Safety /// `component_id` must be valid and correspond to a resource component of type T #[inline] unsafe fn initialize_resource_internal(&mut self, component_id: ComponentId) -> &mut Column { // SAFE: resource archetype always exists let resource_archetype = self .archetypes .archetypes .get_unchecked_mut(ArchetypeId::resource().index()); let resource_archetype_components = &mut resource_archetype.components; let archetype_component_count = &mut self.archetypes.archetype_component_count; let components = &self.components; resource_archetype .unique_components .get_or_insert_with(component_id, || { resource_archetype_components.insert( component_id, ArchetypeComponentInfo { archetype_component_id: ArchetypeComponentId::new( *archetype_component_count, ), storage_type: StorageType::Table, }, ); *archetype_component_count += 1; let component_info = components.get_info_unchecked(component_id); Column::with_capacity(component_info, 1) }) } pub(crate) fn initialize_resource(&mut self) -> ComponentId { let component_id = self.components.get_or_insert_resource_id::(); // SAFE: resource initialized above unsafe { self.initialize_resource_internal(component_id) }; component_id } pub(crate) fn initialize_non_send_resource(&mut self) -> ComponentId { let component_id = self.components.get_or_insert_non_send_resource_id::(); // SAFE: resource initialized above unsafe { self.initialize_resource_internal(component_id) }; component_id } /// returns the resource column if the requested resource exists pub(crate) fn get_populated_resource_column( &self, component_id: ComponentId, ) -> Option<&Column> { let resource_archetype = self.archetypes.resource(); let unique_components = resource_archetype.unique_components(); unique_components.get(component_id).and_then(|column| { if column.is_empty() { None } else { Some(column) } }) } pub(crate) fn validate_non_send_access(&self) { if !self.main_thread_validator.is_main_thread() { panic!( "attempted to access NonSend resource {} off of the main thread", std::any::type_name::() ); } } /// Empties queued entities and adds them to the empty [Archetype]. /// This should be called before doing operations that might operate on queued entities, /// such as inserting a [Component]. pub(crate) fn flush(&mut self) { let empty_archetype = self.archetypes.empty_mut(); unsafe { let table = &mut self.storages.tables[empty_archetype.table_id()]; // PERF: consider pre-allocating space for flushed entities self.entities.flush(|entity, location| { // SAFE: no components are allocated by archetype.allocate() because the archetype // is empty *location = empty_archetype.allocate(entity, table.allocate(entity)); }); } } #[inline] pub fn increment_change_tick(&self) -> u32 { self.change_tick.fetch_add(1, Ordering::AcqRel) } #[inline] pub fn read_change_tick(&self) -> u32 { self.change_tick.load(Ordering::Acquire) } #[inline] pub fn change_tick(&mut self) -> u32 { *self.change_tick.get_mut() } #[inline] pub fn last_change_tick(&self) -> u32 { self.last_change_tick } pub fn check_change_ticks(&mut self) { // Iterate over all component change ticks, clamping their age to max age // PERF: parallelize let change_tick = self.change_tick(); self.storages.tables.check_change_ticks(change_tick); self.storages.sparse_sets.check_change_ticks(change_tick); let resource_archetype = self.archetypes.resource_mut(); for column in resource_archetype.unique_components.values_mut() { column.check_change_ticks(change_tick); } } } impl fmt::Debug for World { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("World") .field("id", &self.id) .field("entity_count", &self.entities.len()) .field("archetype_count", &self.archetypes.len()) .field("component_count", &self.components.len()) .field( "resource_count", &self.archetypes.resource().unique_components.len(), ) .finish() } } unsafe impl Send for World {} unsafe impl Sync for World {} /// Creates `Self` using data from the given [World] pub trait FromWorld { /// Creates `Self` using data from the given [World] fn from_world(world: &mut World) -> Self; } impl FromWorld for T { fn from_world(_world: &mut World) -> Self { T::default() } } struct MainThreadValidator { main_thread: std::thread::ThreadId, } impl MainThreadValidator { fn is_main_thread(&self) -> bool { self.main_thread == std::thread::current().id() } } impl Default for MainThreadValidator { fn default() -> Self { Self { main_thread: std::thread::current().id(), } } }