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