chiark / gitweb /
movehost: Send updates.
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Thu, 1 Apr 2021 11:38:26 +0000 (12:38 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Fri, 2 Apr 2021 19:15:32 +0000 (20:15 +0100)
Just a stub to receive them, right now.

Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
base/misc.rs
daemon/cmdlistener.rs
src/gamestate.rs
src/prelude.rs
src/updates.rs
templates/script.ts

index 7ee1c6f58da340e3b088ff073b9eff9c24ae1e52..f7982cdbf910f06ba77973b6e3d64baf691b3f67 100644 (file)
@@ -9,6 +9,15 @@ use crate::prelude::*;
 
 pub const SVG_SCALE: f64 = 6.;
 
+pub const MOVEHIST_LENS: &[usize] = &[ 1, 3, 10, 0];
+pub const MOVEHIST_LEN_MAX: usize = 10;
+
+#[test]
+fn movehist_len_max() { assert_eq!(
+  MOVEHIST_LENS.iter().max(),
+  Some(&MOVEHIST_LEN_MAX),
+) }
+
 pub fn timestring_abbreviate<'x>(base: &str, this: &'x str)
                                  -> (&'x str, bool)
 {
index 52ed8f9d5d0439d01925f67488b5fd81295d1264..4cab0716d324ac400565cfcddb1ac8fe5e37c293 100644 (file)
@@ -383,6 +383,8 @@ fn execute_game_insn<'cs, 'igr, 'ig: 'igr>(
         nick: nick.to_string(),
         layout: arecord.layout,
         idmap: default(),
+        moveheld: default(),
+        movehist: default(),
       };
       let ipl = IPlayer {
         acctid,
index d5b03cbe96e8c7ef30d964b47b976f04a478990b..eef433826b03d3441e016ccef726a0e3114d0868 100644 (file)
@@ -55,6 +55,8 @@ pub struct GPlayer { // usual variable: gpl
   pub nick: String,
   pub layout: PresentationLayout,
   pub idmap: PerPlayerIdMap,
+  #[serde(default)] pub moveheld: SparseSecondaryMap<PieceId, GMoveHistLast>,
+  #[serde(default)] pub movehist: VecDeque<MoveHistEnt>,
 }
 
 #[derive(Debug,Serialize,Deserialize)]
@@ -73,6 +75,25 @@ pub struct GPiece {  // usual variable: gpc
   pub moveable: PieceMoveable,
 }
 
+#[derive(Debug,Copy,Clone,Serialize,Deserialize)]
+pub struct MoveHistPosx { // usual variable: posx
+  pub pos: Pos,
+  pub angle: CompassAngle,
+  pub facehint: Option<FaceId>,
+}
+
+#[derive(Debug,Copy,Clone,Serialize,Deserialize)]
+pub struct GMoveHistLast {
+  pub held: PlayerId,
+  pub posx: MoveHistPosx,
+}
+
+#[derive(Debug,Clone,Serialize,Deserialize)]
+pub struct MoveHistEnt {
+  pub held: PlayerId,
+  pub posx: OldNew<MoveHistPosx>,
+}
+
 pub type PieceXDataState = Option<Box<dyn PieceXData>>;
 
 #[derive(Debug,Serialize,Deserialize)]
index 5d0d64abd228985b281a5236a2f513c4875dfdef..d9a13edd5003db0a3f70a686f05f1176b1f3974b 100644 (file)
@@ -89,7 +89,7 @@ pub use serde::{de::DeserializeOwned, Deserialize, Serialize};
 pub use serde::{Deserializer, Serializer};
 pub use serde_with::DeserializeFromStr;
 pub use serde_with::SerializeDisplay;
-pub use slotmap::{dense::DenseSlotMap, Key as _};
+pub use slotmap::{dense::DenseSlotMap, SparseSecondaryMap, Key as _};
 pub use strum::{EnumString, EnumIter, EnumProperty};
 pub use strum::{IntoEnumIterator, IntoStaticStr};
 pub use thiserror::Error;
index 9a35845e017e23d08b9d10dd989c3106b17ccb48..0e8a97cfe057821593adf42cc981e289717a34fb 100644 (file)
@@ -55,6 +55,7 @@ pub struct PreparedUpdate {
 pub enum PreparedUpdateEntry {
   Piece(PreparedUpdateEntry_Piece),
   Image(PreparedUpdateEntry_Image),
+  MoveHistEnt(SecondarySlotMap<PlayerId, MoveHistEnt>),
   SetTableSize(Pos),
   SetTableColour(Colour),
   SetLinks(Arc<LinksTable>),
@@ -221,6 +222,7 @@ enum TransmitUpdateEntry<'u> {
   },
   Piece(TransmitUpdateEntry_Piece<'u>),
   Image(TransmitUpdateEntry_Image<'u>),
+  MoveHistEnt(&'u MoveHistEnt),
   RecordedUnpredictable {
     piece: VisiblePieceId,
     cseq: ClientSequence,
@@ -406,6 +408,9 @@ impl PreparedUpdateEntry {
       Image(ims) => {
         ims.json_len(player)
       }
+      MoveHistEnt(ents) => {
+        match ents.get(player) { None => 0, Some(_) => 100 }
+      }
       Log(logent) => {
         logent.logent.html.json_len() * 28
       }
@@ -752,7 +757,55 @@ impl<'r> PrepareUpdatesBuffer<'r> {
                piece, &e);
         PreparedUpdateEntry::Error(ErrorSignaledViaUpdate::InternalError)
       });
+
+    // We're track this on behalf of the client, based on the updates
+    // we are sending.  That means we don't ahve to worry about
+    // occultation, etc. etc.
+    let movehist_update = if let PUE::Piece(PUE_P { ops,.. }) = &update {
+      let mut pu = SecondarySlotMap::new();
+      for (player, PreparedPieceUpdate { op,.. }) in ops { if_chain! {
+        if let Some(ns) = op.new_state();
+        if let Some(gpl) = wants!( self.g.gs.players.get_mut(player), ?player);
+        if let Some(mut ent) = wants!( gpl.moveheld.entry(piece),     ?piece);
+        let &PreparedPieceState { pos, angle, facehint, .. } = ns;
+        let new_posx = MoveHistPosx { pos, angle, facehint };
+
+        then {
+          if let slotmap::sparse_secondary::Entry::Occupied(ref mut oe) = ent {
+            let last = oe.get();
+            if ns.held == Some(last.held) { continue }
+
+            // Generate an update
+            let histent = MoveHistEnt {
+              held: last.held,
+              posx: OldNew::from([last.posx, new_posx]),
+            };
+            gpl.movehist.reserve(MOVEHIST_LEN_MAX);
+            if gpl.movehist.len() == MOVEHIST_LEN_MAX {
+              gpl.movehist.pop_front();
+            }
+            gpl.movehist.push_back(histent.clone());
+            pu.insert(player, histent);
+          }
+
+          if let Some(held) = ns.held {
+            ent.insert(GMoveHistLast { held: held, posx: new_posx });
+          } else {
+            ent.remove();
+          }
+        }
+      } }
+
+      if pu.is_empty() {
+        None
+      } else {
+        Some(PUE::MoveHistEnt(pu))
+      }
+    } else {
+      None
+    };
     self.us.push(update);
+    self.us.extend(movehist_update);
   }
 
   #[throws(InternalError)]
@@ -896,6 +949,12 @@ impl PreparedUpdate {
             _ => continue,
           }
         }
+        PUE::MoveHistEnt(ents) => {
+          match ents.get(player) {
+            Some(mhe) => TUE::MoveHistEnt(mhe),
+            _ => continue,
+          }
+        }
         PUE::Log(logent) => {
           TUE::Log((&tz, &logent))
         }
index 8d9972a618fe54959266546b9db9071014ab0b00..8e23588a1dc8c4f1c7396fc69b471aad09832bb7 100644 (file)
@@ -970,6 +970,10 @@ messages.SetLinks = <MessageHandler>function
   links_elem.innerHTML = msg
 }
 
+messages.MoveHistEnt = <MessageHandler>function
+(todo: object) {
+}
+
 // ----- logs -----
 
 messages.Log = <MessageHandler>function