From 73f6e9be84304295bbeaf06b91692991dc938b41 Mon Sep 17 00:00:00 2001 From: Hennadii Chernyshchyk Date: Mon, 4 Nov 2024 21:35:49 +0200 Subject: [PATCH 1/2] Swap `ComponentId` and `ComponentFns` `ComponentId` is more like a key here, so it should come first. --- src/core/replication_registry.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/core/replication_registry.rs b/src/core/replication_registry.rs index 72605a75..be8ab928 100644 --- a/src/core/replication_registry.rs +++ b/src/core/replication_registry.rs @@ -23,7 +23,7 @@ pub struct ReplicationRegistry { /// Functions for replicated components. /// /// Unique for each component. - components: Vec<(ComponentFns, ComponentId)>, + components: Vec<(ComponentId, ComponentFns)>, /// Serialization/deserialization functions for a component and /// the component's index in [`Self::components`]. @@ -45,7 +45,7 @@ impl ReplicationRegistry { /// [`CommandMarkers::insert`](super::command_markers::CommandMarkers::insert) pub(super) fn register_marker(&mut self, marker_id: CommandMarkerIndex) { self.marker_slots += 1; - for (command_fns, _) in &mut self.components { + for (_, command_fns) in &mut self.components { command_fns.add_marker_slot(marker_id); } } @@ -67,7 +67,7 @@ impl ReplicationRegistry { remove: RemoveFn, ) { let (index, _) = self.init_component_fns::(world); - let (component_fns, _) = &mut self.components[index]; + let (_, component_fns) = &mut self.components[index]; let command_fns = UntypedCommandFns::new(write, remove); // SAFETY: `component_fns` and `command_fns` were created for `C`. @@ -86,7 +86,7 @@ impl ReplicationRegistry { remove: RemoveFn, ) { let (index, _) = self.init_component_fns::(world); - let (component_fns, _) = &mut self.components[index]; + let (_, component_fns) = &mut self.components[index]; let command_fns = UntypedCommandFns::new(write, remove); // SAFETY: `component_fns` and `command_fns` were created for `C`. @@ -122,10 +122,10 @@ impl ReplicationRegistry { let index = self .components .iter() - .position(|&(_, id)| id == component_id) + .position(|&(id, _)| id == component_id) .unwrap_or_else(|| { self.components - .push((ComponentFns::new::(self.marker_slots), component_id)); + .push((component_id, ComponentFns::new::(self.marker_slots))); self.components.len() - 1 }); @@ -142,7 +142,7 @@ impl ReplicationRegistry { .expect("serde function IDs should be obtained from the same instance"); // SAFETY: index obtained from `rules` is always valid. - let (command_fns, _) = unsafe { self.components.get_unchecked(*index) }; + let (_, command_fns) = unsafe { self.components.get_unchecked(*index) }; (command_fns, rule_fns) } From b673344bd2bc2e8e70b7d9b0ae2654643076d9c1 Mon Sep 17 00:00:00 2001 From: Hennadii Chernyshchyk Date: Mon, 4 Nov 2024 21:45:10 +0200 Subject: [PATCH 2/2] Add `ComponentId` to all component-related contexts --- CHANGELOG.md | 4 ++++ src/client.rs | 16 +++++++++++----- src/core/ctx.rs | 20 +++++++++++--------- src/core/replication_registry.rs | 6 +++--- src/core/replication_registry/test_fns.rs | 20 ++++++++++++++------ src/server.rs | 8 ++++++-- 6 files changed, 49 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3452d509..0803320d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [0.28.4] - 2024-10-15 +### Added + +- `ComponentId` to all component-related contexts. + ### Fixed - Synchronize server events with init messages properly when `ServerTick` is not updated every app tick. diff --git a/src/client.rs b/src/client.rs index d87e25eb..2d588951 100644 --- a/src/client.rs +++ b/src/client.rs @@ -338,10 +338,11 @@ fn apply_init_components( let mut components_len = 0u32; while cursor.position() < end_pos { let fns_id = DefaultOptions::new().deserialize_from(&mut *cursor)?; - let (component_fns, rule_fns) = params.registry.get(fns_id); + let (component_id, component_fns, rule_fns) = params.registry.get(fns_id); match components_kind { ComponentsKind::Insert => { - let mut ctx = WriteCtx::new(&mut commands, params.entity_map, message_tick); + let mut ctx = + WriteCtx::new(&mut commands, params.entity_map, component_id, message_tick); // SAFETY: `rule_fns` and `component_fns` were created for the same type. unsafe { @@ -355,7 +356,11 @@ fn apply_init_components( } } ComponentsKind::Removal => { - let mut ctx = RemoveCtx::new(&mut commands, message_tick); + let mut ctx = RemoveCtx { + commands: &mut commands, + message_tick, + component_id, + }; component_fns.remove(&mut ctx, params.entity_markers, &mut client_entity); } } @@ -465,8 +470,9 @@ fn apply_update_components( let mut components_count = 0u32; while cursor.position() < end_pos { let fns_id = DefaultOptions::new().deserialize_from(&mut *cursor)?; - let (component_fns, rule_fns) = params.registry.get(fns_id); - let mut ctx = WriteCtx::new(&mut commands, params.entity_map, message_tick); + let (component_id, component_fns, rule_fns) = params.registry.get(fns_id); + let mut ctx = + WriteCtx::new(&mut commands, params.entity_map, component_id, message_tick); // SAFETY: `rule_fns` and `component_fns` were created for the same type. unsafe { diff --git a/src/core/ctx.rs b/src/core/ctx.rs index 60311a72..6935904c 100644 --- a/src/core/ctx.rs +++ b/src/core/ctx.rs @@ -1,4 +1,4 @@ -use bevy::{prelude::*, reflect::TypeRegistry}; +use bevy::{ecs::component::ComponentId, prelude::*, reflect::TypeRegistry}; use super::{replicon_tick::RepliconTick, server_entity_map::ServerEntityMap, Replicated}; @@ -7,6 +7,9 @@ use super::{replicon_tick::RepliconTick, server_entity_map::ServerEntityMap, Rep pub struct SerializeCtx { /// Current tick. pub server_tick: RepliconTick, + + /// ID of the serializing component. + pub component_id: ComponentId, } /// Replication context for writing and deserialization. @@ -18,6 +21,9 @@ pub struct WriteCtx<'a, 'w, 's> { /// Maps server entities to client entities and vice versa. pub entity_map: &'a mut ServerEntityMap, + /// ID of the writing component. + pub component_id: ComponentId, + /// Tick for the currently processing message. pub message_tick: RepliconTick, @@ -29,11 +35,13 @@ impl<'a, 'w, 's> WriteCtx<'a, 'w, 's> { pub(crate) fn new( commands: &'a mut Commands<'w, 's>, entity_map: &'a mut ServerEntityMap, + component_id: ComponentId, message_tick: RepliconTick, ) -> Self { Self { commands, entity_map, + component_id, message_tick, ignore_mapping: false, } @@ -59,15 +67,9 @@ pub struct RemoveCtx<'a, 'w, 's> { /// Tick for the currently processing message. pub message_tick: RepliconTick, -} -impl<'a, 'w, 's> RemoveCtx<'a, 'w, 's> { - pub(crate) fn new(commands: &'a mut Commands<'w, 's>, message_tick: RepliconTick) -> Self { - Self { - commands, - message_tick, - } - } + /// ID of the removing component. + pub component_id: ComponentId, } /// Replication context for despawn. diff --git a/src/core/replication_registry.rs b/src/core/replication_registry.rs index be8ab928..30031917 100644 --- a/src/core/replication_registry.rs +++ b/src/core/replication_registry.rs @@ -135,16 +135,16 @@ impl ReplicationRegistry { /// Returns associates functions. /// /// See also [`Self::register_rule_fns`]. - pub(crate) fn get(&self, fns_id: FnsId) -> (&ComponentFns, &UntypedRuleFns) { + pub(crate) fn get(&self, fns_id: FnsId) -> (ComponentId, &ComponentFns, &UntypedRuleFns) { let (rule_fns, index) = self .rules .get(fns_id.0) .expect("serde function IDs should be obtained from the same instance"); // SAFETY: index obtained from `rules` is always valid. - let (_, command_fns) = unsafe { self.components.get_unchecked(*index) }; + let (component_id, command_fns) = unsafe { self.components.get_unchecked(*index) }; - (command_fns, rule_fns) + (*component_id, command_fns, rule_fns) } } diff --git a/src/core/replication_registry/test_fns.rs b/src/core/replication_registry/test_fns.rs index 44a02378..07303ae4 100644 --- a/src/core/replication_registry/test_fns.rs +++ b/src/core/replication_registry/test_fns.rs @@ -91,9 +91,12 @@ pub trait TestFnsEntityExt { impl TestFnsEntityExt for EntityWorldMut<'_> { fn serialize(&mut self, fns_info: FnsInfo, server_tick: RepliconTick) -> Vec { let registry = self.world().resource::(); - let (component_fns, rule_fns) = registry.get(fns_info.fns_id()); + let (component_id, component_fns, rule_fns) = registry.get(fns_info.fns_id()); let mut cursor = Cursor::default(); - let ctx = SerializeCtx { server_tick }; + let ctx = SerializeCtx { + server_tick, + component_id, + }; let ptr = self.get_by_id(fns_info.component_id()).unwrap_or_else(|| { let components = self.world().components(); let component_name = components @@ -133,9 +136,10 @@ impl TestFnsEntityExt for EntityWorldMut<'_> { let mut commands = Commands::new_from_entities(&mut queue, world_cell.entities()); - let (component_fns, rule_fns) = registry.get(fns_info.fns_id()); + let (component_id, component_fns, rule_fns) = registry.get(fns_info.fns_id()); let mut cursor = Cursor::new(data); - let mut ctx = WriteCtx::new(&mut commands, &mut entity_map, message_tick); + let mut ctx = + WriteCtx::new(&mut commands, &mut entity_map, component_id, message_tick); unsafe { component_fns @@ -172,8 +176,12 @@ impl TestFnsEntityExt for EntityWorldMut<'_> { let mut queue = CommandQueue::default(); let mut commands = Commands::new_from_entities(&mut queue, world_cell.entities()); - let (component_fns, _) = registry.get(fns_info.fns_id()); - let mut ctx = RemoveCtx::new(&mut commands, message_tick); + let (component_id, component_fns, _) = registry.get(fns_info.fns_id()); + let mut ctx = RemoveCtx { + commands: &mut commands, + message_tick, + component_id, + }; component_fns.remove(&mut ctx, &entity_markers, &mut entity); diff --git a/src/server.rs b/src/server.rs index 710d74c7..958e0635 100644 --- a/src/server.rs +++ b/src/server.rs @@ -406,8 +406,12 @@ fn collect_changes( ) }; - let (component_fns, rule_fns) = registry.get(replicated_component.fns_id); - let ctx = SerializeCtx { server_tick }; + let (component_id, component_fns, rule_fns) = + registry.get(replicated_component.fns_id); + let ctx = SerializeCtx { + server_tick, + component_id, + }; let mut shared_bytes = None; for (init_message, update_message, client) in messages.iter_mut_with_clients() { let visibility = client.visibility().cached_visibility();