1use crate::error::CoreError;
2use anyhow::{bail, Result};
3use borsh::{BorshDeserialize, BorshSerialize};
4use std::{
5 cmp::{Eq, PartialEq},
6 collections::BTreeMap,
7 mem::discriminant,
8};
9
10pub type Region = String;
13pub type Entity = String;
14pub type Component = String;
15pub type ComponentPair = (Component, ComponentValue);
16pub type ComponentTree = BTreeMap<Component, ComponentValue>;
17pub type ComponentType = String;
18pub type ComponentTypeTree = BTreeMap<Component, ComponentType>;
19pub type BlueprintString = String;
20
21#[derive(Clone, BorshDeserialize, BorshSerialize, Debug)]
24pub enum ComponentValue {
25 String(String),
26 Integer(i64),
27 Float(f64),
28 Boolean(bool),
29}
30
31impl ComponentValue {
32 pub fn unwrap_string(self) -> String {
37 use ComponentValue::*;
38
39 match self {
40 String(v) => v,
41 _ => panic!("Not a String"),
42 }
43 }
44
45 pub fn unwrap_float(self) -> f64 {
50 use ComponentValue::*;
51
52 match self {
53 Float(v) => v,
54 _ => panic!("Not a Float"),
55 }
56 }
57
58 pub fn unwrap_int(self) -> i64 {
63 use ComponentValue::*;
64
65 match self {
66 Integer(v) => v,
67 _ => panic!("Not an Integer"),
68 }
69 }
70
71 pub fn unwrap_bool(self) -> bool {
76 use ComponentValue::*;
77
78 match self {
79 Boolean(v) => v,
80 _ => panic!("Not a Boolean"),
81 }
82 }
83}
84
85impl PartialEq for ComponentValue {
86 fn eq(&self, other: &Self) -> bool {
87 match self {
88 ComponentValue::String(v_self) => {
89 let mut is_equal = false;
90 if let ComponentValue::String(v_other) = other {
91 is_equal = v_self == v_other;
92 }
93 is_equal
94 }
95
96 ComponentValue::Integer(v_self) => {
97 let mut is_equal = false;
98 if let ComponentValue::Integer(v_other) = other {
99 is_equal = v_self == v_other;
100 }
101 is_equal
102 }
103
104 ComponentValue::Float(v_self) => {
105 let mut is_equal = false;
106 if let ComponentValue::Float(v_other) = other {
107 is_equal = v_self == v_other;
108 }
109 is_equal
110 }
111
112 ComponentValue::Boolean(v_self) => {
113 let mut is_equal = false;
114 if let ComponentValue::Boolean(v_other) = other {
115 is_equal = v_self == v_other;
116 }
117 is_equal
118 }
119 }
120 }
121}
122
123impl Eq for ComponentValue {}
124
125#[derive(Clone, Debug, Default, Eq, PartialEq)]
129pub struct Blueprint {
130 pub name: String,
132 pub description: String,
134 pub regions: BTreeMap<Region, Vec<Entity>>,
137 pub entities: BTreeMap<Entity, ComponentTypeTree>,
139 pub instances: BTreeMap<Region, BTreeMap<Entity, Vec<ComponentTree>>>,
141}
142
143impl Blueprint {
144 pub fn new(world_name: String, world_description: String) -> Self {
145 Self {
146 name: world_name,
147 description: world_description,
148 entities: BTreeMap::new(),
149 regions: BTreeMap::new(),
150 instances: BTreeMap::new(),
151 }
152 }
153
154 pub fn preload(&mut self, regions: Vec<Region>, entities: Vec<Entity>) {
160 for region_name in regions.into_iter() {
161 self.instances.insert(region_name.clone(), BTreeMap::new());
163
164 let region_mut = self.instances.get_mut(®ion_name).unwrap();
166 for entity_name in entities.clone().into_iter() {
167 region_mut.insert(entity_name, Vec::new());
168 }
169 }
170 }
171
172 pub fn add_entity(&mut self, name: Entity, component_types: ComponentTypeTree) {
173 self.entities.insert(name, component_types);
174 }
175
176 pub fn add_region(&mut self, name: Region, entities: Vec<Entity>) {
177 self.regions.insert(name, entities);
178 }
179
180 pub fn add_instance(
181 &mut self,
182 region: Region,
183 entity: Entity,
184 component_tree: ComponentTree,
185 ) -> Result<()> {
186 let region_mut = match self.instances.get_mut(®ion) {
188 Some(e) => e,
190 None => bail!(CoreError::RegionNotFound),
192 };
193
194 let entity_mut = match region_mut.get_mut(&entity) {
196 Some(e) => e,
198 None => bail!(CoreError::EntityNotFound),
200 };
201
202 entity_mut.push(component_tree);
204
205 Ok(())
206 }
207
208 pub fn add_default_instance(&mut self, region: Region, entity: Entity) -> Result<u64> {
216 let region_mut = match self.instances.get_mut(®ion) {
218 Some(e) => e,
220 None => bail!(CoreError::RegionNotFound),
222 };
223
224 let entity_mut = match region_mut.get_mut(&entity) {
226 Some(e) => e,
228 None => bail!(CoreError::EntityNotFound),
230 };
231
232 let component_type_tree = self.entities.get(&entity).unwrap();
234
235 let mut component_tree: ComponentTree = BTreeMap::new();
237 for k in component_type_tree.keys() {
238 let v_type = component_type_tree.get(k).unwrap().clone();
239
240 let v: ComponentValue;
241 if v_type == "String" {
242 v = ComponentValue::String(String::default())
243 } else if v_type == "f64" {
244 v = ComponentValue::Float(f64::default())
245 } else if v_type == "i64" {
246 v = ComponentValue::Integer(i64::default())
247 } else if v_type == "bool" {
248 v = ComponentValue::Boolean(bool::default())
249 } else {
250 bail!(CoreError::UnsupportedDataType);
251 }
252
253 component_tree.insert(k.to_string(), v);
255 }
256
257 entity_mut.push(component_tree);
259
260 Ok(entity_mut.len() as u64)
262 }
263
264 pub fn get_default_components(&self, entity: &Entity) -> Result<ComponentTree> {
271 let component_type_tree = self.entities.get(entity).unwrap();
273
274 let mut component_tree: ComponentTree = BTreeMap::new();
276 for k in component_type_tree.keys() {
277 let v_type = component_type_tree.get(k).unwrap().clone();
278
279 let v: ComponentValue;
280 if v_type == "String" {
281 v = ComponentValue::String(String::default())
282 } else if v_type == "f64" {
283 v = ComponentValue::Float(f64::default())
284 } else if v_type == "i64" {
285 v = ComponentValue::Integer(i64::default())
286 } else if v_type == "bool" {
287 v = ComponentValue::Boolean(bool::default())
288 } else {
289 bail!(CoreError::UnsupportedDataType);
290 }
291
292 component_tree.insert(k.to_string(), v);
294 }
295
296 Ok(component_tree)
298 }
299
300 pub fn get_instance(
301 &mut self,
302 region: Region,
303 entity: Entity,
304 nonce: u64,
305 ) -> Result<ComponentTree> {
306 let region_mut = match self.instances.get_mut(®ion) {
308 Some(e) => e,
310 None => bail!(CoreError::RegionNotFound),
312 };
313
314 let entity_mut = match region_mut.get_mut(&entity) {
316 Some(e) => e,
318 None => bail!(CoreError::EntityNotFound),
320 };
321
322 let instance = entity_mut[nonce as usize].clone();
324
325 Ok(instance)
326 }
327
328 pub fn get_component_value(
329 &mut self,
330 region: Region,
331 entity: Entity,
332 nonce: u64,
333 component: Component,
334 ) -> Result<ComponentValue> {
335 let component_tree = match self.get_instance(region, entity, nonce) {
336 Ok(ct) => ct,
337 Err(e) => bail!("{}: {}", CoreError::InstanceNotFound, e),
338 };
339
340 let option_value = component_tree.get(&component);
341
342 match option_value {
343 Some(v) => Ok(v.clone()),
344 None => bail!(CoreError::ComponentNotFound),
345 }
346 }
347
348 pub fn set_component_value(
349 &mut self,
350 region: Region,
351 entity: Entity,
352 nonce: u64,
353 component: Component,
354 value: ComponentValue,
355 ) -> Result<()> {
356 let region_mut = match self.instances.get_mut(®ion) {
358 Some(e) => e,
360 None => bail!(CoreError::RegionNotFound),
362 };
363
364 let entity_mut = match region_mut.get_mut(&entity) {
366 Some(e) => e,
368 None => bail!(CoreError::EntityNotFound),
370 };
371
372 let component_tree = &mut entity_mut[nonce as usize];
373
374 let option_value = component_tree.get_mut(&component);
375
376 if option_value.is_none() {
377 bail!(CoreError::ComponentNotFound);
378 }
379
380 let component_value = option_value.unwrap();
381
382 if discriminant(&value) != discriminant(component_value) {
384 bail!(CoreError::MismatchedDataType)
385 }
386
387 *component_value = value;
388
389 Ok(())
390 }
391}