chiark / gitweb /
server side new raise
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Wed, 8 Jul 2020 13:38:47 +0000 (14:38 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Wed, 8 Jul 2020 13:38:47 +0000 (14:38 +0100)
src/bin/server.rs
src/error.rs
src/gamestate.rs
src/global.rs
src/http.rs
src/imports.rs
src/sse.rs

index f17c8778660d7966c7a05e5fdcfcafa95737b98d..97ac32b0042f81a963aee4f20c64f9d34bb38586 100644 (file)
@@ -87,7 +87,7 @@ fn session(form : Json<SessionForm>) -> Result<Template,OE> {
 
     let mut pieces : Vec<_> = ig.gs.pieces.iter().collect();
 
-    pieces.sort_by_key(|(_,pr)| pr.raised);
+    pieces.sort_by_key(|(_,pr)| pr.zlevel);
 
     for (gpid, pr) in pieces {
       let pri = PieceRenderInstructions {
@@ -231,6 +231,7 @@ fn api_piece_op<O: ApiPieceOp>(form : Json<ApiPiece<O>>)
         client,
         sameclient_cseq : form.cseq,
         piece : pri_for_all.id,
+        zg : pc.zlevel.1,
         op : update,
       });
 
@@ -320,6 +321,7 @@ impl ApiPieceOp for ApiPieceUngrab {
 
 #[derive(Debug,Serialize,Deserialize)]
 struct ApiPieceRaise {
+  z : ZCoord,
 }
 #[post("/_/api/raise", format="json", data="<form>")]
 #[throws(OE)]
@@ -333,8 +335,8 @@ impl ApiPieceOp for ApiPieceRaise {
         _: &dyn Lens)
         -> (PieceUpdateOp<()>, Vec<LogEntry>) {
     let pc = gs.pieces.byid_mut(piece).unwrap();
-    pc.raised = gs.gen;
-    let update = PieceUpdateOp::Raise();
+    pc.zlevel = (self.z, gs.gen);
+    let update = PieceUpdateOp::SetZLevel(pc.zlevel);
     (update, vec![])
   }
 }
index 7aabe52cbff59c29e507ec44eeeb978667882994..2ff9da471fd5c702e4aeb6a8a66c00f54b99ed57 100644 (file)
@@ -19,6 +19,8 @@ pub enum OnlineError {
   NoClient,
   #[error("player not part of game (removed?)")]
   NoPlayer,
+  #[error("invalid Z coordinate")]
+  InvalidZCoord,
 }
 
 pub use OnlineError::{NoClient,NoPlayer};
index 5a672dab388ab213d7157539a935f0aebec55b0b..f6169ee5d6b3c58175cdd860cdfce8307e13e22b 100644 (file)
@@ -47,13 +47,36 @@ pub trait Piece : Send + Debug {
   fn describe_html(&self, face : Option<FaceId>) -> String;
 }
 
+#[derive(Debug,Copy,Clone,PartialEq,PartialOrd)]
+#[derive(Serialize,Deserialize)]
+#[serde(into="f64")]
+#[serde(try_from="f64")]
+pub struct ZCoord(f64);
+impl TryFrom<f64> for ZCoord {
+  type Error = OnlineError;
+  #[throws(OnlineError)]
+  fn try_from(v: f64) -> ZCoord {
+    if !v.is_finite() { Err(OnlineError::InvalidZCoord)? }
+    ZCoord(v)
+  }
+}
+impl From<ZCoord> for f64 {
+  fn from(v: ZCoord) -> f64 { v.0 }
+}
+impl Ord for ZCoord {
+  fn cmp(&self, other: &Self) -> cmp::Ordering {
+    self.0.partial_cmp(&other.0).unwrap()
+  }
+}
+impl Eq for ZCoord { }
+
 #[derive(Debug)]
 pub struct PieceRecord {
   pub pos : Pos,
   pub p : Box<dyn Piece>,
   pub face : FaceId,
   pub held : Option<PlayerId>,
-  pub raised : Generation,
+  pub zlevel : (ZCoord,Generation),
   pub gen : Generation,
   pub lastclient : ClientId,
   pub gen_before_lastclient : Generation,
@@ -127,7 +150,7 @@ pub fn xxx_gamestate_init() -> GameState {
       face : 0.into(),
       held : None,
       lastclient : Default::default(),
-      raised: Generation(0),
+      zlevel : (0f64 .try_into().unwrap(), Generation(0)),
       gen,
       gen_before_lastclient : Generation(0),
     };
index 69f6aac779c323512d1c8e555ffab02f0c8d34a5..f19107336e02f0d82a9af661e746c9823b33dd85 100644 (file)
@@ -30,6 +30,7 @@ pub enum PreparedUpdateEntry {
     sameclient_cseq : ClientSequence,
     piece : VisiblePieceId,
     op : PieceUpdateOp<PreparedPieceState>,
+    zg : Generation,
   },
   Log (Arc<LogEntry>),
 }
@@ -59,7 +60,7 @@ pub enum PieceUpdateOp<NS> {
   Insert(NS),
   Modify(NS),
   Move(Pos),
-  Raise(),
+  SetZLevel((ZCoord, Generation)),
 }
 impl<NS> PieceUpdateOp<NS> {
   pub fn new_state(&self) -> Option<&NS> {
@@ -69,7 +70,7 @@ impl<NS> PieceUpdateOp<NS> {
       Insert(ns) => Some(ns),
       Modify(ns) => Some(ns),
       Move(_) => None,
-      Raise() => None,
+      SetZLevel(_) => None,
     }
   }
   pub fn map_new_state<NS2,F: FnOnce(NS) -> NS2>(self, f:F)
@@ -80,7 +81,7 @@ impl<NS> PieceUpdateOp<NS> {
       Insert(ns) => Insert(f(ns)),
       Modify(ns) => Modify(f(ns)),
       Move(pos) => Move(pos),
-      Raise() => Raise(),
+      SetZLevel(zl) => SetZLevel(zl),
     }
   }
 }      
index 292466e11984b43ca3f7121ced8d4ff9a1b2aa70..b9711025e39eb2b0b2f57575762e9ae2b86400c3 100644 (file)
@@ -13,6 +13,7 @@ impl<'r> Responder<'r> for OnlineError {
     let status = match self {
       GameCorrupted => Status::InternalServerError,
       NoClient | NoPlayer => Status::NotFound,
+      InvalidZCoord => Status::BadRequest,
     };
     let mut resp = Responder::respond_to(msg,req).unwrap();
     resp.set_status(status);
index 0cade33f3fa3e349ce6f777b0f467f6b02e982c2..8089436545eab22a45c0b108101a4c0bddf74618 100644 (file)
@@ -8,14 +8,15 @@ pub use std::time::Duration;
 pub use std::sync::{Arc,Mutex,RwLock,Condvar};
 pub use std::collections::HashMap;
 pub use std::borrow::Borrow;
-pub use std::convert::TryFrom;
+pub use std::convert::{TryFrom,TryInto};
 pub use std::str;
 pub use std::str::FromStr;
 pub use std::iter;
 pub use std::iter::repeat_with;
 pub use std::collections::VecDeque;
 pub use std::num::Wrapping;
-
+pub use std::cmp;
+  
 pub use thiserror::Error;
 pub use anyhow::{Context,anyhow};
 pub use fehler::{throws,throw};
index bf5e45cf158b51c95ad2b006d802db4e6e7d93d6..296b57f4b05d2e176f99d1ea2f8bcb8b1bdd1a7a 100644 (file)
@@ -51,6 +51,7 @@ enum TransmitUpdate<'u> {
   Recorded {
     piece : VisiblePieceId,
     cseq : ClientSequence,
+    zg : Generation,
   },
   Piece {
     piece : VisiblePieceId,
@@ -94,9 +95,9 @@ impl Read for UpdateReader {
       for u in &next.us {
         let tu = match u {
           &PreparedUpdateEntry::Piece
-          { piece, client, sameclient_cseq : cseq, .. }
+          { piece, client, sameclient_cseq : cseq, zg, .. }
           if client== self.client => {
-            TransmitUpdate::Recorded { piece, cseq }
+            TransmitUpdate::Recorded { piece, cseq, zg }
           },
           &PreparedUpdateEntry::Piece { piece, ref op, .. } => {
             TransmitUpdate::Piece { piece, op }