finished initial networking impl
Signed-off-by: Sienna Meridian Satterwhite <sienna@r3t.io>
This commit is contained in:
117
crates/lib/src/networking/change_detection.rs
Normal file
117
crates/lib/src/networking/change_detection.rs
Normal file
@@ -0,0 +1,117 @@
|
||||
//! Change detection for networked entities
|
||||
//!
|
||||
//! This module provides systems that detect when networked components change
|
||||
//! and prepare them for delta generation.
|
||||
|
||||
use bevy::prelude::*;
|
||||
|
||||
use crate::networking::{
|
||||
NetworkedEntity,
|
||||
NetworkedTransform,
|
||||
};
|
||||
|
||||
/// System to automatically detect Transform changes and mark entity for sync
|
||||
///
|
||||
/// This system detects changes to Transform components on networked entities
|
||||
/// and triggers persistence by accessing `NetworkedEntity` mutably (which marks
|
||||
/// it as changed via Bevy's change detection).
|
||||
///
|
||||
/// Add this system to your app if you want automatic synchronization of
|
||||
/// Transform changes:
|
||||
///
|
||||
/// ```no_run
|
||||
/// use bevy::prelude::*;
|
||||
/// use lib::networking::auto_detect_transform_changes_system;
|
||||
///
|
||||
/// App::new()
|
||||
/// .add_systems(Update, auto_detect_transform_changes_system);
|
||||
/// ```
|
||||
pub fn auto_detect_transform_changes_system(
|
||||
mut query: Query<
|
||||
&mut NetworkedEntity,
|
||||
(
|
||||
With<NetworkedTransform>,
|
||||
Or<(Changed<Transform>, Changed<GlobalTransform>)>,
|
||||
),
|
||||
>,
|
||||
) {
|
||||
// Simply accessing &mut NetworkedEntity triggers Bevy's change detection
|
||||
for mut _networked in query.iter_mut() {
|
||||
// No-op - the mutable access itself marks NetworkedEntity as changed
|
||||
// This will trigger the delta generation system
|
||||
}
|
||||
}
|
||||
|
||||
/// Resource to track the last sync version for each entity
|
||||
///
|
||||
/// This helps us avoid sending redundant deltas for the same changes.
|
||||
#[derive(Resource, Default)]
|
||||
pub struct LastSyncVersions {
|
||||
/// Map from network_id to the last vector clock we synced
|
||||
versions: std::collections::HashMap<uuid::Uuid, u64>,
|
||||
}
|
||||
|
||||
impl LastSyncVersions {
|
||||
/// Check if we should sync this entity based on version
|
||||
pub fn should_sync(&self, network_id: uuid::Uuid, version: u64) -> bool {
|
||||
match self.versions.get(&network_id) {
|
||||
Some(&last_version) => version > last_version,
|
||||
None => true, // Never synced before
|
||||
}
|
||||
}
|
||||
|
||||
/// Update the last synced version for an entity
|
||||
pub fn update(&mut self, network_id: uuid::Uuid, version: u64) {
|
||||
self.versions.insert(network_id, version);
|
||||
}
|
||||
|
||||
/// Remove tracking for an entity (when despawned)
|
||||
pub fn remove(&mut self, network_id: uuid::Uuid) {
|
||||
self.versions.remove(&network_id);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_last_sync_versions() {
|
||||
let mut versions = LastSyncVersions::default();
|
||||
let id = uuid::Uuid::new_v4();
|
||||
|
||||
// Should sync when never synced before
|
||||
assert!(versions.should_sync(id, 1));
|
||||
|
||||
// Update to version 1
|
||||
versions.update(id, 1);
|
||||
|
||||
// Should not sync same version
|
||||
assert!(!versions.should_sync(id, 1));
|
||||
|
||||
// Should not sync older version
|
||||
assert!(!versions.should_sync(id, 0));
|
||||
|
||||
// Should sync newer version
|
||||
assert!(versions.should_sync(id, 2));
|
||||
|
||||
// Remove and should sync again
|
||||
versions.remove(id);
|
||||
assert!(versions.should_sync(id, 2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multiple_entities() {
|
||||
let mut versions = LastSyncVersions::default();
|
||||
let id1 = uuid::Uuid::new_v4();
|
||||
let id2 = uuid::Uuid::new_v4();
|
||||
|
||||
versions.update(id1, 5);
|
||||
versions.update(id2, 3);
|
||||
|
||||
assert!(!versions.should_sync(id1, 4));
|
||||
assert!(versions.should_sync(id1, 6));
|
||||
assert!(!versions.should_sync(id2, 2));
|
||||
assert!(versions.should_sync(id2, 4));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user