From 624b3a94b498d7410049d2227568534c118a9f7d Mon Sep 17 00:00:00 2001 From: troido Date: Sun, 9 Feb 2020 00:38:00 +0100 Subject: ground is now always up-to-date; view doesn't rebuild whole room --- src/systems/makefloor.rs | 7 --- src/systems/moving.rs | 10 +++-- src/systems/remove.rs | 16 ++++--- src/systems/view.rs | 110 +++++++++++++++++++++-------------------------- 4 files changed, 66 insertions(+), 77 deletions(-) (limited to 'src/systems') 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>, - vis_reader_id: Option>, - 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> = 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 = 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)> = 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 = 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::::fetch(&world).register_reader() - ); - self.vis_reader_id = Some( - WriteStorage::::fetch(&world).register_reader() - ); - } } -fn draw_room(cells: HashMap>, (width, height): (i64, i64)) -> (Vec, Vec>){ +fn cell_sprites(entities: &HashSet, visible: &ReadStorage) -> Vec { + 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>, (width, height): (i64, i64), visible: &ReadStorage) -> (Vec, Vec>){ let size = width * height; let mut values :Vec = Vec::with_capacity(size as usize); let mut mapping: Vec> = Vec::new(); for y in 0..height { for x in 0..width { - let sprites: Vec = match cells.get(&Pos{x: x, y: y}) { - Some(sprites) => {sprites.iter().map(|v| v.sprite.clone()).collect()} + let sprites: Vec = match ground.get(&Pos{x: x, y: y}) { + Some(ents) => {cell_sprites(ents, visible)} None => {vec![]} }; values.push( -- cgit