use crate::reader::{ReadVarInt, Reader};
use crate::varint::varint_len;
use crate::writer::WriteInteger;
use crate::{SerializationError, ToBytes};
use bevy_derive::{Deref, DerefMut};
use bevy_ecs::entity::{Entity, EntityGeneration, EntityIndex};
use bevy_ecs::entity::{EntityMapper, hash_map::EntityHashMap};
use bevy_ecs::world::{EntityWorldMut, World};
use bevy_reflect::Reflect;
#[allow(unused_imports)]
use tracing::{debug, error, info, trace, warn};
const MARKED: u64 = 1 << 63;
#[derive(Default, Debug, Reflect, Deref, DerefMut)]
pub struct EntityMap(pub(crate) EntityHashMap<Entity>);
impl EntityMapper for EntityMap {
fn get_mapped(&mut self, entity: Entity) -> Entity {
self.0.get(&entity).copied().unwrap_or_else(|| {
debug!("Failed to map entity {entity:?}. Map: {self:?}");
entity
})
}
fn set_mapped(&mut self, source: Entity, target: Entity) {
self.0.set_mapped(source, target);
}
}
#[derive(Default, Debug, Reflect, Deref, DerefMut)]
pub struct SendEntityMap(pub(crate) EntityHashMap<Entity>);
impl EntityMapper for SendEntityMap {
fn get_mapped(&mut self, entity: Entity) -> Entity {
match self.0.get(&entity) {
Some(mapped) => {
trace!("Mapping entity {entity:?} to {mapped:?} in SendEntityMap!");
RemoteEntityMap::mark_mapped(*mapped)
}
_ => {
entity
}
}
}
fn set_mapped(&mut self, source: Entity, target: Entity) {
self.0.insert(source, target);
}
}
#[derive(Default, Debug, Reflect, Deref, DerefMut)]
pub struct ReceiveEntityMap(pub(crate) EntityHashMap<Entity>);
impl EntityMapper for ReceiveEntityMap {
fn get_mapped(&mut self, entity: Entity) -> Entity {
if RemoteEntityMap::is_mapped(entity) {
RemoteEntityMap::mark_unmapped(entity)
} else {
self.0.get(&entity).copied().unwrap_or_else(|| {
debug!("Receive: Failed to map entity {entity:?}");
Entity::PLACEHOLDER
})
}
}
fn set_mapped(&mut self, source: Entity, target: Entity) {
self.0.insert(source, target);
}
}
#[derive(Default, Debug, Reflect)]
pub struct RemoteEntityMap {
pub remote_to_local: ReceiveEntityMap,
pub local_to_remote: SendEntityMap,
}
impl RemoteEntityMap {
#[inline]
pub fn insert(&mut self, remote_entity: Entity, local_entity: Entity) {
self.remote_to_local.insert(remote_entity, local_entity);
self.local_to_remote.insert(local_entity, remote_entity);
}
#[inline]
pub fn get_local(&self, remote_entity: Entity) -> Option<Entity> {
let unmapped = Self::mark_unmapped(remote_entity);
if Self::is_mapped(remote_entity) {
trace!("Received entity {unmapped:?} was already mapped, returning it as is");
return Some(unmapped);
};
self.remote_to_local.get(&unmapped).copied()
}
pub(crate) const fn mark_mapped(entity: Entity) -> Entity {
let mut bits = entity.to_bits();
bits |= MARKED;
Entity::from_bits(bits)
}
pub(crate) const fn mark_unmapped(entity: Entity) -> Entity {
let mut bits = entity.to_bits();
bits &= !MARKED;
Entity::from_bits(bits)
}
pub(crate) const fn is_mapped(entity: Entity) -> bool {
entity.to_bits() & MARKED != 0
}
pub fn to_remote(&self, local_entity: Entity) -> Entity {
match self.local_to_remote.get(&local_entity) {
Some(remote_entity) => Self::mark_mapped(*remote_entity),
_ => local_entity,
}
}
#[inline]
pub fn get_remote(&self, local_entity: Entity) -> Option<Entity> {
self.local_to_remote.get(&local_entity).copied()
}
pub fn get_by_remote<'a>(
&mut self,
world: &'a mut World,
remote_entity: Entity,
) -> Option<EntityWorldMut<'a>> {
self.get_local(remote_entity)
.and_then(|e| world.get_entity_mut(e).ok())
}
pub fn remove_by_remote(&mut self, remote_entity: Entity) -> Option<Entity> {
if Self::is_mapped(remote_entity) {
let local = Self::mark_unmapped(remote_entity);
if let Some(remote) = self.local_to_remote.remove(&local) {
self.remote_to_local.remove(&remote);
}
return Some(local);
} else if let Some(local) = self.remote_to_local.remove(&remote_entity) {
self.local_to_remote.remove(&local);
return Some(local);
}
None
}
#[allow(unused)]
pub(crate) fn is_empty(&self) -> bool {
self.remote_to_local.is_empty() && self.local_to_remote.is_empty()
}
pub fn clear(&mut self) {
self.local_to_remote.clear();
self.remote_to_local.clear();
}
}
impl ToBytes for Entity {
fn bytes_len(&self) -> usize {
let mut index = self.index_u32() << 2;
let is_mapped = RemoteEntityMap::is_mapped(*self);
let unmarked = RemoteEntityMap::mark_unmapped(*self);
let generation = unmarked.generation();
let is_first_generation = generation == EntityGeneration::FIRST;
index |= is_first_generation as u32;
index |= (is_mapped as u32) << 1;
let mut len = varint_len(index as u64);
if !is_first_generation {
len += varint_len(generation.to_bits() as u64);
}
len
}
fn to_bytes(&self, buffer: &mut impl WriteInteger) -> Result<(), SerializationError> {
let mut index = self.index_u32() << 2;
let is_mapped = RemoteEntityMap::is_mapped(*self);
let unmarked = RemoteEntityMap::mark_unmapped(*self);
let generation = unmarked.generation();
let is_first_generation = generation == EntityGeneration::FIRST;
index |= is_first_generation as u32;
index |= (is_mapped as u32) << 1;
buffer.write_varint(index as u64)?;
if !is_first_generation {
buffer.write_varint(generation.to_bits() as u64)?;
}
Ok(())
}
fn from_bytes(buffer: &mut Reader) -> Result<Self, SerializationError>
where
Self: Sized,
{
let index = buffer.read_varint()? as u32;
let is_first_generation = (index & 1) != 0;
let is_mapped = (index & 2) != 0;
let generation = if !is_first_generation {
buffer.read_varint()? as u32
} else {
0
};
let row = unsafe { EntityIndex::from_raw_u32(index >> 2).unwrap_unchecked() };
let generation = EntityGeneration::from_bits(generation);
let entity = Entity::from_index_and_generation(row, generation);
if is_mapped {
Ok(RemoteEntityMap::mark_mapped(entity))
} else {
Ok(entity)
}
}
}
#[cfg(test)]
mod tests {
use crate::ToBytes;
use crate::entity_map::RemoteEntityMap;
use crate::reader::Reader;
use crate::writer::Writer;
use bevy_ecs::entity::{Entity, EntityGeneration, EntityIndex};
use test_log::test;
#[test]
fn test_entity_serde_first_generation() {
let e = Entity::from_index_and_generation(
EntityIndex::from_raw_u32(1).unwrap(),
EntityGeneration::FIRST,
);
let mut writer = Writer::with_capacity(100);
e.to_bytes(&mut writer).unwrap();
assert_eq!(writer.len(), 1);
let mut reader = Reader::from(writer.split());
let serde_e = Entity::from_bytes(&mut reader).unwrap();
assert_eq!(e, serde_e);
}
#[test]
fn test_entity_serde_non_first_generation() {
let e = Entity::from_index_and_generation(
EntityIndex::from_raw_u32(1).unwrap(),
EntityGeneration::from_bits(1),
);
let mut writer = Writer::with_capacity(100);
e.to_bytes(&mut writer).unwrap();
assert_eq!(writer.len(), 2);
let mut reader = Reader::from(writer.split());
let serde_e = Entity::from_bytes(&mut reader).unwrap();
assert_eq!(e, serde_e);
}
#[test]
fn test_entity_serde_mapped_first_generation() {
let entity = Entity::from_raw_u32(10).unwrap();
assert!(!RemoteEntityMap::is_mapped(entity));
let entity_mapped = RemoteEntityMap::mark_mapped(entity);
assert!(RemoteEntityMap::is_mapped(entity_mapped));
let mut writer = Writer::with_capacity(100);
entity_mapped.to_bytes(&mut writer).unwrap();
assert_eq!(writer.len(), 1);
let mut reader = Reader::from(writer.split());
let serde_e = Entity::from_bytes(&mut reader).unwrap();
assert_eq!(entity_mapped, serde_e);
}
#[test]
fn test_entity_serde_mapped_non_first_generation() {
let entity = Entity::from_index_and_generation(
EntityIndex::from_raw_u32(10).unwrap(),
EntityGeneration::from_bits(1),
);
assert!(!RemoteEntityMap::is_mapped(entity));
let entity_mapped = RemoteEntityMap::mark_mapped(entity);
assert!(RemoteEntityMap::is_mapped(entity_mapped));
let mut writer = Writer::with_capacity(100);
entity_mapped.to_bytes(&mut writer).unwrap();
assert_eq!(writer.len(), 2);
let mut reader = Reader::from(writer.split());
let serde_e = Entity::from_bytes(&mut reader).unwrap();
assert_eq!(entity_mapped, serde_e);
}
}