diff options
| author | troido <troido@protonmail.com> | 2020-03-09 16:54:26 +0100 |
|---|---|---|
| committer | troido <troido@protonmail.com> | 2020-03-09 16:54:26 +0100 |
| commit | 69ac6eb6153b016c39bbe55c85f15e3478032182 (patch) | |
| tree | 31a0a5cf3d768688c7600902364446d55e3f4395 | |
| parent | a1f45d1b40b23cb7e9f0b277f24ad66880b0bc56 (diff) | |
can now include variables (like health) in serialisation
| -rw-r--r-- | content/encyclopediae/default_encyclopedia.json | 3 | ||||
| -rw-r--r-- | src/assemblage.rs | 26 | ||||
| -rw-r--r-- | src/components/mod.rs | 7 | ||||
| -rw-r--r-- | src/components/serialise.rs | 16 | ||||
| -rw-r--r-- | src/componentwrapper.rs | 13 | ||||
| -rw-r--r-- | src/room.rs | 14 | ||||
| -rw-r--r-- | todo.md | 1 |
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 } @@ -1,6 +1,7 @@ # TODO +- make readme - save time - save variable arguments (health etc) - timer resource |
