diff options
| -rw-r--r-- | src/components/mod.rs | 5 | ||||
| -rw-r--r-- | src/componentwrapper.rs | 4 | ||||
| -rw-r--r-- | src/defaultencyclopedia.rs | 11 | ||||
| -rw-r--r-- | src/main.rs | 1 | ||||
| -rw-r--r-- | src/playerstate.rs | 6 | ||||
| -rw-r--r-- | src/purgatory.rs | 65 | ||||
| -rw-r--r-- | src/room.rs | 110 | ||||
| -rw-r--r-- | src/roomtemplate.rs | 1 | ||||
| -rw-r--r-- | src/systems/attacking.rs | 10 | ||||
| -rw-r--r-- | src/systems/die.rs | 40 | ||||
| -rw-r--r-- | src/systems/mod.rs | 4 | ||||
| -rw-r--r-- | src/world.rs | 12 |
12 files changed, 204 insertions, 65 deletions
diff --git a/src/components/mod.rs b/src/components/mod.rs index 2759144..8c0e6c6 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -135,7 +135,7 @@ pub struct Entered; #[derive(Default, Component, Debug, Clone)] #[storage(NullStorage)] -pub struct Dying; +pub struct Dead; #[derive(Component, Debug, Clone)] #[storage(HashMapStorage)] @@ -194,5 +194,8 @@ pub struct Home { pub home: Pos } +#[derive(Component, Debug, Clone, Default)] +pub struct Mortal; + diff --git a/src/componentwrapper.rs b/src/componentwrapper.rs index 29bf39d..c553f61 100644 --- a/src/componentwrapper.rs +++ b/src/componentwrapper.rs @@ -24,7 +24,8 @@ use crate::{ Volatile, AttackMessage, Autofight, - MonsterAI + MonsterAI, + Mortal }, parameter::{Parameter, ParameterType} }; @@ -138,6 +139,7 @@ components!( Volatile (delay: Int) {Volatile{delay, end_time: None}}; Autofight () {Autofight::default()}; MonsterAI (move_chance: Float, homesickness: Float, view_distance: Int) {MonsterAI{move_chance, homesickness, view_distance}}; + Mortal () {Mortal}; ); diff --git a/src/defaultencyclopedia.rs b/src/defaultencyclopedia.rs index 0234c54..252174d 100644 --- a/src/defaultencyclopedia.rs +++ b/src/defaultencyclopedia.rs @@ -122,7 +122,8 @@ pub fn default_encyclopedia() -> Encyclopedia { "arguments": [["health", "int", 100]], "components": [ "Blocking", - ["Health", {"health": ["arg", "health"], "maxhealth": ["int", 100]}] + ["Health", {"health": ["arg", "health"], "maxhealth": ["int", 100]}], + "Mortal" ], "sprite": "wall", "height": 2 @@ -136,7 +137,10 @@ pub fn default_encyclopedia() -> Encyclopedia { "arguments": [["health", "int", 20]], "sprite": "dummy", "height": 1, - "components": [["Health", {"health": ["arg", "health"], "maxhealth": ["int", 20]}]] + "components": [ + ["Health", {"health": ["arg", "health"], "maxhealth": ["int", 20]}], + "Mortal" + ] }, "wound": { "sprite": "wound", @@ -154,7 +158,8 @@ pub fn default_encyclopedia() -> Encyclopedia { }], ["Health", {"health": ["int", 8], "maxhealth": ["int", 8]}], ["Fighter", {"damage": ["int", 2], "cooldown": ["int", 6]}], - ["Movable", {"cooldown": ["int", 3]}] + ["Movable", {"cooldown": ["int", 3]}], + "Mortal" ] } })).unwrap() diff --git a/src/main.rs b/src/main.rs index 480fc64..5ee6183 100644 --- a/src/main.rs +++ b/src/main.rs @@ -34,6 +34,7 @@ mod worldloader; mod world; mod sprite; mod timestamp; +mod purgatory; pub use self::{ pos::Pos, diff --git a/src/playerstate.rs b/src/playerstate.rs index 629d36f..dc4594b 100644 --- a/src/playerstate.rs +++ b/src/playerstate.rs @@ -108,6 +108,12 @@ impl PlayerState { }) } + pub fn respawn(&mut self) { + self.room = None; + self.pos = RoomPos::Unknown; + self.health = self.maximum_health; + } + pub fn construct(&self, encyclopedia: &Encyclopedia) -> PreEntity { vec![ ComponentWrapper::Visible(Visible{sprite: Sprite{name: "player".to_string()}, height: 1.2, name: self.id.name.clone()}), diff --git a/src/purgatory.rs b/src/purgatory.rs new file mode 100644 index 0000000..df7f3e9 --- /dev/null +++ b/src/purgatory.rs @@ -0,0 +1,65 @@ + +use serde_json::json; +use specs::{ + DispatcherBuilder +}; + +use crate::{ + RoomId, + defaultencyclopedia::default_encyclopedia, + room::Room, + roomtemplate::RoomTemplate, + systems::{ + Move, + RegisterNew, + ControlInput, + View, + Remove, + Create, + Volate, + UpdateCooldowns, + ControlAI, + } +}; + +pub fn purgatory_id() -> RoomId { + RoomId{name: String::from("+")} +} + +pub fn create_purgatory<'a, 'b>() -> Room<'a, 'b> { + let dispatcher = DispatcherBuilder::new() + .with(Volate, "volate", &[]) + .with(RegisterNew::default(), "registernew", &[]) + .with(UpdateCooldowns, "cool_down", &["registernew"]) + .with(ControlInput, "controlinput", &["cool_down"]) + .with(ControlAI, "controlai", &["cool_down"]) + .with(Move, "move", &["controlinput", "controlai"]) + .with(View::default(), "view", &["move", "volate"]) + .with(Create, "create", &["view"]) + .with(Remove, "remove", &["view", "move"]) + .build(); + let mut room = Room::new(purgatory_id(), default_encyclopedia(), dispatcher); + room.load_from_template(&RoomTemplate::from_json(&json!({ + "width": 11, + "height": 11, + "spawn": [5, 5], + "field": [ + " +++ ", + " +++++++ ", + " +++++++++ ", + " +++++++++ ", + "+++++++++++", + "+++++++++++", + "+++++++++++", + " +++++++++ ", + " +++++++++ ", + " +++++++ ", + " +++ ", + ], + "mapping": { + " ": [], + "+": ["floor"] + } + })).unwrap()); + room +} diff --git a/src/room.rs b/src/room.rs index 03ee9db..52621ac 100644 --- a/src/room.rs +++ b/src/room.rs @@ -24,24 +24,6 @@ use crate::{ Emigration, TimeStamp }, - systems::{ - Move, - RegisterNew, - ControlInput, - View, - Remove, - Create, - Take, - Migrate, - Use, - Attacking, - Trapping, - Fight, - Heal, - Volate, - UpdateCooldowns, - ControlAI - }, components::{ Position, Serialise, @@ -61,10 +43,49 @@ use crate::{ RoomId, aerr, Result, - Timestamp + Timestamp, + systems::{ + Move, + RegisterNew, + ControlInput, + View, + Remove, + Create, + Take, + Migrate, + Use, + Attacking, + Trapping, + Fight, + Heal, + Volate, + UpdateCooldowns, + ControlAI, + Die + } }; - +pub fn default_dispatcher<'a, 'b>() -> Dispatcher<'a, 'b> { + DispatcherBuilder::new() + .with(Volate, "volate", &[]) + .with(RegisterNew::default(), "registernew", &[]) + .with(UpdateCooldowns, "cool_down", &["registernew"]) + .with(ControlInput, "controlinput", &["cool_down"]) + .with(ControlAI, "controlai", &["cool_down"]) + .with(Take, "take", &["controlinput", "controlai"]) + .with(Use, "use", &["controlinput", "controlai"]) + .with(Move, "move", &["controlinput", "controlai"]) + .with(Trapping, "trapping", &["move"]) + .with(Fight, "fight", &["move"]) + .with(Heal, "heal", &["registernew"]) + .with(Attacking, "attacking", &["use", "trapping", "fight", "heal"]) + .with(Die, "die", &["attacking"]) + .with(View::default(), "view", &["move", "attacking", "volate", "die"]) + .with(Migrate, "migrate", &["view"]) + .with(Create, "create", &["view"]) + .with(Remove, "remove", &["view", "move"]) + .build() +} pub struct Room<'a, 'b> { world: World, @@ -73,37 +94,28 @@ pub struct Room<'a, 'b> { places: HashMap<String, Pos> } +macro_rules! register_insert { + ($world: expr, ($($comp: ident),*), ($($res: ident),*)) => { + $( + $world.register::<crate::components::$comp>(); + )* + $( + $world.insert(crate::resources::$res::default()); + )* + } +} + + impl <'a, 'b>Room<'a, 'b> { - pub fn new(id: RoomId, encyclopedia: Encyclopedia) -> Room<'a, 'b> { + pub fn new(id: RoomId, encyclopedia: Encyclopedia, dispatcher: Dispatcher<'a, 'b>) -> Room<'a, 'b> { let mut world = World::new(); world.insert(NewEntities::new(encyclopedia)); - world.insert(Players::default()); - world.insert(Spawn::default()); - world.insert(Emigration::default()); - world.register::<Serialise>(); - - let mut dispatcher = DispatcherBuilder::new() - .with(Volate, "volate", &[]) - .with(RegisterNew::default(), "registernew", &[]) - .with(UpdateCooldowns, "cool_down", &["registernew"]) - .with(ControlInput, "controlinput", &["cool_down"]) - .with(ControlAI, "controlai", &["cool_down"]) - .with(Take, "take", &["controlinput", "controlai"]) - .with(Use, "use", &["controlinput", "controlai"]) - .with(Move, "move", &["controlinput", "controlai"]) - .with(Trapping, "trapping", &["move"]) - .with(Fight, "fight", &["move"]) - .with(Heal, "heal", &["registernew"]) - .with(Attacking, "attacking", &["use", "trapping", "fight", "heal"]) - .with(View::default(), "view", &["move", "attacking", "volate"]) - .with(Migrate, "migrate", &["view"]) - .with(Create, "create", &["view"]) - .with(Remove, "remove", &["view", "move"]) - .build(); - - dispatcher.setup(&mut world); - + register_insert!( + world, + (Position, Visible, Controller, Movable, Blocking, Floor, New, Removed, Moved, Player, Inventory, Health, Serialise, RoomExit, Entered, Dead, Trap, Fighter, Healing, Volatile, ControlCooldown, Autofight, MonsterAI, Home, Mortal, AttackInbox, Item), + (Ground, Input, Output, Size, Spawn, Players, Emigration, TimeStamp) + ); Room { world, @@ -136,7 +148,7 @@ impl <'a, 'b>Room<'a, 'b> { pub fn create(id: RoomId, encyclopedia: &Encyclopedia, template: &RoomTemplate) -> Room<'a, 'b> { - let mut room = Self::new(id, encyclopedia.clone()); + let mut room = Self::new(id, encyclopedia.clone(), default_dispatcher()); room.load_from_template(template); room } @@ -239,7 +251,7 @@ impl <'a, 'b>Room<'a, 'b> { } pub fn emigrate(&mut self) -> Vec<(PlayerId, RoomId, RoomPos)> { - let emigrants = self.world.remove::<Emigration>().expect("World does not have Emigrating resource").emigrants; + let emigrants = self.world.remove::<Emigration>().expect("World does not have Emigration resource").emigrants; self.world.insert(Emigration::default()); emigrants } diff --git a/src/roomtemplate.rs b/src/roomtemplate.rs index 2a778a7..b5834e9 100644 --- a/src/roomtemplate.rs +++ b/src/roomtemplate.rs @@ -8,6 +8,7 @@ use crate::{ aerr }; +#[derive(Debug, Clone)] pub struct RoomTemplate { pub size: (i64, i64), pub spawn: Pos, diff --git a/src/systems/attacking.rs b/src/systems/attacking.rs index d28e301..6075bd5 100644 --- a/src/systems/attacking.rs +++ b/src/systems/attacking.rs @@ -9,7 +9,7 @@ use specs::{ }; use crate::{ - components::{Health, AttackInbox, Dying, Removed, Position}, + components::{Health, AttackInbox, Dead, Position}, resources::NewEntities, Template, util @@ -22,12 +22,11 @@ impl <'a> System<'a> for Attacking { Entities<'a>, WriteStorage<'a, AttackInbox>, WriteStorage<'a, Health>, - WriteStorage<'a, Dying>, - WriteStorage<'a, Removed>, + WriteStorage<'a, Dead>, ReadStorage<'a, Position>, Write<'a, NewEntities> ); - fn run(&mut self, (entities, mut attackeds, mut healths, mut deads, mut removals, positions, mut new): Self::SystemData) { + fn run(&mut self, (entities, mut attackeds, mut healths, mut deads, positions, mut new): Self::SystemData) { for (ent, health, attacked) in (&entities, &mut healths, &mut attackeds).join() { let mut wounded = false; for attack in attacked.messages.drain(..) { @@ -38,8 +37,7 @@ impl <'a> System<'a> for Attacking { } health.health = util::clamp(health.health, 0, health.maxhealth); if health.health == 0 { - deads.insert(ent, Dying).unwrap(); - removals.insert(ent, Removed).unwrap(); + deads.insert(ent, Dead).unwrap(); } if let Some(position) = positions.get(ent){ if wounded { diff --git a/src/systems/die.rs b/src/systems/die.rs new file mode 100644 index 0000000..fd953e0 --- /dev/null +++ b/src/systems/die.rs @@ -0,0 +1,40 @@ + +use specs::{ + Write, + WriteStorage, + ReadStorage, + Entities, + System, + Join +}; + +use crate::{ + components::{Mortal, Dead, Removed, Player}, + resources::Emigration, + purgatory, + playerstate::RoomPos +}; + + +pub struct Die; +impl <'a> System<'a> for Die { + type SystemData = ( + Entities<'a>, + ReadStorage<'a, Mortal>, + ReadStorage<'a, Dead>, + WriteStorage<'a, Removed>, + Write<'a, Emigration>, + ReadStorage<'a, Player> + ); + fn run(&mut self, (entities, mortals, deads, mut removeds, mut emigration, players): Self::SystemData) { + // npcs etc get removed when dead + for (entity, _, _) in (&entities, &mortals, &deads).join() { + removeds.insert(entity, Removed).unwrap(); + } + // players move to purgatory when dead + for (player, _) in (&players, &deads).join() { + emigration.emigrants.push((player.id.clone(), purgatory::purgatory_id(), RoomPos::Unknown)); + } + } +} + diff --git a/src/systems/mod.rs b/src/systems/mod.rs index 221ffc4..f4b3edb 100644 --- a/src/systems/mod.rs +++ b/src/systems/mod.rs @@ -15,6 +15,7 @@ mod heal; mod volate; mod updatecooldowns; mod controlai; +mod die; pub use self::{ controlinput::ControlInput, @@ -32,5 +33,6 @@ pub use self::{ heal::Heal, volate::Volate, updatecooldowns::UpdateCooldowns, - controlai::ControlAI + controlai::ControlAI, + die::Die }; diff --git a/src/world.rs b/src/world.rs index 4152889..87dafb8 100644 --- a/src/world.rs +++ b/src/world.rs @@ -1,5 +1,6 @@ use std::collections::HashMap; +use crate::hashmap; use crate::{ PlayerId, @@ -13,7 +14,8 @@ use crate::{ Result, aerr, worldmessages::WorldMessage, - Timestamp + Timestamp, + purgatory }; pub struct World<'a, 'b> { @@ -26,7 +28,6 @@ pub struct World<'a, 'b> { time: Timestamp } - impl <'a, 'b>World<'a, 'b> { pub fn new(encyclopedia: Encyclopedia, template_loader: WorldLoader, persistence: Box<dyn PersistentStorage>, default_room: RoomId) -> Self { @@ -36,7 +37,7 @@ impl <'a, 'b>World<'a, 'b> { default_room, encyclopedia, players: HashMap::new(), - rooms: HashMap::new(), + rooms: hashmap!(purgatory::purgatory_id() => purgatory::create_purgatory()), time: Timestamp(0) } } @@ -66,11 +67,14 @@ impl <'a, 'b>World<'a, 'b> { } pub fn add_player(&mut self, playerid: &PlayerId) -> Result<()> { - let state = self.persistence + let mut state = self.persistence .load_player(playerid.clone()) .unwrap_or_else(|_err| // todo: what if player exists but can't be loaded for another reason? PlayerState::new(playerid.clone()) ); + if state.room == Some(purgatory::purgatory_id()){ + state.respawn(); + } self.add_loaded_player(state) } |
