bevy_ecs/world/deferred_world.rs
1use core::ops::Deref;
2
3use crate::{
4 archetype::Archetype,
5 change_detection::MutUntyped,
6 component::ComponentId,
7 entity::Entity,
8 event::{Event, EventId, Events, SendBatchIds},
9 observer::{Observers, TriggerTargets},
10 prelude::{Component, QueryState},
11 query::{QueryData, QueryFilter},
12 system::{Commands, Query, Resource},
13 traversal::Traversal,
14 world::{error::EntityFetchError, WorldEntityFetch},
15};
16
17use super::{unsafe_world_cell::UnsafeWorldCell, Mut, World};
18
19/// A [`World`] reference that disallows structural ECS changes.
20/// This includes initializing resources, registering components or spawning entities.
21pub struct DeferredWorld<'w> {
22 // SAFETY: Implementors must not use this reference to make structural changes
23 world: UnsafeWorldCell<'w>,
24}
25
26impl<'w> Deref for DeferredWorld<'w> {
27 type Target = World;
28
29 fn deref(&self) -> &Self::Target {
30 // SAFETY: Structural changes cannot be made through &World
31 unsafe { self.world.world() }
32 }
33}
34
35impl<'w> UnsafeWorldCell<'w> {
36 /// Turn self into a [`DeferredWorld`]
37 ///
38 /// # Safety
39 /// Caller must ensure there are no outstanding mutable references to world and no
40 /// outstanding references to the world's command queue, resource or component data
41 #[inline]
42 pub unsafe fn into_deferred(self) -> DeferredWorld<'w> {
43 DeferredWorld { world: self }
44 }
45}
46
47impl<'w> From<&'w mut World> for DeferredWorld<'w> {
48 fn from(world: &'w mut World) -> DeferredWorld<'w> {
49 DeferredWorld {
50 world: world.as_unsafe_world_cell(),
51 }
52 }
53}
54
55impl<'w> DeferredWorld<'w> {
56 /// Reborrow self as a new instance of [`DeferredWorld`]
57 #[inline]
58 pub fn reborrow(&mut self) -> DeferredWorld {
59 DeferredWorld { world: self.world }
60 }
61
62 /// Creates a [`Commands`] instance that pushes to the world's command queue
63 #[inline]
64 pub fn commands(&mut self) -> Commands {
65 // SAFETY: &mut self ensure that there are no outstanding accesses to the queue
66 let command_queue = unsafe { self.world.get_raw_command_queue() };
67 // SAFETY: command_queue is stored on world and always valid while the world exists
68 unsafe { Commands::new_raw_from_entities(command_queue, self.world.entities()) }
69 }
70
71 /// Retrieves a mutable reference to the given `entity`'s [`Component`] of the given type.
72 /// Returns `None` if the `entity` does not have a [`Component`] of the given type.
73 #[inline]
74 pub fn get_mut<T: Component>(&mut self, entity: Entity) -> Option<Mut<T>> {
75 // SAFETY:
76 // - `as_unsafe_world_cell` is the only thing that is borrowing world
77 // - `as_unsafe_world_cell` provides mutable permission to everything
78 // - `&mut self` ensures no other borrows on world data
79 unsafe { self.world.get_entity(entity)?.get_mut() }
80 }
81
82 /// Returns [`EntityMut`]s that expose read and write operations for the
83 /// given `entities`, returning [`Err`] if any of the given entities do not
84 /// exist. Instead of immediately unwrapping the value returned from this
85 /// function, prefer [`World::entity_mut`].
86 ///
87 /// This function supports fetching a single entity or multiple entities:
88 /// - Pass an [`Entity`] to receive a single [`EntityMut`].
89 /// - Pass a slice of [`Entity`]s to receive a [`Vec<EntityMut>`].
90 /// - Pass an array of [`Entity`]s to receive an equally-sized array of [`EntityMut`]s.
91 /// - Pass an [`&EntityHashSet`] to receive an [`EntityHashMap<EntityMut>`].
92 ///
93 /// **As [`DeferredWorld`] does not allow structural changes, all returned
94 /// references are [`EntityMut`]s, which do not allow structural changes
95 /// (i.e. adding/removing components or despawning the entity).**
96 ///
97 /// # Errors
98 ///
99 /// - Returns [`EntityFetchError::NoSuchEntity`] if any of the given `entities` do not exist in the world.
100 /// - Only the first entity found to be missing will be returned.
101 /// - Returns [`EntityFetchError::AliasedMutability`] if the same entity is requested multiple times.
102 ///
103 /// # Examples
104 ///
105 /// For examples, see [`DeferredWorld::entity_mut`].
106 ///
107 /// [`EntityMut`]: crate::world::EntityMut
108 /// [`&EntityHashSet`]: crate::entity::EntityHashSet
109 /// [`EntityHashMap<EntityMut>`]: crate::entity::EntityHashMap
110 #[inline]
111 pub fn get_entity_mut<F: WorldEntityFetch>(
112 &mut self,
113 entities: F,
114 ) -> Result<F::DeferredMut<'_>, EntityFetchError> {
115 let cell = self.as_unsafe_world_cell();
116 // SAFETY: `&mut self` gives mutable access to the entire world,
117 // and prevents any other access to the world.
118 unsafe { entities.fetch_deferred_mut(cell) }
119 }
120
121 /// Returns [`EntityMut`]s that expose read and write operations for the
122 /// given `entities`. This will panic if any of the given entities do not
123 /// exist. Use [`DeferredWorld::get_entity_mut`] if you want to check for
124 /// entity existence instead of implicitly panicking.
125 ///
126 /// This function supports fetching a single entity or multiple entities:
127 /// - Pass an [`Entity`] to receive a single [`EntityMut`].
128 /// - Pass a slice of [`Entity`]s to receive a [`Vec<EntityMut>`].
129 /// - Pass an array of [`Entity`]s to receive an equally-sized array of [`EntityMut`]s.
130 /// - Pass an [`&EntityHashSet`] to receive an [`EntityHashMap<EntityMut>`].
131 ///
132 /// **As [`DeferredWorld`] does not allow structural changes, all returned
133 /// references are [`EntityMut`]s, which do not allow structural changes
134 /// (i.e. adding/removing components or despawning the entity).**
135 ///
136 /// # Panics
137 ///
138 /// If any of the given `entities` do not exist in the world.
139 ///
140 /// # Examples
141 ///
142 /// ## Single [`Entity`]
143 ///
144 /// ```
145 /// # use bevy_ecs::{prelude::*, world::DeferredWorld};
146 /// #[derive(Component)]
147 /// struct Position {
148 /// x: f32,
149 /// y: f32,
150 /// }
151 ///
152 /// # let mut world = World::new();
153 /// # let entity = world.spawn(Position { x: 0.0, y: 0.0 }).id();
154 /// let mut world: DeferredWorld = // ...
155 /// # DeferredWorld::from(&mut world);
156 ///
157 /// let mut entity_mut = world.entity_mut(entity);
158 /// let mut position = entity_mut.get_mut::<Position>().unwrap();
159 /// position.y = 1.0;
160 /// assert_eq!(position.x, 0.0);
161 /// ```
162 ///
163 /// ## Array of [`Entity`]s
164 ///
165 /// ```
166 /// # use bevy_ecs::{prelude::*, world::DeferredWorld};
167 /// #[derive(Component)]
168 /// struct Position {
169 /// x: f32,
170 /// y: f32,
171 /// }
172 ///
173 /// # let mut world = World::new();
174 /// # let e1 = world.spawn(Position { x: 0.0, y: 0.0 }).id();
175 /// # let e2 = world.spawn(Position { x: 1.0, y: 1.0 }).id();
176 /// let mut world: DeferredWorld = // ...
177 /// # DeferredWorld::from(&mut world);
178 ///
179 /// let [mut e1_ref, mut e2_ref] = world.entity_mut([e1, e2]);
180 /// let mut e1_position = e1_ref.get_mut::<Position>().unwrap();
181 /// e1_position.x = 1.0;
182 /// assert_eq!(e1_position.x, 1.0);
183 /// let mut e2_position = e2_ref.get_mut::<Position>().unwrap();
184 /// e2_position.x = 2.0;
185 /// assert_eq!(e2_position.x, 2.0);
186 /// ```
187 ///
188 /// ## Slice of [`Entity`]s
189 ///
190 /// ```
191 /// # use bevy_ecs::{prelude::*, world::DeferredWorld};
192 /// #[derive(Component)]
193 /// struct Position {
194 /// x: f32,
195 /// y: f32,
196 /// }
197 ///
198 /// # let mut world = World::new();
199 /// # let e1 = world.spawn(Position { x: 0.0, y: 1.0 }).id();
200 /// # let e2 = world.spawn(Position { x: 0.0, y: 1.0 }).id();
201 /// # let e3 = world.spawn(Position { x: 0.0, y: 1.0 }).id();
202 /// let mut world: DeferredWorld = // ...
203 /// # DeferredWorld::from(&mut world);
204 ///
205 /// let ids = vec![e1, e2, e3];
206 /// for mut eref in world.entity_mut(&ids[..]) {
207 /// let mut pos = eref.get_mut::<Position>().unwrap();
208 /// pos.y = 2.0;
209 /// assert_eq!(pos.y, 2.0);
210 /// }
211 /// ```
212 ///
213 /// ## [`&EntityHashSet`]
214 ///
215 /// ```
216 /// # use bevy_ecs::{prelude::*, entity::EntityHashSet, world::DeferredWorld};
217 /// #[derive(Component)]
218 /// struct Position {
219 /// x: f32,
220 /// y: f32,
221 /// }
222 ///
223 /// # let mut world = World::new();
224 /// # let e1 = world.spawn(Position { x: 0.0, y: 1.0 }).id();
225 /// # let e2 = world.spawn(Position { x: 0.0, y: 1.0 }).id();
226 /// # let e3 = world.spawn(Position { x: 0.0, y: 1.0 }).id();
227 /// let mut world: DeferredWorld = // ...
228 /// # DeferredWorld::from(&mut world);
229 ///
230 /// let ids = EntityHashSet::from_iter([e1, e2, e3]);
231 /// for (_id, mut eref) in world.entity_mut(&ids) {
232 /// let mut pos = eref.get_mut::<Position>().unwrap();
233 /// pos.y = 2.0;
234 /// assert_eq!(pos.y, 2.0);
235 /// }
236 /// ```
237 ///
238 /// [`EntityMut`]: crate::world::EntityMut
239 /// [`&EntityHashSet`]: crate::entity::EntityHashSet
240 /// [`EntityHashMap<EntityMut>`]: crate::entity::EntityHashMap
241 #[inline]
242 pub fn entity_mut<F: WorldEntityFetch>(&mut self, entities: F) -> F::DeferredMut<'_> {
243 self.get_entity_mut(entities).unwrap()
244 }
245
246 /// Returns [`Query`] for the given [`QueryState`], which is used to efficiently
247 /// run queries on the [`World`] by storing and reusing the [`QueryState`].
248 ///
249 /// # Panics
250 /// If state is from a different world then self
251 #[inline]
252 pub fn query<'s, D: QueryData, F: QueryFilter>(
253 &mut self,
254 state: &'s mut QueryState<D, F>,
255 ) -> Query<'_, 's, D, F> {
256 state.validate_world(self.world.id());
257 state.update_archetypes(self);
258 // SAFETY: We ran validate_world to ensure our state matches
259 unsafe {
260 let world_cell = self.world;
261 Query::new(
262 world_cell,
263 state,
264 world_cell.last_change_tick(),
265 world_cell.change_tick(),
266 )
267 }
268 }
269
270 /// Gets a mutable reference to the resource of the given type
271 ///
272 /// # Panics
273 ///
274 /// Panics if the resource does not exist.
275 /// Use [`get_resource_mut`](DeferredWorld::get_resource_mut) instead if you want to handle this case.
276 #[inline]
277 #[track_caller]
278 pub fn resource_mut<R: Resource>(&mut self) -> Mut<'_, R> {
279 match self.get_resource_mut() {
280 Some(x) => x,
281 None => panic!(
282 "Requested resource {} does not exist in the `World`.
283 Did you forget to add it using `app.insert_resource` / `app.init_resource`?
284 Resources are also implicitly added via `app.add_event`,
285 and can be added by plugins.",
286 core::any::type_name::<R>()
287 ),
288 }
289 }
290
291 /// Gets a mutable reference to the resource of the given type if it exists
292 #[inline]
293 pub fn get_resource_mut<R: Resource>(&mut self) -> Option<Mut<'_, R>> {
294 // SAFETY: &mut self ensure that there are no outstanding accesses to the resource
295 unsafe { self.world.get_resource_mut() }
296 }
297
298 /// Gets a mutable reference to the non-send resource of the given type, if it exists.
299 ///
300 /// # Panics
301 ///
302 /// Panics if the resource does not exist.
303 /// Use [`get_non_send_resource_mut`](World::get_non_send_resource_mut) instead if you want to handle this case.
304 ///
305 /// This function will panic if it isn't called from the same thread that the resource was inserted from.
306 #[inline]
307 #[track_caller]
308 pub fn non_send_resource_mut<R: 'static>(&mut self) -> Mut<'_, R> {
309 match self.get_non_send_resource_mut() {
310 Some(x) => x,
311 None => panic!(
312 "Requested non-send resource {} does not exist in the `World`.
313 Did you forget to add it using `app.insert_non_send_resource` / `app.init_non_send_resource`?
314 Non-send resources can also be added by plugins.",
315 core::any::type_name::<R>()
316 ),
317 }
318 }
319
320 /// Gets a mutable reference to the non-send resource of the given type, if it exists.
321 /// Otherwise returns `None`.
322 ///
323 /// # Panics
324 /// This function will panic if it isn't called from the same thread that the resource was inserted from.
325 #[inline]
326 pub fn get_non_send_resource_mut<R: 'static>(&mut self) -> Option<Mut<'_, R>> {
327 // SAFETY: &mut self ensure that there are no outstanding accesses to the resource
328 unsafe { self.world.get_non_send_resource_mut() }
329 }
330
331 /// Sends an [`Event`].
332 /// This method returns the [ID](`EventId`) of the sent `event`,
333 /// or [`None`] if the `event` could not be sent.
334 #[inline]
335 pub fn send_event<E: Event>(&mut self, event: E) -> Option<EventId<E>> {
336 self.send_event_batch(core::iter::once(event))?.next()
337 }
338
339 /// Sends the default value of the [`Event`] of type `E`.
340 /// This method returns the [ID](`EventId`) of the sent `event`,
341 /// or [`None`] if the `event` could not be sent.
342 #[inline]
343 pub fn send_event_default<E: Event + Default>(&mut self) -> Option<EventId<E>> {
344 self.send_event(E::default())
345 }
346
347 /// Sends a batch of [`Event`]s from an iterator.
348 /// This method returns the [IDs](`EventId`) of the sent `events`,
349 /// or [`None`] if the `event` could not be sent.
350 #[inline]
351 pub fn send_event_batch<E: Event>(
352 &mut self,
353 events: impl IntoIterator<Item = E>,
354 ) -> Option<SendBatchIds<E>> {
355 let Some(mut events_resource) = self.get_resource_mut::<Events<E>>() else {
356 bevy_utils::tracing::error!(
357 "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 ",
358 core::any::type_name::<E>()
359 );
360 return None;
361 };
362 Some(events_resource.send_batch(events))
363 }
364
365 /// Gets a pointer to the resource with the id [`ComponentId`] if it exists.
366 /// The returned pointer may be used to modify the resource, as long as the mutable borrow
367 /// of the [`World`] is still valid.
368 ///
369 /// **You should prefer to use the typed API [`World::get_resource_mut`] where possible and only
370 /// use this in cases where the actual types are not known at compile time.**
371 #[inline]
372 pub fn get_resource_mut_by_id(&mut self, component_id: ComponentId) -> Option<MutUntyped<'_>> {
373 // SAFETY: &mut self ensure that there are no outstanding accesses to the resource
374 unsafe { self.world.get_resource_mut_by_id(component_id) }
375 }
376
377 /// Gets a `!Send` resource to the resource with the id [`ComponentId`] if it exists.
378 /// The returned pointer may be used to modify the resource, as long as the mutable borrow
379 /// of the [`World`] is still valid.
380 ///
381 /// **You should prefer to use the typed API [`World::get_resource_mut`] where possible and only
382 /// use this in cases where the actual types are not known at compile time.**
383 ///
384 /// # Panics
385 /// This function will panic if it isn't called from the same thread that the resource was inserted from.
386 #[inline]
387 pub fn get_non_send_mut_by_id(&mut self, component_id: ComponentId) -> Option<MutUntyped<'_>> {
388 // SAFETY: &mut self ensure that there are no outstanding accesses to the resource
389 unsafe { self.world.get_non_send_resource_mut_by_id(component_id) }
390 }
391
392 /// Retrieves a mutable untyped reference to the given `entity`'s [`Component`] of the given [`ComponentId`].
393 /// Returns `None` if the `entity` does not have a [`Component`] of the given type.
394 ///
395 /// **You should prefer to use the typed API [`World::get_mut`] where possible and only
396 /// use this in cases where the actual types are not known at compile time.**
397 #[inline]
398 pub fn get_mut_by_id(
399 &mut self,
400 entity: Entity,
401 component_id: ComponentId,
402 ) -> Option<MutUntyped<'_>> {
403 // SAFETY: &mut self ensure that there are no outstanding accesses to the resource
404 unsafe { self.world.get_entity(entity)?.get_mut_by_id(component_id) }
405 }
406
407 /// Triggers all `on_add` hooks for [`ComponentId`] in target.
408 ///
409 /// # Safety
410 /// Caller must ensure [`ComponentId`] in target exist in self.
411 #[inline]
412 pub(crate) unsafe fn trigger_on_add(
413 &mut self,
414 archetype: &Archetype,
415 entity: Entity,
416 targets: impl Iterator<Item = ComponentId>,
417 ) {
418 if archetype.has_add_hook() {
419 for component_id in targets {
420 // SAFETY: Caller ensures that these components exist
421 let hooks = unsafe { self.components().get_info_unchecked(component_id) }.hooks();
422 if let Some(hook) = hooks.on_add {
423 hook(DeferredWorld { world: self.world }, entity, component_id);
424 }
425 }
426 }
427 }
428
429 /// Triggers all `on_insert` hooks for [`ComponentId`] in target.
430 ///
431 /// # Safety
432 /// Caller must ensure [`ComponentId`] in target exist in self.
433 #[inline]
434 pub(crate) unsafe fn trigger_on_insert(
435 &mut self,
436 archetype: &Archetype,
437 entity: Entity,
438 targets: impl Iterator<Item = ComponentId>,
439 ) {
440 if archetype.has_insert_hook() {
441 for component_id in targets {
442 // SAFETY: Caller ensures that these components exist
443 let hooks = unsafe { self.components().get_info_unchecked(component_id) }.hooks();
444 if let Some(hook) = hooks.on_insert {
445 hook(DeferredWorld { world: self.world }, entity, component_id);
446 }
447 }
448 }
449 }
450
451 /// Triggers all `on_replace` hooks for [`ComponentId`] in target.
452 ///
453 /// # Safety
454 /// Caller must ensure [`ComponentId`] in target exist in self.
455 #[inline]
456 pub(crate) unsafe fn trigger_on_replace(
457 &mut self,
458 archetype: &Archetype,
459 entity: Entity,
460 targets: impl Iterator<Item = ComponentId>,
461 ) {
462 if archetype.has_replace_hook() {
463 for component_id in targets {
464 // SAFETY: Caller ensures that these components exist
465 let hooks = unsafe { self.components().get_info_unchecked(component_id) }.hooks();
466 if let Some(hook) = hooks.on_replace {
467 hook(DeferredWorld { world: self.world }, entity, component_id);
468 }
469 }
470 }
471 }
472
473 /// Triggers all `on_remove` hooks for [`ComponentId`] in target.
474 ///
475 /// # Safety
476 /// Caller must ensure [`ComponentId`] in target exist in self.
477 #[inline]
478 pub(crate) unsafe fn trigger_on_remove(
479 &mut self,
480 archetype: &Archetype,
481 entity: Entity,
482 targets: impl Iterator<Item = ComponentId>,
483 ) {
484 if archetype.has_remove_hook() {
485 for component_id in targets {
486 // SAFETY: Caller ensures that these components exist
487 let hooks = unsafe { self.components().get_info_unchecked(component_id) }.hooks();
488 if let Some(hook) = hooks.on_remove {
489 hook(DeferredWorld { world: self.world }, entity, component_id);
490 }
491 }
492 }
493 }
494
495 /// Triggers all event observers for [`ComponentId`] in target.
496 ///
497 /// # Safety
498 /// Caller must ensure observers listening for `event` can accept ZST pointers
499 #[inline]
500 pub(crate) unsafe fn trigger_observers(
501 &mut self,
502 event: ComponentId,
503 entity: Entity,
504 components: impl Iterator<Item = ComponentId> + Clone,
505 ) {
506 Observers::invoke::<_>(
507 self.reborrow(),
508 event,
509 entity,
510 components,
511 &mut (),
512 &mut false,
513 );
514 }
515
516 /// Triggers all event observers for [`ComponentId`] in target.
517 ///
518 /// # Safety
519 /// Caller must ensure `E` is accessible as the type represented by `event`
520 #[inline]
521 pub(crate) unsafe fn trigger_observers_with_data<E, T>(
522 &mut self,
523 event: ComponentId,
524 mut entity: Entity,
525 components: &[ComponentId],
526 data: &mut E,
527 mut propagate: bool,
528 ) where
529 T: Traversal,
530 {
531 loop {
532 Observers::invoke::<_>(
533 self.reborrow(),
534 event,
535 entity,
536 components.iter().copied(),
537 data,
538 &mut propagate,
539 );
540 if !propagate {
541 break;
542 }
543 if let Some(traverse_to) = self
544 .get_entity(entity)
545 .ok()
546 .and_then(|entity| entity.get_components::<T>())
547 .and_then(T::traverse)
548 {
549 entity = traverse_to;
550 } else {
551 break;
552 }
553 }
554 }
555
556 /// Sends a "global" [`Trigger`](crate::observer::Trigger) without any targets.
557 pub fn trigger<T: Event>(&mut self, trigger: impl Event) {
558 self.commands().trigger(trigger);
559 }
560
561 /// Sends a [`Trigger`](crate::observer::Trigger) with the given `targets`.
562 pub fn trigger_targets(
563 &mut self,
564 trigger: impl Event,
565 targets: impl TriggerTargets + Send + Sync + 'static,
566 ) {
567 self.commands().trigger_targets(trigger, targets);
568 }
569
570 /// Gets an [`UnsafeWorldCell`] containing the underlying world.
571 ///
572 /// # Safety
573 /// - must only be used to make non-structural ECS changes
574 #[inline]
575 pub(crate) fn as_unsafe_world_cell(&mut self) -> UnsafeWorldCell {
576 self.world
577 }
578}