1#![warn(missing_docs)]
4
5pub extern crate ron;
6
7use ron::Value;
8use specs::{Entity, LazyUpdate, World};
9use std::collections::HashMap;
10
11pub trait ComponentFactory: Send + Sync {
16 fn insert(&self, world: &mut World, entity: Entity, value: &Value);
18 fn insert_lazy(&self, lazy: &LazyUpdate, entity: Entity, value: &Value);
20 fn name() -> &'static str
22 where
23 Self: Sized;
24}
25
26pub struct ComponentRegistry {
28 map: HashMap<String, Box<dyn ComponentFactory>>,
29}
30
31impl ComponentRegistry {
32 pub fn new() -> Self {
34 Self {
35 map: HashMap::new(),
36 }
37 }
38
39 pub fn register(&mut self, name: &str, f: Box<dyn ComponentFactory>) {
41 self.map.insert(name.to_string(), f);
42 }
43
44 pub fn get(&self, name: &str) -> Option<&dyn ComponentFactory> {
46 self.map.get(name).map(|v| &**v)
47 }
48}
49
50impl Default for ComponentRegistry {
51 fn default() -> Self {
52 Self::new()
53 }
54}
55
56#[macro_export]
57macro_rules! impl_component_factory {
68 ($factory:ident, $component:path, $name:expr) => {
69 #[derive(Debug, Default)]
70 pub struct $factory;
71
72 impl $crate::ComponentFactory for $factory {
73 fn insert(&self, world: &mut specs::World, entity: specs::Entity, value: &ron::Value) {
74 match ron::Value::into_rust::<$component>(value.clone()) {
75 Ok(component) => {
76 if let Err(error) = world
77 .write_storage::<$component>()
78 .insert(entity, component)
79 {
80 log::error!(
81 "failed to insert component {} for entity {:?}: {}",
82 stringify!($component),
83 entity,
84 error
85 );
86 }
87 }
88
89 Err(error) => {
90 log::error!(
91 "failed to construct component {} for entity {:?}: {}",
92 stringify!($component),
93 entity,
94 error
95 );
96 }
97 }
98 }
99
100 fn insert_lazy(
101 &self,
102 lazy: &specs::LazyUpdate,
103 entity: specs::Entity,
104 value: &ron::Value,
105 ) {
106 match ron::Value::into_rust::<$component>(value.clone()) {
107 Ok(component) => {
108 lazy.insert(entity, component);
109 }
110
111 Err(error) => {
112 log::error!(
113 "failed to construct component {} for entity {:?}: {}",
114 stringify!($component),
115 entity,
116 error
117 );
118 }
119 }
120 }
121
122 fn name() -> &'static str {
123 $name
124 }
125 }
126 };
127}