summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortroido <troido@protonmail.com>2020-01-31 00:51:48 +0100
committertroido <troido@protonmail.com>2020-01-31 00:51:48 +0100
commit5e414fb932eee5aa90d2181cada3c6cd32e4ec09 (patch)
tree8d9fd198525e0c52fcd43e03215d3a377d84d97c
parent286be37225b5de1fb438db0a4029fd391b35c13e (diff)
systems can create entities (sort of)
-rw-r--r--src/assemblages.rs54
-rw-r--r--src/components.rs11
-rw-r--r--src/controls.rs12
-rw-r--r--src/gameserver.rs10
-rw-r--r--src/main.rs22
-rw-r--r--src/resources.rs13
-rw-r--r--src/room.rs54
-rw-r--r--src/systems.rs41
8 files changed, 128 insertions, 89 deletions
diff --git a/src/assemblages.rs b/src/assemblages.rs
index d56e0f3..61833b4 100644
--- a/src/assemblages.rs
+++ b/src/assemblages.rs
@@ -6,9 +6,29 @@ use specs::{
EntityBuilder
};
-use super::components::{Visible, Blocking};
-
-
+use super::components::{Visible, Blocking, Played};
+
+macro_rules! assemblage {
+ ($name:ident { $($arg:ident : $argt:ident ),* } ; $( $comp:expr ),* ) => {
+ #[derive(Debug, Clone)]
+ pub struct $name {$(
+ pub $arg : $argt
+ )* }
+ impl Assemblage for $name {
+ fn build<'a>(&self, mut builder: EntityBuilder<'a>) -> EntityBuilder<'a>{
+ $(
+ let $arg = &self.$arg;
+ )*
+ $(
+ builder = builder.with($comp);
+ )*
+ builder
+ }
+ }
+ unsafe impl Send for $name {}
+ unsafe impl Sync for $name {}
+ }
+}
pub trait Assemblage {
@@ -17,17 +37,9 @@ pub trait Assemblage {
-pub struct Wall;
-
-impl Assemblage for Wall {
- fn build<'a>(&self, builder: EntityBuilder<'a>) -> EntityBuilder<'a>{
- builder.with(Visible{sprite: "wall".to_string(), height: 2.0}).with(Blocking)
- }
-}
+assemblage!(Wall {}; Visible{sprite: "wall".to_string(), height: 2.0}, Blocking);
-pub struct Grass {
- sprite: String
-}
+assemblage!(Grass { sprite : String}; Visible{sprite: sprite.to_string(), height: 0.1});
impl Grass {
pub fn new() -> Grass {
@@ -37,25 +49,11 @@ impl Grass {
}
}
-impl Assemblage for Grass {
- fn build<'a>(&self, builder: EntityBuilder<'a>) -> EntityBuilder<'a>{
- builder.with(Visible{sprite: self.sprite.to_string(), height: 0.1})
- }
-}
-
-pub struct Player {
- name: String
-}
+assemblage!(Player {name: String}; Visible{sprite: "player".to_string(), height: 1.0}, Played{name: name.to_string()});
impl Player {
pub fn new(name: &str) -> Player {
Player { name: name.to_string()}
}
}
-
-impl Assemblage for Player {
- fn build<'a>(&self, builder: EntityBuilder<'a>) -> EntityBuilder<'a>{
- builder.with(Visible{sprite: "player".to_string(), height: 1.0})
- }
-}
diff --git a/src/components.rs b/src/components.rs
index c72ba61..aae6453 100644
--- a/src/components.rs
+++ b/src/components.rs
@@ -2,7 +2,7 @@
use std::ops;
use specs::{
- VecStorage,
+ DenseVecStorage,
Component
};
@@ -11,7 +11,6 @@ use super::util::clamp;
#[derive(Component, Debug, Hash, PartialEq, Eq, Clone, Copy)]
-#[storage(VecStorage)]
pub struct Position {
pub x: i32,
pub y: i32
@@ -43,16 +42,18 @@ impl Position {
}
#[derive(Component, Debug, Clone)]
-#[storage(VecStorage)]
pub struct Visible {
pub sprite: String,
pub height: f32
}
#[derive(Component, Debug)]
-#[storage(VecStorage)]
pub struct Controller(pub Control);
#[derive(Component, Debug)]
-#[storage(VecStorage)]
pub struct Blocking;
+
+#[derive(Component, Debug)]
+pub struct Played {
+ pub name: String
+}
diff --git a/src/controls.rs b/src/controls.rs
index 6ba7539..5cf6d4f 100644
--- a/src/controls.rs
+++ b/src/controls.rs
@@ -3,7 +3,7 @@
use serde_json::Value;
use super::components::Position;
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub enum Direction {
North,
South,
@@ -39,7 +39,7 @@ impl Direction {
}
}
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub enum Control {
Move(Direction),
Take(u64)
@@ -63,3 +63,11 @@ impl Control {
} else {None}
}
}
+
+#[derive(Debug, Clone)]
+pub enum Action {
+ Join(String),
+ Leave(String),
+ Input(String, Control)
+}
+
diff --git a/src/gameserver.rs b/src/gameserver.rs
index 1124c49..ce4a1e5 100644
--- a/src/gameserver.rs
+++ b/src/gameserver.rs
@@ -3,11 +3,9 @@
use std::collections::HashMap;
use std::io;
-
-
use serde_json::{Value, json};
-use super::controls::Control;
+use super::controls::{Control, Action};
use super::server::Server;
@@ -19,12 +17,6 @@ enum Message {
Invalid(String)
}
-#[derive(Debug)]
-pub enum Action {
- Join(String),
- Leave(String),
- Input(String, Control)
-}
pub struct GameServer {
players: HashMap<(usize, usize), String>,
diff --git a/src/main.rs b/src/main.rs
index 9b313be..abf6039 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -14,7 +14,7 @@ pub mod components;
pub mod resources;
pub mod systems;
-use self::gameserver::{GameServer, Action};
+use self::gameserver::GameServer;
use self::server::unixserver::UnixServer;
use self::server::tcpserver::TcpServer;
use self::server::Server;
@@ -37,19 +37,14 @@ fn main() {
let mut gameserver = GameServer::new(servers);
- let mut room = room::Room::new((32, 32));
+ let mut room = room::Room::new((50, 50));
gen_room(&mut room);
loop {
let actions = gameserver.update();
- for action in actions {
- match action {
- Action::Join(name) => {room.add_player(&name, &Player::new(&name));}
- Action::Leave(name) => {room.remove_player(&name);}
- Action::Input(name, control) => {room.control(name, control);}
- }
- }
+
+ room.set_input(actions);
room.update();
let (field, mapping) = room.view();
let updatemsg = create_update_message(room.get_size(), field, mapping);
@@ -61,13 +56,14 @@ fn main() {
fn gen_room(room: &mut room::Room){
let (width, height) = room.get_size();
+ let wall = Wall{};
for x in 0..width {
- room.add_obj(&Wall, (x, 0));
- room.add_obj(&Wall, (x, height - 1));
+ room.add_obj(&wall, (x, 0));
+ room.add_obj(&wall, (x, height - 1));
}
for y in 1..height-1 {
- room.add_obj(&Wall, (0, y));
- room.add_obj(&Wall, (width - 1, y));
+ room.add_obj(&wall, (0, y));
+ room.add_obj(&wall, (width - 1, y));
}
for x in 1..width-1 {
for y in 1..height-1 {
diff --git a/src/resources.rs b/src/resources.rs
index 3834d8f..0e32423 100644
--- a/src/resources.rs
+++ b/src/resources.rs
@@ -3,6 +3,14 @@ use std::collections::HashMap;
use specs::Entity;
use super::components::{Position, Visible};
+use super::controls::Action;
+use super::assemblages::Assemblage;
+
+
+#[derive(Default)]
+pub struct Input {
+ pub actions: Vec<Action>
+}
#[derive(Default)]
pub struct Size {
@@ -20,3 +28,8 @@ pub struct TopView {
pub struct Floor {
pub cells: HashMap<Position, Vec<Entity>>
}
+
+#[derive(Default)]
+pub struct NewEntities {
+ pub assemblages: Vec<(Position, Box<dyn Assemblage + Send + Sync>)>
+}
diff --git a/src/room.rs b/src/room.rs
index de179aa..fdb7006 100644
--- a/src/room.rs
+++ b/src/room.rs
@@ -1,5 +1,5 @@
-use std::collections::HashMap;
+
use specs::{
World,
WorldExt,
@@ -9,24 +9,28 @@ use specs::{
Entity
};
-use super::controls::Control;
-use super::components::{Position, Controller};
+use super::controls::Action;
+use super::components::Position;
use super::assemblages::Assemblage;
-use super::resources::{Size, TopView};
+use super::resources::{
+ Size,
+ TopView,
+ Input,
+ NewEntities
+};
use super::systems::{
Draw,
Move,
ClearControllers,
- MakeFloor
+ MakeFloor,
+ ControlInput
};
pub struct Room<'a, 'b> {
world: World,
- dispatcher: Dispatcher<'a, 'b>,
- spawn: (i32, i32),
- players: HashMap<String, Entity>
+ dispatcher: Dispatcher<'a, 'b>
}
impl <'a, 'b>Room<'a, 'b> {
@@ -35,10 +39,12 @@ impl <'a, 'b>Room<'a, 'b> {
let (width, height) = size;
let mut world = World::new();
world.insert(Size{width, height});
+ world.insert(Input{actions: Vec::new()});
let mut dispatcher = DispatcherBuilder::new()
+ .with(ControlInput, "controlinput", &[])
.with(MakeFloor, "makefloor", &[])
- .with(Move, "move", &["makefloor"])
+ .with(Move, "move", &["makefloor", "controlinput"])
.with(Draw, "draw", &["move"])
.with(ClearControllers, "clearcontrollers", &["move"])
.build();
@@ -47,9 +53,7 @@ impl <'a, 'b>Room<'a, 'b> {
Room {
world,
- dispatcher,
- spawn: (width / 2, height / 2),
- players: HashMap::new()
+ dispatcher
}
}
@@ -83,6 +87,11 @@ impl <'a, 'b>Room<'a, 'b> {
pub fn update(&mut self) {
self.dispatcher.dispatch(&mut self.world);
+ let assemblages = self.world.remove::<NewEntities>().unwrap_or(NewEntities{assemblages: Vec::new()}).assemblages;
+ self.world.insert(NewEntities{assemblages: Vec::new()});
+ for (pos, assemblage) in assemblages{
+ assemblage.build(self.world.create_entity()).with(pos).build();
+ }
self.world.maintain();
}
@@ -91,25 +100,12 @@ impl <'a, 'b>Room<'a, 'b> {
(width, height)
}
- pub fn add_obj(&mut self, template: &dyn Assemblage, (x, y): (i32, i32)) -> Entity {
- template.build(self.world.create_entity()).with(Position{x, y}).build()
- }
-
- pub fn add_player(&mut self, name: &str, template: &dyn Assemblage) {
- let ent = self.add_obj(template, self.spawn);
- self.players.insert(name.to_string(), ent);
- }
-
- pub fn remove_player(&mut self, name: &str){
- // todo: proper error handling
- let ent = self.players.remove(name).expect("unknown player name");
- self.world.delete_entity(ent).expect("player in world does not have entity");
+ pub fn set_input(&mut self, actions: Vec<Action>){
+ self.world.fetch_mut::<Input>().actions = actions;
}
- pub fn control(&mut self, name: String, control: Control){
- if let Some(ent) = self.players.get(&name){
- let _ = self.world.write_component::<Controller>().insert(*ent, Controller(control));
- }
+ pub fn add_obj(&mut self, template: &dyn Assemblage, (x, y): (i32, i32)) -> Entity {
+ template.build(self.world.create_entity()).with(Position{x, y}).build()
}
}
diff --git a/src/systems.rs b/src/systems.rs
index 4988434..ac19b45 100644
--- a/src/systems.rs
+++ b/src/systems.rs
@@ -1,4 +1,6 @@
+use std::collections::{HashMap, HashSet};
+
use specs::{
ReadStorage,
WriteStorage,
@@ -13,17 +15,25 @@ use super::components::{
Position,
Visible,
Controller,
- Blocking
+ Blocking,
+ Played
};
-use super::controls::Control;
+use super::controls::{
+ Control,
+ Action
+};
use super::resources::{
TopView,
Size,
- Floor
+ Floor,
+ Input,
+ NewEntities
};
+use super::assemblages::Player;
+
pub struct MakeFloor;
impl <'a> System<'a> for MakeFloor {
@@ -76,6 +86,31 @@ impl <'a> System<'a> for Move {
}
+pub struct ControlInput;
+impl <'a> System<'a> for ControlInput {
+ type SystemData = (Entities<'a>, Read<'a, Input>, WriteStorage<'a, Controller>, ReadStorage<'a, Played>, Write<'a, NewEntities>);
+ fn run(&mut self, (entities, input, mut controllers, players, mut new): Self::SystemData) {
+ let mut playercontrols: HashMap<&str, Control> = HashMap::new();
+ let mut leaving = HashSet::new();
+ for action in &input.actions {
+ match action {
+ Action::Join(name) => {new.assemblages.push((Position{x:10, y:10}, Box::new(Player::new(&name))));}
+ Action::Leave(name) => {leaving.insert(name);}
+ Action::Input(name, control) => {playercontrols.insert(name, control.clone());}
+ }
+ }
+ for (player, entity) in (&players, &entities).join() {
+ if let Some(control) = playercontrols.get(player.name.as_str()){
+ let _ = controllers.insert(entity, Controller(control.clone()));
+ }
+ if leaving.contains(&player.name) {
+ let _ = entities.delete(entity);
+ }
+ }
+ }
+}
+
+
pub struct ClearControllers;
impl <'a> System<'a> for ClearControllers {
type SystemData = (Entities<'a>, WriteStorage<'a, Controller>);