summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authortroido <troido@protonmail.com>2020-09-25 16:19:05 +0200
committertroido <troido@protonmail.com>2020-09-25 16:19:05 +0200
commitddf7c12c4927d8696c641d9f72b1fef94e046f77 (patch)
tree7842fbef7f9ee43207fd8573e082e1a25e3e7658 /src
parent87727f9519eb37b565d8cc88e174935bac0e1d12 (diff)
encyclopedia now using serde serialisation too
Diffstat (limited to 'src')
-rw-r--r--src/assemblage.rs8
-rw-r--r--src/encyclopedia.rs160
-rw-r--r--src/worldloader.rs5
3 files changed, 76 insertions, 97 deletions
diff --git a/src/assemblage.rs b/src/assemblage.rs
index f157117..80c10ab 100644
--- a/src/assemblage.rs
+++ b/src/assemblage.rs
@@ -8,8 +8,7 @@ use crate::{
components::Serialise,
Template,
Result as AnyResult,
- aerr,
- fromtoparameter::FromToParameter
+ aerr
};
type ArgumentDef = (String, ParameterType, Option<Parameter>);
@@ -81,12 +80,15 @@ impl Assemblage {
}
}
+#[macro_export]
macro_rules! compmap {
{$($name: ident: $val: expr),*} => {{
+ #[allow(unused_imports)]
+ use crate::fromtoparameter::FromToParameter;
#[allow(unused_mut)]
let mut h = std::collections::HashMap::new();
$(
- h.insert(stringify!($name).to_string(), ParameterExpression::Constant($val.to_parameter()));
+ h.insert(stringify!($name).to_string(), crate::parameterexpression::ParameterExpression::Constant($val.to_parameter()));
)*
h
}}
diff --git a/src/encyclopedia.rs b/src/encyclopedia.rs
index 72cc483..16d26a8 100644
--- a/src/encyclopedia.rs
+++ b/src/encyclopedia.rs
@@ -1,20 +1,20 @@
use std::collections::HashMap;
-use serde_json::{Value, json};
-use serde::Deserialize;
+use serde::{de, Deserialize, Serialize, Deserializer};
use crate::{
assemblage::Assemblage,
componentwrapper::PreEntity,
Template,
template::EntityType,
- Result,
+ Result as AnyResult,
aerr,
ItemId,
item::Item,
item::ItemAction,
- PResult,
- perr,
- parameter::Parameter
+ parameter::Parameter,
+ Sprite,
+ compmap,
+ componentwrapper::ComponentType
};
#[derive(Default, Clone)]
@@ -25,97 +25,14 @@ pub struct Encyclopedia {
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::deserialize(v).map_err(|e| perr!("invalid assemblage {:?}: {}", v, e))?)))
- .collect::<PResult<HashMap<EntityType, Assemblage>>>()?;
- let items =
- val
- .get("items")
- .unwrap_or(&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::deserialize(ent).map_err(|e| perr!("template json error deserializing {:?} {:?}", ent, e))?
- } else {
- let enttyp = EntityType(k.clone());
- assemblages.insert(enttyp.clone(), Assemblage::deserialize(&json!({
- "height": 0.3,
- "sprite": sprite,
- "name": name,
- "item": k
- })).map_err(|e| perr!("invalid assemblage {:?}: {}", v, e))?);
- Template::from_entity_type(enttyp)
- },
- action:
- if let Some(action) = v.get("action") {
- ItemAction::deserialize(action).map_err(|e| perr!("failed to parse ItemAction {:?} {:?}", v, e))?
- } else {
- ItemAction::None
- }
- };
- Ok((id, item))
- })
- .collect::<PResult<HashMap<ItemId, Item>>>()?;
- for (name, v) in
- val
- .get("templates")
- .unwrap_or(&json!({}))
- .as_object().ok_or(perr!("templates not a json dict: {:?}", val.get("templates")))?
- .iter() {
- let enttype = EntityType(v
- .get(0).ok_or(perr!("index 0 not in subtitution template"))?
- .as_str().ok_or(perr!("subtitution origin name not a string"))?
- .to_string());
- let values = v.get(1).ok_or(perr!("index 0 not in subtitution template"))?;
- let mut assemblage = assemblages.get(&enttype).ok_or(perr!("template name '{:?}' does not point to not an assemblage", enttype))?.clone();
- for arg in assemblage.arguments.iter_mut() {
- if let Some(x) = values.get(&arg.0) {
- let param = Parameter::from_typed_json(arg.1, x)?;
- arg.2 = Some(param);
- }
- }
- assemblages.insert(EntityType(name.to_string()), assemblage);
- }
-
- Ok(Encyclopedia{
- assemblages,
- items
- })
- }
-
- pub fn validate(&self) -> Result<()> {
+ pub fn validate(&self) -> AnyResult<()> {
for assemblage in self.assemblages.values() {
assemblage.validate()?;
}
Ok(())
}
- pub fn construct(&self, template: &Template) -> Result<PreEntity> {
+ pub fn construct(&self, template: &Template) -> AnyResult<PreEntity> {
let assemblage = self.assemblages
.get(&template.name)
.ok_or(aerr!("unknown assemblage name: '{:?}' in {:?}", template.name, template))?;
@@ -133,3 +50,64 @@ impl Encyclopedia {
}
}
+
+impl<'de> Deserialize<'de> for Encyclopedia {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where D: Deserializer<'de> {
+ let EncyclopediaSave{mut assemblages, items, templates} = EncyclopediaSave::deserialize(deserializer)?;
+ let mut itemdefs = HashMap::new();
+ for (id, item) in items.into_iter(){
+ let sprite = item.sprite.unwrap_or(Sprite(id.clone()));
+ let name = item.name.unwrap_or(id.clone());
+ let ent = item.entity.unwrap_or_else(||{
+ let enttyp = EntityType(id.clone());
+ assemblages.insert(enttyp.clone(), Assemblage {
+ arguments: Vec::new(),
+ save: true,
+ extract: Vec::new(),
+ components: vec![
+ (ComponentType::Visible, compmap!{height: 0.3_f64, sprite: sprite.0, name: name.clone()}),
+ (ComponentType::Item, compmap!{item: id.clone()})
+ ]
+ });
+ Template::from_entity_type(enttyp)
+ });
+ itemdefs.insert(ItemId(id), Item{
+ ent,
+ name,
+ action: item.action.unwrap_or(ItemAction::None)
+ });
+ }
+ for (templatename, (baseent, mut args)) in templates {
+ let mut assemblage = assemblages.get(&baseent).ok_or(de::Error::custom(format!("template name '{:?}' does not point to not an assemblage", baseent)))?.clone();
+ for arg in assemblage.arguments.iter_mut() {
+ if let Some(param) = args.remove(&arg.0) {
+ // todo: verify argument type
+ arg.2 = Some(param);
+ }
+ }
+ assemblages.insert(templatename, assemblage);
+ }
+
+ Ok(Encyclopedia{
+ assemblages,
+ items: itemdefs
+ })
+ }
+}
+#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
+struct ItemSave {
+ sprite: Option<Sprite>,
+ name: Option<String>,
+ entity: Option<Template>,
+ action: Option<ItemAction>
+}
+#[derive(Debug, Clone, PartialEq, Deserialize)]
+struct EncyclopediaSave {
+ #[serde(default)]
+ assemblages: HashMap<EntityType, Assemblage>,
+ #[serde(default)]
+ items: HashMap<String, ItemSave>,
+ #[serde(default)]
+ templates: HashMap<EntityType, (EntityType, HashMap<String, Parameter>)>
+}
diff --git a/src/worldloader.rs b/src/worldloader.rs
index 414d443..c8738e2 100644
--- a/src/worldloader.rs
+++ b/src/worldloader.rs
@@ -60,15 +60,14 @@ impl WorldLoader {
pub fn load_encyclopedia(&self, name: &str) -> Result<Encyclopedia> {
let fname: String = name.to_string() + ".json";
- let encyclopedia = Encyclopedia::from_json(
+ let encyclopedia: Encyclopedia =
serde_json::from_str(
&fs::read_to_string(
self.directory
.join("encyclopediae")
.join(&fname)
)?
- )?
- )?;
+ ).map_err(|e|aerr!("failed to load encyclopedia {}: {}", name, e))?;
encyclopedia.validate()?;
Ok(encyclopedia)
}