summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authortroido <troido@protonmail.com>2020-02-14 14:36:32 +0100
committertroido <troido@protonmail.com>2020-02-14 14:36:32 +0100
commit4a4cdf7d148be0a2a756f323d27c0ee5b7976438 (patch)
tree7add0a0d735f93cb1fce6ae4f0c476a0d550a3ee /src
parent7821febc8ee4c89ca1825054e0baf39eea3a0380 (diff)
extract the state to save
Diffstat (limited to 'src')
-rw-r--r--src/assemblage.rs31
-rw-r--r--src/components.rs5
-rw-r--r--src/componentwrapper.rs5
-rw-r--r--src/encyclopedia.rs2
-rw-r--r--src/main.rs38
-rw-r--r--src/parameter.rs11
-rw-r--r--src/room.rs20
-rw-r--r--src/roomtemplate.rs2
-rw-r--r--src/savestate.rs40
-rw-r--r--src/systems/mod.rs1
-rw-r--r--src/systems/moving.rs8
-rw-r--r--src/systems/save.rs43
-rw-r--r--src/systems/take.rs8
-rw-r--r--src/systems/view.rs8
-rw-r--r--src/template.rs21
15 files changed, 188 insertions, 55 deletions
diff --git a/src/assemblage.rs b/src/assemblage.rs
index f84037c..dd84837 100644
--- a/src/assemblage.rs
+++ b/src/assemblage.rs
@@ -4,7 +4,9 @@ use serde_json::{Value, json};
use super::componentparameter::ComponentParameter;
use super::parameter::{Parameter, ParameterType};
use super::componentwrapper::{ComponentWrapper, ComponentType};
+use super::components::Serialise;
use crate::hashmap;
+use crate::template::Template;
type ArgumentDef = (String, ParameterType, Option<Parameter>);
@@ -36,16 +38,20 @@ impl Assemblage {
fn parse_definition_components(comps: &Value) -> Result<Vec<(ComponentType, HashMap<String, ComponentParameter>)>, &'static str> {
let mut components = Vec::new();
for tup in comps.as_array().ok_or("components is not a json array")? {
- let comptype = ComponentType::from_str(tup
- .get(0).ok_or("index 0 not in component")?
- .as_str().ok_or("component name not a string")?
- ).ok_or("not a valid componenttype")?;
- let mut parameters: HashMap<String, ComponentParameter> = HashMap::new();
- for (key, value) in tup.get(1).ok_or("index 1 not in component")?.as_object().ok_or("component parameters not a json object")? {
- let param = ComponentParameter::from_json(value)?;
- parameters.insert(key.clone(), param);
+ if let Some(name) = tup.as_str() {
+ components.push((ComponentType::from_str(name).ok_or("not a valid componenttype")?, HashMap::new()));
+ } else {
+ let comptype = ComponentType::from_str(tup
+ .get(0).ok_or("index 0 not in component")?
+ .as_str().ok_or("component name not a string")?
+ ).ok_or("not a valid componenttype")?;
+ let mut parameters: HashMap<String, ComponentParameter> = HashMap::new();
+ for (key, value) in tup.get(1).ok_or("index 1 not in component")?.as_object().ok_or("component parameters not a json object")? {
+ let param = ComponentParameter::from_json(value)?;
+ parameters.insert(key.clone(), param);
+ }
+ components.push((comptype, parameters));
}
- components.push((comptype, parameters));
}
Ok(components)
}
@@ -109,7 +115,9 @@ impl Assemblage {
Ok(arguments)
}
- pub fn instantiate(&self, args: &[Parameter], kwargs: &HashMap<String, Parameter>) -> Result<Vec<ComponentWrapper>, &'static str>{
+ pub fn instantiate(&self, template: &Template) -> Result<Vec<ComponentWrapper>, &'static str>{
+ let args = &template.args;
+ let kwargs = &template.kwargs;
let mut components: Vec<ComponentWrapper> = Vec::new();
let arguments = self.prepare_arguments(args, kwargs)?;
for (comptype, compparams) in &self.components {
@@ -119,6 +127,9 @@ impl Assemblage {
}
components.push(ComponentWrapper::load_component(*comptype, compargs).ok_or("failed to load component")?);
}
+ if template.save {
+ components.push(ComponentWrapper::Serialise(Serialise{template: template.clone()}));
+ }
Ok(components)
}
}
diff --git a/src/components.rs b/src/components.rs
index 185459a..1f5630d 100644
--- a/src/components.rs
+++ b/src/components.rs
@@ -88,3 +88,8 @@ pub struct Health {
pub maxhealth: i64
}
+#[derive(Component, Debug, Clone)]
+pub struct Serialise {
+ pub template: Template
+}
+
diff --git a/src/componentwrapper.rs b/src/componentwrapper.rs
index cf16213..6e11a0b 100644
--- a/src/componentwrapper.rs
+++ b/src/componentwrapper.rs
@@ -2,7 +2,7 @@
use std::collections::HashMap;
use specs::{Builder, world::LazyBuilder};
-use crate::components::{Visible, Blocking, Player, Floor, Item, Inventory, Health};
+use crate::components::{Visible, Blocking, Player, Floor, Item, Inventory, Health, Serialise};
use crate::parameter::{Parameter, ParameterType};
@@ -94,7 +94,8 @@ components!(
Player (name: String) {Player::new(name)};
Item (ent: Template, name: String) {Item{ent, name}};
Inventory (capacity: Int) {Inventory{items: Vec::new(), capacity: capacity as usize}};
- Health (health: Int, maxhealth: Int) {Health{health, maxhealth}}
+ Health (health: Int, maxhealth: Int) {Health{health, maxhealth}};
+ Serialise (template: Template) {Serialise{template}}
);
diff --git a/src/encyclopedia.rs b/src/encyclopedia.rs
index 5cdf90c..920f15e 100644
--- a/src/encyclopedia.rs
+++ b/src/encyclopedia.rs
@@ -22,7 +22,7 @@ impl Encyclopedia {
pub fn construct(&self, template: &Template) -> Result<Vec<ComponentWrapper>, &'static str> {
let assemblage = self.items.get(&template.name).ok_or("unknown assemblage name")?;
- assemblage.instantiate(&template.args, &template.kwargs)
+ assemblage.instantiate(template)
}
}
diff --git a/src/main.rs b/src/main.rs
index 4afcd0a..00f41e4 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -23,6 +23,7 @@ mod componentparameter;
mod encyclopedia;
mod template;
mod roomtemplate;
+mod savestate;
pub use self::pos::Pos;
use self::gameserver::GameServer;
@@ -55,15 +56,22 @@ fn main() {
println!("asciifarm started");
+
+ let mut count = 0;
loop {
let actions = gameserver.update();
room.set_input(actions);
room.update();
+ if count % 20 == 0 {
+ println!("{}", room.save().to_json());
+ }
let messages = room.view();
for (player, message) in messages {
let _ = gameserver.send(&player, message.to_json());
}
+
+ count += 1;
sleep(Duration::from_millis(100));
}
}
@@ -122,30 +130,22 @@ fn gen_room<'a, 'b>() -> Room<'a, 'b> {
fn default_assemblages() -> Encyclopedia {
Encyclopedia::from_json(json!({
"wall": {
- "components": [
- ["Blocking", {}]
- ],
+ "components": ["Blocking"],
"sprite": "wall",
"height": 2
},
"rock": {
- "components": [
- ["Blocking", {}]
- ],
+ "components": ["Blocking"],
"sprite": "rock",
"height": 10
},
"tree": {
- "components": [
- ["Blocking", {}]
- ],
+ "components": ["Blocking"],
"sprite": "tree",
"height": 3
},
"fence": {
- "components": [
- ["Blocking", {}]
- ],
+ "components": ["Blocking"],
"sprite": "fence",
"height": 1
},
@@ -163,7 +163,7 @@ fn default_assemblages() -> Encyclopedia {
]],
"height": ["float", 0.1]
}],
- ["Floor", {}]
+ "Floor"
]
},
"greengrass": {
@@ -176,26 +176,22 @@ fn default_assemblages() -> Encyclopedia {
]],
"height": ["float", 0.1]
}],
- ["Floor", {}]
+ "Floor"
]
},
"ground": {
- "components": [
- ["Floor", {}]
- ],
+ "components": ["Floor"],
"sprite": "ground",
"height": 0.1
},
"floor": {
- "components": [
- ["Floor", {}]
- ],
+ "components": ["Floor"],
"sprite": "floor",
"height": 0.1
},
"bridge": {
"components": [
- ["Floor", {}]
+ "Floor"
],
"sprite": "bridge",
"height": 0.1
diff --git a/src/parameter.rs b/src/parameter.rs
index 56f1cbf..cca0681 100644
--- a/src/parameter.rs
+++ b/src/parameter.rs
@@ -1,5 +1,5 @@
-use serde_json::Value;
+use serde_json::{Value, json};
use crate::template::Template;
#[derive(Debug, PartialEq, Clone)]
@@ -52,6 +52,15 @@ impl Parameter {
};
Self::from_typed_json(typ, val)
}
+
+ pub fn to_json(&self) -> Value {
+ match self {
+ Self::String(s) => json!(s),
+ Self::Int(i) => json!(i),
+ Self::Float(f) => json!(f),
+ Self::Template(t) => t.to_json()
+ }
+ }
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
diff --git a/src/room.rs b/src/room.rs
index 9aad22d..dbcfe0d 100644
--- a/src/room.rs
+++ b/src/room.rs
@@ -5,7 +5,8 @@ use specs::{
World,
WorldExt,
DispatcherBuilder,
- Dispatcher
+ Dispatcher,
+ Join
};
use super::controls::Action;
@@ -27,8 +28,10 @@ use super::systems::{
create::Create,
take::Take
};
+use crate::components::{Position, Serialise};
use crate::encyclopedia::Encyclopedia;
use crate::roomtemplate::RoomTemplate;
+use crate::savestate::SaveState;
@@ -45,6 +48,7 @@ impl <'a, 'b>Room<'a, 'b> {
templates: Vec::new(),
encyclopedia
});
+ world.register::<Serialise>();
let mut dispatcher = DispatcherBuilder::new()
.with(RegisterNew::default(), "registernew", &[])
@@ -78,7 +82,9 @@ impl <'a, 'b>Room<'a, 'b> {
let y = (idx as i64) / width;
for template in templates {
- self.world.fetch_mut::<NewEntities>().templates.push((Pos{x, y}, template.clone()));
+ let mut obj = template.clone();
+ obj.save = false;
+ self.world.fetch_mut::<NewEntities>().templates.push((Pos{x, y}, obj));
}
}
}
@@ -96,6 +102,16 @@ impl <'a, 'b>Room<'a, 'b> {
self.world.fetch_mut::<Input>().actions = actions;
}
+ pub fn save(&self) -> SaveState {
+ let positions = self.world.read_component::<Position>();
+ let serialisers = self.world.write_component::<Serialise>();
+ let mut state = SaveState::new();
+ for (pos, serialiser) in (&positions, &serialisers).join() {
+ state.changes.entry(pos.pos).or_insert(Vec::new()).push(serialiser.template.clone());
+ }
+ state
+ }
+
}
diff --git a/src/roomtemplate.rs b/src/roomtemplate.rs
index e77fbca..cb8ae6a 100644
--- a/src/roomtemplate.rs
+++ b/src/roomtemplate.rs
@@ -11,7 +11,7 @@ pub struct RoomTemplate {
}
impl RoomTemplate {
-
+
pub fn from_json(jsonroom: &Value) -> Result<RoomTemplate, &'static str>{
let size = (
jsonroom.get("width").ok_or("no with")?.as_i64().ok_or("with not a number")?,
diff --git a/src/savestate.rs b/src/savestate.rs
new file mode 100644
index 0000000..8afbbf1
--- /dev/null
+++ b/src/savestate.rs
@@ -0,0 +1,40 @@
+
+use std::collections::HashMap;
+use serde_json::{json, Value};
+use crate::Pos;
+use crate::template::Template;
+
+pub struct SaveState {
+ pub changes: HashMap<Pos, Vec<Template>>
+}
+
+impl SaveState {
+
+ pub fn new() -> Self {
+ Self {
+ changes: HashMap::new()
+ }
+ }
+
+ pub fn to_json(&self) -> Value {
+ json!({
+ "changes": self.changes.iter().map(
+ |(pos, templates)|
+ (pos, templates.iter().map(|t| t.to_json()).collect())
+ ).collect::<Vec<(&Pos, Vec<Value>)>>()
+ })
+ }
+
+ pub fn from_json(val: &Value) -> Option<Self> {
+ let mut changes = HashMap::new();
+ for v in val.get("changes")?.as_array()? {
+ let pos = Pos::from_json(v.get(0)?)?;
+ let mut templates = Vec::new();
+ for t in v.get(1)?.as_array()? {
+ templates.push(Template::from_json(t)?);
+ }
+ changes.insert(pos, templates);
+ }
+ Some(Self {changes})
+ }
+}
diff --git a/src/systems/mod.rs b/src/systems/mod.rs
index 6989e95..7e75706 100644
--- a/src/systems/mod.rs
+++ b/src/systems/mod.rs
@@ -6,4 +6,3 @@ pub mod view;
pub mod remove;
pub mod create;
pub mod take;
-
diff --git a/src/systems/moving.rs b/src/systems/moving.rs
index 3e7803d..f5c1b4a 100644
--- a/src/systems/moving.rs
+++ b/src/systems/moving.rs
@@ -11,9 +11,9 @@ use specs::{
Write
};
-use super::super::pos::Pos;
+use crate::pos::Pos;
-use super::super::components::{
+use crate::components::{
Controller,
Blocking,
Position,
@@ -21,11 +21,11 @@ use super::super::components::{
Moved
};
-use super::super::controls::{
+use crate::controls::{
Control
};
-use super::super::resources::{
+use crate::resources::{
Size,
Ground
};
diff --git a/src/systems/save.rs b/src/systems/save.rs
new file mode 100644
index 0000000..924533a
--- /dev/null
+++ b/src/systems/save.rs
@@ -0,0 +1,43 @@
+
+use std::collections::HashMap;
+
+use specs::{
+ Entities,
+ ReadStorage,
+ System,
+ Join,
+ Read
+};
+
+use crate::pos::Pos;
+
+use crate::components::{
+ Position,
+ Serialise
+};
+
+use crate::savestate::SaveState;
+
+const INTERVAL: i32 = 20;
+
+pub struct Save(pub i32);
+impl <'a> System<'a> for Save {
+ type SystemData = (
+ Entities<'a>,
+ ReadStorage<'a, Position>,
+ ReadStorage<'a, Serialise>,
+ );
+
+ fn run(&mut self, (entities, positions, serialisers): Self::SystemData) {
+ self.0 -= 1;
+ if self.0 > 0 {
+ return
+ }
+ self.0 = INTERVAL;
+ let mut state = SaveState::new();
+ for (pos, serialiser) in (&positions, &serialisers).join() {
+ state.changes.entry(pos.pos).or_insert(Vec::new()).push(serialiser.template.clone());
+ }
+ println!("save {}", state.to_json().to_string());
+ }
+}
diff --git a/src/systems/take.rs b/src/systems/take.rs
index f0e3990..affa3d1 100644
--- a/src/systems/take.rs
+++ b/src/systems/take.rs
@@ -10,9 +10,7 @@ use specs::{
Write
};
-use super::super::pos::Pos;
-
-use super::super::components::{
+use crate::components::{
Controller,
Position,
Removed,
@@ -20,8 +18,8 @@ use super::super::components::{
Item
};
-use super::super::controls::{Control};
-use super::super::resources::{Ground, NewEntities};
+use crate::controls::{Control};
+use crate::resources::{Ground, NewEntities};
diff --git a/src/systems/view.rs b/src/systems/view.rs
index 57e2b28..2bc971e 100644
--- a/src/systems/view.rs
+++ b/src/systems/view.rs
@@ -11,10 +11,10 @@ use specs::{
Entity
};
-use super::super::pos::Pos;
-use super::super::components::{Visible, Player, Position, Inventory, New, Moved, Removed, Health};
-use super::super::resources::{Size, Output, Ground};
-use super::super::worldmessages::{WorldMessage, WorldUpdate, FieldMessage};
+use crate::pos::Pos;
+use crate::components::{Visible, Player, Position, Inventory, New, Moved, Removed, Health};
+use crate::resources::{Size, Output, Ground};
+use crate::worldmessages::{WorldMessage, WorldUpdate, FieldMessage};
#[derive(Default)]
diff --git a/src/template.rs b/src/template.rs
index 0f846fd..5347e51 100644
--- a/src/template.rs
+++ b/src/template.rs
@@ -8,7 +8,8 @@ use crate::parameter::Parameter;
pub struct Template {
pub name: String,
pub args: Vec<Parameter>,
- pub kwargs: HashMap<String, Parameter>
+ pub kwargs: HashMap<String, Parameter>,
+ pub save: bool
}
@@ -18,7 +19,8 @@ impl Template {
Self {
name: name.to_string(),
args: Vec::new(),
- kwargs
+ kwargs,
+ save: true
}
}
@@ -39,6 +41,19 @@ impl Template {
for (key, arg) in val.get("kwargs").unwrap_or(&json!({})).as_object()? {
kwargs.insert(key.to_string(), Parameter::guess_from_json(arg)?);
}
- Some(Template {name, args, kwargs})
+ Some(Template {name, args, kwargs, save: true})
+ }
+
+ pub fn to_json(&self) -> Value {
+ if self.args.is_empty() && self.kwargs.is_empty() {
+ return json!(self.name);
+ }
+ let jsonargs: Vec<Value> = self.args.iter().map(|a| a.to_json()).collect();
+ let jsonkwargs: HashMap<&String, Value> = self.kwargs.iter().map(|(k, a)| (k, a.to_json())).collect();
+ json!({
+ "type": self.name,
+ "args": jsonargs,
+ "kwargs": jsonkwargs
+ })
}
}