Skip to content

Instantly share code, notes, and snippets.

@matthewjberger
Last active April 24, 2021 03:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save matthewjberger/27182fd293b4ab9211f7b99c0669fb18 to your computer and use it in GitHub Desktop.
Save matthewjberger/27182fd293b4ab9211f7b99c0669fb18 to your computer and use it in GitHub Desktop.
serialization/deserialization of legion ecs as a member of another struct
[dependencies]
legion = "0.4.0"
serde = "1.0.125"
serde_json = "1.0.64"
lazy_static = "1.4.0"
use lazy_static::lazy_static;
use legion::{
serialize::{set_entity_serializer, Canon},
*,
};
use serde::{de::DeserializeSeed, Deserialize, Deserializer, Serialize, Serializer};
use std::{
result::Result,
sync::{Arc, RwLock},
};
lazy_static! {
pub static ref COMPONENT_REGISTRY: Arc<RwLock<Registry<String>>> = {
let mut registry = Registry::default();
registry.register::<Position>("position".to_string());
// Purposefully excluding 'Velocity' here,
// so it can be added later in main by mutating the registry
registry.register::<f32>("f32".to_string());
Arc::new(RwLock::new(registry))
};
pub static ref ENTITY_SERIALIZER: Canon = Canon::default();
}
// a component is any type that is 'static, sized, send and sync
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
struct Position {
x: f32,
y: f32,
}
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
struct Velocity {
dx: f32,
dy: f32,
}
pub type Ecs = legion::World;
pub type Entity = legion::Entity;
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct World {
#[serde(serialize_with = "ecs_serialize", deserialize_with = "ecs_deserialize")]
pub ecs: Ecs,
pub number: f32,
pub entities: Vec<Entity>,
}
fn ecs_serialize<S>(ecs: &Ecs, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let registry = (&*COMPONENT_REGISTRY)
.read()
.expect("Failed to get the component registry lock!");
ecs.as_serializable(legion::any(), &*registry, &*ENTITY_SERIALIZER)
.serialize(serializer)
}
fn ecs_deserialize<'de, D>(deserializer: D) -> Result<Ecs, D::Error>
where
D: Deserializer<'de>,
{
(&*COMPONENT_REGISTRY)
.read()
.expect("Failed to get the component registry lock!")
.as_deserialize(&*ENTITY_SERIALIZER)
.deserialize(deserializer)
}
fn main() {
let mut world = World::default();
world
.ecs
.push((Position { x: 0.0, y: 0.0 }, Velocity { dx: 0.0, dy: 0.0 }));
world.entities.push(world.ecs.push(()));
// Register the velocity component by mutating the registry
{
(&*COMPONENT_REGISTRY)
.write()
.expect("Failed to get the component registry lock!")
.register::<Velocity>("velocity".to_string());
}
let json = set_entity_serializer(&*ENTITY_SERIALIZER, || {
serde_json::to_value(world).expect("Failed to serialize the world!")
});
println!("Serialized world: {}", json);
let world: World = set_entity_serializer(&*ENTITY_SERIALIZER, || {
serde_json::from_str(&json.to_string()).expect("Failed to deserialize world!")
});
println!("Deserialized world: {:#?}", world);
// Bonus: Immutable access to an entity
if let Ok(entry) = world.ecs.entry_ref(entity) {
println!("{:#?}", entry.get_component::<Position>());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment