mod entity_ref; mod spawn_batch; mod world_cell; pub use crate::change_detection::{Mut, Ref, CHECK_TICK_THRESHOLD}; pub use entity_ref::{EntityMut, EntityRef}; pub use spawn_batch::*; pub use world_cell::*; use crate::{ archetype::{ArchetypeComponentId, ArchetypeId, ArchetypeRow, Archetypes}, bundle::{Bundle, BundleInserter, BundleSpawner, Bundles}, change_detection::{MutUntyped, TicksMut}, component::{ Component, ComponentDescriptor, ComponentId, ComponentInfo, ComponentTicks, Components, StorageType, TickCells, }, entity::{AllocAtWithoutReplacement, Entities, Entity, EntityLocation}, event::{Event, Events}, ptr::UnsafeCellDeref, query::{DebugCheckedUnwrap, QueryState, ReadOnlyWorldQuery, WorldQuery}, storage::{Column, ComponentSparseSet, ResourceData, SparseSet, Storages, TableRow}, system::Resource, }; use bevy_ptr::{OwningPtr, Ptr}; use bevy_utils::tracing::warn; use std::{ any::TypeId, fmt, sync::atomic::{AtomicU32, Ordering}, }; mod identifier; pub use identifier::WorldId; /// Stores and exposes operations on [entities](Entity), [components](Component), resources, /// 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]. /// /// For complex access patterns involving [`SystemParam`](crate::system::SystemParam), /// consider using [`SystemState`](crate::system::SystemState). /// /// To mutate different parts of the world simultaneously, /// use [`World::resource_scope`] or [`SystemState`](crate::system::SystemState). /// /// ## Resources /// /// Worlds can also store [`Resource`]s, /// which are unique instances of a given type that don't belong to a specific Entity. /// There are also *non send resources*, which can only be accessed on the main thread. /// See [`Resource`] for usage. 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, pub(crate) change_tick: AtomicU32, pub(crate) last_change_tick: u32, pub(crate) last_check_tick: u32, } impl Default for World { fn default() -> Self { Self { id: WorldId::new().expect("More `bevy` `World`s have been created than is supported"), entities: Entities::new(), components: Default::default(), archetypes: Archetypes::new(), storages: Default::default(), bundles: Default::default(), removed_components: Default::default(), archetype_component_access: 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, last_check_tick: 0, } } } impl World { /// Creates a new empty [World] /// # Panics /// /// If [`usize::MAX`] [`World`]s have been created. /// This guarantee allows System Parameters to safely uniquely identify a [`World`], /// since its [`WorldId`] is unique #[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 [Entities] collection mutably /// /// # Safety /// Mutable reference must not be used to put the [`Entities`] data /// in an invalid state for this [`World`] #[inline] pub unsafe fn entities_mut(&mut self) -> &mut Entities { &mut 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 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) } /// Initializes a new [`Component`] type and returns the [`ComponentId`] created for it. pub fn init_component(&mut self) -> ComponentId { self.components.init_component::(&mut self.storages) } /// Initializes a new [`Component`] type and returns the [`ComponentId`] created for it. /// /// This method differs from [`World::init_component`] in that it uses a [`ComponentDescriptor`] /// to initialize the new component type instead of statically available type information. This /// enables the dynamic initialization of new component definitions at runtime for advanced use cases. /// /// While the option to initialize a component from a descriptor is useful in type-erased /// contexts, the standard `World::init_component` function should always be used instead /// when type information is available at compile time. pub fn init_component_with_descriptor( &mut self, descriptor: ComponentDescriptor, ) -> ComponentId { self.components .init_component_with_descriptor(&mut self.storages, descriptor) } /// Returns the [`ComponentId`] of the given [`Component`] type `T`. /// /// The returned `ComponentId` is specific to the `World` instance /// it was retrieved from and should not be used with another `World` instance. /// /// Returns [`None`] if the `Component` type has not yet been initialized within /// the `World` using [`World::init_component`]. /// /// ```rust /// use bevy_ecs::prelude::*; /// /// let mut world = World::new(); /// /// #[derive(Component)] /// struct ComponentA; /// /// let component_a_id = world.init_component::(); /// /// assert_eq!(component_a_id, world.component_id::().unwrap()) /// ``` #[inline] pub fn component_id(&self) -> Option { self.components.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::{component::Component, world::World}; /// /// #[derive(Component)] /// struct Position { /// x: f32, /// y: f32, /// } /// /// let mut world = World::new(); /// let entity = world.spawn(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 { // Lazily evaluate panic!() via unwrap_or_else() to avoid allocation unless failure self.get_entity(entity) .unwrap_or_else(|| panic!("Entity {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::{component::Component, world::World}; /// /// #[derive(Component)] /// struct Position { /// x: f32, /// y: f32, /// } /// /// let mut world = World::new(); /// let entity = world.spawn(Position { x: 0.0, y: 0.0 }).id(); /// let mut entity_mut = world.entity_mut(entity); /// let mut position = entity_mut.get_mut::().unwrap(); /// position.x = 1.0; /// ``` #[inline] pub fn entity_mut(&mut self, entity: Entity) -> EntityMut { // Lazily evaluate panic!() via unwrap_or_else() to avoid allocation unless failure self.get_entity_mut(entity) .unwrap_or_else(|| panic!("Entity {entity:?} does not exist")) } /// Returns the components of an [`Entity`](crate::entity::Entity) through [`ComponentInfo`](crate::component::ComponentInfo). #[inline] pub fn inspect_entity(&self, entity: Entity) -> Vec<&ComponentInfo> { let entity_location = self .entities() .get(entity) .unwrap_or_else(|| panic!("Entity {entity:?} does not exist")); let archetype = self .archetypes() .get(entity_location.archetype_id) .unwrap_or_else(|| { panic!( "Archetype {:?} does not exist", entity_location.archetype_id ) }); archetype .components() .filter_map(|id| self.components().get_info(id)) .collect() } /// Returns an [`EntityMut`] for the given `entity` (if it exists) or spawns one if it doesn't exist. /// This will return [`None`] if the `entity` exists with a different generation. /// /// # Note /// Spawning a specific `entity` value is rarely the right choice. Most apps should favor [`World::spawn`]. /// This method should generally only be used for sharing entities across apps, and only when they have a /// scheme worked out to share an ID space (which doesn't happen by default). #[inline] pub fn get_or_spawn(&mut self, entity: Entity) -> Option { self.flush(); match self.entities.alloc_at_without_replacement(entity) { AllocAtWithoutReplacement::Exists(location) => { // SAFETY: `entity` exists and `location` is that entity's location Some(unsafe { EntityMut::new(self, entity, location) }) } AllocAtWithoutReplacement::DidNotExist => { // SAFETY: entity was just allocated Some(unsafe { self.spawn_at_empty_internal(entity) }) } AllocAtWithoutReplacement::ExistsWithWrongGeneration => None, } } /// 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::{component::Component, world::World}; /// /// #[derive(Component)] /// struct Position { /// x: f32, /// y: f32, /// } /// /// let mut world = World::new(); /// let entity = world.spawn(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)?; // SAFETY: if the Entity is invalid, the function returns early. // Additionally, Entities::get(entity) returns the correct EntityLocation if the entity exists. let entity_ref = unsafe { EntityRef::new(self, entity, location) }; Some(entity_ref) } /// Returns an [`Entity`] iterator of current entities. /// /// This is useful in contexts where you only have read-only access to the [`World`]. #[inline] pub fn iter_entities(&self) -> impl Iterator> + '_ { self.archetypes.iter().flat_map(|archetype| { archetype .entities() .iter() .enumerate() .map(|(archetype_row, archetype_entity)| { let entity = archetype_entity.entity(); let location = EntityLocation { archetype_id: archetype.id(), archetype_row: ArchetypeRow::new(archetype_row), table_id: archetype.table_id(), table_row: archetype_entity.table_row(), }; // SAFETY: entity exists and location accurately specifies the archetype where the entity is stored unsafe { 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::{component::Component, world::World}; /// /// #[derive(Component)] /// struct Position { /// x: f32, /// y: f32, /// } /// /// let mut world = World::new(); /// let entity = world.spawn(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)?; // SAFETY: `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::{component::Component, world::World}; /// /// #[derive(Component)] /// struct Position { /// x: f32, /// y: f32, /// } /// #[derive(Component)] /// struct Label(&'static str); /// #[derive(Component)] /// struct Num(u32); /// /// let mut world = World::new(); /// let entity = world.spawn_empty() /// .insert(Position { x: 0.0, y: 0.0 }) // add a single component /// .insert((Num(1), Label("hello"))) // add a bundle of components /// .id(); /// /// let position = world.entity(entity).get::().unwrap(); /// assert_eq!(position.x, 0.0); /// ``` pub fn spawn_empty(&mut self) -> EntityMut { self.flush(); let entity = self.entities.alloc(); // SAFETY: entity was just allocated unsafe { self.spawn_at_empty_internal(entity) } } /// Spawns a new [`Entity`] with a given [`Bundle`] of [components](`Component`) and returns /// a corresponding [`EntityMut`], which can be used to add components to the entity or /// retrieve its id. /// /// ``` /// use bevy_ecs::{bundle::Bundle, component::Component, world::World}; /// /// #[derive(Component)] /// struct Position { /// x: f32, /// y: f32, /// } /// /// #[derive(Component)] /// struct Velocity { /// x: f32, /// y: f32, /// }; /// /// #[derive(Component)] /// struct Name(&'static str); /// /// #[derive(Bundle)] /// struct PhysicsBundle { /// position: Position, /// velocity: Velocity, /// } /// /// let mut world = World::new(); /// /// // `spawn` can accept a single component: /// world.spawn(Position { x: 0.0, y: 0.0 }); /// // It can also accept a tuple of components: /// world.spawn(( /// Position { x: 0.0, y: 0.0 }, /// Velocity { x: 1.0, y: 1.0 }, /// )); /// // Or it can accept a pre-defined Bundle of components: /// world.spawn(PhysicsBundle { /// position: Position { x: 2.0, y: 2.0 }, /// velocity: Velocity { x: 0.0, y: 4.0 }, /// }); /// /// let entity = world /// // Tuples can also mix Bundles and Components /// .spawn(( /// PhysicsBundle { /// position: Position { x: 2.0, y: 2.0 }, /// velocity: Velocity { x: 0.0, y: 4.0 }, /// }, /// Name("Elaina Proctor"), /// )) /// // Calling id() will return the unique identifier for the spawned entity /// .id(); /// let position = world.entity(entity).get::().unwrap(); /// assert_eq!(position.x, 2.0); /// ``` pub fn spawn(&mut self, bundle: B) -> EntityMut { self.flush(); let entity = self.entities.alloc(); let entity_location = { let bundle_info = self .bundles .init_info::(&mut self.components, &mut self.storages); let mut spawner = bundle_info.get_bundle_spawner( &mut self.entities, &mut self.archetypes, &mut self.components, &mut self.storages, *self.change_tick.get_mut(), ); // SAFETY: bundle's type matches `bundle_info`, entity is allocated but non-existent unsafe { spawner.spawn_non_existent(entity, bundle) } }; // SAFETY: entity and location are valid, as they were just created above unsafe { EntityMut::new(self, entity, entity_location) } } /// # Safety /// must be called on an entity that was just allocated unsafe fn spawn_at_empty_internal(&mut self, entity: Entity) -> EntityMut { let archetype = self.archetypes.empty_mut(); // PERF: consider avoiding allocating entities in the empty archetype unless needed let table_row = self.storages.tables[archetype.table_id()].allocate(entity); // SAFETY: no components are allocated by archetype.allocate() because the archetype is // empty let location = archetype.allocate(entity, table_row); // SAFETY: entity index was just allocated self.entities.set(entity.index(), 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::{component::Component, entity::Entity, world::World}; /// /// #[derive(Component)] /// struct Str(&'static str); /// #[derive(Component)] /// struct Num(u32); /// /// let mut world = World::new(); /// let entities = world.spawn_batch(vec![ /// (Str("a"), Num(0)), // the first entity /// (Str("b"), Num(1)), // 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::{component::Component, world::World}; /// /// #[derive(Component)] /// struct Position { /// x: f32, /// y: f32, /// } /// /// let mut world = World::new(); /// let entity = world.spawn(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::{component::Component, world::World}; /// /// #[derive(Component)] /// struct Position { /// x: f32, /// y: f32, /// } /// /// let mut world = World::new(); /// let entity = world.spawn(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> { // SAFETY: // - lifetimes enforce correct usage of returned borrow // - entity location is checked in `get_entity` unsafe { entity_ref::get_mut(self, entity, self.get_entity(entity)?.location()) } } /// 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::{component::Component, world::World}; /// /// #[derive(Component)] /// struct Position { /// x: f32, /// y: f32, /// } /// /// let mut world = World::new(); /// let entity = world.spawn(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 { if let Some(entity) = self.get_entity_mut(entity) { entity.despawn(); true } else { warn!("error[B0003]: Could not despawn entity {:?} because it doesn't exist in this World.", entity); false } } /// Clears the internal component tracker state. /// /// The world maintains some internal state about changed and removed components. This state /// is used by [`RemovedComponents`] to provide access to the entities that had a specific type /// of component removed since last tick. /// /// The state is also used for change detection when accessing components and resources outside /// of a system, for example via [`World::get_mut()`] or [`World::get_resource_mut()`]. /// /// By clearing this internal state, the world "forgets" about those changes, allowing a new round /// of detection to be recorded. /// /// When using `bevy_ecs` as part of the full Bevy engine, this method is added as a system to the /// main app, to run during the `CoreStage::Last`, so you don't need to call it manually. When using /// `bevy_ecs` as a separate standalone crate however, you need to call this manually. /// /// ``` /// # use bevy_ecs::prelude::*; /// # #[derive(Component, Default)] /// # struct Transform; /// // a whole new world /// let mut world = World::new(); /// /// // you changed it /// let entity = world.spawn(Transform::default()).id(); /// /// // change is detected /// let transform = world.get_mut::(entity).unwrap(); /// assert!(transform.is_changed()); /// /// // update the last change tick /// world.clear_trackers(); /// /// // change is no longer detected /// let transform = world.get_mut::(entity).unwrap(); /// assert!(!transform.is_changed()); /// ``` /// /// [`RemovedComponents`]: crate::system::RemovedComponents 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::{component::Component, entity::Entity, world::World}; /// /// #[derive(Component, Debug, PartialEq)] /// struct Position { /// x: f32, /// y: f32, /// } /// /// #[derive(Component)] /// 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::{component::Component, entity::Entity, world::World}; /// /// #[derive(Component, PartialEq, Eq, PartialOrd, Ord, Debug)] /// struct Order(i32); /// #[derive(Component, PartialEq, Debug)] /// struct Label(&'static str); /// /// let mut world = World::new(); /// let a = world.spawn((Order(2), Label("second"))).id(); /// let b = world.spawn((Order(3), Label("third"))).id(); /// let c = world.spawn((Order(1), Label("first"))).id(); /// let mut entities = world.query::<(Entity, &Order, &Label)>() /// .iter(&world) /// .collect::>(); /// // Sort the query results by their `Order` 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, &Order(1), &Label("first")), /// (a, &Order(2), &Label("second")), /// (b, &Order(3), &Label("third")), /// ]); /// ``` #[inline] pub fn query(&mut self) -> QueryState { self.query_filtered::() } /// 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::{component::Component, entity::Entity, world::World, query::With}; /// /// #[derive(Component)] /// struct A; /// #[derive(Component)] /// struct B; /// /// let mut world = World::new(); /// let e1 = world.spawn(A).id(); /// let e2 = world.spawn((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 { 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 standard starting values. /// /// If the resource already exists, nothing happens. /// /// The value given by the [`FromWorld::from_world`] method will be used. /// Note that any resource with the `Default` trait automatically implements `FromWorld`, /// and those default values will be here instead. #[inline] pub fn init_resource(&mut self) { let component_id = self.components.init_resource::(); if self .storages .resources .get(component_id) .map_or(true, |data| !data.is_present()) { let value = R::from_world(self); OwningPtr::make(value, |ptr| { // SAFETY: component_id was just initialized and corresponds to resource of type R. unsafe { self.insert_resource_by_id(component_id, ptr); } }); } } /// Inserts a new resource with the given `value`. /// /// Resources are "unique" data of a given type. /// If you insert a resource of a type that already exists, /// you will overwrite any existing data. #[inline] pub fn insert_resource(&mut self, value: R) { let component_id = self.components.init_resource::(); OwningPtr::make(value, |ptr| { // SAFETY: component_id was just initialized and corresponds to resource of type R. unsafe { self.insert_resource_by_id(component_id, ptr); } }); } /// Inserts a new non-send resource with standard starting values. /// /// If the resource already exists, nothing happens. /// /// The value given by the [`FromWorld::from_world`] method will be used. /// Note that any resource with the `Default` trait automatically implements `FromWorld`, /// and those default values will be here instead. /// /// # Panics /// /// Panics if called from a thread other than the main thread. #[inline] pub fn init_non_send_resource(&mut self) { let component_id = self.components.init_non_send::(); if self .storages .resources .get(component_id) .map_or(true, |data| !data.is_present()) { let value = R::from_world(self); OwningPtr::make(value, |ptr| { // SAFETY: component_id was just initialized and corresponds to resource of type R. unsafe { self.insert_non_send_by_id(component_id, ptr); } }); } } /// Inserts a new non-send resource with the given `value`. /// /// `NonSend` resources cannot be sent across threads, /// and do not need the `Send + Sync` bounds. /// Systems with `NonSend` resources are always scheduled on the main thread. /// /// # Panics /// If a value is already present, this function will panic if called /// from a different thread than where the original value was inserted from. #[inline] pub fn insert_non_send_resource(&mut self, value: R) { let component_id = self.components.init_non_send::(); OwningPtr::make(value, |ptr| { // SAFETY: component_id was just initialized and corresponds to resource of type R. unsafe { self.insert_non_send_by_id(component_id, ptr); } }); } /// Removes the resource of a given type and returns it, if it exists. Otherwise returns [None]. #[inline] pub fn remove_resource(&mut self) -> Option { let component_id = self.components.get_resource_id(TypeId::of::())?; let (ptr, _) = self.storages.resources.get_mut(component_id)?.remove()?; // SAFETY: `component_id` was gotten via looking up the `R` type unsafe { Some(ptr.read::()) } } /// Removes a `!Send` resource from the world and returns it, if present. /// /// `NonSend` resources cannot be sent across threads, /// and do not need the `Send + Sync` bounds. /// Systems with `NonSend` resources are always scheduled on the main thread. /// /// Returns `None` if a value was not previously present. /// /// # Panics /// If a value is present, this function will panic if called from a different /// thread than where the value was inserted from. #[inline] pub fn remove_non_send_resource(&mut self) -> Option { let component_id = self.components.get_resource_id(TypeId::of::())?; let (ptr, _) = self .storages .non_send_resources .get_mut(component_id)? .remove()?; // SAFETY: `component_id` was gotten via looking up the `R` type unsafe { Some(ptr.read::()) } } /// Returns `true` if a resource of type `R` exists. Otherwise returns `false`. #[inline] pub fn contains_resource(&self) -> bool { self.components .get_resource_id(TypeId::of::()) .and_then(|component_id| self.storages.resources.get(component_id)) .map(|info| info.is_present()) .unwrap_or(false) } /// Returns `true` if a resource of type `R` exists. Otherwise returns `false`. #[inline] pub fn contains_non_send(&self) -> bool { self.components .get_resource_id(TypeId::of::()) .and_then(|component_id| self.storages.non_send_resources.get(component_id)) .map(|info| info.is_present()) .unwrap_or(false) } pub fn is_resource_added(&self) -> bool { self.components .get_resource_id(TypeId::of::()) .and_then(|component_id| self.storages.resources.get(component_id)?.get_ticks()) .map(|ticks| ticks.is_added(self.last_change_tick(), self.read_change_tick())) .unwrap_or(false) } pub fn is_resource_changed(&self) -> bool { self.components .get_resource_id(TypeId::of::()) .and_then(|component_id| self.storages.resources.get(component_id)?.get_ticks()) .map(|ticks| ticks.is_changed(self.last_change_tick(), self.read_change_tick())) .unwrap_or(false) } /// Gets a reference to the resource of the given type /// /// # Panics /// /// Panics if the resource does not exist. /// Use [`get_resource`](World::get_resource) instead if you want to handle this case. /// /// If you want to instead insert a value if the resource does not exist, /// use [`get_resource_or_insert_with`](World::get_resource_or_insert_with). #[inline] #[track_caller] pub fn resource(&self) -> &R { match self.get_resource() { Some(x) => x, None => panic!( "Requested resource {} does not exist in the `World`. Did you forget to add it using `app.insert_resource` / `app.init_resource`? Resources are also implicitly added via `app.add_event`, and can be added by plugins.", std::any::type_name::() ), } } /// Gets a mutable reference to the resource of the given type /// /// # Panics /// /// Panics if the resource does not exist. /// Use [`get_resource_mut`](World::get_resource_mut) instead if you want to handle this case. /// /// If you want to instead insert a value if the resource does not exist, /// use [`get_resource_or_insert_with`](World::get_resource_or_insert_with). #[inline] #[track_caller] pub fn resource_mut(&mut self) -> Mut<'_, R> { match self.get_resource_mut() { Some(x) => x, None => panic!( "Requested resource {} does not exist in the `World`. Did you forget to add it using `app.insert_resource` / `app.init_resource`? Resources are also implicitly added via `app.add_event`, and can be added by plugins.", std::any::type_name::() ), } } /// Gets a reference to the resource of the given type if it exists #[inline] pub fn get_resource(&self) -> Option<&R> { let component_id = self.components.get_resource_id(TypeId::of::())?; // SAFETY: `component_id` was obtained from the type ID of `R`. unsafe { self.get_resource_with_id(component_id) } } /// Gets a mutable reference to the resource of the given type if it exists #[inline] pub fn get_resource_mut(&mut self) -> Option> { // SAFETY: unique world access unsafe { self.get_resource_unchecked_mut() } } /// Gets a mutable reference to the 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() -> R, ) -> Mut<'_, R> { let change_tick = self.change_tick(); let last_change_tick = self.last_change_tick(); let component_id = self.components.init_resource::(); let data = self.initialize_resource_internal(component_id); if !data.is_present() { OwningPtr::make(func(), |ptr| { // SAFETY: component_id was just initialized and corresponds to resource of type R. unsafe { data.insert(ptr, change_tick); } }); } // SAFETY: The resource must be present, as we would have inserted it if it was empty. let data = unsafe { data.get_mut(last_change_tick, change_tick) .debug_checked_unwrap() }; // SAFETY: The underlying type of the resource is `R`. unsafe { data.with_type::() } } /// Gets a mutable reference to the resource of the given type, if it exists /// Otherwise returns [None] /// /// # Safety /// This will allow aliased mutable access to the given resource type. The caller must ensure /// that there is either only one mutable access or multiple immutable accesses 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 an immutable reference to the non-send resource of the given type, if it exists. /// /// # Panics /// /// Panics if the resource does not exist. /// Use [`get_non_send_resource`](World::get_non_send_resource) instead if you want to handle this case. /// /// This function will panic if it isn't called from the same thread that the resource was inserted from. #[inline] #[track_caller] pub fn non_send_resource(&self) -> &R { match self.get_non_send_resource() { Some(x) => x, None => panic!( "Requested non-send resource {} does not exist in the `World`. Did you forget to add it using `app.insert_non_send_resource` / `app.init_non_send_resource`? Non-send resources can also be be added by plugins.", std::any::type_name::() ), } } /// Gets a mutable reference to the non-send resource of the given type, if it exists. /// /// # Panics /// /// Panics if the resource does not exist. /// Use [`get_non_send_resource_mut`](World::get_non_send_resource_mut) instead if you want to handle this case. /// /// This function will panic if it isn't called from the same thread that the resource was inserted from. #[inline] #[track_caller] pub fn non_send_resource_mut(&mut self) -> Mut<'_, R> { match self.get_non_send_resource_mut() { Some(x) => x, None => panic!( "Requested non-send resource {} does not exist in the `World`. Did you forget to add it using `app.insert_non_send_resource` / `app.init_non_send_resource`? Non-send resources can also be be added by plugins.", std::any::type_name::() ), } } /// Gets a reference to the non-send resource of the given type, if it exists. /// Otherwise returns [None]. /// /// # Panics /// This function will panic if it isn't called from the same thread that the resource was inserted from. #[inline] pub fn get_non_send_resource(&self) -> Option<&R> { let component_id = self.components.get_resource_id(TypeId::of::())?; // SAFETY: 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] /// /// # Panics /// This function will panic if it isn't called from the same thread that the resource was inserted from. #[inline] pub fn get_non_send_resource_mut(&mut self) -> Option> { // SAFETY: 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] /// /// # Panics /// This function will panic if it isn't called from the same thread that the resource was inserted from. /// /// # Safety /// This will allow aliased mutable access to the given non-send resource type. The caller must /// ensure that there is either only one mutable access or multiple immutable accesses 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) } // Shorthand helper function for getting the data and change ticks for a resource. #[inline] pub(crate) fn get_resource_with_ticks( &self, component_id: ComponentId, ) -> Option<(Ptr<'_>, TickCells<'_>)> { self.storages.resources.get(component_id)?.get_with_ticks() } // Shorthand helper function for getting the data and change ticks for a resource. /// /// # Panics /// This function will panic if it isn't called from the same thread that the resource was inserted from. #[inline] pub(crate) fn get_non_send_with_ticks( &self, component_id: ComponentId, ) -> Option<(Ptr<'_>, TickCells<'_>)> { self.storages .non_send_resources .get(component_id)? .get_with_ticks() } // Shorthand helper function for getting the [`ArchetypeComponentId`] for a resource. #[inline] pub(crate) fn get_resource_archetype_component_id( &self, component_id: ComponentId, ) -> Option { let resource = self.storages.resources.get(component_id)?; Some(resource.id()) } // Shorthand helper function for getting the [`ArchetypeComponentId`] for a resource. #[inline] pub(crate) fn get_non_send_archetype_component_id( &self, component_id: ComponentId, ) -> Option { let resource = self.storages.non_send_resources.get(component_id)?; Some(resource.id()) } /// For a given batch of ([Entity], [Bundle]) pairs, either spawns each [Entity] with the given /// bundle (if the entity does not exist), or inserts the [Bundle] (if the entity already exists). /// This is faster than doing equivalent operations one-by-one. /// Returns [Ok] if all entities were successfully inserted into or spawned. Otherwise it returns an [Err] /// with a list of entities that could not be spawned or inserted into. A "spawn or insert" operation can /// only fail if an [Entity] is passed in with an "invalid generation" that conflicts with an existing [Entity]. /// /// # Note /// Spawning a specific `entity` value is rarely the right choice. Most apps should use [`World::spawn_batch`]. /// This method should generally only be used for sharing entities across apps, and only when they have a scheme /// worked out to share an ID space (which doesn't happen by default). /// /// ``` /// use bevy_ecs::{entity::Entity, world::World, component::Component}; /// #[derive(Component)] /// struct A(&'static str); /// #[derive(Component, PartialEq, Debug)] /// struct B(f32); /// /// let mut world = World::new(); /// let e0 = world.spawn_empty().id(); /// let e1 = world.spawn_empty().id(); /// world.insert_or_spawn_batch(vec![ /// (e0, (A("a"), B(0.0))), // the first entity /// (e1, (A("b"), B(1.0))), // the second entity /// ]); /// /// assert_eq!(world.get::(e0), Some(&B(0.0))); /// ``` pub fn insert_or_spawn_batch(&mut self, iter: I) -> Result<(), Vec> where I: IntoIterator, I::IntoIter: Iterator, B: Bundle, { self.flush(); let iter = iter.into_iter(); let change_tick = *self.change_tick.get_mut(); let bundle_info = self .bundles .init_info::(&mut self.components, &mut self.storages); enum SpawnOrInsert<'a, 'b> { Spawn(BundleSpawner<'a, 'b>), Insert(BundleInserter<'a, 'b>, ArchetypeId), } impl<'a, 'b> SpawnOrInsert<'a, 'b> { fn entities(&mut self) -> &mut Entities { match self { SpawnOrInsert::Spawn(spawner) => spawner.entities, SpawnOrInsert::Insert(inserter, _) => inserter.entities, } } } let mut spawn_or_insert = SpawnOrInsert::Spawn(bundle_info.get_bundle_spawner( &mut self.entities, &mut self.archetypes, &mut self.components, &mut self.storages, change_tick, )); let mut invalid_entities = Vec::new(); for (entity, bundle) in iter { match spawn_or_insert .entities() .alloc_at_without_replacement(entity) { AllocAtWithoutReplacement::Exists(location) => { match spawn_or_insert { SpawnOrInsert::Insert(ref mut inserter, archetype) if location.archetype_id == archetype => { // SAFETY: `entity` is valid, `location` matches entity, bundle matches inserter unsafe { inserter.insert(entity, location, bundle) }; } _ => { let mut inserter = bundle_info.get_bundle_inserter( &mut self.entities, &mut self.archetypes, &mut self.components, &mut self.storages, location.archetype_id, change_tick, ); // SAFETY: `entity` is valid, `location` matches entity, bundle matches inserter unsafe { inserter.insert(entity, location, bundle) }; spawn_or_insert = SpawnOrInsert::Insert(inserter, location.archetype_id); } }; } AllocAtWithoutReplacement::DidNotExist => { if let SpawnOrInsert::Spawn(ref mut spawner) = spawn_or_insert { // SAFETY: `entity` is allocated (but non existent), bundle matches inserter unsafe { spawner.spawn_non_existent(entity, bundle) }; } else { let mut spawner = bundle_info.get_bundle_spawner( &mut self.entities, &mut self.archetypes, &mut self.components, &mut self.storages, change_tick, ); // SAFETY: `entity` is valid, `location` matches entity, bundle matches inserter unsafe { spawner.spawn_non_existent(entity, bundle) }; spawn_or_insert = SpawnOrInsert::Spawn(spawner); } } AllocAtWithoutReplacement::ExistsWithWrongGeneration => { invalid_entities.push(entity); } } } if invalid_entities.is_empty() { Ok(()) } else { Err(invalid_entities) } } /// Temporarily removes the requested resource from this [`World`], then re-adds it before returning. /// /// This enables safe simultaneous mutable access to both a resource and the rest of the [`World`]. /// For more complex access patterns, consider using [`SystemState`](crate::system::SystemState). /// /// # Example /// ``` /// use bevy_ecs::prelude::*; /// #[derive(Resource)] /// struct A(u32); /// #[derive(Component)] /// struct B(u32); /// let mut world = World::new(); /// world.insert_resource(A(1)); /// let entity = world.spawn(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 last_change_tick = self.last_change_tick(); let change_tick = self.change_tick(); let component_id = self .components .get_resource_id(TypeId::of::()) .unwrap_or_else(|| panic!("resource does not exist: {}", std::any::type_name::())); // If the resource isn't send and sync, validate that we are on the main thread, so that we can access it. let (ptr, mut ticks) = self .storages .resources .get_mut(component_id) .and_then(|info| info.remove()) .unwrap_or_else(|| panic!("resource does not exist: {}", std::any::type_name::())); // Read the value onto the stack to avoid potential mut aliasing. // SAFETY: pointer is of type R let mut value = unsafe { ptr.read::() }; let value_mut = Mut { value: &mut value, ticks: TicksMut { added: &mut ticks.added, changed: &mut ticks.changed, last_change_tick, change_tick, }, }; let result = f(self, value_mut); assert!(!self.contains_resource::(), "Resource `{}` was inserted during a call to World::resource_scope.\n\ This is not allowed as the original resource is reinserted to the world after the FnOnce param is invoked.", std::any::type_name::()); OwningPtr::make(value, |ptr| { // SAFETY: pointer is of type R unsafe { self.storages .resources .get_mut(component_id) .map(|info| info.insert_with_ticks(ptr, ticks)) .unwrap_or_else(|| { panic!( "No resource of type {} exists in the World.", std::any::type_name::() ) }); } }); result } /// Sends an [`Event`]. #[inline] pub fn send_event(&mut self, event: E) { self.send_event_batch(std::iter::once(event)); } /// Sends the default value of the [`Event`] of type `E`. #[inline] pub fn send_event_default(&mut self) { self.send_event_batch(std::iter::once(E::default())); } /// Sends a batch of [`Event`]s from an iterator. #[inline] pub fn send_event_batch(&mut self, events: impl IntoIterator) { match self.get_resource_mut::>() { Some(mut events_resource) => events_resource.extend(events), None => bevy_utils::tracing::error!( "Unable to send event `{}`\n\tEvent must be added to the app with `add_event()`\n\thttps://docs.rs/bevy/*/bevy/app/struct.App.html#method.add_event ", std::any::type_name::() ), } } /// # Safety /// `component_id` must be assigned to a component of type `R` #[inline] pub(crate) unsafe fn get_resource_with_id( &self, component_id: ComponentId, ) -> Option<&R> { self.storages .resources .get(component_id)? .get_data() .map(|ptr| ptr.deref()) } /// # Safety /// `component_id` must be assigned to a component of type `R` /// 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 (ptr, ticks) = self.get_resource_with_ticks(component_id)?; Some(Mut { value: ptr.assert_unique().deref_mut(), ticks: TicksMut::from_tick_cells( ticks, self.last_change_tick(), self.read_change_tick(), ), }) } /// # Safety /// `component_id` must be assigned to a component of type `R` #[inline] pub(crate) unsafe fn get_non_send_with_id( &self, component_id: ComponentId, ) -> Option<&R> { Some( self.storages .non_send_resources .get(component_id)? .get_data()? .deref::(), ) } /// # Safety /// `component_id` must be assigned to a component of type `R`. /// 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> { let (ptr, ticks) = self .storages .non_send_resources .get(component_id)? .get_with_ticks()?; Some(Mut { value: ptr.assert_unique().deref_mut(), ticks: TicksMut { added: ticks.added.deref_mut(), changed: ticks.changed.deref_mut(), last_change_tick: self.last_change_tick(), change_tick: self.read_change_tick(), }, }) } /// Inserts a new resource with the given `value`. Will replace the value if it already existed. /// /// **You should prefer to use the typed API [`World::insert_resource`] where possible and only /// use this in cases where the actual types are not known at compile time.** /// /// # Safety /// The value referenced by `value` must be valid for the given [`ComponentId`] of this world. #[inline] pub unsafe fn insert_resource_by_id( &mut self, component_id: ComponentId, value: OwningPtr<'_>, ) { let change_tick = self.change_tick(); // SAFETY: value is valid for component_id, ensured by caller self.initialize_resource_internal(component_id) .insert(value, change_tick); } /// Inserts a new `!Send` resource with the given `value`. Will replace the value if it already /// existed. /// /// **You should prefer to use the typed API [`World::insert_non_send_resource`] where possible and only /// use this in cases where the actual types are not known at compile time.** /// /// # Panics /// If a value is already present, this function will panic if not called from the same /// thread that the original value was inserted from. /// /// # Safety /// The value referenced by `value` must be valid for the given [`ComponentId`] of this world. #[inline] pub unsafe fn insert_non_send_by_id( &mut self, component_id: ComponentId, value: OwningPtr<'_>, ) { let change_tick = self.change_tick(); // SAFETY: value is valid for component_id, ensured by caller self.initialize_non_send_internal(component_id) .insert(value, change_tick); } /// # Panics /// Panics if `component_id` is not registered as a `Send` component type in this `World` #[inline] fn initialize_resource_internal( &mut self, component_id: ComponentId, ) -> &mut ResourceData { let archetype_component_count = &mut self.archetypes.archetype_component_count; self.storages .resources .initialize_with(component_id, &self.components, || { let id = ArchetypeComponentId::new(*archetype_component_count); *archetype_component_count += 1; id }) } /// # Panics /// panics if `component_id` is not registered in this world #[inline] fn initialize_non_send_internal( &mut self, component_id: ComponentId, ) -> &mut ResourceData { let archetype_component_count = &mut self.archetypes.archetype_component_count; self.storages .non_send_resources .initialize_with(component_id, &self.components, || { let id = ArchetypeComponentId::new(*archetype_component_count); *archetype_component_count += 1; id }) } pub(crate) fn initialize_resource(&mut self) -> ComponentId { let component_id = self.components.init_resource::(); self.initialize_resource_internal(component_id); component_id } pub(crate) fn initialize_non_send_resource(&mut self) -> ComponentId { let component_id = self.components.init_non_send::(); self.initialize_non_send_internal(component_id); component_id } /// Empties queued entities and adds them to the empty [Archetype](crate::archetype::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(); let table = &mut self.storages.tables[empty_archetype.table_id()]; // PERF: consider pre-allocating space for flushed entities // SAFETY: entity is set to a valid location unsafe { self.entities.flush(|entity, location| { // SAFETY: 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) } /// Reads the current change tick of this world. /// /// If you have exclusive (`&mut`) access to the world, consider using [`change_tick()`](Self::change_tick), /// which is more efficient since it does not require atomic synchronization. #[inline] pub fn read_change_tick(&self) -> u32 { self.change_tick.load(Ordering::Acquire) } /// Reads the current change tick of this world. /// /// This does the same thing as [`read_change_tick()`](Self::read_change_tick), only this method /// is more efficient since it does not require atomic synchronization. #[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 } /// Iterates all component change ticks and clamps any older than [`MAX_CHANGE_AGE`](crate::change_detection::MAX_CHANGE_AGE). /// This prevents overflow and thus prevents false positives. /// /// **Note:** Does nothing if the [`World`] counter has not been incremented at least [`CHECK_TICK_THRESHOLD`](crate::change_detection::CHECK_TICK_THRESHOLD) /// times since the previous pass. // TODO: benchmark and optimize pub fn check_change_ticks(&mut self) { let change_tick = self.change_tick(); if change_tick.wrapping_sub(self.last_check_tick) < CHECK_TICK_THRESHOLD { return; } let Storages { ref mut tables, ref mut sparse_sets, ref mut resources, ref mut non_send_resources, } = self.storages; #[cfg(feature = "trace")] let _span = bevy_utils::tracing::info_span!("check component ticks").entered(); tables.check_change_ticks(change_tick); sparse_sets.check_change_ticks(change_tick); resources.check_change_ticks(change_tick); non_send_resources.check_change_ticks(change_tick); if let Some(mut schedules) = self.get_resource_mut::() { schedules.check_change_ticks(change_tick); } self.last_check_tick = change_tick; } pub fn clear_entities(&mut self) { self.storages.tables.clear(); self.storages.sparse_sets.clear(); self.archetypes.clear_entities(); self.entities.clear(); } } impl World { /// Gets a resource to the resource with the id [`ComponentId`] if it exists. /// The returned pointer must not be used to modify the resource, and must not be /// dereferenced after the immutable borrow of the [`World`] ends. /// /// **You should prefer to use the typed API [`World::get_resource`] where possible and only /// use this in cases where the actual types are not known at compile time.** #[inline] pub fn get_resource_by_id(&self, component_id: ComponentId) -> Option> { self.storages.resources.get(component_id)?.get_data() } /// Gets a resource to the resource with the id [`ComponentId`] if it exists. /// The returned pointer may be used to modify the resource, as long as the mutable borrow /// of the [`World`] is still valid. /// /// **You should prefer to use the typed API [`World::get_resource_mut`] where possible and only /// use this in cases where the actual types are not known at compile time.** #[inline] pub fn get_resource_mut_by_id(&mut self, component_id: ComponentId) -> Option> { let change_tick = self.change_tick(); let (ptr, ticks) = self.get_resource_with_ticks(component_id)?; let ticks = // SAFETY: This function has exclusive access to the world so nothing aliases `ticks`. // - index is in-bounds because the column is initialized and non-empty // - no other reference to the ticks of the same row can exist at the same time unsafe { TicksMut::from_tick_cells(ticks, self.last_change_tick(), change_tick) }; Some(MutUntyped { // SAFETY: This function has exclusive access to the world so nothing aliases `ptr`. value: unsafe { ptr.assert_unique() }, ticks, }) } /// Gets a `!Send` resource to the resource with the id [`ComponentId`] if it exists. /// The returned pointer must not be used to modify the resource, and must not be /// dereferenced after the immutable borrow of the [`World`] ends. /// /// **You should prefer to use the typed API [`World::get_resource`] where possible and only /// use this in cases where the actual types are not known at compile time.** /// /// # Panics /// This function will panic if it isn't called from the same thread that the resource was inserted from. #[inline] pub fn get_non_send_by_id(&self, component_id: ComponentId) -> Option> { self.storages .non_send_resources .get(component_id)? .get_data() } /// Gets a `!Send` resource to the resource with the id [`ComponentId`] if it exists. /// The returned pointer may be used to modify the resource, as long as the mutable borrow /// of the [`World`] is still valid. /// /// **You should prefer to use the typed API [`World::get_resource_mut`] where possible and only /// use this in cases where the actual types are not known at compile time.** /// /// # Panics /// This function will panic if it isn't called from the same thread that the resource was inserted from. #[inline] pub fn get_non_send_mut_by_id(&mut self, component_id: ComponentId) -> Option> { let change_tick = self.change_tick(); let (ptr, ticks) = self.get_non_send_with_ticks(component_id)?; let ticks = // SAFETY: This function has exclusive access to the world so nothing aliases `ticks`. // - index is in-bounds because the column is initialized and non-empty // - no other reference to the ticks of the same row can exist at the same time unsafe { TicksMut::from_tick_cells(ticks, self.last_change_tick(), change_tick) }; Some(MutUntyped { // SAFETY: This function has exclusive access to the world so nothing aliases `ptr`. value: unsafe { ptr.assert_unique() }, ticks, }) } /// Removes the resource of a given type, if it exists. Otherwise returns [None]. /// /// **You should prefer to use the typed API [`World::remove_resource`] where possible and only /// use this in cases where the actual types are not known at compile time.** pub fn remove_resource_by_id(&mut self, component_id: ComponentId) -> Option<()> { self.storages .resources .get_mut(component_id)? .remove_and_drop(); Some(()) } /// Removes the resource of a given type, if it exists. Otherwise returns [None]. /// /// **You should prefer to use the typed API [`World::remove_resource`] where possible and only /// use this in cases where the actual types are not known at compile time.** /// /// # Panics /// This function will panic if it isn't called from the same thread that the resource was inserted from. pub fn remove_non_send_by_id(&mut self, component_id: ComponentId) -> Option<()> { self.storages .non_send_resources .get_mut(component_id)? .remove_and_drop(); Some(()) } /// Retrieves an immutable untyped reference to the given `entity`'s [Component] of the given [`ComponentId`]. /// Returns [None] if the `entity` does not have a [Component] of the given type. /// /// **You should prefer to use the typed API [`World::get_mut`] where possible and only /// use this in cases where the actual types are not known at compile time.** /// /// # Panics /// This function will panic if it isn't called from the same thread that the resource was inserted from. #[inline] pub fn get_by_id(&self, entity: Entity, component_id: ComponentId) -> Option> { let info = self.components().get_info(component_id)?; // SAFETY: // - entity_location is valid // - component_id is valid as checked by the line above // - the storage type is accurate as checked by the fetched ComponentInfo unsafe { self.get_component( component_id, info.storage_type(), entity, self.get_entity(entity)?.location(), ) } } /// Retrieves a mutable untyped reference to the given `entity`'s [Component] of the given [`ComponentId`]. /// Returns [None] if the `entity` does not have a [Component] of the given type. /// /// **You should prefer to use the typed API [`World::get_mut`] where possible and only /// use this in cases where the actual types are not known at compile time.** #[inline] pub fn get_mut_by_id( &mut self, entity: Entity, component_id: ComponentId, ) -> Option> { self.components().get_info(component_id)?; // SAFETY: entity_location is valid, component_id is valid as checked by the line above unsafe { entity_ref::get_mut_by_id( self, entity, self.get_entity(entity)?.location(), component_id, ) } } } impl World { /// Get a raw pointer to a particular [`Component`](crate::component::Component) and its [`ComponentTicks`] identified by their [`TypeId`] /// /// # Safety /// - `storage_type` must accurately reflect where the components for `component_id` are stored. /// - `location` must refer to an archetype that contains `entity` /// - the caller must ensure that no aliasing rules are violated #[inline] pub(crate) unsafe fn get_component_and_ticks_with_type( &self, type_id: TypeId, storage_type: StorageType, entity: Entity, location: EntityLocation, ) -> Option<(Ptr<'_>, TickCells<'_>)> { let component_id = self.components.get_id(type_id)?; // SAFETY: component_id is valid, the rest is deferred to caller self.get_component_and_ticks(component_id, storage_type, entity, location) } /// Get a raw pointer to a particular [`Component`](crate::component::Component) and its [`ComponentTicks`] /// /// # Safety /// - `location` must refer to an archetype that contains `entity` /// - `component_id` must be valid /// - `storage_type` must accurately reflect where the components for `component_id` are stored. /// - the caller must ensure that no aliasing rules are violated #[inline] pub(crate) unsafe fn get_component_and_ticks( &self, component_id: ComponentId, storage_type: StorageType, entity: Entity, location: EntityLocation, ) -> Option<(Ptr<'_>, TickCells<'_>)> { match storage_type { StorageType::Table => { let (components, table_row) = self.fetch_table(location, component_id)?; // SAFETY: archetypes only store valid table_rows and caller ensure aliasing rules Some(( components.get_data_unchecked(table_row), TickCells { added: components.get_added_ticks_unchecked(table_row), changed: components.get_changed_ticks_unchecked(table_row), }, )) } StorageType::SparseSet => self.fetch_sparse_set(component_id)?.get_with_ticks(entity), } } /// Get a raw pointer to a particular [`Component`](crate::component::Component) on a particular [`Entity`], identified by the component's type /// /// # Safety /// - `location` must refer to an archetype that contains `entity` /// the archetype /// - `storage_type` must accurately reflect where the components for `component_id` are stored. /// - the caller must ensure that no aliasing rules are violated #[inline] pub(crate) unsafe fn get_component_with_type( &self, type_id: TypeId, storage_type: StorageType, entity: Entity, location: EntityLocation, ) -> Option> { let component_id = self.components.get_id(type_id)?; // SAFETY: component_id is valid, the rest is deferred to caller self.get_component(component_id, storage_type, entity, location) } /// Get a raw pointer to a particular [`Component`](crate::component::Component) on a particular [`Entity`] in the provided [`World`](crate::world::World). /// /// # Safety /// - `location` must refer to an archetype that contains `entity` /// the archetype /// - `component_id` must be valid /// - `storage_type` must accurately reflect where the components for `component_id` are stored. /// - the caller must ensure that no aliasing rules are violated #[inline] pub(crate) unsafe fn get_component( &self, component_id: ComponentId, storage_type: StorageType, entity: Entity, location: EntityLocation, ) -> Option> { // SAFETY: component_id exists and is therefore valid match storage_type { StorageType::Table => { let (components, table_row) = self.fetch_table(location, component_id)?; // SAFETY: archetypes only store valid table_rows and caller ensure aliasing rules Some(components.get_data_unchecked(table_row)) } StorageType::SparseSet => self.fetch_sparse_set(component_id)?.get(entity), } } /// Get a raw pointer to the [`ComponentTicks`] on a particular [`Entity`], identified by the component's [`TypeId`] /// /// # Safety /// - `location` must refer to an archetype that contains `entity` /// the archetype /// - `storage_type` must accurately reflect where the components for `component_id` are stored. /// - the caller must ensure that no aliasing rules are violated #[inline] pub(crate) unsafe fn get_ticks_with_type( &self, type_id: TypeId, storage_type: StorageType, entity: Entity, location: EntityLocation, ) -> Option { let component_id = self.components.get_id(type_id)?; // SAFETY: component_id is valid, the rest is deferred to caller self.get_ticks(component_id, storage_type, entity, location) } /// Get a raw pointer to the [`ComponentTicks`] on a particular [`Entity`] /// /// # Safety /// - `location` must refer to an archetype that contains `entity` /// the archetype /// - `component_id` must be valid /// - `storage_type` must accurately reflect where the components for `component_id` are stored. /// - the caller must ensure that no aliasing rules are violated #[inline] pub(crate) unsafe fn get_ticks( &self, component_id: ComponentId, storage_type: StorageType, entity: Entity, location: EntityLocation, ) -> Option { match storage_type { StorageType::Table => { let (components, table_row) = self.fetch_table(location, component_id)?; // SAFETY: archetypes only store valid table_rows and caller ensure aliasing rules Some(components.get_ticks_unchecked(table_row)) } StorageType::SparseSet => self.fetch_sparse_set(component_id)?.get_ticks(entity), } } #[inline] fn fetch_table( &self, location: EntityLocation, component_id: ComponentId, ) -> Option<(&Column, TableRow)> { let archetype = &self.archetypes[location.archetype_id]; let table = &self.storages.tables[archetype.table_id()]; let components = table.get_column(component_id)?; let table_row = archetype.entity_table_row(location.archetype_row); Some((components, table_row)) } #[inline] fn fetch_sparse_set(&self, component_id: ComponentId) -> Option<&ComponentSparseSet> { self.storages.sparse_sets.get(component_id) } } 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.storages.resources.len()) .finish() } } // TODO: remove allow on lint - https://github.com/bevyengine/bevy/issues/3666 #[allow(clippy::non_send_fields_in_send_ty)] // SAFETY: all methods on the world ensure that non-send resources are only accessible on the main thread unsafe impl Send for World {} // SAFETY: all methods on the world ensure that non-send resources are only accessible on the main thread unsafe impl Sync for World {} /// Creates an instance of the type this trait is implemented for /// using data from the supplied [World]. /// /// This can be helpful for complex initialization or context-aware defaults. 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() } } #[cfg(test)] mod tests { use super::World; use crate::{ change_detection::DetectChangesMut, component::{ComponentDescriptor, ComponentInfo, StorageType}, ptr::OwningPtr, system::Resource, }; use bevy_ecs_macros::Component; use bevy_utils::{HashMap, HashSet}; use std::{ any::TypeId, panic, sync::{ atomic::{AtomicBool, AtomicU32, Ordering}, Arc, Mutex, }, }; // For bevy_ecs_macros use crate as bevy_ecs; type ID = u8; #[derive(Clone, Copy, Debug, PartialEq, Eq)] enum DropLogItem { Create(ID), Drop(ID), } #[derive(Resource, Component)] struct MayPanicInDrop { drop_log: Arc>>, expected_panic_flag: Arc, should_panic: bool, id: u8, } impl MayPanicInDrop { fn new( drop_log: &Arc>>, expected_panic_flag: &Arc, should_panic: bool, id: u8, ) -> Self { println!("creating component with id {id}"); drop_log.lock().unwrap().push(DropLogItem::Create(id)); Self { drop_log: Arc::clone(drop_log), expected_panic_flag: Arc::clone(expected_panic_flag), should_panic, id, } } } impl Drop for MayPanicInDrop { fn drop(&mut self) { println!("dropping component with id {}", self.id); { let mut drop_log = self.drop_log.lock().unwrap(); drop_log.push(DropLogItem::Drop(self.id)); // Don't keep the mutex while panicking, or we'll poison it. drop(drop_log); } if self.should_panic { self.expected_panic_flag.store(true, Ordering::SeqCst); panic!("testing what happens on panic inside drop"); } } } struct DropTestHelper { drop_log: Arc>>, /// Set to `true` right before we intentionally panic, so that if we get /// a panic, we know if it was intended or not. expected_panic_flag: Arc, } impl DropTestHelper { pub fn new() -> Self { Self { drop_log: Arc::new(Mutex::new(Vec::::new())), expected_panic_flag: Arc::new(AtomicBool::new(false)), } } pub fn make_component(&self, should_panic: bool, id: ID) -> MayPanicInDrop { MayPanicInDrop::new(&self.drop_log, &self.expected_panic_flag, should_panic, id) } pub fn finish(self, panic_res: std::thread::Result<()>) -> Vec { let drop_log = self.drop_log.lock().unwrap(); let expected_panic_flag = self.expected_panic_flag.load(Ordering::SeqCst); if !expected_panic_flag { match panic_res { Ok(()) => panic!("Expected a panic but it didn't happen"), Err(e) => panic::resume_unwind(e), } } drop_log.to_owned() } } #[test] fn panic_while_overwriting_component() { let helper = DropTestHelper::new(); let res = panic::catch_unwind(|| { let mut world = World::new(); world .spawn_empty() .insert(helper.make_component(true, 0)) .insert(helper.make_component(false, 1)); println!("Done inserting! Dropping world..."); }); let drop_log = helper.finish(res); assert_eq!( &*drop_log, [ DropLogItem::Create(0), DropLogItem::Create(1), DropLogItem::Drop(0), DropLogItem::Drop(1), ] ); } #[derive(Resource)] struct TestResource(u32); #[test] fn get_resource_by_id() { let mut world = World::new(); world.insert_resource(TestResource(42)); let component_id = world .components() .get_resource_id(std::any::TypeId::of::()) .unwrap(); let resource = world.get_resource_by_id(component_id).unwrap(); // SAFETY: `TestResource` is the correct resource type let resource = unsafe { resource.deref::() }; assert_eq!(resource.0, 42); } #[test] fn get_resource_mut_by_id() { let mut world = World::new(); world.insert_resource(TestResource(42)); let component_id = world .components() .get_resource_id(std::any::TypeId::of::()) .unwrap(); { let mut resource = world.get_resource_mut_by_id(component_id).unwrap(); resource.set_changed(); // SAFETY: `TestResource` is the correct resource type let resource = unsafe { resource.into_inner().deref_mut::() }; resource.0 = 43; } let resource = world.get_resource_by_id(component_id).unwrap(); // SAFETY: `TestResource` is the correct resource type let resource = unsafe { resource.deref::() }; assert_eq!(resource.0, 43); } #[test] fn custom_resource_with_layout() { static DROP_COUNT: AtomicU32 = AtomicU32::new(0); let mut world = World::new(); // SAFETY: the drop function is valid for the layout and the data will be safe to access from any thread let descriptor = unsafe { ComponentDescriptor::new_with_layout( "Custom Test Component".to_string(), StorageType::Table, std::alloc::Layout::new::<[u8; 8]>(), Some(|ptr| { let data = ptr.read::<[u8; 8]>(); assert_eq!(data, [0, 1, 2, 3, 4, 5, 6, 7]); DROP_COUNT.fetch_add(1, std::sync::atomic::Ordering::SeqCst); }), ) }; let component_id = world.init_component_with_descriptor(descriptor); let value: [u8; 8] = [0, 1, 2, 3, 4, 5, 6, 7]; OwningPtr::make(value, |ptr| { // SAFETY: value is valid for the component layout unsafe { world.insert_resource_by_id(component_id, ptr); } }); // SAFETY: [u8; 8] is the correct type for the resource let data = unsafe { world .get_resource_by_id(component_id) .unwrap() .deref::<[u8; 8]>() }; assert_eq!(*data, [0, 1, 2, 3, 4, 5, 6, 7]); assert!(world.remove_resource_by_id(component_id).is_some()); assert_eq!(DROP_COUNT.load(std::sync::atomic::Ordering::SeqCst), 1); } #[derive(Component)] struct Foo; #[derive(Component)] struct Bar; #[derive(Component)] struct Baz; #[test] fn inspect_entity_components() { let mut world = World::new(); let ent0 = world.spawn((Foo, Bar, Baz)).id(); let ent1 = world.spawn((Foo, Bar)).id(); let ent2 = world.spawn((Bar, Baz)).id(); let ent3 = world.spawn((Foo, Baz)).id(); let ent4 = world.spawn(Foo).id(); let ent5 = world.spawn(Bar).id(); let ent6 = world.spawn(Baz).id(); fn to_type_ids(component_infos: Vec<&ComponentInfo>) -> HashSet> { component_infos .into_iter() .map(|component_info| component_info.type_id()) .collect() } let foo_id = TypeId::of::(); let bar_id = TypeId::of::(); let baz_id = TypeId::of::(); assert_eq!( to_type_ids(world.inspect_entity(ent0)), [Some(foo_id), Some(bar_id), Some(baz_id)].into() ); assert_eq!( to_type_ids(world.inspect_entity(ent1)), [Some(foo_id), Some(bar_id)].into() ); assert_eq!( to_type_ids(world.inspect_entity(ent2)), [Some(bar_id), Some(baz_id)].into() ); assert_eq!( to_type_ids(world.inspect_entity(ent3)), [Some(foo_id), Some(baz_id)].into() ); assert_eq!( to_type_ids(world.inspect_entity(ent4)), [Some(foo_id)].into() ); assert_eq!( to_type_ids(world.inspect_entity(ent5)), [Some(bar_id)].into() ); assert_eq!( to_type_ids(world.inspect_entity(ent6)), [Some(baz_id)].into() ); } #[test] fn iterate_entities() { let mut world = World::new(); let mut entity_counters = HashMap::new(); let iterate_and_count_entities = |world: &World, entity_counters: &mut HashMap<_, _>| { entity_counters.clear(); for entity in world.iter_entities() { let counter = entity_counters.entry(entity.id()).or_insert(0); *counter += 1; } }; // Adding one entity and validating iteration let ent0 = world.spawn((Foo, Bar, Baz)).id(); iterate_and_count_entities(&world, &mut entity_counters); assert_eq!(entity_counters[&ent0], 1); assert_eq!(entity_counters.len(), 1); // Spawning three more entities and then validating iteration let ent1 = world.spawn((Foo, Bar)).id(); let ent2 = world.spawn((Bar, Baz)).id(); let ent3 = world.spawn((Foo, Baz)).id(); iterate_and_count_entities(&world, &mut entity_counters); assert_eq!(entity_counters[&ent0], 1); assert_eq!(entity_counters[&ent1], 1); assert_eq!(entity_counters[&ent2], 1); assert_eq!(entity_counters[&ent3], 1); assert_eq!(entity_counters.len(), 4); // Despawning first entity and then validating the iteration assert!(world.despawn(ent0)); iterate_and_count_entities(&world, &mut entity_counters); assert_eq!(entity_counters[&ent1], 1); assert_eq!(entity_counters[&ent2], 1); assert_eq!(entity_counters[&ent3], 1); assert_eq!(entity_counters.len(), 3); // Spawning three more entities, despawning three and then validating the iteration let ent4 = world.spawn(Foo).id(); let ent5 = world.spawn(Bar).id(); let ent6 = world.spawn(Baz).id(); assert!(world.despawn(ent2)); assert!(world.despawn(ent3)); assert!(world.despawn(ent4)); iterate_and_count_entities(&world, &mut entity_counters); assert_eq!(entity_counters[&ent1], 1); assert_eq!(entity_counters[&ent5], 1); assert_eq!(entity_counters[&ent6], 1); assert_eq!(entity_counters.len(), 3); // Despawning remaining entities and then validating the iteration assert!(world.despawn(ent1)); assert!(world.despawn(ent5)); assert!(world.despawn(ent6)); iterate_and_count_entities(&world, &mut entity_counters); assert_eq!(entity_counters.len(), 0); } #[test] fn spawn_empty_bundle() { let mut world = World::new(); world.spawn(()); } }