diff options
| -rw-r--r-- | src/components.rs | 10 | ||||
| -rw-r--r-- | src/systems/makefloor.rs | 7 | ||||
| -rw-r--r-- | src/systems/moving.rs | 10 | ||||
| -rw-r--r-- | src/systems/remove.rs | 16 | ||||
| -rw-r--r-- | src/systems/view.rs | 110 | ||||
| -rw-r--r-- | src/worldmessages.rs | 6 |
6 files changed, 73 insertions, 86 deletions
diff --git a/src/components.rs b/src/components.rs index 5bd6ddd..277dd01 100644 --- a/src/components.rs +++ b/src/components.rs @@ -13,12 +13,11 @@ use super::pos::Pos; #[derive(Debug, Clone)] pub struct Position{ - pub pos: Pos, - pub prev: Option<Pos> + pub pos: Pos } impl Position { pub fn new(pos: Pos) -> Position { - Position{pos, prev: None} + Position{pos} } } @@ -58,12 +57,11 @@ pub struct Moved { #[derive(Component, Debug, Clone)] #[storage(HashMapStorage)] pub struct Player { - pub name: String, - pub is_new: bool + pub name: String } impl Player { pub fn new(name: String) -> Self { - Self{name, is_new: true} + Self{name} } } diff --git a/src/systems/makefloor.rs b/src/systems/makefloor.rs index 74e4389..689fcec 100644 --- a/src/systems/makefloor.rs +++ b/src/systems/makefloor.rs @@ -36,13 +36,6 @@ impl <'a> System<'a> for MakeFloor { 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/moving.rs b/src/systems/moving.rs index 35f73ea..98b0979 100644 --- a/src/systems/moving.rs +++ b/src/systems/moving.rs @@ -7,7 +7,8 @@ use specs::{ WriteStorage, Read, System, - Join + Join, + Write }; use super::super::pos::Pos; @@ -39,12 +40,12 @@ impl <'a> System<'a> for Move { WriteStorage<'a, Position>, Read<'a, Size>, ReadStorage<'a, Blocking>, - Read<'a, Ground>, + Write<'a, Ground>, ReadStorage<'a, Floor>, WriteStorage<'a, Moved> ); - fn run(&mut self, (entities, controllers, mut positions, size, blocking, ground, floor, mut moved): Self::SystemData) { + fn run(&mut self, (entities, controllers, mut positions, size, blocking, mut ground, floor, mut moved): Self::SystemData) { { let mut ents = Vec::new(); for (ent, _moved) in (&*entities, &moved).join() { @@ -71,9 +72,10 @@ 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"); + ground.cells.get_mut(&pos_mut.pos).unwrap().remove(&ent); pos_mut.pos = newpos.clone(); + ground.cells.entry(newpos).or_insert(HashSet::new()).insert(ent); } } _ => {} diff --git a/src/systems/remove.rs b/src/systems/remove.rs index 2c531e2..b73a2fb 100644 --- a/src/systems/remove.rs +++ b/src/systems/remove.rs @@ -3,25 +3,31 @@ use specs::{ ReadStorage, System, Join, + Write, Entities }; -use crate::components::{Removed}; - +use crate::components::{Removed, Position}; +use crate::resources::Ground; pub struct Remove; impl <'a> System<'a> for Remove { type SystemData = ( Entities<'a>, - ReadStorage<'a, Removed> + ReadStorage<'a, Removed>, + ReadStorage<'a, Position>, + Write<'a, Ground> ); - fn run(&mut self, (entities, removals): Self::SystemData) { - for (ent, _) in (&*entities, &removals).join() { + fn run(&mut self, (entities, removals, positions, mut ground): Self::SystemData) { + for (ent, _) in (&*entities, &removals, ).join() { if let Err(msg) = entities.delete(ent){ println!("{:?}", msg); } + if let Some(position) = positions.get(ent) { + ground.cells.get_mut(&position.pos).unwrap().remove(&ent); + } } } } diff --git a/src/systems/view.rs b/src/systems/view.rs index 12b5f78..79078f4 100644 --- a/src/systems/view.rs +++ b/src/systems/view.rs @@ -12,106 +12,94 @@ use specs::{ Read, Write, System, - Join + Join, + Entities, + Entity }; use super::super::pos::Pos; -use super::super::components::{Visible, Player, Position, New}; -use super::super::resources::{Size, Output}; +use super::super::components::{Visible, Player, Position, New, Moved, Removed}; +use super::super::resources::{Size, Output, Ground}; use super::super::worldmessages::{WorldMessage, WorldUpdate, FieldMessage}; #[derive(Default)] -pub struct View { - pos_reader_id: Option<ReaderId<ComponentEvent>>, - vis_reader_id: Option<ReaderId<ComponentEvent>>, - dirty: BitSet -} +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>, ReadStorage<'a, New>); - fn run(&mut self, (positions, visible, size, mut players, mut output, _new): Self::SystemData) { + type SystemData = ( + Entities<'a>, + ReadStorage<'a, Position>, + ReadStorage<'a, Visible>, + Read<'a, Size>, + WriteStorage<'a, Player>, + Write<'a, Output>, + ReadStorage<'a, New>, + ReadStorage<'a, Moved>, + ReadStorage<'a, Removed>, + Read<'a, Ground> + ); + fn run(&mut self, (entities, positions, visible, size, mut players, mut output, new, moved, removed, ground): Self::SystemData) { - let mut cells: HashMap<Pos, Vec<Visible>> = HashMap::new(); - for (pos, vis) in (&positions, &visible).join(){ - cells.entry(pos.pos).or_insert(Vec::new()).push(vis.clone()); - cells.get_mut(&pos.pos).unwrap().sort_by(|a, b| b.height.partial_cmp(&a.height).unwrap()); + let mut changed = HashSet::new(); + for (pos, _new) in (&positions, &new).join() { + changed.insert(pos.pos); } - let width = size.width; - let height = size.height; - let (values, mapping) = draw_room(cells.clone(), (width, height)); - - let field = WorldUpdate::Field(FieldMessage{ - width, - height, - field: values, - mapping - }); - - - self.dirty.clear(); - { - let pos_events = positions.channel().read(self.pos_reader_id.as_mut().unwrap()); - let vis_events = visible.channel().read(self.vis_reader_id.as_mut().unwrap()); - let events = vec![pos_events, vis_events].into_iter().flatten(); - for event in events { - match event { - ComponentEvent::Modified(id) | ComponentEvent::Inserted(id) | ComponentEvent::Removed(id) => { - self.dirty.add(*id); - } - }; - } + for (pos, mov) in (&positions, &moved).join() { + changed.insert(pos.pos); + changed.insert(mov.from); } - let mut changed: HashSet<Pos> = HashSet::new(); - for (pos, _) in (&positions, &self.dirty).join(){ + for (pos, _removed) in (&positions, &removed).join() { changed.insert(pos.pos); - if let Some(prev) = pos.prev{ - changed.insert(prev); - } } + + let has_changed: bool = changed.len() > 0; let mut changes: Vec<(Pos, Vec<String>)> = Vec::new(); for pos in changed { - changes.push((pos, cells.get(&pos).unwrap_or(&Vec::new()).iter().map(|v| v.sprite.clone()).collect())); + changes.push((pos, cell_sprites(ground.cells.get(&pos).unwrap_or(&HashSet::new()), &visible))); } let changed_msg = WorldUpdate::Change(changes); output.output.clear(); - for (mut player, pos) in (&mut players, &positions).join() { + + for (ent, mut player, pos) in (&entities, &mut players, &positions).join() { let mut updates: Vec<WorldUpdate> = Vec::new(); - if player.is_new { - updates.push(field.clone()); + if new.get(ent).is_some() { + let (values, mapping) = draw_room(&ground.cells, (size.width, size.height), &visible); + let field = WorldUpdate::Field(FieldMessage{ + width: size.width, + height: size.height, + field: values, + mapping + }); + updates.push(field); } else if has_changed { updates.push(changed_msg.clone()); } updates.push(WorldUpdate::Pos(pos.pos)); let message = WorldMessage{updates}; output.output.insert(player.name.clone(), message); - player.is_new = false; } } - - fn setup(&mut self, world: &mut World) { - Self::SystemData::setup(world); - self.pos_reader_id = Some( - WriteStorage::<Position>::fetch(&world).register_reader() - ); - self.vis_reader_id = Some( - WriteStorage::<Visible>::fetch(&world).register_reader() - ); - } } -fn draw_room(cells: HashMap<Pos, Vec<Visible>>, (width, height): (i64, i64)) -> (Vec<usize>, Vec<Vec<String>>){ +fn cell_sprites(entities: &HashSet<Entity>, visible: &ReadStorage<Visible>) -> Vec<String> { + let mut visibles: Vec<&Visible> = entities.iter().filter_map(|ent| visible.get(*ent)).collect(); + visibles.sort_by(|a, b| b.height.partial_cmp(&a.height).unwrap()); + visibles.iter().map(|vis| vis.sprite.clone()).collect() +} + +fn draw_room(ground: &HashMap<Pos, HashSet<Entity>>, (width, height): (i64, i64), visible: &ReadStorage<Visible>) -> (Vec<usize>, Vec<Vec<String>>){ let size = width * height; let mut values :Vec<usize> = Vec::with_capacity(size as usize); let mut mapping: Vec<Vec<String>> = Vec::new(); for y in 0..height { for x in 0..width { - let sprites: Vec<String> = match cells.get(&Pos{x: x, y: y}) { - Some(sprites) => {sprites.iter().map(|v| v.sprite.clone()).collect()} + let sprites: Vec<String> = match ground.get(&Pos{x: x, y: y}) { + Some(ents) => {cell_sprites(ents, visible)} None => {vec![]} }; values.push( diff --git a/src/worldmessages.rs b/src/worldmessages.rs index 79cd400..cbbc2ec 100644 --- a/src/worldmessages.rs +++ b/src/worldmessages.rs @@ -4,7 +4,7 @@ use serde::Serialize; use super::util::ToJson; use super::pos::Pos; -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct WorldMessage { pub updates: Vec<WorldUpdate> } @@ -16,7 +16,7 @@ impl ToJson for WorldMessage { } } -#[derive(Clone)] +#[derive(Debug, Clone)] pub enum WorldUpdate { Field(FieldMessage), Pos(Pos), @@ -33,7 +33,7 @@ impl ToJson for WorldUpdate { } } -#[derive(Clone, Serialize)] +#[derive(Debug, Clone, Serialize)] pub struct FieldMessage { pub width: i64, pub height: i64, |
