summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortroido <troido@protonmail.com>2020-04-01 13:27:42 +0200
committertroido <troido@protonmail.com>2020-04-01 13:27:42 +0200
commit1ceb4c6f23287bca98f0c3946d5678dce5d0457c (patch)
treec354643711d0a6066b149206a29d2182b281f50f
parent69ac6eb6153b016c39bbe55c85f15e3478032182 (diff)
better time handling for growing plants
-rw-r--r--content/encyclopediae/default_encyclopedia.json28
-rw-r--r--src/assemblage.rs15
-rw-r--r--src/componentparameter.rs3
-rw-r--r--src/components/mod.rs6
-rw-r--r--src/componentwrapper.rs2
-rw-r--r--src/parameter.rs10
-rw-r--r--src/persistence.rs32
-rw-r--r--src/template.rs2
-rw-r--r--src/world.rs8
-rw-r--r--todo.md3
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::<Option<Vec<(Template, f64)>>>()?)
({json!(v.iter().map(|(t, c)| (t.to_json(), *c)).collect::<Vec<(Value, f64)>>())});
+ SomeTime (Option<Timestamp>) sometime, v
+ (
+ serde_json::from_value::<Option<i64>>(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<SaveState>;
-
fn load_player(&self, id: PlayerId) -> Result<PlayerState>;
+ fn load_world_meta(&self) -> Result<Timestamp>;
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<Timestamp> {
+ 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<P: AsRef<Path>, 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<Template> {
if val.is_string(){
- return Ok(Self::empty(val.as_str().ok_or(aerr!("json string is not a string?"))?));
+ return Ok(Self::empty(val.as_str().unwrap()));
}
let name = EntityType(val.get("type").ok_or(aerr!("template doesn't have 'type'"))?.as_str().ok_or(aerr!("template type not a string"))?.to_string());
let mut args = Vec::new();
diff --git a/src/world.rs b/src/world.rs
index 7b02d90..ecdc540 100644
--- a/src/world.rs
+++ b/src/world.rs
@@ -33,12 +33,12 @@ impl <'a, 'b>World<'a, 'b> {
pub fn new(encyclopedia: Encyclopedia, template_loader: WorldLoader, persistence: Box<dyn PersistentStorage>, default_room: RoomId) -> Self {
World {
template_loader,
+ time: persistence.load_world_meta().unwrap_or(Timestamp(1000000)),
persistence,
default_room,
encyclopedia: encyclopedia.clone(),
players: HashMap::new(),
- rooms: hashmap!(purgatory::purgatory_id() => purgatory::create_purgatory(encyclopedia)),
- time: Timestamp(1000000)
+ rooms: hashmap!(purgatory::purgatory_id() => purgatory::create_purgatory(encyclopedia))
}
}
@@ -164,6 +164,9 @@ impl <'a, 'b>World<'a, 'b> {
}
}
}
+ if let Err(err) = self.persistence.save_world_meta(self.time) {
+ println!("{:?}",err);
+ }
}
pub fn view(&self) -> HashMap<PlayerId, WorldMessage> {
@@ -176,3 +179,4 @@ impl <'a, 'b>World<'a, 'b> {
views
}
}
+
diff --git a/todo.md b/todo.md
index 17071c4..cee0b84 100644
--- a/todo.md
+++ b/todo.md
@@ -3,12 +3,11 @@
- make readme
- save time
-- save variable arguments (health etc)
- timer resource
- log world events to player
- draw new entities
- room unloading
-- relative room locations
+- relative room locations?
- improve error handling
- doors