diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/assemblage.rs | 15 | ||||
| -rw-r--r-- | src/componentparameter.rs | 3 | ||||
| -rw-r--r-- | src/components/mod.rs | 6 | ||||
| -rw-r--r-- | src/componentwrapper.rs | 2 | ||||
| -rw-r--r-- | src/parameter.rs | 10 | ||||
| -rw-r--r-- | src/persistence.rs | 32 | ||||
| -rw-r--r-- | src/template.rs | 2 | ||||
| -rw-r--r-- | src/world.rs | 8 |
8 files changed, 61 insertions, 17 deletions
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 } } + |
