1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
use std::collections::HashMap;
use crate::util::OpaquePtr;
mod codec;
pub use codec::*;
pub struct EntityType {
pub name: &'static str,
pub codecs: &'static [&'static dyn EntityCodec]
}
pub trait EntityComponent {
const CODEC: &'static dyn EntityCodec;
}
pub struct GlobalEntities {
name_to_entity_type: HashMap<&'static str, &'static EntityType>,
entity_type_to_codecs: HashMap<OpaquePtr<EntityType>, Vec<&'static dyn EntityCodec>>
}
impl GlobalEntities {
pub fn new() -> Self {
Self {
name_to_entity_type: HashMap::new(),
entity_type_to_codecs: HashMap::new()
}
}
pub fn with_all(slice: &[&'static EntityType]) -> Self {
let mut entities = Self::new();
entities.register_all(slice);
entities
}
pub fn register(&mut self, entity_type: &'static EntityType) {
let default_codecs = entity_type.codecs.iter()
.copied()
.collect();
self.name_to_entity_type.insert(entity_type.name, entity_type);
self.entity_type_to_codecs.insert(OpaquePtr::new(entity_type), default_codecs);
}
pub fn register_all(&mut self, slice: &[&'static EntityType]) {
self.name_to_entity_type.reserve(slice.len());
self.entity_type_to_codecs.reserve(slice.len());
for &entity_type in slice {
self.register(entity_type);
}
}
pub fn get_entity_type(&self, name: &str) -> Option<&'static EntityType> {
self.name_to_entity_type.get(name).copied()
}
pub fn get_codecs(&self, entity_type: &'static EntityType) -> Option<&Vec<&'static dyn EntityCodec>> {
self.entity_type_to_codecs.get(&OpaquePtr::new(entity_type))
}
pub fn get_entity_type_and_codecs(&self, name: &str) -> Option<(&'static EntityType, &Vec<&'static dyn EntityCodec>)> {
match self.name_to_entity_type.get(name) {
Some(&typ) => {
Some((typ, self.entity_type_to_codecs.get(&OpaquePtr::new(typ)).unwrap()))
},
None => None
}
}
pub fn has_entity_type(&self, entity_type: &'static EntityType) -> bool {
self.entity_type_to_codecs.contains_key(&OpaquePtr::new(entity_type))
}
pub fn entity_types_count(&self) -> usize {
self.name_to_entity_type.len()
}
}
#[macro_export]
macro_rules! entities {
($global_vis:vis $static_id:ident $namespace:literal [
$($entity_id:ident $entity_name:literal [$($component_struct:ident),*]),*
$(,)?
]) => {
$($global_vis static $entity_id: $crate::entity::EntityType = $crate::entity::EntityType {
name: concat!($namespace, ':', $entity_name),
codecs: &[$(<$component_struct as $crate::entity::EntityComponent>::CODEC),*]
};)*
$global_vis static $static_id: [&'static $crate::entity::EntityType; $crate::count!($($entity_id)*)] = [
$(&$entity_id),*
];
};
}
#[macro_export]
macro_rules! entity_component {
($struct_id:ident: default) => {
impl $crate::entity::EntityComponent for $struct_id {
const CODEC: &'static dyn $crate::entity::EntityCodec =
&$crate::entity::DefaultEntityCodec::<$struct_id>::new();
}
};
($struct_id:ident: $codec_struct_id:ident) => {
impl $crate::entity::EntityComponent for $struct_id {
const CODEC: &'static dyn $crate::entity::EntityCodec = &$codec_struct_id;
}
};
}