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
6849 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::{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
22
use 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.
28
pub struct DeferredWorld<'w> {
29
// SAFETY: Implementers must not use this reference to make structural changes
30
world: UnsafeWorldCell<'w>,
31
}
32
33
impl<'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
42
impl<'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
54
impl<'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
62
impl<'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
}
838
839