summaryrefslogtreecommitdiff
path: root/src/encyclopedia.rs
blob: c378b84b08f660bc7d9fb945e2b2d9dfb571091e (plain)
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

use std::collections::HashMap;
use serde_json::{Value, json};
use crate::{
	assemblage::Assemblage,
	componentwrapper::PreEntity,
	Template,
	template::EntityType,
	Result,
	aerr,
	ItemId,
	item::Item,
	item::ItemAction,
	PResult,
	perr
};

#[derive(Default, Clone)]
pub struct Encyclopedia {
	assemblages: HashMap<EntityType, Assemblage>,
	items: HashMap<ItemId, Item>
}

impl Encyclopedia {
	
	pub fn from_json(val: Value) -> PResult<Encyclopedia> {
		let mut assemblages = 
			val
			.get("assemblages")
			.ok_or(perr!("no assemblages in encyclopedia json"))?
			.as_object()
			.ok_or(perr!("encyclopedia assemblages not a json object"))?
			.into_iter()
			.map(|(k, v)| Ok((EntityType(k.clone()), Assemblage::from_json(v)?)))
			.collect::<PResult<HashMap<EntityType, Assemblage>>>()?;
		let items =
			val
			.get("items")
			.ok_or(perr!("no items in encyclopedia json"))?
			.as_object()
			.ok_or(perr!("encyclopedia items not a json object"))?
			.into_iter()
			.map(|(k, v)| {
				let id = ItemId(k.clone());
				let sprite = 
					if let Some(sprite) = v.get("sprite") {
						sprite.as_str().ok_or(perr!("item sprite not a string: {:?}", v))?
					} else {
						k
					};
				let name =
					if let Some(name) = v.get("name") {
						name.as_str().ok_or(perr!("item name not a string: {:?}", v))?.to_string()
					} else {
						k.to_string()
					};
				let item = Item {
					name: name.clone(),
					ent:
						if let Some(ent) = v.get("entity") {
							Template::from_json(ent)?
						} else {
							let enttyp = EntityType(k.clone());
							assemblages.insert(enttyp.clone(), Assemblage::from_json(&json!({
								"height": 0.3,
								"sprite": sprite,
								"name": name,
								"item": k
							}))?);
							Template::from_entity_type(enttyp)
						},
					action: 
						if let Some(action) = v.get("action") {
							ItemAction::from_json(action).ok_or(perr!("failed to parse ItemAction: {:?}", v))?
						} else {
							ItemAction::None
						}
				};
				Ok((id, item))
			})
			.collect::<PResult<HashMap<ItemId, Item>>>()?;
		
		Ok(Encyclopedia{
			assemblages,
			items
		})
	}
	
	pub fn validate(&self) -> Result<()> {
		for assemblage in self.assemblages.values() {
			assemblage.validate()?;
		}
		Ok(())
	}
	
	pub fn construct(&self, template: &Template) -> Result<PreEntity> {
		let assemblage = self.assemblages
			.get(&template.name)
			.ok_or(aerr!("unknown assemblage name: '{:?}' in {:?}", template.name, template))?;
		assemblage.instantiate(template)
	}
	
	pub fn get_item(&self, id: &ItemId) -> Option<Item> {
		self.items.get(id).map(|item| item.clone())
	}
}