bevy_ecs/world/
deferred_world.rs

1use core::ops::Deref;
2
3use crate::{
4    archetype::Archetype,
5    change_detection::MutUntyped,
6    component::ComponentId,
7    entity::Entity,
8    event::{Event, EventId, Events, SendBatchIds},
9    observer::{Observers, TriggerTargets},
10    prelude::{Component, QueryState},
11    query::{QueryData, QueryFilter},
12    system::{Commands, Query, Resource},
13    traversal::Traversal,
14    world::{error::EntityFetchError, WorldEntityFetch},
15};
16
17use super::{unsafe_world_cell::UnsafeWorldCell, Mut, World};
18
19/// A [`World`] reference that disallows structural ECS changes.
20/// This includes initializing resources, registering components or spawning entities.
21pub struct DeferredWorld<'w> {
22    // SAFETY: Implementors must not use this reference to make structural changes
23    world: UnsafeWorldCell<'w>,
24}
25
26impl<'w> Deref for DeferredWorld<'w> {
27    type Target = World;
28
29    fn deref(&self) -> &Self::Target {
30        // SAFETY: Structural changes cannot be made through &World
31        unsafe { self.world.world() }
32    }
33}
34
35impl<'w> UnsafeWorldCell<'w> {
36    /// Turn self into a [`DeferredWorld`]
37    ///
38    /// # Safety
39    /// Caller must ensure there are no outstanding mutable references to world and no
40    /// outstanding references to the world's command queue, resource or component data
41    #[inline]
42    pub unsafe fn into_deferred(self) -> DeferredWorld<'w> {
43        DeferredWorld { world: self }
44    }
45}
46
47impl<'w> From<&'w mut World> for DeferredWorld<'w> {
48    fn from(world: &'w mut World) -> DeferredWorld<'w> {
49        DeferredWorld {
50            world: world.as_unsafe_world_cell(),
51        }
52    }
53}
54
55impl<'w> DeferredWorld<'w> {
56    /// Reborrow self as a new instance of [`DeferredWorld`]
57    #[inline]
58    pub fn reborrow(&mut self) -> DeferredWorld {
59        DeferredWorld { world: self.world }
60    }
61
62    /// Creates a [`Commands`] instance that pushes to the world's command queue
63    #[inline]
64    pub fn commands(&mut self) -> Commands {
65        // SAFETY: &mut self ensure that there are no outstanding accesses to the queue
66        let command_queue = unsafe { self.world.get_raw_command_queue() };
67        // SAFETY: command_queue is stored on world and always valid while the world exists
68        unsafe { Commands::new_raw_from_entities(command_queue, self.world.entities()) }
69    }
70
71    /// Retrieves a mutable reference to the given `entity`'s [`Component`] of the given type.
72    /// Returns `None` if the `entity` does not have a [`Component`] of the given type.
73    #[inline]
74    pub fn get_mut<T: Component>(&mut self, entity: Entity) -> Option<Mut<T>> {
75        // SAFETY:
76        // - `as_unsafe_world_cell` is the only thing that is borrowing world
77        // - `as_unsafe_world_cell` provides mutable permission to everything
78        // - `&mut self` ensures no other borrows on world data
79        unsafe { self.world.get_entity(entity)?.get_mut() }
80    }
81
82    /// Returns [`EntityMut`]s that expose read and write operations for the
83    /// given `entities`, returning [`Err`] if any of the given entities do not
84    /// exist. Instead of immediately unwrapping the value returned from this
85    /// function, prefer [`World::entity_mut`].
86    ///
87    /// This function supports fetching a single entity or multiple entities:
88    /// - Pass an [`Entity`] to receive a single [`EntityMut`].
89    /// - Pass a slice of [`Entity`]s to receive a [`Vec<EntityMut>`].
90    /// - Pass an array of [`Entity`]s to receive an equally-sized array of [`EntityMut`]s.
91    /// - Pass an [`&EntityHashSet`] to receive an [`EntityHashMap<EntityMut>`].
92    ///
93    /// **As [`DeferredWorld`] does not allow structural changes, all returned
94    /// references are [`EntityMut`]s, which do not allow structural changes
95    /// (i.e. adding/removing components or despawning the entity).**
96    ///
97    /// # Errors
98    ///
99    /// - Returns [`EntityFetchError::NoSuchEntity`] if any of the given `entities` do not exist in the world.
100    ///     - Only the first entity found to be missing will be returned.
101    /// - Returns [`EntityFetchError::AliasedMutability`] if the same entity is requested multiple times.
102    ///
103    /// # Examples
104    ///
105    /// For examples, see [`DeferredWorld::entity_mut`].
106    ///
107    /// [`EntityMut`]: crate::world::EntityMut
108    /// [`&EntityHashSet`]: crate::entity::EntityHashSet
109    /// [`EntityHashMap<EntityMut>`]: crate::entity::EntityHashMap
110    #[inline]
111    pub fn get_entity_mut<F: WorldEntityFetch>(
112        &mut self,
113        entities: F,
114    ) -> Result<F::DeferredMut<'_>, EntityFetchError> {
115        let cell = self.as_unsafe_world_cell();
116        // SAFETY: `&mut self` gives mutable access to the entire world,
117        // and prevents any other access to the world.
118        unsafe { entities.fetch_deferred_mut(cell) }
119    }
120
121    /// Returns [`EntityMut`]s that expose read and write operations for the
122    /// given `entities`. This will panic if any of the given entities do not
123    /// exist. Use [`DeferredWorld::get_entity_mut`] if you want to check for
124    /// entity existence instead of implicitly panicking.
125    ///
126    /// This function supports fetching a single entity or multiple entities:
127    /// - Pass an [`Entity`] to receive a single [`EntityMut`].
128    /// - Pass a slice of [`Entity`]s to receive a [`Vec<EntityMut>`].
129    /// - Pass an array of [`Entity`]s to receive an equally-sized array of [`EntityMut`]s.
130    /// - Pass an [`&EntityHashSet`] to receive an [`EntityHashMap<EntityMut>`].
131    ///
132    /// **As [`DeferredWorld`] does not allow structural changes, all returned
133    /// references are [`EntityMut`]s, which do not allow structural changes
134    /// (i.e. adding/removing components or despawning the entity).**
135    ///
136    /// # Panics
137    ///
138    /// If any of the given `entities` do not exist in the world.
139    ///
140    /// # Examples
141    ///
142    /// ## Single [`Entity`]
143    ///
144    /// ```
145    /// # use bevy_ecs::{prelude::*, world::DeferredWorld};
146    /// #[derive(Component)]
147    /// struct Position {
148    ///   x: f32,
149    ///   y: f32,
150    /// }
151    ///
152    /// # let mut world = World::new();
153    /// # let entity = world.spawn(Position { x: 0.0, y: 0.0 }).id();
154    /// let mut world: DeferredWorld = // ...
155    /// #   DeferredWorld::from(&mut world);
156    ///
157    /// let mut entity_mut = world.entity_mut(entity);
158    /// let mut position = entity_mut.get_mut::<Position>().unwrap();
159    /// position.y = 1.0;
160    /// assert_eq!(position.x, 0.0);
161    /// ```
162    ///
163    /// ## Array of [`Entity`]s
164    ///
165    /// ```
166    /// # use bevy_ecs::{prelude::*, world::DeferredWorld};
167    /// #[derive(Component)]
168    /// struct Position {
169    ///   x: f32,
170    ///   y: f32,
171    /// }
172    ///
173    /// # let mut world = World::new();
174    /// # let e1 = world.spawn(Position { x: 0.0, y: 0.0 }).id();
175    /// # let e2 = world.spawn(Position { x: 1.0, y: 1.0 }).id();
176    /// let mut world: DeferredWorld = // ...
177    /// #   DeferredWorld::from(&mut world);
178    ///
179    /// let [mut e1_ref, mut e2_ref] = world.entity_mut([e1, e2]);
180    /// let mut e1_position = e1_ref.get_mut::<Position>().unwrap();
181    /// e1_position.x = 1.0;
182    /// assert_eq!(e1_position.x, 1.0);
183    /// let mut e2_position = e2_ref.get_mut::<Position>().unwrap();
184    /// e2_position.x = 2.0;
185    /// assert_eq!(e2_position.x, 2.0);
186    /// ```
187    ///
188    /// ## Slice of [`Entity`]s
189    ///
190    /// ```
191    /// # use bevy_ecs::{prelude::*, world::DeferredWorld};
192    /// #[derive(Component)]
193    /// struct Position {
194    ///   x: f32,
195    ///   y: f32,
196    /// }
197    ///
198    /// # let mut world = World::new();
199    /// # let e1 = world.spawn(Position { x: 0.0, y: 1.0 }).id();
200    /// # let e2 = world.spawn(Position { x: 0.0, y: 1.0 }).id();
201    /// # let e3 = world.spawn(Position { x: 0.0, y: 1.0 }).id();
202    /// let mut world: DeferredWorld = // ...
203    /// #   DeferredWorld::from(&mut world);
204    ///
205    /// let ids = vec![e1, e2, e3];
206    /// for mut eref in world.entity_mut(&ids[..]) {
207    ///     let mut pos = eref.get_mut::<Position>().unwrap();
208    ///     pos.y = 2.0;
209    ///     assert_eq!(pos.y, 2.0);
210    /// }
211    /// ```
212    ///
213    /// ## [`&EntityHashSet`]
214    ///
215    /// ```
216    /// # use bevy_ecs::{prelude::*, entity::EntityHashSet, world::DeferredWorld};
217    /// #[derive(Component)]
218    /// struct Position {
219    ///   x: f32,
220    ///   y: f32,
221    /// }
222    ///
223    /// # let mut world = World::new();
224    /// # let e1 = world.spawn(Position { x: 0.0, y: 1.0 }).id();
225    /// # let e2 = world.spawn(Position { x: 0.0, y: 1.0 }).id();
226    /// # let e3 = world.spawn(Position { x: 0.0, y: 1.0 }).id();
227    /// let mut world: DeferredWorld = // ...
228    /// #   DeferredWorld::from(&mut world);
229    ///
230    /// let ids = EntityHashSet::from_iter([e1, e2, e3]);
231    /// for (_id, mut eref) in world.entity_mut(&ids) {
232    ///     let mut pos = eref.get_mut::<Position>().unwrap();
233    ///     pos.y = 2.0;
234    ///     assert_eq!(pos.y, 2.0);
235    /// }
236    /// ```
237    ///
238    /// [`EntityMut`]: crate::world::EntityMut
239    /// [`&EntityHashSet`]: crate::entity::EntityHashSet
240    /// [`EntityHashMap<EntityMut>`]: crate::entity::EntityHashMap
241    #[inline]
242    pub fn entity_mut<F: WorldEntityFetch>(&mut self, entities: F) -> F::DeferredMut<'_> {
243        self.get_entity_mut(entities).unwrap()
244    }
245
246    /// Returns [`Query`] for the given [`QueryState`], which is used to efficiently
247    /// run queries on the [`World`] by storing and reusing the [`QueryState`].
248    ///
249    /// # Panics
250    /// If state is from a different world then self
251    #[inline]
252    pub fn query<'s, D: QueryData, F: QueryFilter>(
253        &mut self,
254        state: &'s mut QueryState<D, F>,
255    ) -> Query<'_, 's, D, F> {
256        state.validate_world(self.world.id());
257        state.update_archetypes(self);
258        // SAFETY: We ran validate_world to ensure our state matches
259        unsafe {
260            let world_cell = self.world;
261            Query::new(
262                world_cell,
263                state,
264                world_cell.last_change_tick(),
265                world_cell.change_tick(),
266            )
267        }
268    }
269
270    /// Gets a mutable reference to the resource of the given type
271    ///
272    /// # Panics
273    ///
274    /// Panics if the resource does not exist.
275    /// Use [`get_resource_mut`](DeferredWorld::get_resource_mut) instead if you want to handle this case.
276    #[inline]
277    #[track_caller]
278    pub fn resource_mut<R: Resource>(&mut self) -> Mut<'_, R> {
279        match self.get_resource_mut() {
280            Some(x) => x,
281            None => panic!(
282                "Requested resource {} does not exist in the `World`.
283                Did you forget to add it using `app.insert_resource` / `app.init_resource`?
284                Resources are also implicitly added via `app.add_event`,
285                and can be added by plugins.",
286                core::any::type_name::<R>()
287            ),
288        }
289    }
290
291    /// Gets a mutable reference to the resource of the given type if it exists
292    #[inline]
293    pub fn get_resource_mut<R: Resource>(&mut self) -> Option<Mut<'_, R>> {
294        // SAFETY: &mut self ensure that there are no outstanding accesses to the resource
295        unsafe { self.world.get_resource_mut() }
296    }
297
298    /// Gets a mutable reference to the non-send resource of the given type, if it exists.
299    ///
300    /// # Panics
301    ///
302    /// Panics if the resource does not exist.
303    /// Use [`get_non_send_resource_mut`](World::get_non_send_resource_mut) instead if you want to handle this case.
304    ///
305    /// This function will panic if it isn't called from the same thread that the resource was inserted from.
306    #[inline]
307    #[track_caller]
308    pub fn non_send_resource_mut<R: 'static>(&mut self) -> Mut<'_, R> {
309        match self.get_non_send_resource_mut() {
310            Some(x) => x,
311            None => panic!(
312                "Requested non-send resource {} does not exist in the `World`.
313                Did you forget to add it using `app.insert_non_send_resource` / `app.init_non_send_resource`?
314                Non-send resources can also be added by plugins.",
315                core::any::type_name::<R>()
316            ),
317        }
318    }
319
320    /// Gets a mutable reference to the non-send resource of the given type, if it exists.
321    /// Otherwise returns `None`.
322    ///
323    /// # Panics
324    /// This function will panic if it isn't called from the same thread that the resource was inserted from.
325    #[inline]
326    pub fn get_non_send_resource_mut<R: 'static>(&mut self) -> Option<Mut<'_, R>> {
327        // SAFETY: &mut self ensure that there are no outstanding accesses to the resource
328        unsafe { self.world.get_non_send_resource_mut() }
329    }
330
331    /// Sends an [`Event`].
332    /// This method returns the [ID](`EventId`) of the sent `event`,
333    /// or [`None`] if the `event` could not be sent.
334    #[inline]
335    pub fn send_event<E: Event>(&mut self, event: E) -> Option<EventId<E>> {
336        self.send_event_batch(core::iter::once(event))?.next()
337    }
338
339    /// Sends the default value of the [`Event`] of type `E`.
340    /// This method returns the [ID](`EventId`) of the sent `event`,
341    /// or [`None`] if the `event` could not be sent.
342    #[inline]
343    pub fn send_event_default<E: Event + Default>(&mut self) -> Option<EventId<E>> {
344        self.send_event(E::default())
345    }
346
347    /// Sends a batch of [`Event`]s from an iterator.
348    /// This method returns the [IDs](`EventId`) of the sent `events`,
349    /// or [`None`] if the `event` could not be sent.
350    #[inline]
351    pub fn send_event_batch<E: Event>(
352        &mut self,
353        events: impl IntoIterator<Item = E>,
354    ) -> Option<SendBatchIds<E>> {
355        let Some(mut events_resource) = self.get_resource_mut::<Events<E>>() else {
356            bevy_utils::tracing::error!(
357                "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 ",
358                core::any::type_name::<E>()
359            );
360            return None;
361        };
362        Some(events_resource.send_batch(events))
363    }
364
365    /// Gets a pointer to the resource with the id [`ComponentId`] if it exists.
366    /// The returned pointer may be used to modify the resource, as long as the mutable borrow
367    /// of the [`World`] is still valid.
368    ///
369    /// **You should prefer to use the typed API [`World::get_resource_mut`] where possible and only
370    /// use this in cases where the actual types are not known at compile time.**
371    #[inline]
372    pub fn get_resource_mut_by_id(&mut self, component_id: ComponentId) -> Option<MutUntyped<'_>> {
373        // SAFETY: &mut self ensure that there are no outstanding accesses to the resource
374        unsafe { self.world.get_resource_mut_by_id(component_id) }
375    }
376
377    /// Gets a `!Send` resource to the resource with the id [`ComponentId`] if it exists.
378    /// The returned pointer may be used to modify the resource, as long as the mutable borrow
379    /// of the [`World`] is still valid.
380    ///
381    /// **You should prefer to use the typed API [`World::get_resource_mut`] where possible and only
382    /// use this in cases where the actual types are not known at compile time.**
383    ///
384    /// # Panics
385    /// This function will panic if it isn't called from the same thread that the resource was inserted from.
386    #[inline]
387    pub fn get_non_send_mut_by_id(&mut self, component_id: ComponentId) -> Option<MutUntyped<'_>> {
388        // SAFETY: &mut self ensure that there are no outstanding accesses to the resource
389        unsafe { self.world.get_non_send_resource_mut_by_id(component_id) }
390    }
391
392    /// Retrieves a mutable untyped reference to the given `entity`'s [`Component`] of the given [`ComponentId`].
393    /// Returns `None` if the `entity` does not have a [`Component`] of the given type.
394    ///
395    /// **You should prefer to use the typed API [`World::get_mut`] where possible and only
396    /// use this in cases where the actual types are not known at compile time.**
397    #[inline]
398    pub fn get_mut_by_id(
399        &mut self,
400        entity: Entity,
401        component_id: ComponentId,
402    ) -> Option<MutUntyped<'_>> {
403        // SAFETY: &mut self ensure that there are no outstanding accesses to the resource
404        unsafe { self.world.get_entity(entity)?.get_mut_by_id(component_id) }
405    }
406
407    /// Triggers all `on_add` hooks for [`ComponentId`] in target.
408    ///
409    /// # Safety
410    /// Caller must ensure [`ComponentId`] in target exist in self.
411    #[inline]
412    pub(crate) unsafe fn trigger_on_add(
413        &mut self,
414        archetype: &Archetype,
415        entity: Entity,
416        targets: impl Iterator<Item = ComponentId>,
417    ) {
418        if archetype.has_add_hook() {
419            for component_id in targets {
420                // SAFETY: Caller ensures that these components exist
421                let hooks = unsafe { self.components().get_info_unchecked(component_id) }.hooks();
422                if let Some(hook) = hooks.on_add {
423                    hook(DeferredWorld { world: self.world }, entity, component_id);
424                }
425            }
426        }
427    }
428
429    /// Triggers all `on_insert` hooks for [`ComponentId`] in target.
430    ///
431    /// # Safety
432    /// Caller must ensure [`ComponentId`] in target exist in self.
433    #[inline]
434    pub(crate) unsafe fn trigger_on_insert(
435        &mut self,
436        archetype: &Archetype,
437        entity: Entity,
438        targets: impl Iterator<Item = ComponentId>,
439    ) {
440        if archetype.has_insert_hook() {
441            for component_id in targets {
442                // SAFETY: Caller ensures that these components exist
443                let hooks = unsafe { self.components().get_info_unchecked(component_id) }.hooks();
444                if let Some(hook) = hooks.on_insert {
445                    hook(DeferredWorld { world: self.world }, entity, component_id);
446                }
447            }
448        }
449    }
450
451    /// Triggers all `on_replace` hooks for [`ComponentId`] in target.
452    ///
453    /// # Safety
454    /// Caller must ensure [`ComponentId`] in target exist in self.
455    #[inline]
456    pub(crate) unsafe fn trigger_on_replace(
457        &mut self,
458        archetype: &Archetype,
459        entity: Entity,
460        targets: impl Iterator<Item = ComponentId>,
461    ) {
462        if archetype.has_replace_hook() {
463            for component_id in targets {
464                // SAFETY: Caller ensures that these components exist
465                let hooks = unsafe { self.components().get_info_unchecked(component_id) }.hooks();
466                if let Some(hook) = hooks.on_replace {
467                    hook(DeferredWorld { world: self.world }, entity, component_id);
468                }
469            }
470        }
471    }
472
473    /// Triggers all `on_remove` hooks for [`ComponentId`] in target.
474    ///
475    /// # Safety
476    /// Caller must ensure [`ComponentId`] in target exist in self.
477    #[inline]
478    pub(crate) unsafe fn trigger_on_remove(
479        &mut self,
480        archetype: &Archetype,
481        entity: Entity,
482        targets: impl Iterator<Item = ComponentId>,
483    ) {
484        if archetype.has_remove_hook() {
485            for component_id in targets {
486                // SAFETY: Caller ensures that these components exist
487                let hooks = unsafe { self.components().get_info_unchecked(component_id) }.hooks();
488                if let Some(hook) = hooks.on_remove {
489                    hook(DeferredWorld { world: self.world }, entity, component_id);
490                }
491            }
492        }
493    }
494
495    /// Triggers all event observers for [`ComponentId`] in target.
496    ///
497    /// # Safety
498    /// Caller must ensure observers listening for `event` can accept ZST pointers
499    #[inline]
500    pub(crate) unsafe fn trigger_observers(
501        &mut self,
502        event: ComponentId,
503        entity: Entity,
504        components: impl Iterator<Item = ComponentId> + Clone,
505    ) {
506        Observers::invoke::<_>(
507            self.reborrow(),
508            event,
509            entity,
510            components,
511            &mut (),
512            &mut false,
513        );
514    }
515
516    /// Triggers all event observers for [`ComponentId`] in target.
517    ///
518    /// # Safety
519    /// Caller must ensure `E` is accessible as the type represented by `event`
520    #[inline]
521    pub(crate) unsafe fn trigger_observers_with_data<E, T>(
522        &mut self,
523        event: ComponentId,
524        mut entity: Entity,
525        components: &[ComponentId],
526        data: &mut E,
527        mut propagate: bool,
528    ) where
529        T: Traversal,
530    {
531        loop {
532            Observers::invoke::<_>(
533                self.reborrow(),
534                event,
535                entity,
536                components.iter().copied(),
537                data,
538                &mut propagate,
539            );
540            if !propagate {
541                break;
542            }
543            if let Some(traverse_to) = self
544                .get_entity(entity)
545                .ok()
546                .and_then(|entity| entity.get_components::<T>())
547                .and_then(T::traverse)
548            {
549                entity = traverse_to;
550            } else {
551                break;
552            }
553        }
554    }
555
556    /// Sends a "global" [`Trigger`](crate::observer::Trigger) without any targets.
557    pub fn trigger<T: Event>(&mut self, trigger: impl Event) {
558        self.commands().trigger(trigger);
559    }
560
561    /// Sends a [`Trigger`](crate::observer::Trigger) with the given `targets`.
562    pub fn trigger_targets(
563        &mut self,
564        trigger: impl Event,
565        targets: impl TriggerTargets + Send + Sync + 'static,
566    ) {
567        self.commands().trigger_targets(trigger, targets);
568    }
569
570    /// Gets an [`UnsafeWorldCell`] containing the underlying world.
571    ///
572    /// # Safety
573    /// - must only be used to make non-structural ECS changes
574    #[inline]
575    pub(crate) fn as_unsafe_world_cell(&mut self) -> UnsafeWorldCell {
576        self.world
577    }
578}