bevy_ecs/world/
deferred_world.rs

1use std::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};
14
15use super::{
16    unsafe_world_cell::{UnsafeEntityCell, UnsafeWorldCell},
17    EntityMut, Mut, World,
18};
19
20/// A [`World`] reference that disallows structural ECS changes.
21/// This includes initializing resources, registering components or spawning entities.
22pub struct DeferredWorld<'w> {
23    // SAFETY: Implementors must not use this reference to make structural changes
24    world: UnsafeWorldCell<'w>,
25}
26
27impl<'w> Deref for DeferredWorld<'w> {
28    type Target = World;
29
30    fn deref(&self) -> &Self::Target {
31        // SAFETY: Structural changes cannot be made through &World
32        unsafe { self.world.world() }
33    }
34}
35
36impl<'w> UnsafeWorldCell<'w> {
37    /// Turn self into a [`DeferredWorld`]
38    ///
39    /// # Safety
40    /// Caller must ensure there are no outstanding mutable references to world and no
41    /// outstanding references to the world's command queue, resource or component data
42    #[inline]
43    pub unsafe fn into_deferred(self) -> DeferredWorld<'w> {
44        DeferredWorld { world: self }
45    }
46}
47
48impl<'w> From<&'w mut World> for DeferredWorld<'w> {
49    fn from(world: &'w mut World) -> DeferredWorld<'w> {
50        DeferredWorld {
51            world: world.as_unsafe_world_cell(),
52        }
53    }
54}
55
56impl<'w> DeferredWorld<'w> {
57    /// Reborrow self as a new instance of [`DeferredWorld`]
58    #[inline]
59    pub fn reborrow(&mut self) -> DeferredWorld {
60        DeferredWorld { world: self.world }
61    }
62
63    /// Creates a [`Commands`] instance that pushes to the world's command queue
64    #[inline]
65    pub fn commands(&mut self) -> Commands {
66        // SAFETY: &mut self ensure that there are no outstanding accesses to the queue
67        let command_queue = unsafe { self.world.get_raw_command_queue() };
68        // SAFETY: command_queue is stored on world and always valid while the world exists
69        unsafe { Commands::new_raw_from_entities(command_queue, self.world.entities()) }
70    }
71
72    /// Retrieves a mutable reference to the given `entity`'s [`Component`] of the given type.
73    /// Returns `None` if the `entity` does not have a [`Component`] of the given type.
74    #[inline]
75    pub fn get_mut<T: Component>(&mut self, entity: Entity) -> Option<Mut<T>> {
76        // SAFETY:
77        // - `as_unsafe_world_cell` is the only thing that is borrowing world
78        // - `as_unsafe_world_cell` provides mutable permission to everything
79        // - `&mut self` ensures no other borrows on world data
80        unsafe { self.world.get_entity(entity)?.get_mut() }
81    }
82
83    /// Retrieves an [`EntityMut`] that exposes read and write operations for the given `entity`.
84    /// Returns [`None`] if the `entity` does not exist.
85    /// Instead of unwrapping the value returned from this function, prefer [`Self::entity_mut`].
86    #[inline]
87    pub fn get_entity_mut(&mut self, entity: Entity) -> Option<EntityMut> {
88        let location = self.entities.get(entity)?;
89        // SAFETY: if the Entity is invalid, the function returns early.
90        // Additionally, Entities::get(entity) returns the correct EntityLocation if the entity exists.
91        let entity_cell = UnsafeEntityCell::new(self.as_unsafe_world_cell(), entity, location);
92        // SAFETY: The UnsafeEntityCell has read access to the entire world.
93        let entity_ref = unsafe { EntityMut::new(entity_cell) };
94        Some(entity_ref)
95    }
96
97    /// Retrieves an [`EntityMut`] that exposes read and write operations for the given `entity`.
98    /// This will panic if the `entity` does not exist. Use [`Self::get_entity_mut`] if you want
99    /// to check for entity existence instead of implicitly panic-ing.
100    #[inline]
101    pub fn entity_mut(&mut self, entity: Entity) -> EntityMut {
102        #[inline(never)]
103        #[cold]
104        fn panic_no_entity(entity: Entity) -> ! {
105            panic!("Entity {entity:?} does not exist");
106        }
107
108        match self.get_entity_mut(entity) {
109            Some(entity) => entity,
110            None => panic_no_entity(entity),
111        }
112    }
113
114    /// Returns [`Query`] for the given [`QueryState`], which is used to efficiently
115    /// run queries on the [`World`] by storing and reusing the [`QueryState`].
116    ///
117    /// # Panics
118    /// If state is from a different world then self
119    #[inline]
120    pub fn query<'s, D: QueryData, F: QueryFilter>(
121        &'w mut self,
122        state: &'s mut QueryState<D, F>,
123    ) -> Query<'w, 's, D, F> {
124        state.validate_world(self.world.id());
125        state.update_archetypes(self);
126        // SAFETY: We ran validate_world to ensure our state matches
127        unsafe {
128            let world_cell = self.world;
129            Query::new(
130                world_cell,
131                state,
132                world_cell.last_change_tick(),
133                world_cell.change_tick(),
134            )
135        }
136    }
137
138    /// Gets a mutable reference to the resource of the given type
139    ///
140    /// # Panics
141    ///
142    /// Panics if the resource does not exist.
143    /// Use [`get_resource_mut`](DeferredWorld::get_resource_mut) instead if you want to handle this case.
144    #[inline]
145    #[track_caller]
146    pub fn resource_mut<R: Resource>(&mut self) -> Mut<'_, R> {
147        match self.get_resource_mut() {
148            Some(x) => x,
149            None => panic!(
150                "Requested resource {} does not exist in the `World`. 
151                Did you forget to add it using `app.insert_resource` / `app.init_resource`? 
152                Resources are also implicitly added via `app.add_event`,
153                and can be added by plugins.",
154                std::any::type_name::<R>()
155            ),
156        }
157    }
158
159    /// Gets a mutable reference to the resource of the given type if it exists
160    #[inline]
161    pub fn get_resource_mut<R: Resource>(&mut self) -> Option<Mut<'_, R>> {
162        // SAFETY: &mut self ensure that there are no outstanding accesses to the resource
163        unsafe { self.world.get_resource_mut() }
164    }
165
166    /// Gets a mutable reference to the non-send resource of the given type, if it exists.
167    ///
168    /// # Panics
169    ///
170    /// Panics if the resource does not exist.
171    /// Use [`get_non_send_resource_mut`](World::get_non_send_resource_mut) instead if you want to handle this case.
172    ///
173    /// This function will panic if it isn't called from the same thread that the resource was inserted from.
174    #[inline]
175    #[track_caller]
176    pub fn non_send_resource_mut<R: 'static>(&mut self) -> Mut<'_, R> {
177        match self.get_non_send_resource_mut() {
178            Some(x) => x,
179            None => panic!(
180                "Requested non-send resource {} does not exist in the `World`. 
181                Did you forget to add it using `app.insert_non_send_resource` / `app.init_non_send_resource`? 
182                Non-send resources can also be added by plugins.",
183                std::any::type_name::<R>()
184            ),
185        }
186    }
187
188    /// Gets a mutable reference to the non-send resource of the given type, if it exists.
189    /// Otherwise returns `None`.
190    ///
191    /// # Panics
192    /// This function will panic if it isn't called from the same thread that the resource was inserted from.
193    #[inline]
194    pub fn get_non_send_resource_mut<R: 'static>(&mut self) -> Option<Mut<'_, R>> {
195        // SAFETY: &mut self ensure that there are no outstanding accesses to the resource
196        unsafe { self.world.get_non_send_resource_mut() }
197    }
198
199    /// Sends an [`Event`].
200    /// This method returns the [ID](`EventId`) of the sent `event`,
201    /// or [`None`] if the `event` could not be sent.
202    #[inline]
203    pub fn send_event<E: Event>(&mut self, event: E) -> Option<EventId<E>> {
204        self.send_event_batch(std::iter::once(event))?.next()
205    }
206
207    /// Sends the default value of the [`Event`] of type `E`.
208    /// This method returns the [ID](`EventId`) of the sent `event`,
209    /// or [`None`] if the `event` could not be sent.
210    #[inline]
211    pub fn send_event_default<E: Event + Default>(&mut self) -> Option<EventId<E>> {
212        self.send_event(E::default())
213    }
214
215    /// Sends a batch of [`Event`]s from an iterator.
216    /// This method returns the [IDs](`EventId`) of the sent `events`,
217    /// or [`None`] if the `event` could not be sent.
218    #[inline]
219    pub fn send_event_batch<E: Event>(
220        &mut self,
221        events: impl IntoIterator<Item = E>,
222    ) -> Option<SendBatchIds<E>> {
223        let Some(mut events_resource) = self.get_resource_mut::<Events<E>>() else {
224            bevy_utils::tracing::error!(
225                "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 ",
226                std::any::type_name::<E>()
227            );
228            return None;
229        };
230        Some(events_resource.send_batch(events))
231    }
232
233    /// Gets a pointer to the resource with the id [`ComponentId`] if it exists.
234    /// The returned pointer may be used to modify the resource, as long as the mutable borrow
235    /// of the [`World`] is still valid.
236    ///
237    /// **You should prefer to use the typed API [`World::get_resource_mut`] where possible and only
238    /// use this in cases where the actual types are not known at compile time.**
239    #[inline]
240    pub fn get_resource_mut_by_id(&mut self, component_id: ComponentId) -> Option<MutUntyped<'_>> {
241        // SAFETY: &mut self ensure that there are no outstanding accesses to the resource
242        unsafe { self.world.get_resource_mut_by_id(component_id) }
243    }
244
245    /// Gets a `!Send` resource to the resource with the id [`ComponentId`] if it exists.
246    /// The returned pointer may be used to modify the resource, as long as the mutable borrow
247    /// of the [`World`] is still valid.
248    ///
249    /// **You should prefer to use the typed API [`World::get_resource_mut`] where possible and only
250    /// use this in cases where the actual types are not known at compile time.**
251    ///
252    /// # Panics
253    /// This function will panic if it isn't called from the same thread that the resource was inserted from.
254    #[inline]
255    pub fn get_non_send_mut_by_id(&mut self, component_id: ComponentId) -> Option<MutUntyped<'_>> {
256        // SAFETY: &mut self ensure that there are no outstanding accesses to the resource
257        unsafe { self.world.get_non_send_resource_mut_by_id(component_id) }
258    }
259
260    /// Retrieves a mutable untyped reference to the given `entity`'s [`Component`] of the given [`ComponentId`].
261    /// Returns `None` if the `entity` does not have a [`Component`] of the given type.
262    ///
263    /// **You should prefer to use the typed API [`World::get_mut`] where possible and only
264    /// use this in cases where the actual types are not known at compile time.**
265    #[inline]
266    pub fn get_mut_by_id(
267        &mut self,
268        entity: Entity,
269        component_id: ComponentId,
270    ) -> Option<MutUntyped<'_>> {
271        // SAFETY: &mut self ensure that there are no outstanding accesses to the resource
272        unsafe { self.world.get_entity(entity)?.get_mut_by_id(component_id) }
273    }
274
275    /// Triggers all `on_add` hooks for [`ComponentId`] in target.
276    ///
277    /// # Safety
278    /// Caller must ensure [`ComponentId`] in target exist in self.
279    #[inline]
280    pub(crate) unsafe fn trigger_on_add(
281        &mut self,
282        archetype: &Archetype,
283        entity: Entity,
284        targets: impl Iterator<Item = ComponentId>,
285    ) {
286        if archetype.has_add_hook() {
287            for component_id in targets {
288                // SAFETY: Caller ensures that these components exist
289                let hooks = unsafe { self.components().get_info_unchecked(component_id) }.hooks();
290                if let Some(hook) = hooks.on_add {
291                    hook(DeferredWorld { world: self.world }, entity, component_id);
292                }
293            }
294        }
295    }
296
297    /// Triggers all `on_insert` hooks for [`ComponentId`] in target.
298    ///
299    /// # Safety
300    /// Caller must ensure [`ComponentId`] in target exist in self.
301    #[inline]
302    pub(crate) unsafe fn trigger_on_insert(
303        &mut self,
304        archetype: &Archetype,
305        entity: Entity,
306        targets: impl Iterator<Item = ComponentId>,
307    ) {
308        if archetype.has_insert_hook() {
309            for component_id in targets {
310                // SAFETY: Caller ensures that these components exist
311                let hooks = unsafe { self.components().get_info_unchecked(component_id) }.hooks();
312                if let Some(hook) = hooks.on_insert {
313                    hook(DeferredWorld { world: self.world }, entity, component_id);
314                }
315            }
316        }
317    }
318
319    /// Triggers all `on_remove` hooks for [`ComponentId`] in target.
320    ///
321    /// # Safety
322    /// Caller must ensure [`ComponentId`] in target exist in self.
323    #[inline]
324    pub(crate) unsafe fn trigger_on_remove(
325        &mut self,
326        archetype: &Archetype,
327        entity: Entity,
328        targets: impl Iterator<Item = ComponentId>,
329    ) {
330        if archetype.has_remove_hook() {
331            for component_id in targets {
332                let hooks =
333                // SAFETY: Caller ensures that these components exist
334                    unsafe { self.world.components().get_info_unchecked(component_id) }.hooks();
335                if let Some(hook) = hooks.on_remove {
336                    hook(DeferredWorld { world: self.world }, entity, component_id);
337                }
338            }
339        }
340    }
341
342    /// Triggers all event observers for [`ComponentId`] in target.
343    ///
344    /// # Safety
345    /// Caller must ensure observers listening for `event` can accept ZST pointers
346    #[inline]
347    pub(crate) unsafe fn trigger_observers(
348        &mut self,
349        event: ComponentId,
350        entity: Entity,
351        components: impl Iterator<Item = ComponentId>,
352    ) {
353        Observers::invoke(self.reborrow(), event, entity, components, &mut ());
354    }
355
356    /// Triggers all event observers for [`ComponentId`] in target.
357    ///
358    /// # Safety
359    /// Caller must ensure `E` is accessible as the type represented by `event`
360    #[inline]
361    pub(crate) unsafe fn trigger_observers_with_data<E>(
362        &mut self,
363        event: ComponentId,
364        entity: Entity,
365        components: impl Iterator<Item = ComponentId>,
366        data: &mut E,
367    ) {
368        Observers::invoke(self.reborrow(), event, entity, components, data);
369    }
370
371    /// Sends a "global" [`Trigger`] without any targets.
372    pub fn trigger<T: Event>(&mut self, trigger: impl Event) {
373        self.commands().trigger(trigger);
374    }
375
376    /// Sends a [`Trigger`] with the given `targets`.
377    pub fn trigger_targets(&mut self, trigger: impl Event, targets: impl TriggerTargets) {
378        self.commands().trigger_targets(trigger, targets);
379    }
380
381    /// Gets an [`UnsafeWorldCell`] containing the underlying world.
382    ///
383    /// # Safety
384    /// - must only be used to to make non-structural ECS changes
385    #[inline]
386    pub(crate) fn as_unsafe_world_cell(&mut self) -> UnsafeWorldCell {
387        self.world
388    }
389}