chiark / gitweb /
hidden: Make it possible to completely hide a piece
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 28 Feb 2021 15:58:32 +0000 (15:58 +0000)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 28 Feb 2021 15:58:32 +0000 (15:58 +0000)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
daemon/api.rs
daemon/session.rs
src/hidden.rs
src/updates.rs

index 5628af90e219423669924f963b5f2e30b03438f2..ba278a6a9c4d1671db5346c37eb2d8d0b5d327c7 100644 (file)
@@ -266,7 +266,9 @@ api_route!{
       let was = was.map(|was| htmlescape::encode_minimal(&was.nick));
 
       let gpl = players.byid_mut(player)?;
-      let pri = piece_pri(&gs.occults, player, gpl, piece, pc);
+      let pri = piece_pri(&gs.occults, player, gpl, piece, pc)
+        .ok_or(OE::PieceGone)?;
+
       let pcs = pri.describe(pc, &p).0;
 
       pc.held = Some(player);
@@ -298,15 +300,16 @@ api_route!{
     let gpl = gs.players.byid_mut(player).unwrap();
     let pc = gs.pieces.byid_mut(piece).unwrap();
 
-    if pc.held != Some(player) { throw!(OnlineError::PieceHeld) }
-    pc.held = None;
-
-    let update = PieceUpdateOp::Modify(());
     let (logents, who_by) = log_did_to_piece_whoby(
       &gs.occults, player, gpl, piece, pc, p,
       "released"
     );
+    let who_by = who_by.ok_or(OE::PieceGone)?;
 
+    if pc.held != Some(player) { throw!(OnlineError::PieceHeld) }
+    pc.held = None;
+
+    let update = PieceUpdateOp::Modify(());
     let vanilla = (WhatResponseToClientOp::Predictable,
                    update,
                    logents);
index 9087c281e2d4ce55df7674904a3be6cc27fb866b..346bc4091ae9bc84c0b028b1ea0f2df2c2fac4d6 100644 (file)
@@ -111,9 +111,12 @@ fn session_inner(form: Json<SessionForm>,
     pieces.sort_by_key(|(_,pr)| &pr.zlevel);
 
     for (piece, gpc) in pieces {
-      let pri = piece_pri(&ig.gs.occults, player, gpl, piece, gpc);
       let pto = if let Some(pto) = ig.ipieces.get(piece) { pto }
       else { continue /* was deleted */ };
+
+      let pri = piece_pri(&ig.gs.occults, player, gpl, piece, gpc);
+      let pri = if let Some(pri) = pri { pri } else { continue /*invisible*/};
+
       let defs = pri.make_defs(gpc, pto)?;
       alldefs.push((pri.vpid, defs));
       let desc = pri.describe(&gpc, pto);
index c733edd39e122cf102e23c05715bc52719fce7d8..830943ae0a07f3f9ca60f19d8d1d694dc8e663cd 100644 (file)
@@ -173,19 +173,20 @@ impl PerPlayerIdMap {
 
 // ========== public entrypoints ==========
 
+/// None => do not render at all
 pub fn piece_pri(
   _occults: &GameOccults, // xxx
   player: PlayerId,
   gpl: &mut GPlayer,
   piece: PieceId,
   pc: &GPiece,
-) -> PieceRenderInstructions {
+) -> Option<PieceRenderInstructions> {
   let vpid = gpl.idmap.fwd_or_insert(piece);
   let angle = pc.angle;
   let occluded = PriOccluded::Visible; // xxx
   trace!("{} {:?} => {} angle={:?}",
          player, piece, vpid, angle);
-  PieceRenderInstructions { vpid, occluded }
+  Some(PieceRenderInstructions { vpid, occluded })
 }
 
 pub fn piece_at_all_occluded(
index d6d6da2815e3cf293fce98570767d07eadb45d55..46441b8d4feb49e903769b0b88a79f0207be6c41 100644 (file)
@@ -205,16 +205,19 @@ pub fn log_did_to_piece_whoby(
   gpl: &mut GPlayer,
   piece: PieceId, pc: &GPiece, p: &dyn PieceTrait,
   did: &str,
-) -> (Vec<LogEntry>, Html) {
+) -> (Vec<LogEntry>, Option<Html>) {
   let who_by = Html(htmlescape::encode_minimal(&gpl.nick));
-  let pri = piece_pri(occults, player, gpl, piece, pc);
-  let log = vec![ LogEntry { html: Html(format!(
-    "{} {} {}",
-    &who_by.0,
-    did,
-    pri.describe(pc, &p).0,
-  ))}];
-  (log, who_by)
+  if let Some(pri) = piece_pri(occults, player, gpl, piece, pc) {
+    let log = vec![ LogEntry { html: Html(format!(
+      "{} {} {}",
+      &who_by.0,
+      did,
+      pri.describe(pc, &p).0,
+    ))}];
+    (log, Some(who_by))
+  } else {
+    (vec![], None)
+  }
 }
 
 pub fn log_did_to_piece(
@@ -491,9 +494,11 @@ impl<'r> PrepareUpdatesBuffer<'r> {
                          pc: &mut GPiece,
                          p: &Box<dyn PieceTrait>,
                          op: PieceUpdateOp<(),()>,
-                         pri: &PieceRenderInstructions)
-                         -> PreparedPieceUpdate
+                         pri: &Option<PieceRenderInstructions>)
+                         -> Option<PreparedPieceUpdate>
   {
+    let pri = match pri { Some(pri) => pri, None => return None };
+
     max_z.update_max(&pc.zlevel.z);
 
     let op = op.try_map(
@@ -507,10 +512,10 @@ impl<'r> PrepareUpdatesBuffer<'r> {
       }
     )?;
 
-    PreparedPieceUpdate {
+    Some(PreparedPieceUpdate {
       piece: pri.vpid,
       op,
-    }
+    })
   }
 
 
@@ -546,14 +551,16 @@ impl<'r> PrepareUpdatesBuffer<'r> {
             &mut gs.max_z, pc, p, ops, &pri
           )?
         }
-        _ => PreparedPieceUpdate {
+        _ => Some(PreparedPieceUpdate {
           // The piece is deleted, so we can't leak anything.
           piece: gpl.idmap.fwd_or_insert(piece),
           op: PieceUpdateOp::Delete(),
-        }
+        })
       };
 
-      out.insert(player, op);
+      if let Some(op) = op {
+        out.insert(player, op);
+      }
     }
 
     PreparedUpdateEntry_Piece {