From 1ceb4c6f23287bca98f0c3946d5678dce5d0457c Mon Sep 17 00:00:00 2001 From: troido Date: Wed, 1 Apr 2020 13:27:42 +0200 Subject: better time handling for growing plants --- content/encyclopediae/default_encyclopedia.json | 28 ++++++++++++++++++---- src/assemblage.rs | 15 ++++++++---- src/componentparameter.rs | 3 ++- src/components/mod.rs | 6 +++++ src/componentwrapper.rs | 2 +- src/parameter.rs | 10 +++++++- src/persistence.rs | 32 ++++++++++++++++++++----- src/template.rs | 2 +- src/world.rs | 8 +++++-- todo.md | 3 +-- 10 files changed, 85 insertions(+), 24 deletions(-) diff --git a/content/encyclopediae/default_encyclopedia.json b/content/encyclopediae/default_encyclopedia.json index ea1684b..e682fe2 100644 --- a/content/encyclopediae/default_encyclopedia.json +++ b/content/encyclopediae/default_encyclopedia.json @@ -91,7 +91,7 @@ "height": 0.4 }, "player": { - "arguments": [["name", "string", null]], + "arguments": [["name", "string"]], "components": [ ["Visible", { "sprite": ["string", "player"], @@ -106,7 +106,7 @@ ] }, "portal": { - "arguments": [["destination", "string", null], ["dest_pos", "string", ""]], + "arguments": [["destination", "string"], ["dest_pos", "string", ""]], "components": [ ["RoomExit", {"destination": ["arg", "destination"], "dest_pos": ["arg", "dest_pos"]}], "Floor" @@ -160,7 +160,7 @@ ] }, "spawner": { - "arguments": [["template", "template", null], ["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]], "components": [ ["Spawner", { "template": ["arg", "template"], @@ -172,7 +172,7 @@ ] }, "letter": { - "arguments": [["char", "string", null]], + "arguments": [["char", "string"]], "components": [["Visible", { "name": ["concat", [["string", "letter_"], ["arg", "char"]]], "sprite": ["concat", [["string", "emptyletter-"], ["arg", "char"]]], @@ -196,15 +196,33 @@ "item": ["build", "plantedradishseed"] }, "plantedradishseed": { + "arguments": [["target_time", "sometime", null]], "sprite": "seed", "height": 0.05, "name": "seed", + "components": [ + ["Grow", { + "delay": ["int", 100], + "target_time": ["arg", "target_time"], + "into": ["template", "radishseedling"] + }] + ] + }, + "radishseedling": { + "arguments": [["target_time", "sometime", null]], + "sprite": "seedling", + "height": 0.05, + "name": "seedling", "components": [ ["Grow", { "delay": ["int", 200], + "target_time": ["arg", "target_time"], "into": ["template", "radishplant"] }] - ] + ], + "extract": { + "target_time": ["Grow", "target_time"] + } }, "radishes": { "sprite": "food", diff --git a/src/assemblage.rs b/src/assemblage.rs index 8e3a349..df60b45 100644 --- a/src/assemblage.rs +++ b/src/assemblage.rs @@ -31,11 +31,16 @@ impl Assemblage { let tup = arg.as_array().ok_or(aerr!("argument is not an array"))?; let key = tup.get(0).ok_or(aerr!("argument has no name"))?.as_str().ok_or(aerr!("argument name is not a string"))?.to_string(); let typ = ParameterType::from_str(tup.get(1).ok_or(aerr!("argument has no type"))?.as_str().ok_or(aerr!("argument type not a string"))?).ok_or(aerr!("failed to parse argument type"))?; - let def = tup.get(2).ok_or("argument has no default")?; - if def.is_null() { + if let Some(def) = tup.get(2){ + arguments.push( + ( + key.clone(), + typ, + Some(Parameter::from_typed_json(typ, def).ok_or(aerr!("invalid argument default"))?) + ) + ); + } else { arguments.push((key.clone(), typ, None)); - } else { - arguments.push((key.clone(), typ, Some(Parameter::from_typed_json(typ, def).ok_or(aerr!("invalid argument default"))?))); } } Ok(arguments) @@ -159,7 +164,7 @@ impl Assemblage { None } }; - let param = value.ok_or(aerr!("argument has no value"))?; + let param = value.ok_or(aerr!(&format!("argument <{:?}> has no value", (idx, (name, typ, def)))))?; if param.paramtype() != *typ { return Err(aerr!("argument has incorrect type")); } diff --git a/src/componentparameter.rs b/src/componentparameter.rs index bcf42e9..068df76 100644 --- a/src/componentparameter.rs +++ b/src/componentparameter.rs @@ -55,7 +55,8 @@ impl ComponentParameter { Some(Parameter::String(string)) } Self::TemplateSelf => Some(Parameter::Template(template.clone())), - Self::TemplateName => Some(Parameter::String(template.name.0.clone())) + Self::TemplateName => Some(Parameter::String(template.name.0.clone())), + } } diff --git a/src/components/mod.rs b/src/components/mod.rs index b43eba1..071b5e0 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -226,4 +226,10 @@ pub struct Grow { pub into: Template } +#[derive(Component, Debug, Clone)] +#[storage(HashMapStorage)] +pub struct CreationTime { + pub time: Timestamp +} + diff --git a/src/componentwrapper.rs b/src/componentwrapper.rs index b1fd64d..345c986 100644 --- a/src/componentwrapper.rs +++ b/src/componentwrapper.rs @@ -181,7 +181,7 @@ components!( Faction (faction: String) {Faction::from_str(faction.as_str())?}; Interactable (action: String) {Interactable::from_str(action.as_str())?}; Loot (loot: LootList); - Grow (delay: Int, into: Template) {Grow{delay, into, target_time: None}}; + Grow (into: Template, delay: Int, target_time: SomeTime); Equipment () {panic!("equipment from parameters not implemented")}; ); diff --git a/src/parameter.rs b/src/parameter.rs index 829c5cf..a56dd23 100644 --- a/src/parameter.rs +++ b/src/parameter.rs @@ -3,7 +3,8 @@ use serde_json::{Value, json}; use crate::{ Template, components::item::ItemAction, - Pos + Pos, + Timestamp }; @@ -75,6 +76,13 @@ parameters!( Some((Template::from_json(item.get(0)?).ok()?, item.get(1)?.as_f64()?)) ).collect::>>()?) ({json!(v.iter().map(|(t, c)| (t.to_json(), *c)).collect::>())}); + SomeTime (Option) sometime, v + ( + serde_json::from_value::>(v.clone()) + .ok()? + .map(|time| Timestamp(time)) + ) + (json!(v.map(|timestamp| timestamp.0))); ); diff --git a/src/persistence.rs b/src/persistence.rs index 2903ec6..bbf9595 100644 --- a/src/persistence.rs +++ b/src/persistence.rs @@ -3,12 +3,13 @@ use std::path::{PathBuf, Path}; use std::fs; use std::env; use serde_json; -use serde_json::Value; +use serde_json::{Value, json}; use crate::{ PlayerId, RoomId, savestate::SaveState, playerstate::PlayerState, + Timestamp, Result, aerr }; @@ -16,13 +17,12 @@ use crate::{ pub trait PersistentStorage { fn load_room(&self, id: RoomId) -> Result; - fn load_player(&self, id: PlayerId) -> Result; + fn load_world_meta(&self) -> Result; fn save_room(&self, id: RoomId, state: SaveState) -> Result<()>; - fn save_player(&self, id: PlayerId, sate: PlayerState) -> Result<()>; - + fn save_world_meta(&self, time: Timestamp) -> Result<()>; } @@ -78,6 +78,20 @@ impl PersistentStorage for FileStorage { PlayerState::from_json(&json) } + fn load_world_meta(&self) -> Result { + let mut path = self.directory.clone(); + path.push("world.save.json"); + let text = fs::read_to_string(path)?; + let json: Value = serde_json::from_str(&text)?; + Ok( + Timestamp( + json + .get("steps").ok_or(aerr!("world data does not have steps"))? + .as_i64().ok_or(aerr!("timestamp not an int"))? + ) + ) + } + fn save_room(&self, id: RoomId, state: SaveState) -> Result<()> { let mut path = self.directory.clone(); path.push("rooms"); @@ -85,7 +99,6 @@ impl PersistentStorage for FileStorage { let fname = id.to_string() + ".save.json"; path.push(fname); let text = state.to_json().to_string(); - // todo: write to a temp file first write_file_safe(path, text)?; Ok(()) } @@ -97,10 +110,17 @@ impl PersistentStorage for FileStorage { let fname = id.to_string() + ".save.json"; path.push(fname); let text = state.to_json().to_string(); - // todo: write to a temp file first write_file_safe(path, text)?; Ok(()) } + + fn save_world_meta(&self, time: Timestamp) -> Result<()> { + let mut path = self.directory.clone(); + fs::create_dir_all(&path)?; + path.push("world.save.json"); + write_file_safe(path, json!({"steps": time.0}).to_string())?; + Ok(()) + } } fn write_file_safe, C: AsRef<[u8]>>(path: P, contents: C) -> Result<()> { diff --git a/src/template.rs b/src/template.rs index cf0fee2..496d08e 100644 --- a/src/template.rs +++ b/src/template.rs @@ -42,7 +42,7 @@ impl Template { pub fn from_json(val: &Value) -> Result