use bevy::{
ecs::{change_detection::Tick, component::ComponentId, entity::EntityAllocator},
prelude::*,
};
use crate::{prelude::*, shared::server_entity_map::ServerEntityMap};
#[non_exhaustive]
pub struct SerializeCtx<'a> {
pub entity: Entity,
pub component_id: ComponentId,
pub last_changed: Tick,
pub server_tick: RepliconTick,
pub diff_cursor: Option<DiffIndex>,
pub storage: &'a mut ReplicationStorage,
pub type_registry: &'a AppTypeRegistry,
}
impl EntityStorageCtx for SerializeCtx<'_> {
fn entity(&self) -> Entity {
self.entity
}
fn storage(&self) -> &ReplicationStorage {
self.storage
}
fn storage_mut(&mut self) -> &mut ReplicationStorage {
self.storage
}
}
#[non_exhaustive]
pub struct WriteCtx<'a> {
pub entity: Entity,
pub component_id: ComponentId,
pub message_tick: RepliconTick,
pub entity_map: &'a mut ServerEntityMap,
pub storage: &'a mut ReplicationStorage,
pub type_registry: &'a AppTypeRegistry,
pub(crate) spawner: BufferedSpawner<'a>,
pub(crate) ignore_mapping: bool,
}
impl EntityStorageCtx for WriteCtx<'_> {
fn entity(&self) -> Entity {
self.entity
}
fn storage(&self) -> &ReplicationStorage {
self.storage
}
fn storage_mut(&mut self) -> &mut ReplicationStorage {
self.storage
}
}
impl EntityMapper for WriteCtx<'_> {
fn get_mapped(&mut self, server_entity: Entity) -> Entity {
if self.ignore_mapping {
return server_entity;
}
self.entity_map
.server_entry(server_entity)
.or_insert_with(|| self.spawner.spawn_empty())
}
fn set_mapped(&mut self, _source: Entity, _target: Entity) {
unimplemented!()
}
}
#[non_exhaustive]
pub struct RemoveCtx {
pub component_id: ComponentId,
pub message_tick: RepliconTick,
}
#[non_exhaustive]
pub struct DespawnCtx {
pub message_tick: RepliconTick,
}
pub(crate) struct BufferedSpawner<'a> {
allocator: &'a EntityAllocator,
spawn_buffer: &'a mut EntityBuffer,
}
impl<'a> BufferedSpawner<'a> {
pub(crate) fn new(allocator: &'a EntityAllocator, spawn_buffer: &'a mut EntityBuffer) -> Self {
debug_assert!(spawn_buffer.is_empty(), "buffer should freed before reuse");
Self {
allocator,
spawn_buffer,
}
}
fn spawn_empty(&mut self) -> Entity {
let entity = self.allocator.alloc();
self.spawn_buffer.push(entity);
entity
}
}
#[derive(Default, Deref)]
pub(crate) struct EntityBuffer(Vec<Entity>);
impl EntityBuffer {
pub(crate) fn spawn(&mut self, world: &mut World) {
for entity in self.0.drain(..) {
world
.spawn_empty_at(entity)
.expect("all buffered entities must be valid");
}
}
pub(crate) fn free(&mut self, world: &mut World) {
world.entity_allocator_mut().free_many(&self.0);
self.0.clear();
}
pub(crate) fn push(&mut self, entity: Entity) {
self.0.push(entity);
}
}