summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/components/mod.rs5
-rw-r--r--src/componentwrapper.rs4
-rw-r--r--src/defaultencyclopedia.rs11
-rw-r--r--src/main.rs1
-rw-r--r--src/playerstate.rs6
-rw-r--r--src/purgatory.rs65
-rw-r--r--src/room.rs110
-rw-r--r--src/roomtemplate.rs1
-rw-r--r--src/systems/attacking.rs10
-rw-r--r--src/systems/die.rs40
-rw-r--r--src/systems/mod.rs4
-rw-r--r--src/world.rs12
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)
}