diff options
Diffstat (limited to 'src/systems/view.rs')
| -rw-r--r-- | src/systems/view.rs | 96 |
1 files changed, 65 insertions, 31 deletions
diff --git a/src/systems/view.rs b/src/systems/view.rs index 209b1a5..b854348 100644 --- a/src/systems/view.rs +++ b/src/systems/view.rs @@ -1,8 +1,14 @@ -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use specs::{ + BitSet, + storage::ComponentEvent, + ReaderId, + World, + SystemData, ReadStorage, + WriteStorage, Read, Write, System, @@ -10,39 +16,29 @@ use specs::{ }; use super::super::pos::Pos; - -use super::super::components::{ - Visible, - Played -}; - -use super::super::resources::{ - Size, - Output -}; - -use super::super::worldmessages::{ - WorldMessage, - WorldUpdate, - FieldMessage -}; +use super::super::components::{Visible, Played, Position}; +use super::super::resources::{Size, Output}; +use super::super::worldmessages::{WorldMessage, WorldUpdate, FieldMessage}; +#[derive(Default)] +pub struct View { + reader_id: Option<ReaderId<ComponentEvent>>, + dirty: BitSet +} -pub struct View; impl <'a> System<'a> for View { - type SystemData = (ReadStorage<'a, Pos>, ReadStorage<'a, Visible>, Read<'a, Size>, ReadStorage<'a, Played>, Write<'a, Output>); - fn run(&mut self, (positions, visible, size, players, mut output): Self::SystemData) { - + type SystemData = (ReadStorage<'a, Position>, ReadStorage<'a, Visible>, Read<'a, Size>, WriteStorage<'a, Played>, Write<'a, Output>); + fn run(&mut self, (positions, visible, size, mut players, mut output): Self::SystemData) { let mut cells: HashMap<Pos, Vec<Visible>> = HashMap::new(); for (pos, vis) in (&positions, &visible).join(){ - cells.entry(*pos).or_insert(Vec::new()).push(vis.clone()); - cells.get_mut(pos).unwrap().sort_by(|a, b| b.height.partial_cmp(&a.height).unwrap()); + 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 width = size.width; let height = size.height; - let (values, mapping) = draw_room(cells, (width, height)); + let (values, mapping) = draw_room(cells.clone(), (width, height)); let field = WorldUpdate::Field(FieldMessage{ width, @@ -50,19 +46,57 @@ impl <'a> System<'a> for View { field: values, mapping }); + + + self.dirty.clear(); + { + let events = positions.channel().read(self.reader_id.as_mut().unwrap()); + for event in events { + match event { + ComponentEvent::Modified(id) | ComponentEvent::Inserted(id) | ComponentEvent::Removed(id) => { + self.dirty.add(*id); + } + }; + } + } + let mut changed: HashSet<Pos> = HashSet::new(); + for (pos, _) in (&positions, &self.dirty).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().iter().map(|v| v.sprite.clone()).collect())); + } + let changed_msg = WorldUpdate::Change(changes); + + output.output.clear(); - for (player, pos) in (&players, &positions).join() { - - let message = WorldMessage{updates: vec![ - field.clone(), - WorldUpdate::Pos(*pos) - ]}; + for (mut player, pos) in (&mut players, &positions).join() { + let mut updates: Vec<WorldUpdate> = Vec::new(); + if player.is_new { + updates.push(field.clone()); + } 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.reader_id = Some( + WriteStorage::<Position>::fetch(&world).register_reader() + ); + } } - fn draw_room(cells: HashMap<Pos, Vec<Visible>>, (width, height): (i32, i32)) -> (Vec<usize>, Vec<Vec<String>>){ let size = width * height; |
