Skip to main content

bevy_ecs/observer/
mod.rs

1//! Observers are a push-based tool for responding to [`Event`]s. The [`Observer`] component holds a [`System`] that runs whenever a matching [`Event`]
2//! is triggered.
3//!
4//! See [`Event`] and [`Observer`] for in-depth documentation and usage examples.
5
6mod centralized_storage;
7mod condition;
8mod distributed_storage;
9mod entity_cloning;
10mod runner;
11mod system_param;
12
13pub use centralized_storage::*;
14pub use condition::*;
15pub use distributed_storage::*;
16pub use runner::*;
17pub use system_param::*;
18
19use crate::{
20    change_detection::MaybeLocation,
21    event::Event,
22    prelude::*,
23    world::{DeferredWorld, *},
24};
25
26impl World {
27    /// Spawns a "global" [`Observer`] which will watch for the given event.
28    /// Returns its [`Entity`] as a [`EntityWorldMut`].
29    ///
30    /// `system` can be any system whose first parameter is [`On`].
31    ///
32    /// # Example
33    ///
34    /// ```
35    /// # use bevy_ecs::prelude::*;
36    /// #[derive(Component)]
37    /// struct A;
38    ///
39    /// # let mut world = World::new();
40    /// world.add_observer(|_: On<Add, A>| {
41    ///     // ...
42    /// });
43    /// world.add_observer(|_: On<Remove, A>| {
44    ///     // ...
45    /// });
46    /// ```
47    ///
48    /// **Calling [`observe`](EntityWorldMut::observe) on the returned
49    /// [`EntityWorldMut`] will observe the observer itself, which you very
50    /// likely do not want.**
51    ///
52    /// # Panics
53    ///
54    /// Panics if the given system is an exclusive system.
55    pub fn add_observer<M>(&mut self, observer: impl IntoObserver<M>) -> EntityWorldMut<'_> {
56        self.spawn(observer.into_observer())
57    }
58
59    /// Triggers the given [`Event`], which will run any [`Observer`]s watching for it.
60    ///
61    /// For a variant that borrows the `event` rather than consuming it, use [`World::trigger_ref`] instead.
62    #[track_caller]
63    pub fn trigger<'a, E: Event<Trigger<'a>: Default>>(&mut self, mut event: E) {
64        self.trigger_ref_with_caller(
65            &mut event,
66            &mut <E::Trigger<'a> as Default>::default(),
67            MaybeLocation::caller(),
68        );
69    }
70
71    /// Triggers the given [`Event`] using the given [`Trigger`](crate::event::Trigger), which will run any [`Observer`]s watching for it.
72    ///
73    /// For a variant that borrows the `event` rather than consuming it, use [`World::trigger_ref`] instead.
74    #[track_caller]
75    pub fn trigger_with<'a, E: Event>(&mut self, mut event: E, mut trigger: E::Trigger<'a>) {
76        self.trigger_ref_with_caller(&mut event, &mut trigger, MaybeLocation::caller());
77    }
78
79    /// Triggers the given mutable [`Event`] reference, which will run any [`Observer`]s watching for it.
80    ///
81    /// Compared to [`World::trigger`], this method is most useful when it's necessary to check
82    /// or use the event after it has been modified by observers.
83    #[track_caller]
84    pub fn trigger_ref<'a, E: Event<Trigger<'a>: Default>>(&mut self, event: &mut E) {
85        self.trigger_ref_with_caller(
86            event,
87            &mut <E::Trigger<'a> as Default>::default(),
88            MaybeLocation::caller(),
89        );
90    }
91
92    /// Triggers the given mutable [`Event`] reference using the given mutable [`Trigger`](crate::event::Trigger) reference, which
93    /// will run any [`Observer`]s watching for it.
94    ///
95    /// Compared to [`World::trigger`], this method is most useful when it's necessary to check
96    /// or use the event after it has been modified by observers.
97    pub fn trigger_ref_with<'a, E: Event>(&mut self, event: &mut E, trigger: &mut E::Trigger<'a>) {
98        self.trigger_ref_with_caller(event, trigger, MaybeLocation::caller());
99    }
100
101    pub(crate) fn trigger_ref_with_caller<'a, E: Event>(
102        &mut self,
103        event: &mut E,
104        trigger: &mut E::Trigger<'a>,
105        caller: MaybeLocation,
106    ) {
107        let event_key = self.register_event_key::<E>();
108        // SAFETY: event_key was just registered and matches `event`
109        unsafe {
110            DeferredWorld::from(self).trigger_raw(event_key, event, trigger, caller);
111        }
112    }
113
114    /// Splits `&mut self` into a [`DeferredWorld`] and the [`CachedObservers`]
115    /// registered for `event_key`, or returns `None` if no observers exist.
116    ///
117    /// # Safety
118    ///
119    /// Caller must not use the returned [`DeferredWorld`] to access observer
120    /// storage, as it aliases with the returned [`CachedObservers`] reference.
121    unsafe fn split_for_event(
122        &mut self,
123        event_key: crate::event::EventKey,
124    ) -> Option<(DeferredWorld<'_>, &CachedObservers)> {
125        let world_cell = self.as_unsafe_world_cell();
126        let observers = world_cell.observers();
127        let observers = observers.try_get_observers(event_key)?;
128        // SAFETY: The caller guarantees the returned `DeferredWorld` will not
129        // be used to access observer storage (which `observers` borrows).
130        Some((unsafe { world_cell.into_deferred() }, observers))
131    }
132
133    /// Triggers global [`Observer`]s for `event_key` with untyped event and
134    /// trigger data.
135    ///
136    /// Dynamic equivalent of [`World::trigger`]. Only fires global observers,
137    /// not entity- or component-scoped ones.
138    ///
139    /// Use [`World::trigger_dynamic_targets`] to also fire entity-scoped
140    /// observers.
141    ///
142    /// # Safety
143    ///
144    /// - `event_data` must point to a valid, aligned value whose layout matches
145    ///   what observers registered for this `event_key` expect.
146    /// - `trigger_data` must point to a valid, aligned value whose layout
147    ///   matches what observers registered for this `event_key` expect.
148    #[track_caller]
149    pub unsafe fn trigger_dynamic(
150        &mut self,
151        event_key: crate::event::EventKey,
152        mut event_data: bevy_ptr::PtrMut,
153        mut trigger_data: bevy_ptr::PtrMut,
154    ) {
155        // SAFETY: We have exclusive access via `&mut self` and will not
156        // access observer storage through the returned `DeferredWorld`.
157        let Some((mut world, observers)) = (unsafe { self.split_for_event(event_key) }) else {
158            return;
159        };
160
161        let context = TriggerContext {
162            event_key,
163            caller: MaybeLocation::caller(),
164        };
165
166        // SAFETY: no outstanding world references besides `observers`
167        unsafe {
168            world.as_unsafe_world_cell().increment_trigger_id();
169        }
170
171        for (observer, runner) in observers.global_observers() {
172            // SAFETY:
173            // - `observers` come from `world` and correspond to `event_key`
174            // - caller guarantees `event_data` and `trigger_data` are valid
175            unsafe {
176                (runner)(
177                    world.reborrow(),
178                    *observer,
179                    &context,
180                    event_data.reborrow(),
181                    trigger_data.reborrow(),
182                );
183            }
184        }
185    }
186
187    /// Triggers [`Observer`]s for `event_key` targeting `entity`, with untyped
188    /// event and trigger data.
189    ///
190    /// Fires global and entity-scoped observers. Dynamic equivalent of
191    /// [`EntityWorldMut::trigger`].
192    ///
193    /// # Safety
194    ///
195    /// - `event_data` must point to a valid, aligned value whose layout matches
196    ///   what observers registered for this `event_key` expect.
197    /// - `trigger_data` must point to a valid, aligned value whose layout
198    ///   matches what observers registered for this `event_key` expect.
199    #[track_caller]
200    pub unsafe fn trigger_dynamic_targets(
201        &mut self,
202        event_key: crate::event::EventKey,
203        entity: Entity,
204        event_data: bevy_ptr::PtrMut,
205        trigger_data: bevy_ptr::PtrMut,
206    ) {
207        // SAFETY: We have exclusive access via `&mut self` and will not
208        // access observer storage through the returned `DeferredWorld`.
209        let Some((world, observers)) = (unsafe { self.split_for_event(event_key) }) else {
210            return;
211        };
212
213        let context = TriggerContext {
214            event_key,
215            caller: MaybeLocation::caller(),
216        };
217
218        // SAFETY:
219        // - `observers` come from `world` and correspond to `event_key`
220        // - caller guarantees `event_data` and `trigger_data` are valid
221        // - `trigger_entity_internal` increments the trigger id
222        unsafe {
223            crate::event::trigger_entity_internal(
224                world,
225                observers,
226                event_data,
227                trigger_data,
228                entity,
229                &context,
230            );
231        }
232    }
233
234    /// Triggers [`Observer`]s for `event_key` targeting `entity` and
235    /// `components`, with untyped event and trigger data.
236    ///
237    /// Fires global, entity-scoped, and component-scoped observers.
238    /// Dynamic equivalent of [`EntityComponentsTrigger`].
239    ///
240    /// [`EntityComponentsTrigger`]: crate::event::EntityComponentsTrigger
241    ///
242    /// # Safety
243    ///
244    /// - `event_data` must point to a valid, aligned value whose layout matches
245    ///   what observers registered for this `event_key` expect.
246    /// - `trigger_data` must point to a valid, aligned value whose layout
247    ///   matches what observers registered for this `event_key` expect.
248    #[track_caller]
249    pub unsafe fn trigger_dynamic_targets_components(
250        &mut self,
251        event_key: crate::event::EventKey,
252        entity: Entity,
253        components: &[crate::component::ComponentId],
254        mut event_data: bevy_ptr::PtrMut,
255        mut trigger_data: bevy_ptr::PtrMut,
256    ) {
257        // SAFETY: We have exclusive access via `&mut self` and will not
258        // access observer storage through the returned `DeferredWorld`.
259        let Some((mut world, observers)) = (unsafe { self.split_for_event(event_key) }) else {
260            return;
261        };
262
263        let context = TriggerContext {
264            event_key,
265            caller: MaybeLocation::caller(),
266        };
267
268        // SAFETY:
269        // - `observers` come from `world` and correspond to `event_key`
270        // - caller guarantees `event_data` and `trigger_data` are valid
271        // - `trigger_entity_internal` increments the trigger id
272        unsafe {
273            crate::event::trigger_entity_internal(
274                world.reborrow(),
275                observers,
276                event_data.reborrow(),
277                trigger_data.reborrow(),
278                entity,
279                &context,
280            );
281        }
282
283        // Trigger observers watching for specific components.
284        for id in components {
285            if let Some(component_observers) = observers.component_observers().get(id) {
286                for (observer, runner) in component_observers.global_observers() {
287                    // SAFETY: same as above, caller guarantees data validity
288                    unsafe {
289                        (runner)(
290                            world.reborrow(),
291                            *observer,
292                            &context,
293                            event_data.reborrow(),
294                            trigger_data.reborrow(),
295                        );
296                    }
297                }
298
299                if let Some(map) = component_observers
300                    .entity_component_observers()
301                    .get(&entity)
302                {
303                    for (observer, runner) in map {
304                        // SAFETY: same as above, caller guarantees data validity
305                        unsafe {
306                            (runner)(
307                                world.reborrow(),
308                                *observer,
309                                &context,
310                                event_data.reborrow(),
311                                trigger_data.reborrow(),
312                            );
313                        }
314                    }
315                }
316            }
317        }
318    }
319
320    /// Register an observer to the cache, called when an observer is created
321    pub(crate) fn register_observer(&mut self, observer_entity: Entity) {
322        // SAFETY: References do not alias.
323        let (observer_state, archetypes, observers) = unsafe {
324            let observer_state: *const Observer = self.get::<Observer>(observer_entity).unwrap();
325            // Populate ObservedBy for each observed entity.
326            for watched_entity in (*observer_state).descriptor.entities.iter().copied() {
327                let mut entity_mut = self.entity_mut(watched_entity);
328                let mut observed_by = entity_mut.entry::<ObservedBy>().or_default().into_mut();
329                observed_by.0.push(observer_entity);
330            }
331            (&*observer_state, &mut self.archetypes, &mut self.observers)
332        };
333        let descriptor = &observer_state.descriptor;
334
335        for &event_key in &descriptor.event_keys {
336            let cache = observers.get_observers_mut(event_key);
337
338            if descriptor.components.is_empty() && descriptor.entities.is_empty() {
339                cache
340                    .global_observers
341                    .insert(observer_entity, observer_state.runner);
342            } else if descriptor.components.is_empty() {
343                // Observer is not targeting any components so register it as an entity observer
344                for &watched_entity in &observer_state.descriptor.entities {
345                    let map = cache.entity_observers.entry(watched_entity).or_default();
346                    map.insert(observer_entity, observer_state.runner);
347                }
348            } else {
349                // Register observer for each watched component
350                for &component in &descriptor.components {
351                    let observers =
352                        cache
353                            .component_observers
354                            .entry(component)
355                            .or_insert_with(|| {
356                                if let Some(flag) = Observers::is_archetype_cached(event_key) {
357                                    archetypes.update_flags(component, flag, true);
358                                }
359                                CachedComponentObservers::default()
360                            });
361                    if descriptor.entities.is_empty() {
362                        // Register for all triggers targeting the component
363                        observers
364                            .global_observers
365                            .insert(observer_entity, observer_state.runner);
366                    } else {
367                        // Register for each watched entity
368                        for &watched_entity in &descriptor.entities {
369                            let map = observers
370                                .entity_component_observers
371                                .entry(watched_entity)
372                                .or_default();
373                            map.insert(observer_entity, observer_state.runner);
374                        }
375                    }
376                }
377            }
378        }
379    }
380
381    /// Remove the observer from the cache, called when an observer gets despawned
382    pub(crate) fn unregister_observer(&mut self, entity: Entity, descriptor: ObserverDescriptor) {
383        // Remove this observer from all the corresponding ObservedBy components.
384        for &observing in descriptor.entities.iter() {
385            let Ok(mut observing) = self.get_entity_mut(observing) else {
386                // This can happen when ObservedBy is despawning and is despawning the related
387                // observers.
388                continue;
389            };
390            let Some(mut observed_by) = observing.get_mut::<ObservedBy>() else {
391                // In "normal" usage, this should be impossible, but there's nothing stopping a user
392                // from just removing the ObservedBy component themselves. While that's odd usage,
393                // there's no reason to panic if a user does so.
394                continue;
395            };
396
397            observed_by.0.retain(|e| *e != entity);
398            if observed_by.0.is_empty() {
399                observing.remove::<ObservedBy>();
400            }
401        }
402
403        let archetypes = &mut self.archetypes;
404        let observers = &mut self.observers;
405
406        for &event_key in &descriptor.event_keys {
407            let cache = observers.get_observers_mut(event_key);
408            if descriptor.components.is_empty() && descriptor.entities.is_empty() {
409                cache.global_observers.remove(&entity);
410            } else if descriptor.components.is_empty() {
411                for watched_entity in &descriptor.entities {
412                    // This check should be unnecessary since this observer hasn't been unregistered yet
413                    let Some(observers) = cache.entity_observers.get_mut(watched_entity) else {
414                        continue;
415                    };
416                    observers.remove(&entity);
417                    if observers.is_empty() {
418                        cache.entity_observers.remove(watched_entity);
419                    }
420                }
421            } else {
422                for component in &descriptor.components {
423                    let Some(observers) = cache.component_observers.get_mut(component) else {
424                        continue;
425                    };
426                    if descriptor.entities.is_empty() {
427                        observers.global_observers.remove(&entity);
428                    } else {
429                        for watched_entity in &descriptor.entities {
430                            let Some(map) =
431                                observers.entity_component_observers.get_mut(watched_entity)
432                            else {
433                                continue;
434                            };
435                            map.remove(&entity);
436                            if map.is_empty() {
437                                observers.entity_component_observers.remove(watched_entity);
438                            }
439                        }
440                    }
441
442                    if observers.global_observers.is_empty()
443                        && observers.entity_component_observers.is_empty()
444                    {
445                        cache.component_observers.remove(component);
446                        if let Some(flag) = Observers::is_archetype_cached(event_key)
447                            && let Some(by_component) = archetypes.by_component.get(component)
448                        {
449                            for archetype in by_component.keys() {
450                                let archetype = &mut archetypes.archetypes[archetype.index()];
451                                if archetype.contains(*component) {
452                                    let no_longer_observed = archetype
453                                        .iter_components()
454                                        .all(|id| !cache.component_observers.contains_key(&id));
455
456                                    if no_longer_observed {
457                                        archetype.flags.set(flag, false);
458                                    }
459                                }
460                            }
461                        }
462                    }
463                }
464            }
465        }
466    }
467}
468
469#[cfg(test)]
470mod tests {
471    use alloc::{vec, vec::Vec};
472    use core::any::type_name;
473
474    use bevy_ptr::OwningPtr;
475
476    use crate::{
477        archetype::{Archetype, ArchetypeId},
478        change_detection::MaybeLocation,
479        error::Result,
480        event::{EntityComponentsTrigger, Event, GlobalTrigger},
481        hierarchy::ChildOf,
482        observer::{Discard, ObservedBy, Observer},
483        prelude::*,
484        world::DeferredWorld,
485    };
486
487    #[derive(Component)]
488    struct A;
489
490    #[derive(Component)]
491    struct B;
492
493    #[derive(Component)]
494    #[component(storage = "SparseSet")]
495    struct S;
496
497    #[derive(Event)]
498    struct EventA;
499
500    #[derive(EntityEvent)]
501    struct EntityEventA(Entity);
502
503    #[derive(EntityEvent)]
504    #[entity_event(trigger = EntityComponentsTrigger<'a>)]
505    struct EntityComponentsEvent(Entity);
506
507    #[derive(Event)]
508    struct EventWithData {
509        counter: usize,
510    }
511
512    #[derive(Resource, Default)]
513    struct Order(Vec<&'static str>);
514
515    impl Order {
516        #[track_caller]
517        fn observed(&mut self, name: &'static str) {
518            self.0.push(name);
519        }
520    }
521
522    #[derive(Component, EntityEvent)]
523    #[entity_event(propagate, auto_propagate)]
524    struct EventPropagating(Entity);
525
526    #[test]
527    fn observer_order_spawn_despawn() {
528        let mut world = World::new();
529        world.init_resource::<Order>();
530
531        world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add"));
532        world.add_observer(|_: On<Insert, A>, mut res: ResMut<Order>| res.observed("insert"));
533        world.add_observer(|_: On<Discard, A>, mut res: ResMut<Order>| {
534            res.observed("discard");
535        });
536        world.add_observer(|_: On<Remove, A>, mut res: ResMut<Order>| res.observed("remove"));
537
538        let entity = world.spawn(A).id();
539        world.despawn(entity);
540        assert_eq!(
541            vec!["add", "insert", "discard", "remove"],
542            world.resource::<Order>().0
543        );
544    }
545
546    #[test]
547    fn observer_order_insert_remove() {
548        let mut world = World::new();
549        world.init_resource::<Order>();
550
551        world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add"));
552        world.add_observer(|_: On<Insert, A>, mut res: ResMut<Order>| res.observed("insert"));
553        world.add_observer(|_: On<Discard, A>, mut res: ResMut<Order>| {
554            res.observed("discard");
555        });
556        world.add_observer(|_: On<Remove, A>, mut res: ResMut<Order>| res.observed("remove"));
557
558        let mut entity = world.spawn_empty();
559        entity.insert(A);
560        entity.remove::<A>();
561        entity.flush();
562        assert_eq!(
563            vec!["add", "insert", "discard", "remove"],
564            world.resource::<Order>().0
565        );
566    }
567
568    #[test]
569    fn observer_order_insert_remove_sparse() {
570        let mut world = World::new();
571        world.init_resource::<Order>();
572
573        world.add_observer(|_: On<Add, S>, mut res: ResMut<Order>| res.observed("add"));
574        world.add_observer(|_: On<Insert, S>, mut res: ResMut<Order>| res.observed("insert"));
575        world.add_observer(|_: On<Discard, S>, mut res: ResMut<Order>| {
576            res.observed("discard");
577        });
578        world.add_observer(|_: On<Remove, S>, mut res: ResMut<Order>| res.observed("remove"));
579
580        let mut entity = world.spawn_empty();
581        entity.insert(S);
582        entity.remove::<S>();
583        entity.flush();
584        assert_eq!(
585            vec!["add", "insert", "discard", "remove"],
586            world.resource::<Order>().0
587        );
588    }
589
590    #[test]
591    fn observer_order_replace() {
592        let mut world = World::new();
593        world.init_resource::<Order>();
594
595        let entity = world.spawn(A).id();
596
597        world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add"));
598        world.add_observer(|_: On<Insert, A>, mut res: ResMut<Order>| res.observed("insert"));
599        world.add_observer(|_: On<Discard, A>, mut res: ResMut<Order>| {
600            res.observed("discard");
601        });
602        world.add_observer(|_: On<Remove, A>, mut res: ResMut<Order>| res.observed("remove"));
603
604        let mut entity = world.entity_mut(entity);
605        entity.insert(A);
606        entity.flush();
607        assert_eq!(vec!["discard", "insert"], world.resource::<Order>().0);
608    }
609
610    #[test]
611    fn observer_order_recursive() {
612        let mut world = World::new();
613        world.init_resource::<Order>();
614        world.add_observer(
615            |add: On<Add, A>, mut res: ResMut<Order>, mut commands: Commands| {
616                res.observed("add_a");
617                commands.entity(add.entity).insert(B);
618            },
619        );
620        world.add_observer(
621            |remove: On<Remove, A>, mut res: ResMut<Order>, mut commands: Commands| {
622                res.observed("remove_a");
623                commands.entity(remove.entity).remove::<B>();
624            },
625        );
626
627        world.add_observer(
628            |add: On<Add, B>, mut res: ResMut<Order>, mut commands: Commands| {
629                res.observed("add_b");
630                commands.entity(add.entity).remove::<A>();
631            },
632        );
633        world.add_observer(|_: On<Remove, B>, mut res: ResMut<Order>| {
634            res.observed("remove_b");
635        });
636
637        let entity = world.spawn(A).flush();
638        let entity = world.get_entity(entity).unwrap();
639        assert!(!entity.contains::<A>());
640        assert!(!entity.contains::<B>());
641        assert_eq!(
642            vec!["add_a", "add_b", "remove_a", "remove_b"],
643            world.resource::<Order>().0
644        );
645    }
646
647    #[test]
648    fn observer_trigger_ref() {
649        let mut world = World::new();
650
651        world.add_observer(|mut event: On<EventWithData>| event.counter += 1);
652        world.add_observer(|mut event: On<EventWithData>| event.counter += 2);
653        world.add_observer(|mut event: On<EventWithData>| event.counter += 4);
654
655        let mut event = EventWithData { counter: 0 };
656        world.trigger_ref(&mut event);
657        assert_eq!(7, event.counter);
658    }
659
660    #[test]
661    fn observer_multiple_listeners() {
662        let mut world = World::new();
663        world.init_resource::<Order>();
664
665        world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add_1"));
666        world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add_2"));
667
668        world.spawn(A).flush();
669        assert_eq!(vec!["add_2", "add_1"], world.resource::<Order>().0);
670        // we have one A entity and two observers
671        assert_eq!(world.query::<&A>().query(&world).count(), 1);
672        assert_eq!(world.query::<&Observer>().query(&world).count(), 2);
673    }
674
675    #[test]
676    fn observer_multiple_events() {
677        let mut world = World::new();
678        world.init_resource::<Order>();
679        let on_remove = world.register_event_key::<Remove>();
680        world.spawn(
681            // SAFETY: Add and Remove are both unit types, so this is safe
682            unsafe {
683                Observer::new(|_: On<Add, A>, mut res: ResMut<Order>| {
684                    res.observed("add/remove");
685                })
686                .with_event_key(on_remove)
687            },
688        );
689
690        let entity = world.spawn(A).id();
691        world.despawn(entity);
692        assert_eq!(
693            vec!["add/remove", "add/remove"],
694            world.resource::<Order>().0
695        );
696    }
697
698    #[test]
699    fn observer_multiple_components() {
700        let mut world = World::new();
701        world.init_resource::<Order>();
702        world.register_component::<A>();
703        world.register_component::<B>();
704
705        world.add_observer(|_: On<Add, (A, B)>, mut res: ResMut<Order>| {
706            res.observed("add_ab");
707        });
708
709        let entity = world.spawn(A).id();
710        world.entity_mut(entity).insert(B);
711        assert_eq!(vec!["add_ab", "add_ab"], world.resource::<Order>().0);
712    }
713
714    #[test]
715    fn observer_despawn() {
716        let mut world = World::new();
717
718        let system: fn(On<Add, A>) = |_| {
719            panic!("Observer triggered after being despawned.");
720        };
721        let observer = world.add_observer(system).id();
722        world.despawn(observer);
723        world.spawn(A).flush();
724    }
725
726    // Regression test for https://github.com/bevyengine/bevy/issues/14961
727    #[test]
728    fn observer_despawn_archetype_flags() {
729        let mut world = World::new();
730        world.init_resource::<Order>();
731
732        let entity = world.spawn((A, B)).flush();
733
734        world.add_observer(|_: On<Remove, A>, mut res: ResMut<Order>| {
735            res.observed("remove_a");
736        });
737
738        let system: fn(On<Remove, B>) = |_: On<Remove, B>| {
739            panic!("Observer triggered after being despawned.");
740        };
741
742        let observer = world.add_observer(system).flush();
743        world.despawn(observer);
744
745        world.despawn(entity);
746
747        assert_eq!(vec!["remove_a"], world.resource::<Order>().0);
748    }
749
750    #[test]
751    fn observer_multiple_matches() {
752        let mut world = World::new();
753        world.init_resource::<Order>();
754
755        world.add_observer(|_: On<Add, (A, B)>, mut res: ResMut<Order>| {
756            res.observed("add_ab");
757        });
758
759        world.spawn((A, B)).flush();
760        assert_eq!(vec!["add_ab"], world.resource::<Order>().0);
761    }
762
763    #[test]
764    fn observer_entity_routing() {
765        let mut world = World::new();
766        world.init_resource::<Order>();
767
768        let system: fn(On<EntityEventA>) = |_| {
769            panic!("Trigger routed to non-targeted entity.");
770        };
771
772        world.spawn_empty().observe(system);
773        let entity = world
774            .spawn_empty()
775            .observe(|_: On<EntityEventA>, mut res: ResMut<Order>| res.observed("a_1"))
776            .id();
777        world.add_observer(move |event: On<EntityEventA>, mut res: ResMut<Order>| {
778            assert_eq!(event.event_target(), entity);
779            res.observed("a_2");
780        });
781
782        world.trigger(EntityEventA(entity));
783        assert_eq!(vec!["a_2", "a_1"], world.resource::<Order>().0);
784    }
785
786    #[test]
787    fn observer_multiple_targets() {
788        #[derive(Resource, Default)]
789        struct R(i32);
790
791        let mut world = World::new();
792        let component_a = world.register_component::<A>();
793        let component_b = world.register_component::<B>();
794        world.init_resource::<R>();
795
796        // targets (entity_1, A)
797        let entity_1 = world
798            .spawn_empty()
799            .observe(|_: On<EntityComponentsEvent, A>, mut res: ResMut<R>| res.0 += 1)
800            .id();
801        // targets (entity_2, B)
802        let entity_2 = world
803            .spawn_empty()
804            .observe(|_: On<EntityComponentsEvent, B>, mut res: ResMut<R>| res.0 += 10)
805            .id();
806        // targets any entity or component
807        world.add_observer(|_: On<EntityComponentsEvent>, mut res: ResMut<R>| res.0 += 100);
808        // targets any entity, and components A or B
809        world
810            .add_observer(|_: On<EntityComponentsEvent, (A, B)>, mut res: ResMut<R>| res.0 += 1000);
811        // test all tuples
812        world.add_observer(
813            |_: On<EntityComponentsEvent, (A, B, (A, B))>, mut res: ResMut<R>| res.0 += 10000,
814        );
815        world.add_observer(
816            |_: On<EntityComponentsEvent, (A, B, (A, B), ((A, B), (A, B)))>, mut res: ResMut<R>| {
817                res.0 += 100000;
818            },
819        );
820        world.add_observer(
821            |_: On<EntityComponentsEvent, (A, B, (A, B), (B, A), (A, B, ((A, B), (B, A))))>,
822             mut res: ResMut<R>| res.0 += 1000000,
823        );
824
825        // trigger for an entity and a component
826        world.trigger_with(
827            EntityComponentsEvent(entity_1),
828            EntityComponentsTrigger {
829                components: &[component_a],
830                old_archetype: None,
831                new_archetype: None,
832            },
833        );
834        // only observer that doesn't trigger is the one only watching entity_2
835        assert_eq!(1111101, world.resource::<R>().0);
836        world.resource_mut::<R>().0 = 0;
837
838        // trigger for both entities, but no components: trigger once per entity target
839        world.trigger_with(
840            EntityComponentsEvent(entity_1),
841            EntityComponentsTrigger {
842                components: &[],
843                old_archetype: None,
844                new_archetype: None,
845            },
846        );
847        world.trigger_with(
848            EntityComponentsEvent(entity_2),
849            EntityComponentsTrigger {
850                components: &[],
851                old_archetype: None,
852                new_archetype: None,
853            },
854        );
855
856        // only the observer that doesn't require components triggers - once per entity
857        assert_eq!(200, world.resource::<R>().0);
858        world.resource_mut::<R>().0 = 0;
859
860        // trigger for both entities and both components: trigger once per entity target
861        // we only get 2222211 because a given observer can trigger only once per entity target
862        world.trigger_with(
863            EntityComponentsEvent(entity_1),
864            EntityComponentsTrigger {
865                components: &[component_a, component_b],
866                old_archetype: None,
867                new_archetype: None,
868            },
869        );
870        world.trigger_with(
871            EntityComponentsEvent(entity_2),
872            EntityComponentsTrigger {
873                components: &[component_a, component_b],
874                old_archetype: None,
875                new_archetype: None,
876            },
877        );
878        assert_eq!(2222211, world.resource::<R>().0);
879        world.resource_mut::<R>().0 = 0;
880    }
881
882    #[test]
883    fn observer_dynamic_component() {
884        let mut world = World::new();
885        world.init_resource::<Order>();
886
887        let component_id = world.register_component::<A>();
888        world.spawn(
889            Observer::new(|_: On<Add>, mut res: ResMut<Order>| res.observed("event_a"))
890                .with_component(component_id),
891        );
892
893        let mut entity = world.spawn_empty();
894        OwningPtr::make(A, |ptr| {
895            // SAFETY: we registered `component_id` above.
896            unsafe { entity.insert_by_id(component_id, ptr) };
897        });
898
899        assert_eq!(vec!["event_a"], world.resource::<Order>().0);
900    }
901
902    #[test]
903    fn observer_dynamic_trigger() {
904        let mut world = World::new();
905        world.init_resource::<Order>();
906        let event_a = world.register_event_key::<EventA>();
907
908        // SAFETY: we registered `event_a` above and it matches the type of EventA
909        let observe = unsafe {
910            Observer::with_dynamic_runner(
911                |mut world, _observer, _trigger_context, _event, _trigger| {
912                    world.resource_mut::<Order>().observed("event_a");
913                },
914            )
915            .with_event_key(event_a)
916        };
917        world.spawn(observe);
918
919        world.commands().queue(move |world: &mut World| {
920            // SAFETY: we registered `event_a` above and it matches the type of EventA
921            unsafe {
922                DeferredWorld::from(world).trigger_raw(
923                    event_a,
924                    &mut EventA,
925                    &mut GlobalTrigger,
926                    MaybeLocation::caller(),
927                );
928            }
929        });
930        world.flush();
931        assert_eq!(vec!["event_a"], world.resource::<Order>().0);
932    }
933
934    /// Collects `u32` values read by dynamic observers through `PtrMut`.
935    #[derive(Resource, Default)]
936    struct DynamicValues(Vec<u32>);
937
938    #[test]
939    fn observer_fully_dynamic_trigger() {
940        use core::alloc::Layout;
941
942        let mut world = World::new();
943        world.init_resource::<Order>();
944        world.init_resource::<DynamicValues>();
945
946        // Register a dynamic event whose data is a u32.
947        let event_id = world.register_component_with_descriptor(
948            // SAFETY: u32 layout with no drop
949            unsafe {
950                crate::component::ComponentDescriptor::new_with_layout(
951                    "DynamicEvent",
952                    crate::component::StorageType::Table,
953                    Layout::new::<u32>(),
954                    None,
955                    false,
956                    crate::component::ComponentCloneBehavior::Ignore,
957                    None,
958                )
959            },
960        );
961        // SAFETY: event_id was just registered for use as an event
962        let event_key = unsafe { crate::event::EventKey::new(event_id) };
963
964        // SAFETY: event_key was just created, observer reads event_data as u32
965        let observe = unsafe {
966            Observer::with_dynamic_runner(
967                |mut world, _observer, _trigger_context, event, _trigger| {
968                    // SAFETY: caller passes a valid u32 pointer as event data
969                    let value = *event.as_ref().deref::<u32>();
970                    world.resource_mut::<Order>().observed("dynamic_event");
971                    world.resource_mut::<DynamicValues>().0.push(value);
972                },
973            )
974            .with_event_key(event_key)
975        };
976        world.spawn(observe);
977
978        let mut event_data: u32 = 42;
979        let mut trigger_data: u32 = 0;
980        // SAFETY: pointers are valid u32s matching the registered layout
981        unsafe {
982            world.trigger_dynamic(
983                event_key,
984                bevy_ptr::PtrMut::from(&mut event_data),
985                bevy_ptr::PtrMut::from(&mut trigger_data),
986            );
987        }
988
989        assert_eq!(vec!["dynamic_event"], world.resource::<Order>().0);
990        assert_eq!(vec![42], world.resource::<DynamicValues>().0);
991    }
992
993    #[test]
994    fn observer_fully_dynamic_trigger_targets() {
995        use core::alloc::Layout;
996
997        let mut world = World::new();
998        world.init_resource::<Order>();
999        world.init_resource::<DynamicValues>();
1000
1001        let event_id = world.register_component_with_descriptor(
1002            // SAFETY: u32 layout with no drop
1003            unsafe {
1004                crate::component::ComponentDescriptor::new_with_layout(
1005                    "DynamicEntityEvent",
1006                    crate::component::StorageType::Table,
1007                    Layout::new::<u32>(),
1008                    None,
1009                    false,
1010                    crate::component::ComponentCloneBehavior::Ignore,
1011                    None,
1012                )
1013            },
1014        );
1015        // SAFETY: event_id was just registered for use as an event
1016        let event_key = unsafe { crate::event::EventKey::new(event_id) };
1017
1018        let target = world.spawn_empty().id();
1019        let other = world.spawn_empty().id();
1020
1021        // SAFETY: event_key was just created, observer reads event_data as u32
1022        let global = unsafe {
1023            Observer::with_dynamic_runner(
1024                |mut world, _observer, _trigger_context, event, _trigger| {
1025                    let value = *event.as_ref().deref::<u32>();
1026                    world.resource_mut::<Order>().observed("global");
1027                    world.resource_mut::<DynamicValues>().0.push(value);
1028                },
1029            )
1030            .with_event_key(event_key)
1031        };
1032        world.spawn(global);
1033
1034        // SAFETY: event_key was just created, observer reads event_data as u32
1035        let entity_scoped = unsafe {
1036            Observer::with_dynamic_runner(
1037                |mut world, _observer, _trigger_context, event, _trigger| {
1038                    let value = *event.as_ref().deref::<u32>();
1039                    world.resource_mut::<Order>().observed("entity_scoped");
1040                    world.resource_mut::<DynamicValues>().0.push(value);
1041                },
1042            )
1043            .with_event_key(event_key)
1044            .with_entity(target)
1045        };
1046        world.spawn(entity_scoped);
1047
1048        // Trigger targeting `target`: both global and entity-scoped should fire.
1049        let mut event_data: u32 = 7;
1050        let mut trigger_data: u32 = 0;
1051        // SAFETY: pointers are valid u32s matching the registered layout
1052        unsafe {
1053            world.trigger_dynamic_targets(
1054                event_key,
1055                target,
1056                bevy_ptr::PtrMut::from(&mut event_data),
1057                bevy_ptr::PtrMut::from(&mut trigger_data),
1058            );
1059        }
1060
1061        assert_eq!(vec!["global", "entity_scoped"], world.resource::<Order>().0);
1062        assert_eq!(vec![7, 7], world.resource::<DynamicValues>().0);
1063
1064        // Trigger targeting `other`: only global should fire.
1065        world.resource_mut::<Order>().0.clear();
1066        world.resource_mut::<DynamicValues>().0.clear();
1067        let mut event_data: u32 = 99;
1068        let mut trigger_data: u32 = 0;
1069        // SAFETY: pointers are valid u32s matching the registered layout
1070        unsafe {
1071            world.trigger_dynamic_targets(
1072                event_key,
1073                other,
1074                bevy_ptr::PtrMut::from(&mut event_data),
1075                bevy_ptr::PtrMut::from(&mut trigger_data),
1076            );
1077        }
1078
1079        assert_eq!(vec!["global"], world.resource::<Order>().0);
1080        assert_eq!(vec![99], world.resource::<DynamicValues>().0);
1081    }
1082
1083    #[test]
1084    fn observer_fully_dynamic_trigger_targets_components() {
1085        use core::alloc::Layout;
1086
1087        let mut world = World::new();
1088        world.init_resource::<Order>();
1089        world.init_resource::<DynamicValues>();
1090
1091        let event_id = world.register_component_with_descriptor(
1092            // SAFETY: u32 layout with no drop
1093            unsafe {
1094                crate::component::ComponentDescriptor::new_with_layout(
1095                    "DynamicComponentEvent",
1096                    crate::component::StorageType::Table,
1097                    Layout::new::<u32>(),
1098                    None,
1099                    false,
1100                    crate::component::ComponentCloneBehavior::Ignore,
1101                    None,
1102                )
1103            },
1104        );
1105        // SAFETY: event_id was just registered for use as an event
1106        let event_key = unsafe { crate::event::EventKey::new(event_id) };
1107
1108        // Register a dynamic component to scope an observer to.
1109        let comp_id = world.register_component_with_descriptor(
1110            // SAFETY: ZST layout with no drop
1111            unsafe {
1112                crate::component::ComponentDescriptor::new_with_layout(
1113                    "DynamicComp",
1114                    crate::component::StorageType::Table,
1115                    Layout::new::<()>(),
1116                    None,
1117                    false,
1118                    crate::component::ComponentCloneBehavior::Ignore,
1119                    None,
1120                )
1121            },
1122        );
1123
1124        let target = world.spawn_empty().id();
1125
1126        // SAFETY: event_key was just created, observer reads event_data as u32
1127        let global = unsafe {
1128            Observer::with_dynamic_runner(
1129                |mut world, _observer, _trigger_context, event, _trigger| {
1130                    let value = *event.as_ref().deref::<u32>();
1131                    world.resource_mut::<Order>().observed("global");
1132                    world.resource_mut::<DynamicValues>().0.push(value);
1133                },
1134            )
1135            .with_event_key(event_key)
1136        };
1137        world.spawn(global);
1138
1139        // SAFETY: event_key was just created, observer reads event_data as u32
1140        let comp_scoped = unsafe {
1141            Observer::with_dynamic_runner(
1142                |mut world, _observer, _trigger_context, event, _trigger| {
1143                    let value = *event.as_ref().deref::<u32>();
1144                    world.resource_mut::<Order>().observed("comp_scoped");
1145                    world.resource_mut::<DynamicValues>().0.push(value);
1146                },
1147            )
1148            .with_event_key(event_key)
1149            .with_component(comp_id)
1150        };
1151        world.spawn(comp_scoped);
1152
1153        // Trigger with `comp_id` in the components list: both should fire.
1154        let mut event_data: u32 = 5;
1155        let mut trigger_data: u32 = 0;
1156        // SAFETY: pointers are valid u32s matching the registered layout
1157        unsafe {
1158            world.trigger_dynamic_targets_components(
1159                event_key,
1160                target,
1161                &[comp_id],
1162                bevy_ptr::PtrMut::from(&mut event_data),
1163                bevy_ptr::PtrMut::from(&mut trigger_data),
1164            );
1165        }
1166
1167        assert_eq!(vec!["global", "comp_scoped"], world.resource::<Order>().0);
1168        assert_eq!(vec![5, 5], world.resource::<DynamicValues>().0);
1169
1170        // Trigger without components: only global should fire.
1171        world.resource_mut::<Order>().0.clear();
1172        world.resource_mut::<DynamicValues>().0.clear();
1173        let mut event_data: u32 = 10;
1174        let mut trigger_data: u32 = 0;
1175        // SAFETY: pointers are valid u32s matching the registered layout
1176        unsafe {
1177            world.trigger_dynamic_targets_components(
1178                event_key,
1179                target,
1180                &[],
1181                bevy_ptr::PtrMut::from(&mut event_data),
1182                bevy_ptr::PtrMut::from(&mut trigger_data),
1183            );
1184        }
1185
1186        assert_eq!(vec!["global"], world.resource::<Order>().0);
1187        assert_eq!(vec![10], world.resource::<DynamicValues>().0);
1188    }
1189
1190    #[test]
1191    fn observer_propagating() {
1192        let mut world = World::new();
1193        world.init_resource::<Order>();
1194
1195        let parent = world.spawn_empty().id();
1196        let child = world.spawn(ChildOf(parent)).id();
1197
1198        world.entity_mut(parent).observe(
1199            move |event: On<EventPropagating>, mut res: ResMut<Order>| {
1200                res.observed("parent");
1201
1202                assert_eq!(event.event_target(), parent);
1203                assert_eq!(event.original_event_target(), child);
1204            },
1205        );
1206
1207        world.entity_mut(child).observe(
1208            move |event: On<EventPropagating>, mut res: ResMut<Order>| {
1209                res.observed("child");
1210                assert_eq!(event.event_target(), child);
1211                assert_eq!(event.original_event_target(), child);
1212            },
1213        );
1214
1215        world.trigger(EventPropagating(child));
1216
1217        assert_eq!(vec!["child", "parent"], world.resource::<Order>().0);
1218    }
1219
1220    #[test]
1221    fn observer_propagating_redundant_dispatch_same_entity() {
1222        let mut world = World::new();
1223        world.init_resource::<Order>();
1224
1225        let parent = world
1226            .spawn_empty()
1227            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1228                res.observed("parent");
1229            })
1230            .id();
1231
1232        let child = world
1233            .spawn(ChildOf(parent))
1234            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1235                res.observed("child");
1236            })
1237            .id();
1238
1239        world.trigger(EventPropagating(child));
1240        world.trigger(EventPropagating(child));
1241
1242        assert_eq!(
1243            vec!["child", "parent", "child", "parent"],
1244            world.resource::<Order>().0
1245        );
1246    }
1247
1248    #[test]
1249    fn observer_propagating_redundant_dispatch_parent_child() {
1250        let mut world = World::new();
1251        world.init_resource::<Order>();
1252
1253        let parent = world
1254            .spawn_empty()
1255            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1256                res.observed("parent");
1257            })
1258            .id();
1259
1260        let child = world
1261            .spawn(ChildOf(parent))
1262            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1263                res.observed("child");
1264            })
1265            .id();
1266
1267        world.trigger(EventPropagating(child));
1268        world.trigger(EventPropagating(parent));
1269
1270        assert_eq!(
1271            vec!["child", "parent", "parent"],
1272            world.resource::<Order>().0
1273        );
1274    }
1275
1276    #[test]
1277    fn observer_propagating_halt() {
1278        let mut world = World::new();
1279        world.init_resource::<Order>();
1280
1281        let parent = world
1282            .spawn_empty()
1283            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1284                res.observed("parent");
1285            })
1286            .id();
1287
1288        let child = world
1289            .spawn(ChildOf(parent))
1290            .observe(|mut event: On<EventPropagating>, mut res: ResMut<Order>| {
1291                res.observed("child");
1292                event.propagate(false);
1293            })
1294            .id();
1295
1296        world.trigger(EventPropagating(child));
1297
1298        assert_eq!(vec!["child"], world.resource::<Order>().0);
1299    }
1300
1301    #[test]
1302    fn observer_propagating_join() {
1303        let mut world = World::new();
1304        world.init_resource::<Order>();
1305
1306        let parent = world
1307            .spawn_empty()
1308            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1309                res.observed("parent");
1310            })
1311            .id();
1312
1313        let child_a = world
1314            .spawn(ChildOf(parent))
1315            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1316                res.observed("child_a");
1317            })
1318            .id();
1319
1320        let child_b = world
1321            .spawn(ChildOf(parent))
1322            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1323                res.observed("child_b");
1324            })
1325            .id();
1326
1327        world.trigger(EventPropagating(child_a));
1328        world.trigger(EventPropagating(child_b));
1329
1330        assert_eq!(
1331            vec!["child_a", "parent", "child_b", "parent"],
1332            world.resource::<Order>().0
1333        );
1334    }
1335
1336    #[test]
1337    fn observer_propagating_no_next() {
1338        let mut world = World::new();
1339        world.init_resource::<Order>();
1340
1341        let entity = world
1342            .spawn_empty()
1343            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1344                res.observed("event");
1345            })
1346            .id();
1347
1348        world.trigger(EventPropagating(entity));
1349        assert_eq!(vec!["event"], world.resource::<Order>().0);
1350    }
1351
1352    #[test]
1353    fn observer_propagating_parallel_propagation() {
1354        let mut world = World::new();
1355        world.init_resource::<Order>();
1356
1357        let parent_a = world
1358            .spawn_empty()
1359            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1360                res.observed("parent_a");
1361            })
1362            .id();
1363
1364        let child_a = world
1365            .spawn(ChildOf(parent_a))
1366            .observe(|mut event: On<EventPropagating>, mut res: ResMut<Order>| {
1367                res.observed("child_a");
1368                event.propagate(false);
1369            })
1370            .id();
1371
1372        let parent_b = world
1373            .spawn_empty()
1374            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1375                res.observed("parent_b");
1376            })
1377            .id();
1378
1379        let child_b = world
1380            .spawn(ChildOf(parent_b))
1381            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1382                res.observed("child_b");
1383            })
1384            .id();
1385
1386        world.trigger(EventPropagating(child_a));
1387        world.trigger(EventPropagating(child_b));
1388
1389        assert_eq!(
1390            vec!["child_a", "child_b", "parent_b"],
1391            world.resource::<Order>().0
1392        );
1393    }
1394
1395    #[test]
1396    fn observer_propagating_world() {
1397        let mut world = World::new();
1398        world.init_resource::<Order>();
1399
1400        world.add_observer(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1401            res.observed("event");
1402        });
1403
1404        let grandparent = world.spawn_empty().id();
1405        let parent = world.spawn(ChildOf(grandparent)).id();
1406        let child = world.spawn(ChildOf(parent)).id();
1407
1408        world.trigger(EventPropagating(child));
1409
1410        assert_eq!(vec!["event", "event", "event"], world.resource::<Order>().0);
1411    }
1412
1413    #[test]
1414    fn observer_propagating_world_skipping() {
1415        let mut world = World::new();
1416        world.init_resource::<Order>();
1417
1418        world.add_observer(
1419            |event: On<EventPropagating>, query: Query<&A>, mut res: ResMut<Order>| {
1420                if query.get(event.event_target()).is_ok() {
1421                    res.observed("event");
1422                }
1423            },
1424        );
1425
1426        let grandparent = world.spawn(A).id();
1427        let parent = world.spawn(ChildOf(grandparent)).id();
1428        let child = world.spawn((A, ChildOf(parent))).id();
1429
1430        world.trigger(EventPropagating(child));
1431
1432        assert_eq!(vec!["event", "event"], world.resource::<Order>().0);
1433    }
1434
1435    // Originally for https://github.com/bevyengine/bevy/issues/18452
1436    #[test]
1437    fn observer_modifies_relationship() {
1438        fn on_add(add: On<Add, A>, mut commands: Commands) {
1439            commands
1440                .entity(add.entity)
1441                .with_related_entities::<crate::hierarchy::ChildOf>(|rsc| {
1442                    rsc.spawn_empty();
1443                });
1444        }
1445
1446        let mut world = World::new();
1447        world.add_observer(on_add);
1448        world.spawn(A);
1449    }
1450
1451    // Regression test for https://github.com/bevyengine/bevy/issues/14467
1452    // Fails prior to https://github.com/bevyengine/bevy/pull/15398
1453    #[test]
1454    fn observer_on_remove_during_despawn_spawn_empty() {
1455        let mut world = World::new();
1456
1457        // Observe the removal of A - this will run during despawn
1458        world.add_observer(|_: On<Remove, A>, mut cmd: Commands| {
1459            // Spawn a new entity - this reserves a new ID and requires a flush
1460            // afterward before Entities::free can be called.
1461            cmd.spawn_empty();
1462        });
1463
1464        let ent = world.spawn(A).id();
1465
1466        // Despawn our entity, which runs the Remove observer and allocates a
1467        // new Entity.
1468        // Should not panic - if it does, then Entities was not flushed properly
1469        // after the observer's spawn_empty.
1470        world.despawn(ent);
1471    }
1472
1473    #[test]
1474    #[should_panic]
1475    fn observer_invalid_params() {
1476        #[derive(Resource)]
1477        struct ResA;
1478
1479        #[derive(Resource)]
1480        struct ResB;
1481
1482        let mut world = World::new();
1483        // This fails because `ResA` is not present in the world
1484        world.add_observer(|_: On<EventA>, _: Res<ResA>, mut commands: Commands| {
1485            commands.insert_resource(ResB);
1486        });
1487        world.trigger(EventA);
1488    }
1489
1490    #[test]
1491    fn observer_apply_deferred_from_param_set() {
1492        #[derive(Resource)]
1493        struct ResA;
1494
1495        let mut world = World::new();
1496        world.add_observer(
1497            |_: On<EventA>, mut params: ParamSet<(Query<Entity>, Commands)>| {
1498                params.p1().insert_resource(ResA);
1499            },
1500        );
1501
1502        world.trigger(EventA);
1503        world.flush();
1504
1505        assert!(world.get_resource::<ResA>().is_some());
1506    }
1507
1508    #[test]
1509    #[track_caller]
1510    fn observer_caller_location_event() {
1511        #[derive(Event)]
1512        struct EventA;
1513
1514        let caller = MaybeLocation::caller();
1515        let mut world = World::new();
1516        world.add_observer(move |event: On<EventA>| {
1517            assert_eq!(event.caller(), caller);
1518        });
1519        world.trigger(EventA);
1520    }
1521
1522    #[test]
1523    #[track_caller]
1524    fn observer_caller_location_command_archetype_move() {
1525        #[derive(Component)]
1526        struct Component;
1527
1528        let caller = MaybeLocation::caller();
1529        let mut world = World::new();
1530        world.add_observer(move |event: On<Add, Component>| {
1531            assert_eq!(event.caller(), caller);
1532        });
1533        world.add_observer(move |event: On<Remove, Component>| {
1534            assert_eq!(event.caller(), caller);
1535        });
1536        world.commands().spawn(Component).clear();
1537    }
1538
1539    #[test]
1540    fn observer_watch_entities() {
1541        let mut world = World::new();
1542        world.init_resource::<Order>();
1543        let entities = world
1544            .spawn_batch(core::iter::repeat_n((), 4))
1545            .collect::<Vec<_>>();
1546        let observer = Observer::new(|_: On<EntityEventA>, mut order: ResMut<Order>| {
1547            order.observed("a");
1548        });
1549        world.spawn(observer.with_entities(entities.iter().copied().take(2)));
1550
1551        world.trigger(EntityEventA(entities[0]));
1552        world.trigger(EntityEventA(entities[1]));
1553        assert_eq!(vec!["a", "a"], world.resource::<Order>().0);
1554        world.trigger(EntityEventA(entities[2]));
1555        world.trigger(EntityEventA(entities[3]));
1556        assert_eq!(vec!["a", "a"], world.resource::<Order>().0);
1557    }
1558
1559    #[test]
1560    fn unregister_global_observer() {
1561        let mut world = World::new();
1562        let mut observer = world.add_observer(|_: On<EventA>| {});
1563        observer.remove::<Observer>();
1564        let id = observer.id();
1565        let event_key = world.event_key::<EventA>().unwrap();
1566        assert!(!world
1567            .observers
1568            .get_observers_mut(event_key)
1569            .global_observers
1570            .contains_key(&id));
1571    }
1572
1573    #[test]
1574    fn unregister_entity_observer() {
1575        let mut world = World::new();
1576        let entity = world.spawn_empty().id();
1577        let observer = Observer::new(|_: On<EventA>| {}).with_entity(entity);
1578        let mut observer = world.spawn(observer);
1579        observer.remove::<Observer>();
1580        let event_key = world.event_key::<EventA>().unwrap();
1581        assert!(!world
1582            .observers
1583            .get_observers_mut(event_key)
1584            .entity_observers
1585            .contains_key(&entity));
1586    }
1587
1588    #[test]
1589    fn unregister_component_observer() {
1590        let mut world = World::new();
1591        let a = world.register_component::<A>();
1592        let observer = Observer::new(|_: On<EventA>| {}).with_component(a);
1593        let mut observer = world.spawn(observer);
1594        observer.remove::<Observer>();
1595        let event_key = world.event_key::<EventA>().unwrap();
1596        assert!(!world
1597            .observers
1598            .get_observers_mut(event_key)
1599            .component_observers()
1600            .contains_key(&a));
1601    }
1602
1603    #[derive(Resource)]
1604    struct RunConditionFlag(bool);
1605
1606    #[test]
1607    fn observer_run_condition_true() {
1608        let mut world = World::new();
1609        world.insert_resource(RunConditionFlag(true));
1610        world.init_resource::<Order>();
1611
1612        world.add_observer(
1613            (|_: On<EventA>, mut order: ResMut<Order>| {
1614                order.observed("event");
1615            })
1616            .run_if(|flag: Res<RunConditionFlag>| flag.0),
1617        );
1618
1619        world.trigger(EventA);
1620        assert_eq!(vec!["event"], world.resource::<Order>().0);
1621    }
1622
1623    #[test]
1624    fn observer_run_condition_false() {
1625        let mut world = World::new();
1626        world.insert_resource(RunConditionFlag(false));
1627        world.init_resource::<Order>();
1628
1629        world.add_observer(
1630            (|_: On<EventA>, mut order: ResMut<Order>| {
1631                order.observed("event");
1632            })
1633            .run_if(|flag: Res<RunConditionFlag>| flag.0),
1634        );
1635
1636        world.trigger(EventA);
1637        assert!(world.resource::<Order>().0.is_empty());
1638    }
1639
1640    #[test]
1641    fn observer_run_condition_chained() {
1642        let mut world = World::new();
1643        world.insert_resource(RunConditionFlag(true));
1644        world.init_resource::<Order>();
1645
1646        #[derive(Resource)]
1647        struct SecondFlag(bool);
1648        world.insert_resource(SecondFlag(true));
1649
1650        world.add_observer(
1651            (|_: On<EventA>, mut order: ResMut<Order>| {
1652                order.observed("event");
1653            })
1654            .run_if(|flag: Res<RunConditionFlag>| flag.0)
1655            .run_if(|flag: Res<SecondFlag>| flag.0),
1656        );
1657
1658        world.trigger(EventA);
1659        assert_eq!(vec!["event"], world.resource::<Order>().0);
1660
1661        world.resource_mut::<Order>().0.clear();
1662        world.resource_mut::<SecondFlag>().0 = false;
1663        world.trigger(EventA);
1664        assert!(world.resource::<Order>().0.is_empty());
1665    }
1666
1667    #[test]
1668    fn observer_run_condition_re_evaluated() {
1669        let mut world = World::new();
1670        world.insert_resource(RunConditionFlag(false));
1671        world.init_resource::<Order>();
1672
1673        world.add_observer(
1674            (|_: On<EventA>, mut order: ResMut<Order>| {
1675                order.observed("event");
1676            })
1677            .run_if(|flag: Res<RunConditionFlag>| flag.0),
1678        );
1679
1680        world.trigger(EventA);
1681        assert!(world.resource::<Order>().0.is_empty());
1682
1683        world.resource_mut::<RunConditionFlag>().0 = true;
1684        world.trigger(EventA);
1685        assert_eq!(vec!["event"], world.resource::<Order>().0);
1686    }
1687
1688    #[test]
1689    fn observer_run_condition_result_bool() {
1690        let mut world = World::new();
1691        world.init_resource::<Order>();
1692
1693        world.add_observer(
1694            (|_: On<EventA>, mut order: ResMut<Order>| {
1695                order.observed("err");
1696            })
1697            .run_if(|| -> Result<bool> { Err(core::fmt::Error.into()) }),
1698        );
1699        world.add_observer(
1700            (|_: On<EventA>, mut order: ResMut<Order>| {
1701                order.observed("false");
1702            })
1703            .run_if(|| -> Result<bool> { Ok(false) }),
1704        );
1705        world.add_observer(
1706            (|_: On<EventA>, mut order: ResMut<Order>| {
1707                order.observed("true");
1708            })
1709            .run_if(|| -> Result<bool> { Ok(true) }),
1710        );
1711
1712        world.trigger(EventA);
1713        assert_eq!(vec!["true"], world.resource::<Order>().0);
1714    }
1715
1716    #[test]
1717    fn observer_conditions_and_change_detection() {
1718        #[derive(Resource, Default)]
1719        struct Bool2(pub bool);
1720
1721        let mut world = World::new();
1722        world.init_resource::<Order>();
1723        world.insert_resource(RunConditionFlag(false));
1724        world.insert_resource(Bool2(false));
1725
1726        world.add_observer(
1727            (|_: On<EventA>, mut order: ResMut<Order>| {
1728                order.observed("event");
1729            })
1730            .run_if(|res1: Res<RunConditionFlag>| res1.is_changed())
1731            .run_if(|res2: Res<Bool2>| res2.is_changed()),
1732        );
1733
1734        // both resources were just added.
1735        world.trigger(EventA);
1736        assert_eq!(vec!["event"], world.resource::<Order>().0);
1737
1738        // nothing has changed
1739        world.resource_mut::<Order>().0.clear();
1740        world.trigger(EventA);
1741        assert!(world.resource::<Order>().0.is_empty());
1742
1743        // RunConditionFlag has changed, but observer did not run
1744        world.resource_mut::<RunConditionFlag>().0 = true;
1745        world.trigger(EventA);
1746        assert!(world.resource::<Order>().0.is_empty());
1747
1748        // internal state for the Bool2 condition was updated in the
1749        // previous run, so observer still does not run
1750        world.resource_mut::<Bool2>().0 = true;
1751        world.trigger(EventA);
1752        assert!(world.resource::<Order>().0.is_empty());
1753
1754        // internal state for Bool2 was updated, so observer still does not run
1755        world.resource_mut::<RunConditionFlag>().0 = false;
1756        world.trigger(EventA);
1757        assert!(world.resource::<Order>().0.is_empty());
1758
1759        // now check that it works correctly changing Bool2 first and then RunConditionFlag
1760        world.resource_mut::<Bool2>().0 = false;
1761        world.resource_mut::<RunConditionFlag>().0 = true;
1762        world.trigger(EventA);
1763        assert_eq!(vec!["event"], world.resource::<Order>().0);
1764    }
1765
1766    #[test]
1767    fn entity_observer_with_run_condition() {
1768        let mut world = World::new();
1769        world.insert_resource(RunConditionFlag(true));
1770        world.init_resource::<Order>();
1771
1772        let entity = world
1773            .spawn_empty()
1774            .observe(
1775                (|_: On<EntityEventA>, mut order: ResMut<Order>| {
1776                    order.observed("entity_event");
1777                })
1778                .run_if(|flag: Res<RunConditionFlag>| flag.0),
1779            )
1780            .id();
1781
1782        world.trigger(EntityEventA(entity));
1783        assert_eq!(vec!["entity_event"], world.resource::<Order>().0);
1784
1785        world.resource_mut::<Order>().0.clear();
1786        world.resource_mut::<RunConditionFlag>().0 = false;
1787        world.trigger(EntityEventA(entity));
1788        assert!(world.resource::<Order>().0.is_empty());
1789    }
1790
1791    #[test]
1792    fn observer_builder_run_if() {
1793        let mut world = World::new();
1794        world.insert_resource(RunConditionFlag(true));
1795        world.init_resource::<Order>();
1796
1797        let observer = Observer::new(|_: On<EventA>, mut order: ResMut<Order>| {
1798            order.observed("event");
1799        })
1800        .run_if(|flag: Res<RunConditionFlag>| flag.0);
1801
1802        world.spawn(observer);
1803
1804        world.trigger(EventA);
1805        assert_eq!(vec!["event"], world.resource::<Order>().0);
1806
1807        world.resource_mut::<Order>().0.clear();
1808        world.resource_mut::<RunConditionFlag>().0 = false;
1809        world.trigger(EventA);
1810        assert!(world.resource::<Order>().0.is_empty());
1811    }
1812
1813    #[test]
1814    fn observer_new_old_archetypes() {
1815        #[derive(Resource, Default)]
1816        struct Changes(Vec<(&'static str, Option<ArchetypeId>, Option<ArchetypeId>)>);
1817
1818        let mut world = World::new();
1819        world.init_resource::<Changes>();
1820
1821        fn observer<E: for<'a> Event<Trigger<'a> = EntityComponentsTrigger<'a>>>(
1822            e: On<E, A>,
1823            mut c: ResMut<Changes>,
1824        ) {
1825            c.0.push((
1826                type_name::<E>(),
1827                e.trigger().old_archetype.map(Archetype::id),
1828                e.trigger().new_archetype.map(Archetype::id),
1829            ));
1830        }
1831
1832        let empty = world.spawn(()).archetype().id();
1833        let a = world.spawn(A).archetype().id();
1834        let ab = world.spawn((A, B)).archetype().id();
1835
1836        world.add_observer(observer::<Add>);
1837        world.add_observer(observer::<Insert>);
1838        world.add_observer(observer::<Discard>);
1839        world.add_observer(observer::<Remove>);
1840        world.add_observer(observer::<Despawn>);
1841
1842        let mut entity = world.spawn((A, B));
1843        entity.remove::<(A, B)>();
1844        entity.insert(A);
1845        entity.insert(A);
1846        entity.despawn();
1847
1848        assert_eq!(
1849            &world.resource_mut::<Changes>().0,
1850            &[
1851                ("bevy_ecs::lifecycle::Add", None, Some(ab)),
1852                ("bevy_ecs::lifecycle::Insert", None, Some(ab)),
1853                ("bevy_ecs::lifecycle::Discard", Some(ab), Some(empty)),
1854                ("bevy_ecs::lifecycle::Remove", Some(ab), Some(empty)),
1855                ("bevy_ecs::lifecycle::Add", Some(empty), Some(a)),
1856                ("bevy_ecs::lifecycle::Insert", Some(empty), Some(a)),
1857                ("bevy_ecs::lifecycle::Discard", Some(a), Some(a)),
1858                ("bevy_ecs::lifecycle::Insert", Some(a), Some(a)),
1859                ("bevy_ecs::lifecycle::Despawn", Some(a), None),
1860                ("bevy_ecs::lifecycle::Discard", Some(a), None),
1861                ("bevy_ecs::lifecycle::Remove", Some(a), None),
1862            ],
1863        );
1864    }
1865
1866    #[test]
1867    fn despawning_observer_removes_observed_by() {
1868        let mut world = World::new();
1869
1870        #[derive(EntityEvent)]
1871        struct Hi {
1872            entity: Entity,
1873        }
1874
1875        let target = world.spawn_empty().id();
1876        let observer = world
1877            .spawn(Observer::new(|_: On<Hi>| {}).with_entity(target))
1878            .id();
1879
1880        assert_eq!(
1881            world.entity(target).get::<ObservedBy>().unwrap().get(),
1882            &[observer]
1883        );
1884
1885        world.entity_mut(observer).despawn();
1886
1887        assert!(!world.entity(target).contains::<ObservedBy>());
1888    }
1889
1890    #[test]
1891    fn despawning_observer_removes_observed_by_repeated() {
1892        let mut world = World::new();
1893
1894        #[derive(EntityEvent)]
1895        struct Hi {
1896            entity: Entity,
1897        }
1898
1899        let target = world.spawn_empty().id();
1900        let observer = world
1901            // Observe the same entity multiple times.
1902            .spawn(Observer::new(|_: On<Hi>| {}).with_entities([target, target]))
1903            .id();
1904
1905        // Having an observer observe the same entity multiple times is likely not desired, but
1906        // preventing this is not worth it, so make sure it behaves correctly.
1907        assert_eq!(
1908            world.entity(target).get::<ObservedBy>().unwrap().get(),
1909            &[observer, observer]
1910        );
1911
1912        world.entity_mut(observer).despawn();
1913
1914        assert!(!world.entity(target).contains::<ObservedBy>());
1915    }
1916}