naia_bevy_shared/
change_detection.rs

1use std::any::TypeId;
2
3use bevy_ecs::{
4    component::Component,
5    entity::Entity,
6    event::EventWriter,
7    prelude::Event,
8    query::{Added, Changed},
9    removal_detection::RemovedComponents,
10    system::{Query, ResMut},
11};
12
13use naia_shared::{ComponentKind, Replicate};
14
15use crate::{HostOwned, HostOwnedMap};
16
17#[derive(Event)]
18pub enum HostSyncEvent {
19    Insert(TypeId, Entity, ComponentKind),
20    Remove(TypeId, Entity, ComponentKind),
21    Despawn(TypeId, Entity),
22}
23
24impl HostSyncEvent {
25    pub fn host_id(&self) -> TypeId {
26        match self {
27            HostSyncEvent::Insert(type_id, _, _) => *type_id,
28            HostSyncEvent::Remove(type_id, _, _) => *type_id,
29            HostSyncEvent::Despawn(type_id, _) => *type_id,
30        }
31    }
32}
33
34pub fn on_host_owned_added(
35    query: Query<(Entity, &HostOwned), Changed<HostOwned>>,
36    mut host_owned_map: ResMut<HostOwnedMap>,
37) {
38    for (entity, host_owned) in query.iter() {
39        host_owned_map.insert(entity, *host_owned);
40    }
41}
42
43pub fn on_despawn(
44    mut events: EventWriter<HostSyncEvent>,
45    query: Query<Entity>,
46    mut removals: RemovedComponents<HostOwned>,
47    mut host_owned_map: ResMut<HostOwnedMap>,
48) {
49    for entity in removals.read() {
50        if let Ok(_) = query.get(entity) {
51            // Entity is still alive, expected if Auth is reset on Delegated Entity
52        } else {
53            // info!("despawn on HostOwned entity: {:?}", entity);
54            let Some(host_owned) = host_owned_map.remove(&entity) else {
55                panic!("HostOwned entity {:?} not found in HostOwnedMap", entity);
56            };
57            events.send(HostSyncEvent::Despawn(host_owned.type_id(), entity));
58        }
59    }
60}
61
62pub fn on_component_added<R: Replicate + Component>(
63    mut events: EventWriter<HostSyncEvent>,
64    query: Query<(Entity, &HostOwned), Added<R>>,
65) {
66    for (entity, host_owned) in query.iter() {
67        events.send(HostSyncEvent::Insert(
68            host_owned.type_id(),
69            entity,
70            ComponentKind::of::<R>(),
71        ));
72    }
73}
74
75pub fn on_component_removed<R: Replicate + Component>(
76    mut events: EventWriter<HostSyncEvent>,
77    query: Query<&HostOwned>,
78    mut removals: RemovedComponents<R>,
79) {
80    for entity in removals.read() {
81        if let Ok(host_owned) = query.get(entity) {
82            events.send(HostSyncEvent::Remove(
83                host_owned.type_id(),
84                entity,
85                ComponentKind::of::<R>(),
86            ));
87        }
88    }
89}