summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortroido <troido@protonmail.com>2020-03-09 16:54:26 +0100
committertroido <troido@protonmail.com>2020-03-09 16:54:26 +0100
commit69ac6eb6153b016c39bbe55c85f15e3478032182 (patch)
tree31a0a5cf3d768688c7600902364446d55e3f4395
parenta1f45d1b40b23cb7e9f0b277f24ad66880b0bc56 (diff)
can now include variables (like health) in serialisation
-rw-r--r--content/encyclopediae/default_encyclopedia.json3
-rw-r--r--src/assemblage.rs26
-rw-r--r--src/components/mod.rs7
-rw-r--r--src/components/serialise.rs16
-rw-r--r--src/componentwrapper.rs13
-rw-r--r--src/room.rs14
-rw-r--r--todo.md1
7 files changed, 61 insertions, 19 deletions
diff --git a/content/encyclopediae/default_encyclopedia.json b/content/encyclopediae/default_encyclopedia.json
index bf5a1b2..ea1684b 100644
--- a/content/encyclopediae/default_encyclopedia.json
+++ b/content/encyclopediae/default_encyclopedia.json
@@ -120,7 +120,8 @@
"Mortal"
],
"sprite": "wall",
- "height": 2
+ "height": 2,
+ "extract": {"health": ["Health", "health"]}
},
"spiketrap": {
"components": [["Trap", {"damage": ["int", 8]}]],
diff --git a/src/assemblage.rs b/src/assemblage.rs
index adf1ba5..8e3a349 100644
--- a/src/assemblage.rs
+++ b/src/assemblage.rs
@@ -18,7 +18,8 @@ type ArgumentDef = (String, ParameterType, Option<Parameter>);
pub struct Assemblage {
pub arguments: Vec<ArgumentDef>,
pub components: Vec<(ComponentType, HashMap<String, ComponentParameter>)>,
- pub save: bool
+ pub save: bool,
+ pub extract: Vec<(String, ComponentType, String)>
}
impl Assemblage {
@@ -78,7 +79,26 @@ impl Assemblage {
let mut assemblage = Self {
arguments: Self::parse_definition_arguments(val.get("arguments").unwrap_or(&json!([])))?,
components: Self::parse_definition_components(val.get("components").unwrap_or(&json!([])))?,
- save: val.get("save").unwrap_or(&json!(true)).as_bool().ok_or(aerr!("assemblage save not a bool"))?
+ save: val.get("save").unwrap_or(&json!(true)).as_bool().ok_or(aerr!("assemblage save not a bool"))?,
+ extract: val
+ .get("extract")
+ .unwrap_or(&json!({}))
+ .as_object().ok_or(aerr!("assemblage extract not a bool"))?
+ .into_iter()
+ .map(|(argname, val)| {
+ Ok((
+ argname.to_string(),
+ ComponentType::from_str(
+ val
+ .get(0).ok_or(aerr!("index 0 not in extract value"))?
+ .as_str().ok_or(aerr!("extract component name not a string"))?
+ ).ok_or(aerr!("extract invalid component name"))?,
+ val.get(1)
+ .ok_or(aerr!("index 1 not in extract value"))?
+ .as_str().ok_or(aerr!("extract member name not a string"))?.to_string()
+ ))
+ })
+ .collect::<Result<Vec<(String, ComponentType, String)>>>()?
};
let name = if let Some(nameval) = val.get("name") {
Some(nameval.as_str().ok_or(aerr!("name not a string"))?.to_string())
@@ -161,7 +181,7 @@ impl Assemblage {
components.push(ComponentWrapper::load_component(*comptype, compargs).ok_or(aerr!("failed to load component"))?);
}
if template.save && self.save {
- components.push(ComponentWrapper::Serialise(Serialise{template: template.clone()}));
+ components.push(ComponentWrapper::Serialise(Serialise{template: template.clone(), extract: self.extract.clone() }));
}
Ok(components)
}
diff --git a/src/components/mod.rs b/src/components/mod.rs
index c3e8d5d..b43eba1 100644
--- a/src/components/mod.rs
+++ b/src/components/mod.rs
@@ -5,6 +5,7 @@ pub mod faction;
pub mod interactable;
pub mod equipment;
pub mod inventory;
+pub mod serialise;
pub use item::Item;
pub use messages::{
@@ -16,6 +17,7 @@ pub use faction::Faction;
pub use interactable::Interactable;
pub use equipment::Equipment;
pub use inventory::Inventory;
+pub use serialise::Serialise;
use specs::{
DenseVecStorage,
@@ -119,11 +121,6 @@ impl Health {
}
#[derive(Component, Debug, Clone)]
-pub struct Serialise {
- pub template: Template
-}
-
-#[derive(Component, Debug, Clone)]
pub struct RoomExit {
pub destination: RoomId,
pub dest_pos: RoomPos
diff --git a/src/components/serialise.rs b/src/components/serialise.rs
new file mode 100644
index 0000000..aa79d93
--- /dev/null
+++ b/src/components/serialise.rs
@@ -0,0 +1,16 @@
+
+use specs::{
+ Component,
+ DenseVecStorage
+};
+use crate::{
+ Template,
+ componentwrapper::ComponentType
+};
+
+
+#[derive(Component, Debug, Clone)]
+pub struct Serialise {
+ pub template: Template,
+ pub extract: Vec<(String, ComponentType, String)>
+}
diff --git a/src/componentwrapper.rs b/src/componentwrapper.rs
index a49ac79..b1fd64d 100644
--- a/src/componentwrapper.rs
+++ b/src/componentwrapper.rs
@@ -83,27 +83,24 @@ macro_rules! components {
}
use specs::{World, Entity, WorldExt};
- pub fn extract_parameter(typ: ComponentType, parameter: &str, world: World, ent: Entity) -> Option<Parameter> {
+ pub fn extract_parameter(typ: ComponentType, parameter: &str, world: &World, ent: Entity) -> Option<Parameter> {
match typ {
$(
#[allow(path_statements)]
ComponentType::$comp => {
- None::<Parameter>
$(
- ;
if parameter == stringify!($paramname) {
#[allow(unreachable_code, non_snake_case)]
- Some(Parameter::$paramtype({
+ return Some(Parameter::$paramtype({
let components = world.read_component::<crate::components::$comp>();
#[allow(unused_variables)]
let $comp = components.get(ent)?;
$extraction
}))
- } else {
- None
}
)*
+ None::<Parameter>
}
)*
}
@@ -119,7 +116,7 @@ macro_rules! components {
};
// full definition minus variable exraction
(pre: ($($done: tt)*) $comp: ident ($($paramname: ident : $paramtype: ident),*) $creation: expr; $($tail:tt)*) => {
- components!(pre: ($($done)* $comp ($($paramname : $paramtype, {panic!(format!("can not extract {} for {}", stringify!($paramname), stringify!($comp)))}),*) $creation;) $($tail)*);
+ components!(pre: ($($done)* $comp ($($paramname : $paramtype, {None?}),*) $creation;) $($tail)*);
};
// full definition
(pre: ($($done: tt)*) $comp: ident ($($paramname: ident : $paramtype: ident ($extraction: expr)),*) $creation: expr; $($tail:tt)*) => {
@@ -146,7 +143,7 @@ components!(
Item (ent: Template, name: String, action: Action);
Inventory () {panic!("inventory from parameters not implemented")};
Health (health: Int, maxhealth: Int);
- Serialise (template: Template);
+ Serialise () {panic!("serialise from parameters not implemented")};
RoomExit (destination: String, dest_pos: String) {
RoomExit {
destination: RoomId::from_str(&destination),
diff --git a/src/room.rs b/src/room.rs
index e78cbd5..983ba11 100644
--- a/src/room.rs
+++ b/src/room.rs
@@ -38,6 +38,7 @@ use crate::{
savestate::SaveState,
Template,
playerstate::{PlayerState, RoomPos},
+ componentwrapper::extract_parameter,
Pos,
PlayerId,
RoomId,
@@ -201,11 +202,20 @@ impl <'a, 'b>Room<'a, 'b> {
}
pub fn save(&self) -> SaveState {
+ let entities = self.world.entities();
let positions = self.world.read_component::<Position>();
let serialisers = self.world.read_component::<Serialise>();
let mut state = SaveState::new();
- for (pos, serialiser) in (&positions, &serialisers).join() {
- state.changes.entry(pos.pos).or_insert_with(Vec::new).push(serialiser.template.clone());
+ for (entity, pos, serialiser) in (&entities, &positions, &serialisers).join() {
+ let mut template = serialiser.template.clone();
+ for (argument, component, member) in &serialiser.extract {
+ if let Some(parameter) = extract_parameter(*component, member.as_str(), &self.world, entity){
+ template.kwargs.insert(argument.clone(), parameter);
+ } else {
+ println!("failed to extract parameter {:?} from {:?}", member, component);
+ }
+ }
+ state.changes.entry(pos.pos).or_insert_with(Vec::new).push(template);
}
state
}
diff --git a/todo.md b/todo.md
index 2d869b3..17071c4 100644
--- a/todo.md
+++ b/todo.md
@@ -1,6 +1,7 @@
# TODO
+- make readme
- save time
- save variable arguments (health etc)
- timer resource