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