summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main.rs9
-rw-r--r--src/sprite.rs2
-rw-r--r--src/systems/view.rs26
-rw-r--r--src/worldmessages.rs103
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());
+ }
+ }
+}
+