diff options
| -rw-r--r-- | src/components.rs | 11 | ||||
| -rw-r--r-- | src/componentwrapper.rs | 13 | ||||
| -rw-r--r-- | src/encyclopedia.rs | 12 | ||||
| -rw-r--r-- | src/main.rs | 7 | ||||
| -rw-r--r-- | src/parameter.rs | 2 | ||||
| -rw-r--r-- | src/resources.rs | 8 | ||||
| -rw-r--r-- | src/room.rs | 50 | ||||
| -rw-r--r-- | src/systems/controlinput.rs | 26 | ||||
| -rw-r--r-- | src/systems/create.rs | 51 | ||||
| -rw-r--r-- | src/systems/makefloor.rs | 35 | ||||
| -rw-r--r-- | src/systems/mod.rs | 4 | ||||
| -rw-r--r-- | src/systems/moving.rs | 24 | ||||
| -rw-r--r-- | src/systems/remove.rs | 27 | ||||
| -rw-r--r-- | src/systems/view.rs | 6 |
14 files changed, 198 insertions, 78 deletions
diff --git a/src/components.rs b/src/components.rs index 34dbe97..5bd6ddd 100644 --- a/src/components.rs +++ b/src/components.rs @@ -45,6 +45,17 @@ pub struct Blocking; pub struct Floor; #[derive(Component, Debug, Clone)] +pub struct New; + +#[derive(Component, Debug, Clone)] +pub struct Removed; + +#[derive(Component, Debug, Clone)] +pub struct Moved { + pub from: Pos +} + +#[derive(Component, Debug, Clone)] #[storage(HashMapStorage)] pub struct Player { pub name: String, diff --git a/src/componentwrapper.rs b/src/componentwrapper.rs index 8bf8552..e821b8b 100644 --- a/src/componentwrapper.rs +++ b/src/componentwrapper.rs @@ -1,9 +1,8 @@ use std::collections::HashMap; -use specs::{Builder, EntityBuilder}; +use specs::{Builder, world::LazyBuilder}; use crate::components::{Visible, Blocking, Player, Floor}; -use crate::hashmap; use crate::parameter::{Parameter, ParameterType}; @@ -20,7 +19,7 @@ macro_rules! components { impl ComponentWrapper { - pub fn build<'a>(&self, builder: EntityBuilder<'a>) -> EntityBuilder<'a> { + pub fn build<'a>(&self, builder: LazyBuilder<'a>) -> LazyBuilder<'a> { match self.clone() { $( Self::$comp(c) => builder.with(c), @@ -28,11 +27,12 @@ macro_rules! components { } } - pub fn load_component(comptype: ComponentType, mut parameters_: HashMap<&str, Parameter>) -> Option<Self> { + pub fn load_component(comptype: ComponentType, parameters_: HashMap<&str, Parameter>) -> Option<Self> { match comptype { $( ComponentType::$comp => Some(Self::$comp({ + #[allow(unused_mut)] let mut $paramlist = parameters_; $creation })), @@ -63,6 +63,7 @@ macro_rules! components { match self { $( Self::$comp => { + #[allow(unused_mut)] let mut h = HashMap::new(); $( h.insert(stringify!($paramname), ParameterType::$paramtype); @@ -82,8 +83,8 @@ components!( height: parameters.remove("height")?.as_f64()? } }; - Blocking [] p {Blocking}; - Floor [] p {Floor}; + Blocking [] _p {Blocking}; + Floor [] _p {Floor}; Player [name: String] parameters {Player::new(parameters.remove("name")?.as_string()?)} ); diff --git a/src/encyclopedia.rs b/src/encyclopedia.rs index 19d4297..5cdf90c 100644 --- a/src/encyclopedia.rs +++ b/src/encyclopedia.rs @@ -12,12 +12,6 @@ pub struct Encyclopedia { impl Encyclopedia { - pub fn new() -> Encyclopedia { - Encyclopedia { - items: HashMap::new() - } - } - pub fn from_json(val: Value) -> Result<Encyclopedia, &'static str> { let mut items = HashMap::new(); for (k, v) in val.as_object().ok_or("encyclopedia not a json object")?.into_iter() { @@ -26,12 +20,6 @@ impl Encyclopedia { Ok(Encyclopedia{items}) } - pub fn add_assemblage(&mut self, name: &str, assemblage: Assemblage) -> Result<(), &'static str> { - //todo: what if name exists - self.items.insert(name.to_string(), assemblage); - Ok(()) - } - pub fn construct(&self, template: &Template) -> Result<Vec<ComponentWrapper>, &'static str> { let assemblage = self.items.get(&template.name).ok_or("unknown assemblage name")?; assemblage.instantiate(&template.args, &template.kwargs) diff --git a/src/main.rs b/src/main.rs index 65d744a..d2cfd13 100644 --- a/src/main.rs +++ b/src/main.rs @@ -38,20 +38,23 @@ use self::roomtemplate::RoomTemplate; fn main() { + let mut servers: Vec<Box<dyn Server>> = Vec::new(); let addr = Path::new("\0rustifarm"); let unixserver = UnixServer::new(&addr).expect("binding unix server failed"); + servers.push(Box::new(unixserver)); let addr = "127.0.0.1:1234".parse().unwrap(); let inetserver = TcpServer::new(&addr).expect("binding inet server failed"); + servers.push(Box::new(inetserver)); - - let servers: Vec<Box<dyn Server>> = vec![Box::new(unixserver), Box::new(inetserver)]; let mut gameserver = GameServer::new(servers); let mut room = gen_room(); + println!("asciifarm started"); + loop { let actions = gameserver.update(); diff --git a/src/parameter.rs b/src/parameter.rs index 6d15e93..41137bb 100644 --- a/src/parameter.rs +++ b/src/parameter.rs @@ -11,6 +11,7 @@ pub enum Parameter { impl Parameter { + #[allow(dead_code)] pub fn string(string: &str) -> Self { Self::String(string.to_string()) } @@ -58,6 +59,7 @@ impl Parameter { Some(self.as_str()?.to_string()) } + #[allow(dead_code)] pub fn as_i64(&self) -> Option<i64> { if let Self::Int(num) = self { Some(*num) diff --git a/src/resources.rs b/src/resources.rs index bda745f..15d93c4 100644 --- a/src/resources.rs +++ b/src/resources.rs @@ -1,5 +1,5 @@ -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use specs::Entity; use super::pos::Pos; @@ -7,6 +7,7 @@ use super::controls::Action; // use super::oldassemblage::Assemblage; use super::worldmessages::WorldMessage; use super::template::Template; +use crate::encyclopedia::Encyclopedia; #[derive(Default)] @@ -32,10 +33,11 @@ pub struct Spawn { #[derive(Default)] pub struct Ground { - pub cells: HashMap<Pos, Vec<Entity>> + pub cells: HashMap<Pos, HashSet<Entity>> } #[derive(Default)] pub struct NewEntities { - pub templates: Vec<(Pos, Template)> + pub templates: Vec<(Pos, Template)>, + pub encyclopedia: Encyclopedia } diff --git a/src/room.rs b/src/room.rs index dc7c849..84a1040 100644 --- a/src/room.rs +++ b/src/room.rs @@ -4,15 +4,12 @@ use std::collections::HashMap; use specs::{ World, WorldExt, - Builder, DispatcherBuilder, - Dispatcher, - Entity + Dispatcher }; use super::controls::Action; use super::pos::Pos; -use super::components::Position; use super::worldmessages::WorldMessage; use super::resources::{ Size, @@ -23,35 +20,38 @@ use super::resources::{ }; use super::systems::{ moving::Move, - clearcontrols::ClearControllers, makefloor::MakeFloor, controlinput::ControlInput, - view::View + view::View, + remove::Remove, + create::Create }; -use super::componentwrapper::ComponentWrapper; use crate::encyclopedia::Encyclopedia; -use crate::template::Template; use crate::roomtemplate::RoomTemplate; pub struct Room<'a, 'b> { world: World, - dispatcher: Dispatcher<'a, 'b>, - encyclopedia: Encyclopedia + dispatcher: Dispatcher<'a, 'b> } impl <'a, 'b>Room<'a, 'b> { pub fn new(encyclopedia: Encyclopedia) -> Room<'a, 'b> { let mut world = World::new(); + world.insert(NewEntities{ + templates: Vec::new(), + encyclopedia + }); let mut dispatcher = DispatcherBuilder::new() .with(ControlInput, "controlinput", &[]) - .with(MakeFloor, "makefloor", &[]) + .with(MakeFloor::default(), "makefloor", &[]) .with(Move, "move", &["makefloor", "controlinput"]) - .with(ClearControllers, "clearcontrollers", &["move"]) .with(View::default(), "view", &["move"]) + .with(Create, "create", &["view", "controlinput"]) + .with(Remove, "remove", &["view", "move"]) .build(); dispatcher.setup(&mut world); @@ -59,8 +59,7 @@ impl <'a, 'b>Room<'a, 'b> { Room { world, - dispatcher, - encyclopedia + dispatcher } } @@ -77,9 +76,7 @@ impl <'a, 'b>Room<'a, 'b> { let y = (idx as i64) / width; for template in templates { - if let Err(msg) = self.add_entity(template, Pos{x, y}){ - println!("{}", msg); - } + self.world.fetch_mut::<NewEntities>().templates.push((Pos{x, y}, template.clone())); } } } @@ -90,13 +87,6 @@ impl <'a, 'b>Room<'a, 'b> { pub fn update(&mut self) { self.dispatcher.dispatch(&mut self.world); - let templates = self.world.remove::<NewEntities>().unwrap_or(NewEntities::default()).templates; - self.world.insert(NewEntities::default()); - for (pos, template) in templates{ - if let Err(msg) = self.add_entity(&template, pos){ - println!("failed to add entity {:?}: {}", template, msg); - } - } self.world.maintain(); } @@ -104,18 +94,6 @@ impl <'a, 'b>Room<'a, 'b> { self.world.fetch_mut::<Input>().actions = actions; } - pub fn add_entity(&mut self, template: &Template, pos: Pos) -> Result<Entity, &'static str> { - let preentity = self.encyclopedia.construct(template)?; - Ok(self.add_complist(&preentity, pos)) - } -// - pub fn add_complist(&mut self, template: &Vec<ComponentWrapper>, pos: Pos) -> Entity{ - let mut builder = self.world.create_entity(); - for comp in template { - builder = comp.build(builder); - } - builder.with(Position::new(pos)).build() - } } diff --git a/src/systems/controlinput.rs b/src/systems/controlinput.rs index 27ef5cf..0771b1e 100644 --- a/src/systems/controlinput.rs +++ b/src/systems/controlinput.rs @@ -11,7 +11,7 @@ use specs::{ Join }; -use crate::components::{Controller, Player}; +use crate::components::{Controller, Player, Removed}; use crate::controls::{Control, Action}; use crate::resources::{Input, NewEntities, Spawn}; use crate::hashmap; @@ -23,8 +23,26 @@ use crate::parameter::Parameter; pub struct ControlInput; impl <'a> System<'a> for ControlInput { - type SystemData = (Entities<'a>, Read<'a, Input>, WriteStorage<'a, Controller>, ReadStorage<'a, Player>, Write<'a, NewEntities>, Read<'a, Spawn>); - fn run(&mut self, (entities, input, mut controllers, players, mut new, spawn): Self::SystemData) { + type SystemData = ( + Entities<'a>, + Read<'a, Input>, + WriteStorage<'a, Controller>, + ReadStorage<'a, Player>, + Write<'a, NewEntities>, + Read<'a, Spawn>, + WriteStorage<'a, Removed> + ); + fn run(&mut self, (entities, input, mut controllers, players, mut new, spawn, mut removed): Self::SystemData) { + { + let mut ents = Vec::new(); + for (ent, _controller) in (&*entities, &controllers).join() { + ents.push(ent); + } + for ent in ents { + controllers.remove(ent); + } + } + let mut playercontrols: HashMap<&str, Control> = HashMap::new(); let mut leaving = HashSet::new(); for action in &input.actions { @@ -44,7 +62,7 @@ impl <'a> System<'a> for ControlInput { let _ = controllers.insert(entity, Controller(control.clone())); } if leaving.contains(&player.name) { - let _ = entities.delete(entity); + let _ = removed.insert(entity, Removed); } } } diff --git a/src/systems/create.rs b/src/systems/create.rs new file mode 100644 index 0000000..35ef747 --- /dev/null +++ b/src/systems/create.rs @@ -0,0 +1,51 @@ + +use specs::{ + Read, + Write, + WriteStorage, + System, + Join, + Entities, + LazyUpdate, + Builder +}; + +use crate::components::{New, Position}; +use crate::resources::{NewEntities}; + + + +pub struct Create; +impl <'a> System<'a> for Create { + type SystemData = ( + Entities<'a>, + Write<'a, NewEntities>, + Read<'a, LazyUpdate>, + WriteStorage<'a, New> + ); + + fn run(&mut self, (entities, mut new_entities, updater, mut new): Self::SystemData) { + { + let mut ents = Vec::new(); + for (ent, _new) in (&entities, &new).join() { + ents.push(ent); + } + for ent in ents { + new.remove(ent); + } + } + for (pos, template) in &new_entities.templates { + let mut builder = updater.create_entity(&entities); + match new_entities.encyclopedia.construct(template) { + Ok(comps) => { + for comp in comps { + builder = comp.build(builder); + } + builder.with(Position::new(*pos)).with(New).build(); + }, + Err(msg) => {println!("{}", msg);} + } + } + new_entities.templates.clear(); + } +} diff --git a/src/systems/makefloor.rs b/src/systems/makefloor.rs index 8b550bc..74e4389 100644 --- a/src/systems/makefloor.rs +++ b/src/systems/makefloor.rs @@ -1,4 +1,5 @@ +use std::collections::HashSet; use specs::{ ReadStorage, @@ -8,20 +9,40 @@ use specs::{ Join }; -use super::super::components::Position; +use crate::components::{ + Position, + New, + Moved, + Removed +}; -use super::super::resources::{ +use crate::resources::{ Ground }; +#[derive(Default)] pub struct MakeFloor; impl <'a> System<'a> for MakeFloor { - type SystemData = (Entities<'a>, Write<'a, Ground>, ReadStorage<'a, Position>); - fn run(&mut self, (entities, mut ground, positions): Self::SystemData) { - ground.cells.clear(); - for (ent, pos) in (&entities, &positions).join() { - ground.cells.entry(pos.pos).or_insert(Vec::new()).push(ent); + type SystemData = ( + Entities<'a>, + Write<'a, Ground>, + ReadStorage<'a, Position>, + ReadStorage<'a, New>, + ReadStorage<'a, Moved>, + ReadStorage<'a, Removed> + ); + fn run(&mut self, (entities, mut ground, positions, new, moved, removed): Self::SystemData) { + for (ent, pos, _new) in (&entities, &positions, &new).join() { + ground.cells.entry(pos.pos).or_insert(HashSet::new()).insert(ent); + } + for (ent, pos, mov) in (&entities, &positions, &moved).join() { + ground.cells.entry(pos.pos).or_insert(HashSet::new()).insert(ent); + ground.cells.get_mut(&mov.from).unwrap().remove(&ent); + } + for (ent, pos, _removed) in (&entities, &positions, &removed).join() { + ground.cells.get_mut(&pos.pos).unwrap().remove(&ent); } } } + diff --git a/src/systems/mod.rs b/src/systems/mod.rs index 0382e39..a4dd473 100644 --- a/src/systems/mod.rs +++ b/src/systems/mod.rs @@ -1,8 +1,10 @@ -pub mod clearcontrols; +// pub mod clearcontrols; pub mod controlinput; pub mod makefloor; pub mod moving; pub mod view; +pub mod remove; +pub mod create; diff --git a/src/systems/moving.rs b/src/systems/moving.rs index 28c3d3f..35f73ea 100644 --- a/src/systems/moving.rs +++ b/src/systems/moving.rs @@ -1,5 +1,8 @@ +use std::collections::HashSet; + use specs::{ + Entities, ReadStorage, WriteStorage, Read, @@ -13,7 +16,8 @@ use super::super::components::{ Controller, Blocking, Position, - Floor + Floor, + Moved }; use super::super::controls::{ @@ -30,22 +34,33 @@ use super::super::resources::{ pub struct Move; impl <'a> System<'a> for Move { type SystemData = ( + Entities<'a>, ReadStorage<'a, Controller>, WriteStorage<'a, Position>, Read<'a, Size>, ReadStorage<'a, Blocking>, Read<'a, Ground>, ReadStorage<'a, Floor>, + WriteStorage<'a, Moved> ); - fn run(&mut self, (controllers, mut positions, size, blocking, ground, floor): Self::SystemData) { - for (controller, mut pos) in (&controllers, &mut positions.restrict_mut()).join(){ + fn run(&mut self, (entities, controllers, mut positions, size, blocking, ground, floor, mut moved): Self::SystemData) { + { + let mut ents = Vec::new(); + for (ent, _moved) in (&*entities, &moved).join() { + ents.push(ent); + } + for ent in ents { + moved.remove(ent); + } + } + for (ent, controller, mut pos) in (&entities, &controllers, &mut positions.restrict_mut()).join(){ match &controller.0 { Control::Move(direction) => { let newpos = (pos.get_unchecked().pos + direction.to_position()).clamp(Pos::new(0, 0), Pos::new(size.width - 1, size.height - 1)); let mut blocked = false; let mut on_floor = false; - for ent in ground.cells.get(&newpos).unwrap_or(&Vec::new()) { + for ent in ground.cells.get(&newpos).unwrap_or(&HashSet::new()) { if blocking.get(*ent).is_some(){ blocked = true; break; @@ -57,6 +72,7 @@ impl <'a> System<'a> for Move { if !blocked && on_floor { let mut pos_mut = pos.get_mut_unchecked(); pos_mut.prev = Some(pos_mut.pos); + moved.insert(ent, Moved{from: pos_mut.pos}).expect("can't insert Moved"); pos_mut.pos = newpos.clone(); } } diff --git a/src/systems/remove.rs b/src/systems/remove.rs new file mode 100644 index 0000000..2c531e2 --- /dev/null +++ b/src/systems/remove.rs @@ -0,0 +1,27 @@ + +use specs::{ + ReadStorage, + System, + Join, + Entities +}; + +use crate::components::{Removed}; + + + +pub struct Remove; +impl <'a> System<'a> for Remove { + type SystemData = ( + Entities<'a>, + ReadStorage<'a, Removed> + ); + + fn run(&mut self, (entities, removals): Self::SystemData) { + for (ent, _) in (&*entities, &removals).join() { + if let Err(msg) = entities.delete(ent){ + println!("{:?}", msg); + } + } + } +} diff --git a/src/systems/view.rs b/src/systems/view.rs index fec5ee7..12b5f78 100644 --- a/src/systems/view.rs +++ b/src/systems/view.rs @@ -16,7 +16,7 @@ use specs::{ }; use super::super::pos::Pos; -use super::super::components::{Visible, Player, Position}; +use super::super::components::{Visible, Player, Position, New}; use super::super::resources::{Size, Output}; use super::super::worldmessages::{WorldMessage, WorldUpdate, FieldMessage}; @@ -29,8 +29,8 @@ pub struct View { } impl <'a> System<'a> for View { - type SystemData = (ReadStorage<'a, Position>, ReadStorage<'a, Visible>, Read<'a, Size>, WriteStorage<'a, Player>, Write<'a, Output>); - fn run(&mut self, (positions, visible, size, mut players, mut output): Self::SystemData) { + type SystemData = (ReadStorage<'a, Position>, ReadStorage<'a, Visible>, Read<'a, Size>, WriteStorage<'a, Player>, Write<'a, Output>, ReadStorage<'a, New>); + fn run(&mut self, (positions, visible, size, mut players, mut output, _new): Self::SystemData) { let mut cells: HashMap<Pos, Vec<Visible>> = HashMap::new(); for (pos, vis) in (&positions, &visible).join(){ |
