From 523a635dc88bc7890a0e1d3c062a8165259761d6 Mon Sep 17 00:00:00 2001 From: troido Date: Thu, 24 Sep 2020 09:38:18 +0200 Subject: don't try to read into the json data structure all manually --- Cargo.toml | 2 + content/encyclopediae/default_encyclopedia.json | 5 +- src/components/flags.rs | 21 ++---- src/components/mod.rs | 3 +- src/componentwrapper.rs | 8 ++- src/item.rs | 4 +- src/parameter.rs | 17 +++++ src/pos.rs | 18 +++-- src/purgatory.rs | 3 +- src/resources/mod.rs | 8 ++- src/roomtemplate.rs | 49 ++++++++++++- src/systems/spawn.rs | 11 ++- src/template.rs | 95 ++++++++++++++++++++++++- src/worldloader.rs | 3 +- 14 files changed, 206 insertions(+), 41 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b91b315..db2e00b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,3 +20,5 @@ structopt = "0.3" unicode_categories = "0.1.1" base64 = "0.12.0" ring = "0.16.12" +strum = "0.19" +strum_macros = "0.19" diff --git a/content/encyclopediae/default_encyclopedia.json b/content/encyclopediae/default_encyclopedia.json index ca12897..8ea6bcc 100644 --- a/content/encyclopediae/default_encyclopedia.json +++ b/content/encyclopediae/default_encyclopedia.json @@ -49,7 +49,7 @@ "save": false }, "spawner": { - "arguments": [["template", "template"], ["amount", "int", 1], ["delay", "int", 0], ["clan", "string", ""], ["initial_spawn", "bool", true]], + "arguments": [["template", "template"], ["amount", "int", 1], ["delay", "int", 0], ["clan", "string", ""], ["initial_spawn", "bool", true], ["radius", "int", 0]], "components": [ ["Timer", { "delay": ["arg", "delay"], @@ -60,7 +60,8 @@ ["Spawner", { "template": ["arg", "template"], "amount": ["arg", "amount"], - "clan": ["arg", "clan"] + "clan": ["arg", "clan"], + "radius": ["arg", "radius"] }] ] }, diff --git a/src/components/flags.rs b/src/components/flags.rs index d985bf2..25ec4ea 100644 --- a/src/components/flags.rs +++ b/src/components/flags.rs @@ -4,26 +4,17 @@ use specs::{ Component, VecStorage, }; +use strum_macros::{EnumString, Display}; +use serde::{Serialize, Deserialize}; -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, EnumString, Display, Serialize, Deserialize)] pub enum Flag { Blocking, Floor, Occupied, - Soil -} - -use Flag::*; -impl Flag { - pub fn from_str(s: &str) -> Option { - Some(match s { - "Blocking" => Blocking, - "Floor" => Floor, - "Occupied" => Occupied, - "Soil" => Soil, - _ => None? - }) - } + Soil, + Build, + Hot } diff --git a/src/components/mod.rs b/src/components/mod.rs index 38a14bd..3f804da 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -184,7 +184,8 @@ pub struct Spawner { pub amount: usize, pub clan: Clan, pub template: Template, - pub saturated: bool + pub saturated: bool, + pub radius: i64 } #[derive(Component, Debug, Clone, PartialEq, Eq, Hash)] diff --git a/src/componentwrapper.rs b/src/componentwrapper.rs index 08d95ee..b952657 100644 --- a/src/componentwrapper.rs +++ b/src/componentwrapper.rs @@ -3,6 +3,7 @@ use std::collections::{HashMap, HashSet}; use serde::Deserialize; use specs::Builder; use rand::Rng; +use std::str::FromStr; use crate::{ PlayerId, @@ -166,7 +167,7 @@ components!(all: Healing (delay: i64, health: i64) {Healing{delay, health, next_heal: None}}; Autofight () {Autofight::default()}; MonsterAI (move_chance: f64, homesickness: f64, view_distance: i64); - Spawner (amount: i64, clan: String, template: Template) { + Spawner (amount: i64, clan: String, template: Template, radius: i64) { Spawner{ amount: amount as usize, clan: Clan{name: @@ -177,7 +178,8 @@ components!(all: } }, template: template.unsaved(), - saturated: false + saturated: false, + radius } }; Clan (name: String); @@ -212,7 +214,7 @@ components!(all: Flags( flags .iter() - .map(|s| Flag::from_str(s)) + .map(|s| Flag::from_str(s).ok()) .collect::>>().ok_or(aerr!("invalid flag name"))? ) }; diff --git a/src/item.rs b/src/item.rs index 88fd583..0abf35d 100644 --- a/src/item.rs +++ b/src/item.rs @@ -52,8 +52,8 @@ impl ItemAction { "eat" => Eat(arg.as_i64()?), "build" => Build( Template::from_json(arg.get(0)?).ok()?, - arg.get(1)?.as_array()?.iter().map(|v| Flag::from_str(v.as_str()?)).collect::>>()?, - arg.get(2)?.as_array()?.iter().map(|v| Flag::from_str(v.as_str()?)).collect::>>()? + arg.get(1)?.as_array()?.iter().map(|v| Flag::from_str(v.as_str()?).ok()).collect::>>()?, + arg.get(2)?.as_array()?.iter().map(|v| Flag::from_str(v.as_str()?).ok()).collect::>>()? ), "none" => None, "equip" => Equip(Equippable::from_json(arg)?), diff --git a/src/parameter.rs b/src/parameter.rs index 99ecdd7..c307a27 100644 --- a/src/parameter.rs +++ b/src/parameter.rs @@ -1,5 +1,6 @@ use serde_json::{Value, json}; +use serde::{de, Serialize, Deserialize, Serializer, Deserializer}; use crate::{ Template, Pos, @@ -114,6 +115,22 @@ impl Parameter { } } + +impl Serialize for Parameter { + fn serialize(&self, serializer: S) -> Result + where S: Serializer, + { + self.to_json().serialize(serializer) + } +} +impl<'de> Deserialize<'de> for Parameter { + fn deserialize(deserializer: D) -> Result + where D: Deserializer<'de>, + { + Self::guess_from_json(&Value::deserialize(deserializer)?).map_err(|e| de::Error::custom(e.text)) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/pos.rs b/src/pos.rs index 9263561..4c0d9cc 100644 --- a/src/pos.rs +++ b/src/pos.rs @@ -2,7 +2,7 @@ use std::ops::{Add, Sub}; use serde_json::Value; -use serde::{Serialize, Serializer, ser::SerializeTuple}; +use serde::{Serialize, Serializer, Deserialize, Deserializer}; use crate::util::clamp; #[derive(Debug, Hash, PartialEq, Eq, Clone, Copy, Default)] @@ -47,13 +47,17 @@ impl Pos { impl Serialize for Pos { fn serialize(&self, serializer: S) -> Result - where - S: Serializer, + where S: Serializer, { - let mut tup = serializer.serialize_tuple(2)?; - tup.serialize_element(&self.x)?; - tup.serialize_element(&self.y)?; - tup.end() + (self.x, self.y).serialize(serializer) + } +} +impl<'de> Deserialize<'de> for Pos { + fn deserialize(deserializer: D) -> Result + where D: Deserializer<'de>, + { + let (x, y) = <(i64, i64)>::deserialize(deserializer)?; + Ok(Self{x, y}) } } diff --git a/src/purgatory.rs b/src/purgatory.rs index 27db35a..f387b83 100644 --- a/src/purgatory.rs +++ b/src/purgatory.rs @@ -1,6 +1,7 @@ use serde_json::json; +use serde::Deserialize; use specs::{ DispatcherBuilder }; @@ -30,7 +31,7 @@ pub fn create_purgatory<'a, 'b>(encyclopedia: &Encyclopedia) -> Room<'a, 'b> { .with(Move, "move", &["controlinput", "controlai"]) .build(); let mut room = Room::new(purgatory_id(), encyclopedia.clone(), Some(dispatcher)); - room.load_from_template(&RoomTemplate::from_json(&json!({ + room.load_from_template(&RoomTemplate::deserialize(&json!({ "width": 15, "height": 20, "spawn": [7, 9], diff --git a/src/resources/mod.rs b/src/resources/mod.rs index 627a396..025bc6e 100644 --- a/src/resources/mod.rs +++ b/src/resources/mod.rs @@ -7,7 +7,7 @@ pub use ground::Ground; pub use newentities::NewEntities; pub use roompermissions::RoomPermissions; -use std::collections::{HashMap}; +use std::collections::{HashMap, HashSet}; use specs::{Entity}; use crate::{ @@ -17,7 +17,8 @@ use crate::{ PlayerId, RoomId, playerstate::RoomPos, - Timestamp + Timestamp, + components::Flag }; @@ -58,3 +59,6 @@ pub struct Time { pub time: Timestamp } +#[derive(Default, Debug, Clone)] +pub struct RoomFlags(pub HashSet); + diff --git a/src/roomtemplate.rs b/src/roomtemplate.rs index 87c94fe..7110e64 100644 --- a/src/roomtemplate.rs +++ b/src/roomtemplate.rs @@ -1,6 +1,7 @@ use std::collections::HashMap; use serde_json::{json, Value, value}; +use serde::{Deserialize, Deserializer, de, Serialize}; use crate::{ Pos, Template, @@ -18,6 +19,52 @@ pub struct RoomTemplate { pub permissions: RoomPermissions } +#[derive(Debug, Clone, Serialize, Deserialize)] +struct RoomTemplateSave { + pub width: i64, + pub height: i64, + pub spawn: Pos, + pub field: Vec, + pub mapping: HashMap, + #[serde(default)] + pub places: HashMap, + #[serde(default)] + pub permissions: RoomPermissions +} +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(untagged)] +enum TemplateList { + Single(Template), + List(Vec