bevy_ecs/world/
deferred_world.rs

1use core::ops::Deref;
2
3use crate::{
4    archetype::Archetype,
5    change_detection::{MaybeLocation, MutUntyped},
6    component::{ComponentId, HookContext, Mutable},
7    entity::Entity,
8    event::{Event, EventId, Events, SendBatchIds},
9    observer::{Observers, TriggerTargets},
10    prelude::{Component, QueryState},
11    query::{QueryData, QueryFilter},
12    relationship::RelationshipHookMode,
13    resource::Resource,
14    system::{Commands, Query},
15    traversal::Traversal,
16    world::{error::EntityMutableFetchError, EntityFetcher, WorldEntityFetch},
17};
18
19use super::{unsafe_world_cell::UnsafeWorldCell, Mut, World, ON_INSERT, ON_REPLACE};
20
21/// A [`World`] reference that disallows structural ECS changes.
22/// This includes initializing resources, registering components or spawning entities.
23pub struct DeferredWorld<'w> {
24    // SAFETY: Implementors must not use this reference to make structural changes
25    world: UnsafeWorldCell<'w>,
26}
27
28impl<'w> Deref for DeferredWorld<'w> {
29    type Target = World;
30
31    fn deref(&self) -> &Self::Target {
32        // SAFETY: Structural changes cannot be made through &World
33        unsafe { self.world.world() }
34    }
35}
36
37impl<'w> UnsafeWorldCell<'w> {
38    /// Turn self into a [`DeferredWorld`]
39    ///
40    /// # Safety
41    /// Caller must ensure there are no outstanding mutable references to world and no
42    /// outstanding references to the world's command queue, resource or component data
43    #[inline]
44    pub unsafe fn into_deferred(self) -> DeferredWorld<'w> {
45        DeferredWorld { world: self }
46    }
47}
48
49impl<'w> From<&'w mut World> for DeferredWorld<'w> {
50    fn from(world: &'w mut World) -> DeferredWorld<'w> {
51        DeferredWorld {
52            world: world.as_unsafe_world_cell(),
53        }
54    }
55}
56
57impl<'w> DeferredWorld<'w> {
58    /// Reborrow self as a new instance of [`DeferredWorld`]
59    #[inline]
60    pub fn reborrow(&mut self) -> DeferredWorld {
61        DeferredWorld { world: self.world }
62    }
63
64    /// Creates a [`Commands`] instance that pushes to the world's command queue
65    #[inline]
66    pub fn commands(&mut self) -> Commands {
67        // SAFETY: &mut self ensure that there are no outstanding accesses to the queue
68        let command_queue = unsafe { self.world.get_raw_command_queue() };
69        // SAFETY: command_queue is stored on world and always valid while the world exists
70        unsafe { Commands::new_raw_from_entities(command_queue, self.world.entities()) }
71    }
72
73    /// Retrieves a mutable reference to the given `entity`'s [`Component`] of the given type.
74    /// Returns `None` if the `entity` does not have a [`Component`] of the given type.
75    #[inline]
76    pub fn get_mut<T: Component<Mutability = Mutable>>(
77        &mut self,
78        entity: Entity,
79    ) -> Option<Mut<T>> {
80        self.get_entity_mut(entity).ok()?.into_mut()
81    }
82
83    /// Temporarily removes a [`Component`] `T` from the provided [`Entity`] and
84    /// runs the provided closure on it, returning the result if `T` was available.
85    /// This will trigger the `OnRemove` and `OnReplace` component hooks without
86    /// causing an archetype move.
87    ///
88    /// This is most useful with immutable components, where removal and reinsertion
89    /// is the only way to modify a value.
90    ///
91    /// If you do not need to ensure the above hooks are triggered, and your component
92    /// is mutable, prefer using [`get_mut`](DeferredWorld::get_mut).
93    #[inline]
94    pub(crate) fn modify_component<T: Component, R>(
95        &mut self,
96        entity: Entity,
97        f: impl FnOnce(&mut T) -> R,
98    ) -> Result<Option<R>, EntityMutableFetchError> {
99        // If the component is not registered, then it doesn't exist on this entity, so no action required.
100        let Some(component_id) = self.component_id::<T>() else {
101            return Ok(None);
102        };
103
104        self.modify_component_by_id(entity, component_id, move |component| {
105            // SAFETY: component matches the component_id collected in the above line
106            let mut component = unsafe { component.with_type::<T>() };
107
108            f(&mut component)
109        })
110    }
111
112    /// Temporarily removes a [`Component`] identified by the provided
113    /// [`ComponentId`] from the provided [`Entity`] and runs the provided
114    /// closure on it, returning the result if the component was available.
115    /// This will trigger the `OnRemove` and `OnReplace` component hooks without
116    /// causing an archetype move.
117    ///
118    /// This is most useful with immutable components, where removal and reinsertion
119    /// is the only way to modify a value.
120    ///
121    /// If you do not need to ensure the above hooks are triggered, and your component
122    /// is mutable, prefer using [`get_mut_by_id`](DeferredWorld::get_mut_by_id).
123    ///
124    /// You should prefer the typed [`modify_component`](DeferredWorld::modify_component)
125    /// whenever possible.
126    #[inline]
127    pub(crate) fn modify_component_by_id<R>(
128        &mut self,
129        entity: Entity,
130        component_id: ComponentId,
131        f: impl for<'a> FnOnce(MutUntyped<'a>) -> R,
132    ) -> Result<Option<R>, EntityMutableFetchError> {
133        let entity_cell = self.get_entity_mut(entity)?;
134
135        if !entity_cell.contains_id(component_id) {
136            return Ok(None);
137        }
138
139        let archetype = &raw const *entity_cell.archetype();
140
141        // SAFETY:
142        // - DeferredWorld ensures archetype pointer will remain valid as no
143        //   relocations will occur.
144        // - component_id exists on this world and this entity
145        // - ON_REPLACE is able to accept ZST events
146        unsafe {
147            let archetype = &*archetype;
148            self.trigger_on_replace(
149                archetype,
150                entity,
151                [component_id].into_iter(),
152                MaybeLocation::caller(),
153                RelationshipHookMode::Run,
154            );
155            if archetype.has_replace_observer() {
156                self.trigger_observers(
157                    ON_REPLACE,
158                    entity,
159                    [component_id].into_iter(),
160                    MaybeLocation::caller(),
161                );
162            }
163        }
164
165        let mut entity_cell = self
166            .get_entity_mut(entity)
167            .expect("entity access confirmed above");
168
169        // SAFETY: we will run the required hooks to simulate removal/replacement.
170        let mut component = unsafe {
171            entity_cell
172                .get_mut_assume_mutable_by_id(component_id)
173                .expect("component access confirmed above")
174        };
175
176        let result = f(component.reborrow());
177
178        // Simulate adding this component by updating the relevant ticks
179        *component.ticks.added = *component.ticks.changed;
180
181        // SAFETY:
182        // - DeferredWorld ensures archetype pointer will remain valid as no
183        //   relocations will occur.
184        // - component_id exists on this world and this entity
185        // - ON_REPLACE is able to accept ZST events
186        unsafe {
187            let archetype = &*archetype;
188            self.trigger_on_insert(
189                archetype,
190                entity,
191                [component_id].into_iter(),
192                MaybeLocation::caller(),
193                RelationshipHookMode::Run,
194            );
195            if archetype.has_insert_observer() {
196                self.trigger_observers(
197                    ON_INSERT,
198                    entity,
199                    [component_id].into_iter(),
200                    MaybeLocation::caller(),
201                );
202            }
203        }
204
205        Ok(Some(result))
206    }
207
208    /// Returns [`EntityMut`]s that expose read and write operations for the
209    /// given `entities`, returning [`Err`] if any of the given entities do not
210    /// exist. Instead of immediately unwrapping the value returned from this
211    /// function, prefer [`World::entity_mut`].
212    ///
213    /// This function supports fetching a single entity or multiple entities:
214    /// - Pass an [`Entity`] to receive a single [`EntityMut`].
215    /// - Pass a slice of [`Entity`]s to receive a [`Vec<EntityMut>`].
216    /// - Pass an array of [`Entity`]s to receive an equally-sized array of [`EntityMut`]s.
217    /// - Pass an [`&EntityHashSet`] to receive an [`EntityHashMap<EntityMut>`].
218    ///
219    /// **As [`DeferredWorld`] does not allow structural changes, all returned
220    /// references are [`EntityMut`]s, which do not allow structural changes
221    /// (i.e. adding/removing components or despawning the entity).**
222    ///
223    /// # Errors
224    ///
225    /// - Returns [`EntityMutableFetchError::EntityDoesNotExist`] if any of the given `entities` do not exist in the world.
226    ///     - Only the first entity found to be missing will be returned.
227    /// - Returns [`EntityMutableFetchError::AliasedMutability`] if the same entity is requested multiple times.
228    ///
229    /// # Examples
230    ///
231    /// For examples, see [`DeferredWorld::entity_mut`].
232    ///
233    /// [`EntityMut`]: crate::world::EntityMut
234    /// [`&EntityHashSet`]: crate::entity::EntityHashSet
235    /// [`EntityHashMap<EntityMut>`]: crate::entity::EntityHashMap
236    /// [`Vec<EntityMut>`]: alloc::vec::Vec
237    #[inline]
238    pub fn get_entity_mut<F: WorldEntityFetch>(
239        &mut self,
240        entities: F,
241    ) -> Result<F::DeferredMut<'_>, EntityMutableFetchError> {
242        let cell = self.as_unsafe_world_cell();
243        // SAFETY: `&mut self` gives mutable access to the entire world,
244        // and prevents any other access to the world.
245        unsafe { entities.fetch_deferred_mut(cell) }
246    }
247
248    /// Returns [`EntityMut`]s that expose read and write operations for the
249    /// given `entities`. This will panic if any of the given entities do not
250    /// exist. Use [`DeferredWorld::get_entity_mut`] if you want to check for
251    /// entity existence instead of implicitly panicking.
252    ///
253    /// This function supports fetching a single entity or multiple entities:
254    /// - Pass an [`Entity`] to receive a single [`EntityMut`].
255    /// - Pass a slice of [`Entity`]s to receive a [`Vec<EntityMut>`].
256    /// - Pass an array of [`Entity`]s to receive an equally-sized array of [`EntityMut`]s.
257    /// - Pass an [`&EntityHashSet`] to receive an [`EntityHashMap<EntityMut>`].
258    ///
259    /// **As [`DeferredWorld`] does not allow structural changes, all returned
260    /// references are [`EntityMut`]s, which do not allow structural changes
261    /// (i.e. adding/removing components or despawning the entity).**
262    ///
263    /// # Panics
264    ///
265    /// If any of the given `entities` do not exist in the world.
266    ///
267    /// # Examples
268    ///
269    /// ## Single [`Entity`]
270    ///
271    /// ```
272    /// # use bevy_ecs::{prelude::*, world::DeferredWorld};
273    /// #[derive(Component)]
274    /// struct Position {
275    ///   x: f32,
276    ///   y: f32,
277    /// }
278    ///
279    /// # let mut world = World::new();
280    /// # let entity = world.spawn(Position { x: 0.0, y: 0.0 }).id();
281    /// let mut world: DeferredWorld = // ...
282    /// #   DeferredWorld::from(&mut world);
283    ///
284    /// let mut entity_mut = world.entity_mut(entity);
285    /// let mut position = entity_mut.get_mut::<Position>().unwrap();
286    /// position.y = 1.0;
287    /// assert_eq!(position.x, 0.0);
288    /// ```
289    ///
290    /// ## Array of [`Entity`]s
291    ///
292    /// ```
293    /// # use bevy_ecs::{prelude::*, world::DeferredWorld};
294    /// #[derive(Component)]
295    /// struct Position {
296    ///   x: f32,
297    ///   y: f32,
298    /// }
299    ///
300    /// # let mut world = World::new();
301    /// # let e1 = world.spawn(Position { x: 0.0, y: 0.0 }).id();
302    /// # let e2 = world.spawn(Position { x: 1.0, y: 1.0 }).id();
303    /// let mut world: DeferredWorld = // ...
304    /// #   DeferredWorld::from(&mut world);
305    ///
306    /// let [mut e1_ref, mut e2_ref] = world.entity_mut([e1, e2]);
307    /// let mut e1_position = e1_ref.get_mut::<Position>().unwrap();
308    /// e1_position.x = 1.0;
309    /// assert_eq!(e1_position.x, 1.0);
310    /// let mut e2_position = e2_ref.get_mut::<Position>().unwrap();
311    /// e2_position.x = 2.0;
312    /// assert_eq!(e2_position.x, 2.0);
313    /// ```
314    ///
315    /// ## Slice of [`Entity`]s
316    ///
317    /// ```
318    /// # use bevy_ecs::{prelude::*, world::DeferredWorld};
319    /// #[derive(Component)]
320    /// struct Position {
321    ///   x: f32,
322    ///   y: f32,
323    /// }
324    ///
325    /// # let mut world = World::new();
326    /// # let e1 = world.spawn(Position { x: 0.0, y: 1.0 }).id();
327    /// # let e2 = world.spawn(Position { x: 0.0, y: 1.0 }).id();
328    /// # let e3 = world.spawn(Position { x: 0.0, y: 1.0 }).id();
329    /// let mut world: DeferredWorld = // ...
330    /// #   DeferredWorld::from(&mut world);
331    ///
332    /// let ids = vec![e1, e2, e3];
333    /// for mut eref in world.entity_mut(&ids[..]) {
334    ///     let mut pos = eref.get_mut::<Position>().unwrap();
335    ///     pos.y = 2.0;
336    ///     assert_eq!(pos.y, 2.0);
337    /// }
338    /// ```
339    ///
340    /// ## [`&EntityHashSet`]
341    ///
342    /// ```
343    /// # use bevy_ecs::{prelude::*, entity::EntityHashSet, world::DeferredWorld};
344    /// #[derive(Component)]
345    /// struct Position {
346    ///   x: f32,
347    ///   y: f32,
348    /// }
349    ///
350    /// # let mut world = World::new();
351    /// # let e1 = world.spawn(Position { x: 0.0, y: 1.0 }).id();
352    /// # let e2 = world.spawn(Position { x: 0.0, y: 1.0 }).id();
353    /// # let e3 = world.spawn(Position { x: 0.0, y: 1.0 }).id();
354    /// let mut world: DeferredWorld = // ...
355    /// #   DeferredWorld::from(&mut world);
356    ///
357    /// let ids = EntityHashSet::from_iter([e1, e2, e3]);
358    /// for (_id, mut eref) in world.entity_mut(&ids) {
359    ///     let mut pos = eref.get_mut::<Position>().unwrap();
360    ///     pos.y = 2.0;
361    ///     assert_eq!(pos.y, 2.0);
362    /// }
363    /// ```
364    ///
365    /// [`EntityMut`]: crate::world::EntityMut
366    /// [`&EntityHashSet`]: crate::entity::EntityHashSet
367    /// [`EntityHashMap<EntityMut>`]: crate::entity::EntityHashMap
368    /// [`Vec<EntityMut>`]: alloc::vec::Vec
369    #[inline]
370    pub fn entity_mut<F: WorldEntityFetch>(&mut self, entities: F) -> F::DeferredMut<'_> {
371        self.get_entity_mut(entities).unwrap()
372    }
373
374    /// Simultaneously provides access to entity data and a command queue, which
375    /// will be applied when the [`World`] is next flushed.
376    ///
377    /// This allows using borrowed entity data to construct commands where the
378    /// borrow checker would otherwise prevent it.
379    ///
380    /// See [`World::entities_and_commands`] for the non-deferred version.
381    ///
382    /// # Example
383    ///
384    /// ```rust
385    /// # use bevy_ecs::{prelude::*, world::DeferredWorld};
386    /// #[derive(Component)]
387    /// struct Targets(Vec<Entity>);
388    /// #[derive(Component)]
389    /// struct TargetedBy(Entity);
390    ///
391    /// # let mut _world = World::new();
392    /// # let e1 = _world.spawn_empty().id();
393    /// # let e2 = _world.spawn_empty().id();
394    /// # let eid = _world.spawn(Targets(vec![e1, e2])).id();
395    /// let mut world: DeferredWorld = // ...
396    /// #   DeferredWorld::from(&mut _world);
397    /// let (entities, mut commands) = world.entities_and_commands();
398    ///
399    /// let entity = entities.get(eid).unwrap();
400    /// for &target in entity.get::<Targets>().unwrap().0.iter() {
401    ///     commands.entity(target).insert(TargetedBy(eid));
402    /// }
403    /// # _world.flush();
404    /// # assert_eq!(_world.get::<TargetedBy>(e1).unwrap().0, eid);
405    /// # assert_eq!(_world.get::<TargetedBy>(e2).unwrap().0, eid);
406    /// ```
407    pub fn entities_and_commands(&mut self) -> (EntityFetcher, Commands) {
408        let cell = self.as_unsafe_world_cell();
409        // SAFETY: `&mut self` gives mutable access to the entire world, and prevents simultaneous access.
410        let fetcher = unsafe { EntityFetcher::new(cell) };
411        // SAFETY:
412        // - `&mut self` gives mutable access to the entire world, and prevents simultaneous access.
413        // - Command queue access does not conflict with entity access.
414        let raw_queue = unsafe { cell.get_raw_command_queue() };
415        // SAFETY: `&mut self` ensures the commands does not outlive the world.
416        let commands = unsafe { Commands::new_raw_from_entities(raw_queue, cell.entities()) };
417
418        (fetcher, commands)
419    }
420
421    /// Returns [`Query`] for the given [`QueryState`], which is used to efficiently
422    /// run queries on the [`World`] by storing and reusing the [`QueryState`].
423    ///
424    /// # Panics
425    /// If state is from a different world then self
426    #[inline]
427    pub fn query<'s, D: QueryData, F: QueryFilter>(
428        &mut self,
429        state: &'s mut QueryState<D, F>,
430    ) -> Query<'_, 's, D, F> {
431        // SAFETY: We have mutable access to the entire world
432        unsafe { state.query_unchecked(self.world) }
433    }
434
435    /// Gets a mutable reference to the resource of the given type
436    ///
437    /// # Panics
438    ///
439    /// Panics if the resource does not exist.
440    /// Use [`get_resource_mut`](DeferredWorld::get_resource_mut) instead if you want to handle this case.
441    #[inline]
442    #[track_caller]
443    pub fn resource_mut<R: Resource>(&mut self) -> Mut<'_, R> {
444        match self.get_resource_mut() {
445            Some(x) => x,
446            None => panic!(
447                "Requested resource {} does not exist in the `World`.
448                Did you forget to add it using `app.insert_resource` / `app.init_resource`?
449                Resources are also implicitly added via `app.add_event`,
450                and can be added by plugins.",
451                core::any::type_name::<R>()
452            ),
453        }
454    }
455
456    /// Gets a mutable reference to the resource of the given type if it exists
457    #[inline]
458    pub fn get_resource_mut<R: Resource>(&mut self) -> Option<Mut<'_, R>> {
459        // SAFETY: &mut self ensure that there are no outstanding accesses to the resource
460        unsafe { self.world.get_resource_mut() }
461    }
462
463    /// Gets a mutable reference to the non-send resource of the given type, if it exists.
464    ///
465    /// # Panics
466    ///
467    /// Panics if the resource does not exist.
468    /// Use [`get_non_send_resource_mut`](World::get_non_send_resource_mut) instead if you want to handle this case.
469    ///
470    /// This function will panic if it isn't called from the same thread that the resource was inserted from.
471    #[inline]
472    #[track_caller]
473    pub fn non_send_resource_mut<R: 'static>(&mut self) -> Mut<'_, R> {
474        match self.get_non_send_resource_mut() {
475            Some(x) => x,
476            None => panic!(
477                "Requested non-send resource {} does not exist in the `World`.
478                Did you forget to add it using `app.insert_non_send_resource` / `app.init_non_send_resource`?
479                Non-send resources can also be added by plugins.",
480                core::any::type_name::<R>()
481            ),
482        }
483    }
484
485    /// Gets a mutable reference to the non-send resource of the given type, if it exists.
486    /// Otherwise returns `None`.
487    ///
488    /// # Panics
489    /// This function will panic if it isn't called from the same thread that the resource was inserted from.
490    #[inline]
491    pub fn get_non_send_resource_mut<R: 'static>(&mut self) -> Option<Mut<'_, R>> {
492        // SAFETY: &mut self ensure that there are no outstanding accesses to the resource
493        unsafe { self.world.get_non_send_resource_mut() }
494    }
495
496    /// Sends an [`Event`].
497    /// This method returns the [ID](`EventId`) of the sent `event`,
498    /// or [`None`] if the `event` could not be sent.
499    #[inline]
500    pub fn send_event<E: Event>(&mut self, event: E) -> Option<EventId<E>> {
501        self.send_event_batch(core::iter::once(event))?.next()
502    }
503
504    /// Sends the default value of the [`Event`] of type `E`.
505    /// This method returns the [ID](`EventId`) of the sent `event`,
506    /// or [`None`] if the `event` could not be sent.
507    #[inline]
508    pub fn send_event_default<E: Event + Default>(&mut self) -> Option<EventId<E>> {
509        self.send_event(E::default())
510    }
511
512    /// Sends a batch of [`Event`]s from an iterator.
513    /// This method returns the [IDs](`EventId`) of the sent `events`,
514    /// or [`None`] if the `event` could not be sent.
515    #[inline]
516    pub fn send_event_batch<E: Event>(
517        &mut self,
518        events: impl IntoIterator<Item = E>,
519    ) -> Option<SendBatchIds<E>> {
520        let Some(mut events_resource) = self.get_resource_mut::<Events<E>>() else {
521            log::error!(
522                "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 ",
523                core::any::type_name::<E>()
524            );
525            return None;
526        };
527        Some(events_resource.send_batch(events))
528    }
529
530    /// Gets a pointer to the resource with the id [`ComponentId`] if it exists.
531    /// The returned pointer may be used to modify the resource, as long as the mutable borrow
532    /// of the [`World`] is still valid.
533    ///
534    /// **You should prefer to use the typed API [`World::get_resource_mut`] where possible and only
535    /// use this in cases where the actual types are not known at compile time.**
536    #[inline]
537    pub fn get_resource_mut_by_id(&mut self, component_id: ComponentId) -> Option<MutUntyped<'_>> {
538        // SAFETY: &mut self ensure that there are no outstanding accesses to the resource
539        unsafe { self.world.get_resource_mut_by_id(component_id) }
540    }
541
542    /// Gets a `!Send` resource to the resource with the id [`ComponentId`] if it exists.
543    /// The returned pointer may be used to modify the resource, as long as the mutable borrow
544    /// of the [`World`] is still valid.
545    ///
546    /// **You should prefer to use the typed API [`World::get_resource_mut`] where possible and only
547    /// use this in cases where the actual types are not known at compile time.**
548    ///
549    /// # Panics
550    /// This function will panic if it isn't called from the same thread that the resource was inserted from.
551    #[inline]
552    pub fn get_non_send_mut_by_id(&mut self, component_id: ComponentId) -> Option<MutUntyped<'_>> {
553        // SAFETY: &mut self ensure that there are no outstanding accesses to the resource
554        unsafe { self.world.get_non_send_resource_mut_by_id(component_id) }
555    }
556
557    /// Retrieves a mutable untyped reference to the given `entity`'s [`Component`] of the given [`ComponentId`].
558    /// Returns `None` if the `entity` does not have a [`Component`] of the given type.
559    ///
560    /// **You should prefer to use the typed API [`World::get_mut`] where possible and only
561    /// use this in cases where the actual types are not known at compile time.**
562    #[inline]
563    pub fn get_mut_by_id(
564        &mut self,
565        entity: Entity,
566        component_id: ComponentId,
567    ) -> Option<MutUntyped<'_>> {
568        self.get_entity_mut(entity)
569            .ok()?
570            .into_mut_by_id(component_id)
571            .ok()
572    }
573
574    /// Triggers all `on_add` hooks for [`ComponentId`] in target.
575    ///
576    /// # Safety
577    /// Caller must ensure [`ComponentId`] in target exist in self.
578    #[inline]
579    pub(crate) unsafe fn trigger_on_add(
580        &mut self,
581        archetype: &Archetype,
582        entity: Entity,
583        targets: impl Iterator<Item = ComponentId>,
584        caller: MaybeLocation,
585    ) {
586        if archetype.has_add_hook() {
587            for component_id in targets {
588                // SAFETY: Caller ensures that these components exist
589                let hooks = unsafe { self.components().get_info_unchecked(component_id) }.hooks();
590                if let Some(hook) = hooks.on_add {
591                    hook(
592                        DeferredWorld { world: self.world },
593                        HookContext {
594                            entity,
595                            component_id,
596                            caller,
597                            relationship_hook_mode: RelationshipHookMode::Run,
598                        },
599                    );
600                }
601            }
602        }
603    }
604
605    /// Triggers all `on_insert` hooks for [`ComponentId`] in target.
606    ///
607    /// # Safety
608    /// Caller must ensure [`ComponentId`] in target exist in self.
609    #[inline]
610    pub(crate) unsafe fn trigger_on_insert(
611        &mut self,
612        archetype: &Archetype,
613        entity: Entity,
614        targets: impl Iterator<Item = ComponentId>,
615        caller: MaybeLocation,
616        relationship_hook_mode: RelationshipHookMode,
617    ) {
618        if archetype.has_insert_hook() {
619            for component_id in targets {
620                // SAFETY: Caller ensures that these components exist
621                let hooks = unsafe { self.components().get_info_unchecked(component_id) }.hooks();
622                if let Some(hook) = hooks.on_insert {
623                    hook(
624                        DeferredWorld { world: self.world },
625                        HookContext {
626                            entity,
627                            component_id,
628                            caller,
629                            relationship_hook_mode,
630                        },
631                    );
632                }
633            }
634        }
635    }
636
637    /// Triggers all `on_replace` hooks for [`ComponentId`] in target.
638    ///
639    /// # Safety
640    /// Caller must ensure [`ComponentId`] in target exist in self.
641    #[inline]
642    pub(crate) unsafe fn trigger_on_replace(
643        &mut self,
644        archetype: &Archetype,
645        entity: Entity,
646        targets: impl Iterator<Item = ComponentId>,
647        caller: MaybeLocation,
648        relationship_hook_mode: RelationshipHookMode,
649    ) {
650        if archetype.has_replace_hook() {
651            for component_id in targets {
652                // SAFETY: Caller ensures that these components exist
653                let hooks = unsafe { self.components().get_info_unchecked(component_id) }.hooks();
654                if let Some(hook) = hooks.on_replace {
655                    hook(
656                        DeferredWorld { world: self.world },
657                        HookContext {
658                            entity,
659                            component_id,
660                            caller,
661                            relationship_hook_mode,
662                        },
663                    );
664                }
665            }
666        }
667    }
668
669    /// Triggers all `on_remove` hooks for [`ComponentId`] in target.
670    ///
671    /// # Safety
672    /// Caller must ensure [`ComponentId`] in target exist in self.
673    #[inline]
674    pub(crate) unsafe fn trigger_on_remove(
675        &mut self,
676        archetype: &Archetype,
677        entity: Entity,
678        targets: impl Iterator<Item = ComponentId>,
679        caller: MaybeLocation,
680    ) {
681        if archetype.has_remove_hook() {
682            for component_id in targets {
683                // SAFETY: Caller ensures that these components exist
684                let hooks = unsafe { self.components().get_info_unchecked(component_id) }.hooks();
685                if let Some(hook) = hooks.on_remove {
686                    hook(
687                        DeferredWorld { world: self.world },
688                        HookContext {
689                            entity,
690                            component_id,
691                            caller,
692                            relationship_hook_mode: RelationshipHookMode::Run,
693                        },
694                    );
695                }
696            }
697        }
698    }
699
700    /// Triggers all `on_despawn` hooks for [`ComponentId`] in target.
701    ///
702    /// # Safety
703    /// Caller must ensure [`ComponentId`] in target exist in self.
704    #[inline]
705    pub(crate) unsafe fn trigger_on_despawn(
706        &mut self,
707        archetype: &Archetype,
708        entity: Entity,
709        targets: impl Iterator<Item = ComponentId>,
710        caller: MaybeLocation,
711    ) {
712        if archetype.has_despawn_hook() {
713            for component_id in targets {
714                // SAFETY: Caller ensures that these components exist
715                let hooks = unsafe { self.components().get_info_unchecked(component_id) }.hooks();
716                if let Some(hook) = hooks.on_despawn {
717                    hook(
718                        DeferredWorld { world: self.world },
719                        HookContext {
720                            entity,
721                            component_id,
722                            caller,
723                            relationship_hook_mode: RelationshipHookMode::Run,
724                        },
725                    );
726                }
727            }
728        }
729    }
730
731    /// Triggers all event observers for [`ComponentId`] in target.
732    ///
733    /// # Safety
734    /// Caller must ensure observers listening for `event` can accept ZST pointers
735    #[inline]
736    pub(crate) unsafe fn trigger_observers(
737        &mut self,
738        event: ComponentId,
739        target: Entity,
740        components: impl Iterator<Item = ComponentId> + Clone,
741        caller: MaybeLocation,
742    ) {
743        Observers::invoke::<_>(
744            self.reborrow(),
745            event,
746            target,
747            components,
748            &mut (),
749            &mut false,
750            caller,
751        );
752    }
753
754    /// Triggers all event observers for [`ComponentId`] in target.
755    ///
756    /// # Safety
757    /// Caller must ensure `E` is accessible as the type represented by `event`
758    #[inline]
759    pub(crate) unsafe fn trigger_observers_with_data<E, T>(
760        &mut self,
761        event: ComponentId,
762        mut target: Entity,
763        components: impl Iterator<Item = ComponentId> + Clone,
764        data: &mut E,
765        mut propagate: bool,
766        caller: MaybeLocation,
767    ) where
768        T: Traversal<E>,
769    {
770        loop {
771            Observers::invoke::<_>(
772                self.reborrow(),
773                event,
774                target,
775                components.clone(),
776                data,
777                &mut propagate,
778                caller,
779            );
780            if !propagate {
781                break;
782            }
783            if let Some(traverse_to) = self
784                .get_entity(target)
785                .ok()
786                .and_then(|entity| entity.get_components::<T>())
787                .and_then(|item| T::traverse(item, data))
788            {
789                target = traverse_to;
790            } else {
791                break;
792            }
793        }
794    }
795
796    /// Sends a "global" [`Trigger`](crate::observer::Trigger) without any targets.
797    pub fn trigger(&mut self, trigger: impl Event) {
798        self.commands().trigger(trigger);
799    }
800
801    /// Sends a [`Trigger`](crate::observer::Trigger) with the given `targets`.
802    pub fn trigger_targets(
803        &mut self,
804        trigger: impl Event,
805        targets: impl TriggerTargets + Send + Sync + 'static,
806    ) {
807        self.commands().trigger_targets(trigger, targets);
808    }
809
810    /// Gets an [`UnsafeWorldCell`] containing the underlying world.
811    ///
812    /// # Safety
813    /// - must only be used to make non-structural ECS changes
814    #[inline]
815    pub(crate) fn as_unsafe_world_cell(&mut self) -> UnsafeWorldCell {
816        self.world
817    }
818}