mod entity_ref; mod spawn_batch; mod world_cell; pub use crate::change_detection::Mut; pub use entity_ref::*; pub use spawn_batch::*; pub use world_cell::*; use crate::{ archetype::{ArchetypeComponentId, ArchetypeComponentInfo, ArchetypeId, Archetypes}, bundle::{Bundle, BundleInserter, BundleSpawner, Bundles}, change_detection::Ticks, component::{Component, ComponentId, ComponentTicks, Components, StorageType}, entity::{AllocAtWithoutReplacement, Entities, Entity}, query::{FilterFetch, QueryState, WorldQuery}, storage::{Column, SparseSet, Storages}, system::Resource, }; use std::{ any::TypeId, fmt, mem::ManuallyDrop, 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 *resources*, 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. /// /// ## Usage of global resources /// /// 1. Insert the resource into the `World`, using [`World::insert_resource`]. /// 2. Fetch the resource from a system, using [`Res`](crate::system::Res) or [`ResMut`](crate::system::ResMut). /// /// ``` /// # let mut world = World::default(); /// # let mut schedule = Schedule::default(); /// # schedule.add_stage("update", SystemStage::parallel()); /// # use bevy_ecs::prelude::*; /// # /// struct MyResource { value: u32 } /// /// world.insert_resource(MyResource { value: 42 }); /// /// fn read_resource_system(resource: Res) { /// assert_eq!(resource.value, 42); /// } /// /// fn write_resource_system(mut resource: ResMut) { /// assert_eq!(resource.value, 42); /// resource.value = 0; /// assert_eq!(resource.value, 0); /// } /// # /// # schedule.add_system_to_stage("update", read_resource_system.label("first")); /// # schedule.add_system_to_stage("update", write_resource_system.after("first")); /// # schedule.run_once(&mut 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: WorldId::new().expect("More `bevy` `World`s have been created than is supported"), 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] /// # 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) } pub fn init_component(&mut self) -> ComponentId { self.components.init_component::(&mut self.storages) } /// 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() /// .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 { // Lazily evaluate panic!() via unwrap_or_else() to avoid allocation unless failure self.get_entity(entity) .unwrap_or_else(|| panic!("Entity {:?} does not exist", entity)) } /// 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() /// .insert(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 {:?} does not exist", entity)) } /// 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) => { // SAFE: `entity` exists and `location` is that entity's location Some(unsafe { EntityMut::new(self, entity, location) }) } AllocAtWithoutReplacement::DidNotExist => { // SAFE: entity was just allocated Some(unsafe { self.spawn_at_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() /// .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::{component::Component, world::World}; /// /// #[derive(Component)] /// 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::{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() /// .insert(Position { x: 0.0, y: 0.0 }) // add a single component /// .insert_bundle((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(&mut self) -> EntityMut { self.flush(); let entity = self.entities.alloc(); // SAFE: entity was just allocated unsafe { self.spawn_at_internal(entity) } } /// # Safety /// must be called on an entity that was just allocated unsafe fn spawn_at_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); // 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::{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() /// .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::{component::Component, world::World}; /// /// #[derive(Component)] /// 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> { // SAFE: lifetimes enforce correct usage of returned borrow unsafe { self.get_entity_mut(entity)?.get_unchecked_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::{component::Component, world::World}; /// /// #[derive(Component)] /// 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::{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().insert_bundle((Order(2), Label("second"))).id(); /// let b = world.spawn().insert_bundle((Order(3), Label("third"))).id(); /// let c = world.spawn().insert_bundle((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 { 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::{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().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 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) { if !self.contains_resource::() { let resource = R::from_world(self); self.insert_resource(resource); } } /// 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::(); // 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 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_non_send_resource(&mut self) { if !self.contains_resource::() { let resource = R::from_world(self); self.insert_non_send_resource(resource); } } /// 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. #[inline] pub fn insert_non_send_resource(&mut self, value: R) { self.validate_non_send_access::(); let component_id = self.components.init_non_send::(); // SAFE: component_id just initialized and corresponds to resource of type R 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]. #[inline] pub fn remove_resource(&mut self) -> Option { // SAFE: R is Send + Sync unsafe { self.remove_resource_unchecked() } } #[inline] pub fn remove_non_send_resource(&mut self) -> Option { self.validate_non_send_access::(); // SAFE: we are on main thread unsafe { self.remove_resource_unchecked() } } #[inline] /// # Safety /// Only remove `NonSend` resources from the main thread /// as they cannot be sent across theads #[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 R is dropped let (ptr, _) = unsafe { column.swap_remove_and_forget_unchecked(0) }; // SAFE: column is of type R Some(unsafe { ptr.cast::().read() }) } /// Returns `true` if a resource of type `R` 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() } pub fn is_resource_added(&self) -> bool { let component_id = if let Some(component_id) = self.components.get_resource_id(TypeId::of::()) { component_id } else { return false; }; let column = if let Some(column) = self.get_populated_resource_column(component_id) { column } else { return false; }; // SAFE: resources table always have row 0 let ticks = unsafe { column.get_ticks_unchecked(0) }; ticks.is_added(self.last_change_tick(), self.read_change_tick()) } pub fn is_resource_changed(&self) -> bool { let component_id = if let Some(component_id) = self.components.get_resource_id(TypeId::of::()) { component_id } else { return false; }; let column = if let Some(column) = self.get_populated_resource_column(component_id) { column } else { return false; }; // SAFE: resources table always have row 0 let ticks = unsafe { column.get_ticks_unchecked(0) }; ticks.is_changed(self.last_change_tick(), self.read_change_tick()) } /// 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.add_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.add_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::())?; // SAFE: unique world access 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> { // SAFE: unique world access unsafe { self.get_resource_unchecked_mut() } } // PERF: optimize this to avoid redundant lookups /// 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> { if !self.contains_resource::() { self.insert_resource(func()); } self.resource_mut() } /// 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 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 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. #[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.add_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. #[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.add_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] #[inline] pub fn get_non_send_resource(&self) -> Option<&R> { 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] #[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] /// /// # 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) } /// 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().id(); /// let e1 = world.spawn().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 => { // SAFE: `entity` is valid, `location` matches entity, bundle matches inserter unsafe { inserter.insert(entity, location.index, 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, ); // SAFE: `entity` is valid, `location` matches entity, bundle matches inserter unsafe { inserter.insert(entity, location.index, bundle) }; spawn_or_insert = SpawnOrInsert::Insert(inserter, location.archetype_id); } }; } AllocAtWithoutReplacement::DidNotExist => { if let SpawnOrInsert::Spawn(ref mut spawner) = spawn_or_insert { // SAFE: `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, ); // SAFE: `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::{component::Component, world::{World, Mut}}; /// #[derive(Component)] /// struct A(u32); /// #[derive(Component)] /// 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::()) }); assert!( !column.is_empty(), "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 R is dropped unsafe { column.swap_remove_and_forget_unchecked(0) } }; // SAFE: pointer is of type T and valid to move out of // Read the value onto the stack to avoid potential mut aliasing. let mut value = unsafe { std::ptr::read(ptr.cast::()) }; let value_mut = Mut { value: &mut value, ticks: Ticks { component_ticks: &mut ticks, last_change_tick: self.last_change_tick(), change_tick: self.change_tick(), }, }; let result = f(self, value_mut); assert!(!self.contains_resource::()); 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::())); // Wrap the value in MaybeUninit to prepare for passing the value back into the ECS let mut nodrop_wrapped_value = std::mem::MaybeUninit::new(value); unsafe { // SAFE: pointer is of type T, and valid to move out of column.push(nodrop_wrapped_value.as_mut_ptr() as *mut _, ticks); } result } /// # 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> { let column = self.get_populated_resource_column(component_id)?; Some(&*column.get_data_ptr().as_ptr().cast::()) } /// # 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 column = self.get_populated_resource_column(component_id)?; Some(Mut { value: &mut *column.get_data_ptr().cast::().as_ptr(), ticks: Ticks { component_ticks: &mut *column.get_ticks_mut_ptr_unchecked(0), last_change_tick: self.last_change_tick(), 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> { self.validate_non_send_access::(); self.get_resource_with_id(component_id) } /// # 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> { 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 `R` #[inline] unsafe fn insert_resource_with_id(&mut self, component_id: ComponentId, value: R) { let change_tick = self.change_tick(); let column = self.initialize_resource_internal(component_id); if column.is_empty() { let mut value = ManuallyDrop::new(value); // SAFE: column is of type R and has been allocated above let data = (&mut *value as *mut R).cast::(); column.push(data, ComponentTicks::new(change_tick)); } else { // SAFE: column is of type R and has already been allocated *column.get_data_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 `R` #[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.init_resource::(); // 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.init_non_send::(); // 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) { assert!( self.main_thread_validator.is_main_thread(), "attempted to access NonSend resource {} off of the main thread", std::any::type_name::(), ); } /// 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(); unsafe { let table = &mut self.storages.tables[empty_archetype.table_id()]; // PERF: consider pre-allocating space for flushed entities // SAFE: entity is set to a valid location 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); } } pub fn clear_entities(&mut self) { self.storages.tables.clear(); self.storages.sparse_sets.clear(); self.archetypes.clear_entities(); self.entities.clear(); } } 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() } } // TODO: remove allow on lint - https://github.com/bevyengine/bevy/issues/3666 #[allow(clippy::non_send_fields_in_send_ty)] unsafe impl Send for World {} 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() } } 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(), } } } #[cfg(test)] mod tests { use super::World; use bevy_ecs_macros::Component; use std::{ panic, sync::{ atomic::{AtomicBool, 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(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 = Arc::try_unwrap(self.drop_log) .unwrap() .into_inner() .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 } } #[test] fn panic_while_overwriting_component() { let helper = DropTestHelper::new(); let res = panic::catch_unwind(|| { let mut world = World::new(); world .spawn() .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) ] ); } }