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