#![warn(missing_docs)]
pub extern crate ron;
use ron::Value;
use specs::{Entity, LazyUpdate, World};
use std::collections::HashMap;
pub trait ComponentFactory: Send + Sync {
fn insert(&self, world: &mut World, entity: Entity, value: &Value);
fn insert_lazy(&self, lazy: &LazyUpdate, entity: Entity, value: &Value);
fn name() -> &'static str
where
Self: Sized;
}
pub struct ComponentRegistry {
map: HashMap<String, Box<dyn ComponentFactory>>,
}
impl ComponentRegistry {
pub fn new() -> Self {
Self {
map: HashMap::new(),
}
}
pub fn register(&mut self, name: &str, f: Box<dyn ComponentFactory>) {
self.map.insert(name.to_string(), f);
}
pub fn get(&self, name: &str) -> Option<&dyn ComponentFactory> {
self.map.get(name).map(|v| &**v)
}
}
impl Default for ComponentRegistry {
fn default() -> Self {
Self::new()
}
}
#[macro_export]
macro_rules! impl_component_factory {
($factory:ident, $component:path, $name:expr) => {
#[derive(Debug, Default)]
pub struct $factory;
impl $crate::ComponentFactory for $factory {
fn insert(&self, world: &mut specs::World, entity: specs::Entity, value: &ron::Value) {
match ron::Value::into_rust::<$component>(value.clone()) {
Ok(component) => {
if let Err(error) = world
.write_storage::<$component>()
.insert(entity, component)
{
log::error!(
"failed to insert component {} for entity {:?}: {}",
stringify!($component),
entity,
error
);
}
}
Err(error) => {
log::error!(
"failed to construct component {} for entity {:?}: {}",
stringify!($component),
entity,
error
);
}
}
}
fn insert_lazy(
&self,
lazy: &specs::LazyUpdate,
entity: specs::Entity,
value: &ron::Value,
) {
match ron::Value::into_rust::<$component>(value.clone()) {
Ok(component) => {
lazy.insert(entity, component);
}
Err(error) => {
log::error!(
"failed to construct component {} for entity {:?}: {}",
stringify!($component),
entity,
error
);
}
}
}
fn name() -> &'static str {
$name
}
}
};
}