bevy_ecs/world/deferred_world.rs
1use std::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};
14
15use super::{
16 unsafe_world_cell::{UnsafeEntityCell, UnsafeWorldCell},
17 EntityMut, Mut, World,
18};
19
20/// A [`World`] reference that disallows structural ECS changes.
21/// This includes initializing resources, registering components or spawning entities.
22pub struct DeferredWorld<'w> {
23 // SAFETY: Implementors must not use this reference to make structural changes
24 world: UnsafeWorldCell<'w>,
25}
26
27impl<'w> Deref for DeferredWorld<'w> {
28 type Target = World;
29
30 fn deref(&self) -> &Self::Target {
31 // SAFETY: Structural changes cannot be made through &World
32 unsafe { self.world.world() }
33 }
34}
35
36impl<'w> UnsafeWorldCell<'w> {
37 /// Turn self into a [`DeferredWorld`]
38 ///
39 /// # Safety
40 /// Caller must ensure there are no outstanding mutable references to world and no
41 /// outstanding references to the world's command queue, resource or component data
42 #[inline]
43 pub unsafe fn into_deferred(self) -> DeferredWorld<'w> {
44 DeferredWorld { world: self }
45 }
46}
47
48impl<'w> From<&'w mut World> for DeferredWorld<'w> {
49 fn from(world: &'w mut World) -> DeferredWorld<'w> {
50 DeferredWorld {
51 world: world.as_unsafe_world_cell(),
52 }
53 }
54}
55
56impl<'w> DeferredWorld<'w> {
57 /// Reborrow self as a new instance of [`DeferredWorld`]
58 #[inline]
59 pub fn reborrow(&mut self) -> DeferredWorld {
60 DeferredWorld { world: self.world }
61 }
62
63 /// Creates a [`Commands`] instance that pushes to the world's command queue
64 #[inline]
65 pub fn commands(&mut self) -> Commands {
66 // SAFETY: &mut self ensure that there are no outstanding accesses to the queue
67 let command_queue = unsafe { self.world.get_raw_command_queue() };
68 // SAFETY: command_queue is stored on world and always valid while the world exists
69 unsafe { Commands::new_raw_from_entities(command_queue, self.world.entities()) }
70 }
71
72 /// Retrieves a mutable reference to the given `entity`'s [`Component`] of the given type.
73 /// Returns `None` if the `entity` does not have a [`Component`] of the given type.
74 #[inline]
75 pub fn get_mut<T: Component>(&mut self, entity: Entity) -> Option<Mut<T>> {
76 // SAFETY:
77 // - `as_unsafe_world_cell` is the only thing that is borrowing world
78 // - `as_unsafe_world_cell` provides mutable permission to everything
79 // - `&mut self` ensures no other borrows on world data
80 unsafe { self.world.get_entity(entity)?.get_mut() }
81 }
82
83 /// Retrieves an [`EntityMut`] that exposes read and write operations for the given `entity`.
84 /// Returns [`None`] if the `entity` does not exist.
85 /// Instead of unwrapping the value returned from this function, prefer [`Self::entity_mut`].
86 #[inline]
87 pub fn get_entity_mut(&mut self, entity: Entity) -> Option<EntityMut> {
88 let location = self.entities.get(entity)?;
89 // SAFETY: if the Entity is invalid, the function returns early.
90 // Additionally, Entities::get(entity) returns the correct EntityLocation if the entity exists.
91 let entity_cell = UnsafeEntityCell::new(self.as_unsafe_world_cell(), entity, location);
92 // SAFETY: The UnsafeEntityCell has read access to the entire world.
93 let entity_ref = unsafe { EntityMut::new(entity_cell) };
94 Some(entity_ref)
95 }
96
97 /// Retrieves an [`EntityMut`] that exposes read and write operations for the given `entity`.
98 /// This will panic if the `entity` does not exist. Use [`Self::get_entity_mut`] if you want
99 /// to check for entity existence instead of implicitly panic-ing.
100 #[inline]
101 pub fn entity_mut(&mut self, entity: Entity) -> EntityMut {
102 #[inline(never)]
103 #[cold]
104 fn panic_no_entity(entity: Entity) -> ! {
105 panic!("Entity {entity:?} does not exist");
106 }
107
108 match self.get_entity_mut(entity) {
109 Some(entity) => entity,
110 None => panic_no_entity(entity),
111 }
112 }
113
114 /// Returns [`Query`] for the given [`QueryState`], which is used to efficiently
115 /// run queries on the [`World`] by storing and reusing the [`QueryState`].
116 ///
117 /// # Panics
118 /// If state is from a different world then self
119 #[inline]
120 pub fn query<'s, D: QueryData, F: QueryFilter>(
121 &'w mut self,
122 state: &'s mut QueryState<D, F>,
123 ) -> Query<'w, 's, D, F> {
124 state.validate_world(self.world.id());
125 state.update_archetypes(self);
126 // SAFETY: We ran validate_world to ensure our state matches
127 unsafe {
128 let world_cell = self.world;
129 Query::new(
130 world_cell,
131 state,
132 world_cell.last_change_tick(),
133 world_cell.change_tick(),
134 )
135 }
136 }
137
138 /// Gets a mutable reference to the resource of the given type
139 ///
140 /// # Panics
141 ///
142 /// Panics if the resource does not exist.
143 /// Use [`get_resource_mut`](DeferredWorld::get_resource_mut) instead if you want to handle this case.
144 #[inline]
145 #[track_caller]
146 pub fn resource_mut<R: Resource>(&mut self) -> Mut<'_, R> {
147 match self.get_resource_mut() {
148 Some(x) => x,
149 None => panic!(
150 "Requested resource {} does not exist in the `World`.
151 Did you forget to add it using `app.insert_resource` / `app.init_resource`?
152 Resources are also implicitly added via `app.add_event`,
153 and can be added by plugins.",
154 std::any::type_name::<R>()
155 ),
156 }
157 }
158
159 /// Gets a mutable reference to the resource of the given type if it exists
160 #[inline]
161 pub fn get_resource_mut<R: Resource>(&mut self) -> Option<Mut<'_, R>> {
162 // SAFETY: &mut self ensure that there are no outstanding accesses to the resource
163 unsafe { self.world.get_resource_mut() }
164 }
165
166 /// Gets a mutable reference to the non-send resource of the given type, if it exists.
167 ///
168 /// # Panics
169 ///
170 /// Panics if the resource does not exist.
171 /// Use [`get_non_send_resource_mut`](World::get_non_send_resource_mut) instead if you want to handle this case.
172 ///
173 /// This function will panic if it isn't called from the same thread that the resource was inserted from.
174 #[inline]
175 #[track_caller]
176 pub fn non_send_resource_mut<R: 'static>(&mut self) -> Mut<'_, R> {
177 match self.get_non_send_resource_mut() {
178 Some(x) => x,
179 None => panic!(
180 "Requested non-send resource {} does not exist in the `World`.
181 Did you forget to add it using `app.insert_non_send_resource` / `app.init_non_send_resource`?
182 Non-send resources can also be added by plugins.",
183 std::any::type_name::<R>()
184 ),
185 }
186 }
187
188 /// Gets a mutable reference to the non-send resource of the given type, if it exists.
189 /// Otherwise returns `None`.
190 ///
191 /// # Panics
192 /// This function will panic if it isn't called from the same thread that the resource was inserted from.
193 #[inline]
194 pub fn get_non_send_resource_mut<R: 'static>(&mut self) -> Option<Mut<'_, R>> {
195 // SAFETY: &mut self ensure that there are no outstanding accesses to the resource
196 unsafe { self.world.get_non_send_resource_mut() }
197 }
198
199 /// Sends an [`Event`].
200 /// This method returns the [ID](`EventId`) of the sent `event`,
201 /// or [`None`] if the `event` could not be sent.
202 #[inline]
203 pub fn send_event<E: Event>(&mut self, event: E) -> Option<EventId<E>> {
204 self.send_event_batch(std::iter::once(event))?.next()
205 }
206
207 /// Sends the default value of the [`Event`] of type `E`.
208 /// This method returns the [ID](`EventId`) of the sent `event`,
209 /// or [`None`] if the `event` could not be sent.
210 #[inline]
211 pub fn send_event_default<E: Event + Default>(&mut self) -> Option<EventId<E>> {
212 self.send_event(E::default())
213 }
214
215 /// Sends a batch of [`Event`]s from an iterator.
216 /// This method returns the [IDs](`EventId`) of the sent `events`,
217 /// or [`None`] if the `event` could not be sent.
218 #[inline]
219 pub fn send_event_batch<E: Event>(
220 &mut self,
221 events: impl IntoIterator<Item = E>,
222 ) -> Option<SendBatchIds<E>> {
223 let Some(mut events_resource) = self.get_resource_mut::<Events<E>>() else {
224 bevy_utils::tracing::error!(
225 "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 ",
226 std::any::type_name::<E>()
227 );
228 return None;
229 };
230 Some(events_resource.send_batch(events))
231 }
232
233 /// Gets a pointer to the resource with the id [`ComponentId`] if it exists.
234 /// The returned pointer may be used to modify the resource, as long as the mutable borrow
235 /// of the [`World`] is still valid.
236 ///
237 /// **You should prefer to use the typed API [`World::get_resource_mut`] where possible and only
238 /// use this in cases where the actual types are not known at compile time.**
239 #[inline]
240 pub fn get_resource_mut_by_id(&mut self, component_id: ComponentId) -> Option<MutUntyped<'_>> {
241 // SAFETY: &mut self ensure that there are no outstanding accesses to the resource
242 unsafe { self.world.get_resource_mut_by_id(component_id) }
243 }
244
245 /// Gets a `!Send` resource to the resource with the id [`ComponentId`] if it exists.
246 /// The returned pointer may be used to modify the resource, as long as the mutable borrow
247 /// of the [`World`] is still valid.
248 ///
249 /// **You should prefer to use the typed API [`World::get_resource_mut`] where possible and only
250 /// use this in cases where the actual types are not known at compile time.**
251 ///
252 /// # Panics
253 /// This function will panic if it isn't called from the same thread that the resource was inserted from.
254 #[inline]
255 pub fn get_non_send_mut_by_id(&mut self, component_id: ComponentId) -> Option<MutUntyped<'_>> {
256 // SAFETY: &mut self ensure that there are no outstanding accesses to the resource
257 unsafe { self.world.get_non_send_resource_mut_by_id(component_id) }
258 }
259
260 /// Retrieves a mutable untyped reference to the given `entity`'s [`Component`] of the given [`ComponentId`].
261 /// Returns `None` if the `entity` does not have a [`Component`] of the given type.
262 ///
263 /// **You should prefer to use the typed API [`World::get_mut`] where possible and only
264 /// use this in cases where the actual types are not known at compile time.**
265 #[inline]
266 pub fn get_mut_by_id(
267 &mut self,
268 entity: Entity,
269 component_id: ComponentId,
270 ) -> Option<MutUntyped<'_>> {
271 // SAFETY: &mut self ensure that there are no outstanding accesses to the resource
272 unsafe { self.world.get_entity(entity)?.get_mut_by_id(component_id) }
273 }
274
275 /// Triggers all `on_add` hooks for [`ComponentId`] in target.
276 ///
277 /// # Safety
278 /// Caller must ensure [`ComponentId`] in target exist in self.
279 #[inline]
280 pub(crate) unsafe fn trigger_on_add(
281 &mut self,
282 archetype: &Archetype,
283 entity: Entity,
284 targets: impl Iterator<Item = ComponentId>,
285 ) {
286 if archetype.has_add_hook() {
287 for component_id in targets {
288 // SAFETY: Caller ensures that these components exist
289 let hooks = unsafe { self.components().get_info_unchecked(component_id) }.hooks();
290 if let Some(hook) = hooks.on_add {
291 hook(DeferredWorld { world: self.world }, entity, component_id);
292 }
293 }
294 }
295 }
296
297 /// Triggers all `on_insert` hooks for [`ComponentId`] in target.
298 ///
299 /// # Safety
300 /// Caller must ensure [`ComponentId`] in target exist in self.
301 #[inline]
302 pub(crate) unsafe fn trigger_on_insert(
303 &mut self,
304 archetype: &Archetype,
305 entity: Entity,
306 targets: impl Iterator<Item = ComponentId>,
307 ) {
308 if archetype.has_insert_hook() {
309 for component_id in targets {
310 // SAFETY: Caller ensures that these components exist
311 let hooks = unsafe { self.components().get_info_unchecked(component_id) }.hooks();
312 if let Some(hook) = hooks.on_insert {
313 hook(DeferredWorld { world: self.world }, entity, component_id);
314 }
315 }
316 }
317 }
318
319 /// Triggers all `on_remove` hooks for [`ComponentId`] in target.
320 ///
321 /// # Safety
322 /// Caller must ensure [`ComponentId`] in target exist in self.
323 #[inline]
324 pub(crate) unsafe fn trigger_on_remove(
325 &mut self,
326 archetype: &Archetype,
327 entity: Entity,
328 targets: impl Iterator<Item = ComponentId>,
329 ) {
330 if archetype.has_remove_hook() {
331 for component_id in targets {
332 let hooks =
333 // SAFETY: Caller ensures that these components exist
334 unsafe { self.world.components().get_info_unchecked(component_id) }.hooks();
335 if let Some(hook) = hooks.on_remove {
336 hook(DeferredWorld { world: self.world }, entity, component_id);
337 }
338 }
339 }
340 }
341
342 /// Triggers all event observers for [`ComponentId`] in target.
343 ///
344 /// # Safety
345 /// Caller must ensure observers listening for `event` can accept ZST pointers
346 #[inline]
347 pub(crate) unsafe fn trigger_observers(
348 &mut self,
349 event: ComponentId,
350 entity: Entity,
351 components: impl Iterator<Item = ComponentId>,
352 ) {
353 Observers::invoke(self.reborrow(), event, entity, components, &mut ());
354 }
355
356 /// Triggers all event observers for [`ComponentId`] in target.
357 ///
358 /// # Safety
359 /// Caller must ensure `E` is accessible as the type represented by `event`
360 #[inline]
361 pub(crate) unsafe fn trigger_observers_with_data<E>(
362 &mut self,
363 event: ComponentId,
364 entity: Entity,
365 components: impl Iterator<Item = ComponentId>,
366 data: &mut E,
367 ) {
368 Observers::invoke(self.reborrow(), event, entity, components, data);
369 }
370
371 /// Sends a "global" [`Trigger`] without any targets.
372 pub fn trigger<T: Event>(&mut self, trigger: impl Event) {
373 self.commands().trigger(trigger);
374 }
375
376 /// Sends a [`Trigger`] with the given `targets`.
377 pub fn trigger_targets(&mut self, trigger: impl Event, targets: impl TriggerTargets) {
378 self.commands().trigger_targets(trigger, targets);
379 }
380
381 /// Gets an [`UnsafeWorldCell`] containing the underlying world.
382 ///
383 /// # Safety
384 /// - must only be used to to make non-structural ECS changes
385 #[inline]
386 pub(crate) fn as_unsafe_world_cell(&mut self) -> UnsafeWorldCell {
387 self.world
388 }
389}