pub mod component_fns;
pub(crate) mod component_mask;
pub mod ctx;
pub mod receive_fns;
pub mod rule_fns;
pub(crate) mod serde_fns;
pub mod test_fns;
use bevy::{ecs::component::ComponentId, prelude::*};
use log::trace;
use serde::{Deserialize, Serialize};
use super::receive_markers::ReceiveMarkerIndex;
use crate::{prelude::*, shared::replication::registry::serde_fns::SerdeFns};
use component_fns::ComponentFns;
use ctx::DespawnCtx;
use receive_fns::{MutWrite, RemoveFn, UntypedReceiveFns, WriteFn};
use rule_fns::UntypedRuleFns;
#[derive(Resource)]
pub struct ReplicationRegistry {
pub despawn: DespawnFn,
components: Vec<(ComponentId, ComponentFns)>,
rules: Vec<(ComponentIndex, UntypedRuleFns)>,
marker_slots: usize,
}
impl ReplicationRegistry {
pub(super) fn register_marker(&mut self, marker_id: ReceiveMarkerIndex) {
self.marker_slots += 1;
for (_, receive_fns) in &mut self.components {
receive_fns.add_marker_slot(marker_id);
}
}
pub(super) fn set_marker_fns<C: Component<Mutability: MutWrite<C>>>(
&mut self,
world: &mut World,
marker_id: ReceiveMarkerIndex,
write: WriteFn<C>,
remove: RemoveFn,
) {
let (index, _) = self.init_component_fns::<C>(world);
let (_, component_fns) = &mut self.components[index.0];
let receive_fns = UntypedReceiveFns::new(write, remove);
unsafe {
component_fns.set_marker_fns(marker_id, receive_fns);
}
}
pub(super) fn set_receive_fns<C: Component<Mutability: MutWrite<C>>>(
&mut self,
world: &mut World,
write: WriteFn<C>,
remove: RemoveFn,
) {
let (index, _) = self.init_component_fns::<C>(world);
let (_, component_fns) = &mut self.components[index.0];
let receive_fns = UntypedReceiveFns::new(write, remove);
unsafe {
component_fns.set_receive_fns(receive_fns);
}
}
pub fn register_rule_fns<C: Component<Mutability: MutWrite<C>>>(
&mut self,
world: &mut World,
rule_fns: RuleFns<C>,
) -> (ComponentId, FnsId) {
let (index, component_id) = self.init_component_fns::<C>(world);
self.rules.push((index, rule_fns.into()));
let fns_id = FnsId(self.rules.len() - 1);
trace!("registering `{fns_id:?}` for `{}`", ShortName::of::<C>());
(component_id, fns_id)
}
pub(crate) fn init_component_fns<C: Component<Mutability: MutWrite<C>>>(
&mut self,
world: &mut World,
) -> (ComponentIndex, ComponentId) {
let component_id = world.register_component::<C>();
let index = self
.components
.iter()
.position(|&(id, _)| id == component_id)
.unwrap_or_else(|| {
self.components
.push((component_id, ComponentFns::new::<C>(self.marker_slots)));
self.components.len() - 1
});
(ComponentIndex(index), component_id)
}
pub(crate) fn get<'a>(&'a self, fns_id: FnsId) -> (ComponentIndex, ComponentId, SerdeFns<'a>) {
let (index, rule_fns) = self
.rules
.get(fns_id.0)
.unwrap_or_else(|| panic!("replication `{fns_id:?}` should be registered first"));
let (component_id, component_fns) = unsafe { self.get_by_index(*index).unwrap_unchecked() };
let fns = unsafe { SerdeFns::new(component_fns, rule_fns) };
(*index, *component_id, fns)
}
pub(crate) fn get_by_index(
&self,
index: ComponentIndex,
) -> Option<&(ComponentId, ComponentFns)> {
self.components.get(index.0)
}
}
impl Default for ReplicationRegistry {
fn default() -> Self {
Self {
despawn,
components: Default::default(),
rules: Default::default(),
marker_slots: 0,
}
}
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct FnsId(usize);
#[derive(Debug, Serialize, Deserialize, Eq, Hash, PartialEq, Clone, Copy)]
pub(crate) struct ComponentIndex(usize);
pub type DespawnFn = fn(&DespawnCtx, EntityWorldMut);
pub fn despawn(_ctx: &DespawnCtx, entity: EntityWorldMut) {
entity.despawn();
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn rule_fns() {
let mut world = World::new();
let mut registry = ReplicationRegistry::default();
registry.register_rule_fns(&mut world, RuleFns::<A>::default());
assert_eq!(registry.rules.len(), 1);
assert_eq!(registry.components.len(), 1);
}
#[test]
fn duplicate_rule_fns() {
let mut world = World::new();
let mut registry = ReplicationRegistry::default();
registry.register_rule_fns(&mut world, RuleFns::<A>::default());
registry.register_rule_fns(&mut world, RuleFns::<A>::default());
assert_eq!(registry.rules.len(), 2);
assert_eq!(
registry.components.len(),
1,
"multiple serde registrations for the same component should result only in a single receive functions instance"
);
}
#[test]
fn different_rule_fns() {
let mut world = World::new();
let mut registry = ReplicationRegistry::default();
registry.register_rule_fns(&mut world, RuleFns::<A>::default());
registry.register_rule_fns(&mut world, RuleFns::<B>::default());
assert_eq!(registry.rules.len(), 2);
assert_eq!(registry.components.len(), 2);
}
#[derive(Component, Serialize, Deserialize)]
struct A;
#[derive(Component, Deserialize, Serialize)]
struct B;
}