diff options
| author | troido <troido@protonmail.com> | 2020-01-31 00:51:48 +0100 |
|---|---|---|
| committer | troido <troido@protonmail.com> | 2020-01-31 00:51:48 +0100 |
| commit | 5e414fb932eee5aa90d2181cada3c6cd32e4ec09 (patch) | |
| tree | 8d9fd198525e0c52fcd43e03215d3a377d84d97c | |
| parent | 286be37225b5de1fb438db0a4029fd391b35c13e (diff) | |
systems can create entities (sort of)
| -rw-r--r-- | src/assemblages.rs | 54 | ||||
| -rw-r--r-- | src/components.rs | 11 | ||||
| -rw-r--r-- | src/controls.rs | 12 | ||||
| -rw-r--r-- | src/gameserver.rs | 10 | ||||
| -rw-r--r-- | src/main.rs | 22 | ||||
| -rw-r--r-- | src/resources.rs | 13 | ||||
| -rw-r--r-- | src/room.rs | 54 | ||||
| -rw-r--r-- | src/systems.rs | 41 |
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>); |
