use std::collections::HashMap; use serde_json::{Value, json}; use serde::Serialize; use crate::util::ToJson; 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>, )* } 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 mut updates: Vec = Vec::new(); $( if let Some(update) = &self.$name { updates.push(json!([$strname, update])); } )* json!(["world", updates]) } } } } worldmessages!( field, FieldMessage, "field"; pos, Pos, "playerpos"; change, ChangeMessage, "changecells"; inventory, InventoryMessage, "inventory"; health, HealthMessage, "health"; ground, GroundMessage, "ground"; ); pub type ChangeMessage = Vec<(Pos, Vec)>; pub type HealthMessage = (i64, i64); pub type InventoryMessage = Vec; pub type GroundMessage = Vec; #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize)] pub struct FieldMessage { pub width: i64, pub height: i64, pub field: Vec, pub mapping: Vec> } #[derive(Debug, Clone, Default)] pub struct MessageCache { pub cache: HashMap } 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()); } } }