diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/assemblage.rs | 5 | ||||
| -rw-r--r-- | src/components/mod.rs | 12 | ||||
| -rw-r--r-- | src/componentwrapper.rs | 6 | ||||
| -rw-r--r-- | src/encyclopedia.rs | 70 | ||||
| -rw-r--r-- | src/parameter.rs | 2 | ||||
| -rw-r--r-- | src/playerstate.rs | 5 | ||||
| -rw-r--r-- | src/room.rs | 10 | ||||
| -rw-r--r-- | src/systems/mod.rs | 6 | ||||
| -rw-r--r-- | src/systems/replace.rs | 46 | ||||
| -rw-r--r-- | src/systems/spawntrigger.rs | 34 | ||||
| -rw-r--r-- | src/template.rs | 14 |
11 files changed, 134 insertions, 76 deletions
diff --git a/src/assemblage.rs b/src/assemblage.rs index 2ef62f0..96e44e9 100644 --- a/src/assemblage.rs +++ b/src/assemblage.rs @@ -58,7 +58,7 @@ impl Assemblage { .as_str().ok_or(perr!("component name not a string"))?; let comptype = ComponentType::from_str(name).ok_or(perr!("{} not a valid componenttype", name))?; let mut parameters: HashMap<String, ComponentParameter> = HashMap::new(); - for (key, value) in tup.get(1).ok_or(perr!("index 1 not in component"))?.as_object().ok_or(perr!("component parameters not a json object"))? { + for (key, value) in tup.get(1).ok_or(perr!("index 1 not in component"))?.as_object().ok_or(perr!("component parameters not a json object: {:?}", tup.get(1)))? { let param = ComponentParameter::from_json(value)?; parameters.insert(key.clone(), param); } @@ -100,6 +100,9 @@ impl Assemblage { }])); } + if let Some(substitute) = val.get("substitute") { + components.push(json!(["Substitute", {"into": ["template", substitute]}])); + } Ok(components) } diff --git a/src/components/mod.rs b/src/components/mod.rs index 394284a..ee5176e 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -253,3 +253,15 @@ pub struct Minable { pub total: i64, pub trigger: Trigger } + +#[derive(Component, Debug, Clone)] +pub struct OnSpawn { + pub trigger: Trigger +} + + +#[derive(Component, Debug, Clone)] +pub struct Substitute { + pub into: Template +} + diff --git a/src/componentwrapper.rs b/src/componentwrapper.rs index 392c0dc..ee2f22f 100644 --- a/src/componentwrapper.rs +++ b/src/componentwrapper.rs @@ -293,6 +293,12 @@ components!(all: }; Removed; LootHolder () {panic!("LootHolder from parameters not implemented")}; + OnSpawn (trigger: String) { + OnSpawn { + trigger: Trigger::from_str(&trigger).ok_or(aerr!("invalid trigger name {}", trigger))? + } + }; + Substitute (into: Template); ); diff --git a/src/encyclopedia.rs b/src/encyclopedia.rs index ba9ad94..54fa82b 100644 --- a/src/encyclopedia.rs +++ b/src/encyclopedia.rs @@ -19,9 +19,7 @@ use crate::{ #[derive(Default, Clone)] pub struct Encyclopedia { assemblages: HashMap<EntityType, Assemblage>, - items: HashMap<ItemId, Item>, - assemblage_substitute: HashMap<EntityType, EntityType>, - item_substitute: HashMap<ItemId, ItemId>, + items: HashMap<ItemId, Item> } impl Encyclopedia { @@ -93,7 +91,7 @@ impl Encyclopedia { .as_str().ok_or(perr!("subtitution origin name not a string"))? .to_string()); let values = v.get(1).ok_or(perr!("index 0 not in subtitution template"))?; - let mut assemblage = assemblages.get(&enttype).ok_or(perr!("template name '{:?}' points not an assemblage", enttype))?.clone(); + let mut assemblage = assemblages.get(&enttype).ok_or(perr!("template name '{:?}' does not point to not an assemblage", enttype))?.clone(); for arg in assemblage.arguments.iter_mut() { if let Some(x) = values.get(&arg.0) { let param = Parameter::from_typed_json(arg.1, x).ok_or(perr!("subtitution parameter has wrong type"))?; @@ -103,51 +101,11 @@ impl Encyclopedia { assemblages.insert(EntityType(name.to_string()), assemblage); } - let assemblage_substitute = val - .get("assemblage_substitute") - .unwrap_or(&json!({})) - .as_object().ok_or(perr!("assemblage_subtitute not a json dict"))? - .iter() - .chain( - val - .get("substitute") - .unwrap_or(&json!({})) - .as_object().ok_or(perr!("substitute not a json dict"))? - .iter() - ) - .map(|(from, into)| { - Ok(( - EntityType(from.to_string()), - EntityType(into.as_str().ok_or(perr!("substitution value not a string: {:?}", into))?.to_string()) - )) - }) - .collect::<PResult<HashMap<EntityType, EntityType>>>()?; - - let item_substitute = val - .get("item_substitute") - .unwrap_or(&json!({})) - .as_object().ok_or(perr!("item_subtitute not a json dict"))? - .iter() - .chain( - val - .get("substitute") - .unwrap_or(&json!({})) - .as_object().ok_or(perr!("substitute not a json dict"))? - .iter() - ) - .map(|(from, into)| { - Ok(( - ItemId(from.to_string()), - ItemId(into.as_str().ok_or(perr!("substitution value not a string: {:?}", into))?.to_string()) - )) - }) - .collect::<PResult<HashMap<ItemId, ItemId>>>()?; Ok(Encyclopedia{ assemblages, - items, - assemblage_substitute, - item_substitute + items }) + } pub fn validate(&self) -> Result<()> { @@ -158,11 +116,6 @@ impl Encyclopedia { } pub fn construct(&self, template: &Template) -> Result<PreEntity> { - if let Some(new_name) = self.assemblage_substitute.get(&template.name){ - let mut into = template.clone(); - into.name = new_name.clone(); - return self.construct(&into); - } let assemblage = self.assemblages .get(&template.name) .ok_or(aerr!("unknown assemblage name: '{:?}' in {:?}", template.name, template))?; @@ -170,20 +123,7 @@ impl Encyclopedia { } pub fn get_item(&self, id: &ItemId) -> Option<Item> { - let actual_id = if let Some(into) = self.item_substitute.get(id) { - into - } else { - id - }; - self.items.get(actual_id).map(|item| item.clone()) - } - - pub fn substitute_item(&self, id: &ItemId) -> ItemId { - if let Some(into) = self.item_substitute.get(id) { - into.clone() - } else { - id.clone() - } + self.items.get(id).map(|item| item.clone()) } } diff --git a/src/parameter.rs b/src/parameter.rs index 196f5fe..01a7f40 100644 --- a/src/parameter.rs +++ b/src/parameter.rs @@ -67,7 +67,7 @@ parameters!( Int (i64) int, v (v.as_i64()?) (json!(v)); Pos (Pos) pos, v (Pos::from_json(v)?) (json!(v)); Float (f64) float, v (v.as_f64()?) (json!(v)); - Template (Template) template, v (Template::from_json(v).ok()?) (v.to_json()); + Template (Template) template, v (Template::from_json(v).ok()?) (json!(["template", v.to_json()])); Interaction (Interactable) interaction, _v (Interactable::from_json(_v)?) (panic!("interactions can't be serialized")); Bool (bool) bool, v (v.as_bool()?) (json!(v)); List (Vec<Parameter>) list, v diff --git a/src/playerstate.rs b/src/playerstate.rs index 778fc7f..f9f6a4e 100644 --- a/src/playerstate.rs +++ b/src/playerstate.rs @@ -164,9 +164,8 @@ impl PlayerState { ComponentWrapper::Player(Player::new(self.id.clone())), ComponentWrapper::Inventory(Inventory{ items: self.inventory.iter().map( |(itemid, is_equipped)| { - let id = encyclopedia.substitute_item(itemid); - let item = encyclopedia.get_item(&id).ok_or(aerr!("failed to load item '{:?} in inventory of player {:?}", itemid, self))?; - Ok(InventoryEntry{itemid: id, item, is_equipped: *is_equipped}) + let item = encyclopedia.get_item(&itemid).ok_or(aerr!("failed to load item '{:?} in inventory of player {:?}", itemid, self))?; + Ok(InventoryEntry{itemid: itemid.clone(), item, is_equipped: *is_equipped}) }).collect::<Result<Vec<InventoryEntry>>>()?, capacity: self.inventory_capacity }), diff --git a/src/room.rs b/src/room.rs index 9583a93..d0f22df 100644 --- a/src/room.rs +++ b/src/room.rs @@ -67,13 +67,16 @@ use crate::{ Timeout, Clear, Building, - Deduplicate + Deduplicate, + SpawnTrigger, + Replace } }; pub fn default_dispatcher<'a, 'b>() -> Dispatcher<'a, 'b> { DispatcherBuilder::new() .with(Deduplicate, "deduplicate", &[]) + .with(Replace, "replace", &[]) .with(Timeout, "timeout", &[]) .with(UpdateCooldowns, "cool_down", &[]) .with(Spawn, "spawn", &[]) @@ -82,11 +85,12 @@ pub fn default_dispatcher<'a, 'b>() -> Dispatcher<'a, 'b> { .with(Take, "take", &["controlinput", "controlai"]) .with(Use, "use", &["controlinput", "controlai"]) .with(Interact, "interact", &["controlinput", "controlai"]) + .with(SpawnTrigger, "spawntrigger", &["spawn", "deduplicate", "replace"]) .with(Move, "move", &["controlinput", "controlai"]) .with(Trapping, "trapping", &["move"]) .with(Fight, "fight", &["move"]) .with(Heal, "heal", &[]) - .with(Attacking, "attacking", &["use", "trapping", "fight", "heal", "interact"]) + .with(Attacking, "attacking", &["use", "trapping", "fight", "heal", "interact", "spawntrigger"]) .with(Die, "die", &["attacking"]) .with(DropLoot, "droploot", &["attacking"]) .with(Building, "building", &["attacking"]) @@ -120,7 +124,7 @@ impl <'a, 'b>Room<'a, 'b> { world.insert(NewEntities::new(encyclopedia)); register_insert!( world, - (Position, Visible, Controller, Movable, New, Removed, Moved, Player, Inventory, Health, Serialise, RoomExit, Entered, TriggerBox, Trap, Fighter, Healing, ControlCooldown, Autofight, MonsterAI, Home, AttackInbox, Item, Spawner, Clan, Faction, Interactable, Loot, Timer, Equipment, TimeOffset, Flags, Ear, Build, Whitelist, Dedup, Minable, LootHolder), + (Position, Visible, Controller, Movable, New, Removed, Moved, Player, Inventory, Health, Serialise, RoomExit, Entered, TriggerBox, Trap, Fighter, Healing, ControlCooldown, Autofight, MonsterAI, Home, AttackInbox, Item, Spawner, Clan, Faction, Interactable, Loot, Timer, Equipment, TimeOffset, Flags, Ear, Build, Whitelist, Dedup, Minable, LootHolder, OnSpawn, Substitute), (Ground, Input, Output, Size, Spawn, Players, Emigration, Time) ); diff --git a/src/systems/mod.rs b/src/systems/mod.rs index 024f54f..7323dee 100644 --- a/src/systems/mod.rs +++ b/src/systems/mod.rs @@ -22,6 +22,8 @@ mod timeout; mod clear; mod building; mod deduplicate; +mod spawntrigger; +mod replace; pub use self::{ controlinput::ControlInput, @@ -46,5 +48,7 @@ pub use self::{ timeout::Timeout, clear::Clear, building::Building, - deduplicate::Deduplicate + deduplicate::Deduplicate, + spawntrigger::SpawnTrigger, + replace::Replace }; diff --git a/src/systems/replace.rs b/src/systems/replace.rs new file mode 100644 index 0000000..4ed516b --- /dev/null +++ b/src/systems/replace.rs @@ -0,0 +1,46 @@ + +use specs::{ + ReadStorage, + System, + Join, + Write, + WriteStorage, + Entities +}; + +use crate::{ + components::{ + Position, + Substitute, + Removed, + Serialise + }, + resources::{NewEntities} +}; + + +pub struct Replace; +impl <'a> System<'a> for Replace { + type SystemData = ( + Entities<'a>, + ReadStorage<'a, Position>, + Write<'a, NewEntities>, + ReadStorage<'a, Substitute>, + WriteStorage<'a, Removed>, + ReadStorage<'a, Serialise> + ); + + fn run(&mut self, (entities, positions, mut new, substitutes, mut removeds, serialisations): Self::SystemData) { + for (entity, position, substitute, serialisation) in (&entities, &positions, &substitutes, (&serialisations).maybe()).join(){ + // todo: better error handling + let mut template = substitute.into.clone(); + if let Some(serialise) = serialisation { + // todo: extraction? + template = template.merge(serialise.template.clone()); + } + let preent = new.encyclopedia.construct(&template).unwrap(); + new.to_build.push((position.pos, preent)); + removeds.insert(entity, Removed).unwrap(); + } + } +} diff --git a/src/systems/spawntrigger.rs b/src/systems/spawntrigger.rs new file mode 100644 index 0000000..95e95a8 --- /dev/null +++ b/src/systems/spawntrigger.rs @@ -0,0 +1,34 @@ + + +use specs::{ + WriteStorage, + ReadStorage, + Entities, + System, + Join +}; + +use crate::{ + components::{ + TriggerBox, + OnSpawn, + New + } +}; + + +pub struct SpawnTrigger; +impl <'a> System<'a> for SpawnTrigger { + type SystemData = ( + Entities<'a>, + WriteStorage<'a, TriggerBox>, + ReadStorage<'a, OnSpawn>, + ReadStorage<'a, New> + ); + + fn run(&mut self, (entities, mut triggerboxes, onspawns, news): Self::SystemData) { + for (entity, onspawn, _new) in (&entities, &onspawns, &news).join(){ + TriggerBox::add_message(&mut triggerboxes, entity, onspawn.trigger); + } + } +} diff --git a/src/template.rs b/src/template.rs index 6b2dec3..0ac03cd 100644 --- a/src/template.rs +++ b/src/template.rs @@ -12,7 +12,7 @@ use crate::{ pub struct EntityType(pub String); #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] -enum SaveOption { +pub enum SaveOption { Default, False, Always @@ -23,7 +23,7 @@ pub struct Template { pub name: EntityType, pub args: Vec<Parameter>, pub kwargs: HashMap<String, Parameter>, - save: SaveOption, + pub save: SaveOption, } @@ -65,6 +65,16 @@ impl Template { self } + pub fn merge(mut self, other: Template) -> Self { + if self.save == SaveOption::Default { + self.save = other.save; + } + for (key, value) in other.kwargs { + self.kwargs.entry(key).or_insert(value); + } + self + } + pub fn from_json(v: &Value) -> PResult<Template> { let val = match v { Value::String(s) => json!({"type": s}), |
