diff options
| -rw-r--r-- | src/main.rs | 9 | ||||
| -rw-r--r-- | src/sprite.rs | 2 | ||||
| -rw-r--r-- | src/systems/view.rs | 26 | ||||
| -rw-r--r-- | src/worldmessages.rs | 103 |
4 files changed, 95 insertions, 45 deletions
diff --git a/src/main.rs b/src/main.rs index b0ffb77..21b6b71 100644 --- a/src/main.rs +++ b/src/main.rs @@ -48,6 +48,7 @@ use self::persistence::FileStorage; use crate::controls::Action; use crate::worldloader::WorldLoader; use crate::world::World; +use crate::worldmessages::MessageCache; @@ -74,6 +75,7 @@ fn main() -> Result<()>{ println!("asciifarm started"); + let mut message_cache = MessageCache::default(); let mut count = 0; loop { @@ -96,7 +98,12 @@ fn main() -> Result<()>{ world.save(); } let messages = world.view(); - for (player, message) in messages { + for (player, mut message) in messages { + message_cache.trim(&player, &mut message); + if message.is_empty(){ + continue; + } + println!("{}: {}", player.name, message.to_json()); let _ = gameserver.send(&player, message.to_json()); } diff --git a/src/sprite.rs b/src/sprite.rs index d6f40ca..0e08b86 100644 --- a/src/sprite.rs +++ b/src/sprite.rs @@ -1,7 +1,7 @@ use serde::{Serialize, Serializer}; -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Hash, Eq)] pub struct Sprite { pub name: String } diff --git a/src/systems/view.rs b/src/systems/view.rs index f82ae0a..6e53eb1 100644 --- a/src/systems/view.rs +++ b/src/systems/view.rs @@ -14,7 +14,7 @@ use specs::{ use crate::{Pos, Sprite}; use crate::components::{Visible, Player, Position, Inventory, New, Moved, Removed, Health}; use crate::resources::{Size, Output, Ground}; -use crate::worldmessages::{WorldMessage, WorldUpdate, FieldMessage}; +use crate::worldmessages::{WorldMessage, FieldMessage}; #[derive(Default)] @@ -55,34 +55,32 @@ impl <'a> System<'a> for View { for pos in changed { changes.push((pos, cell_sprites(ground.cells.get(&pos).unwrap_or(&HashSet::new()), &visible))); } - let changed_msg = WorldUpdate::Change(changes); - - output.output.clear(); for (ent, player, pos) in (&entities, &players, &positions).join() { - let mut updates: Vec<WorldUpdate> = Vec::new(); + let mut updates = WorldMessage::default(); if new.get(ent).is_some() { let (values, mapping) = draw_room(&ground.cells, (size.width, size.height), &visible); - let field = WorldUpdate::Field(FieldMessage{ + let field = FieldMessage{ width: size.width, height: size.height, field: values, mapping - }); - updates.push(field); + }; + updates.field = Some(field); } else if has_changed { - updates.push(changed_msg.clone()); + updates.change = Some(changes.clone()); } if let Some(inventory) = inventories.get(ent){ - updates.push(WorldUpdate::Inventory(inventory.items.iter().map(|item| item.name.clone()).collect())); + updates.inventory = Some(inventory.items.iter().map(|item| item.name.clone()).collect()); } if let Some(health) = healths.get(ent){ - updates.push(WorldUpdate::Health(health.health, health.maxhealth)); + updates.health = Some((health.health, health.maxhealth)); + } + updates.pos = Some(pos.pos); + if !updates.is_empty() { + output.output.insert(player.id.clone(), updates); } - updates.push(WorldUpdate::Pos(pos.pos)); - let message = WorldMessage{updates}; - output.output.insert(player.id.clone(), message); } } } diff --git a/src/worldmessages.rs b/src/worldmessages.rs index 2e80763..1efe477 100644 --- a/src/worldmessages.rs +++ b/src/worldmessages.rs @@ -1,44 +1,72 @@ +use std::collections::HashMap; use serde_json::{Value, json}; use serde::Serialize; use crate::util::ToJson; -use crate::{Pos, Sprite}; +use crate::{Pos, Sprite, PlayerId}; +macro_rules! worldmessages { + ($($name: ident, $typ: ident, $strname: expr);*;) => { + + #[derive(Debug, Clone, Default, PartialEq, Eq)] + pub struct WorldMessage { + $( + pub $name: Option<$typ>, + )* + } -#[derive(Debug, Clone)] -pub struct WorldMessage { - pub updates: Vec<WorldUpdate> -} + impl WorldMessage { + + pub fn remove_old(&mut self, previous: &WorldMessage){ + $( + if self.$name == previous.$name { + self.$name = None; + } + )* + } + + pub fn add(&mut self, other: &WorldMessage){ + $( + if other.$name.is_some() { + self.$name = other.$name.clone(); + } + )* + } + + pub fn is_empty(&self) -> bool { + true $( && self.$name.is_none())* + } + } -impl ToJson for WorldMessage { - fn to_json(&self) -> Value { - let updates: Vec<Value> = self.updates.iter().map(|u| u.to_json()).collect(); - json!(["world", updates]) + impl ToJson for WorldMessage { + fn to_json(&self) -> Value { + let mut updates: Vec<Value> = Vec::new(); + $( + if let Some(update) = &self.$name { + updates.push(json!([$strname, update])); + } + )* + json!(["world", updates]) + } + } } } -#[derive(Debug, Clone)] -pub enum WorldUpdate { - Field(FieldMessage), - Pos(Pos), - Change(Vec<(Pos, Vec<Sprite>)>), - Inventory(Vec<String>), - Health(i64, i64) -} +worldmessages!( + field, FieldMessage, "field"; + pos, Pos, "playerpos"; + change, ChangeMessage, "changecells"; + inventory, InventoryMessage, "inventory"; + health, HealthMessage, "health"; +); -impl ToJson for WorldUpdate { - fn to_json(&self) -> Value { - match self { - WorldUpdate::Field(msg) => json!(["field", msg]), - WorldUpdate::Pos(pos) => json!(["playerpos", pos]), - WorldUpdate::Change(changes) => json!(["changecells", changes]), - WorldUpdate::Inventory(items) => json!(["inventory", items]), - WorldUpdate::Health(health, maxhealth) => json!(["health", [health, maxhealth]]) - } - } -} -#[derive(Debug, Clone, Serialize)] +pub type ChangeMessage = Vec<(Pos, Vec<Sprite>)>; +pub type HealthMessage = (i64, i64); +pub type InventoryMessage = Vec<String>; + + +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize)] pub struct FieldMessage { pub width: i64, pub height: i64, @@ -46,5 +74,22 @@ pub struct FieldMessage { pub mapping: Vec<Vec<Sprite>> } +#[derive(Debug, Clone, Default)] +pub struct MessageCache { + pub cache: HashMap<PlayerId, WorldMessage> +} + +impl MessageCache { + + pub fn trim(&mut self, player: &PlayerId, msg: &mut WorldMessage){ + if let Some(cached) = self.cache.get_mut(player){ + msg.remove_old(cached); + cached.add(&msg); + } else { + self.cache.insert(player.clone(), msg.clone()); + } + } +} + |
