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