chiark / gitweb /
Support held_change_hook
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Tue, 16 Mar 2021 22:30:00 +0000 (22:30 +0000)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Fri, 19 Mar 2021 20:05:30 +0000 (20:05 +0000)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
daemon/api.rs
src/gamestate.rs
src/hidden.rs

index 2d1304466738ecf5e247affb152d8a93e740e5b3..50e8e94ca2a1743d558a6e69d9fa8bc07ba2e290 100644 (file)
@@ -121,6 +121,7 @@ fn api_piece_op<O: op::Complex>(form: Json<ApiPiece<O>>)
   let gpl = gs.players.byid(player)?;
   let piece = vpiece_decode(gs, player, gpl, form.piece)
     .ok_or(OE::PieceGone)?;
+  let was_held = gs.pieces.get(piece).as_ref().map(|gpc| gpc.held);
   use ApiPieceOpError::*;
 
   match (||{
@@ -174,11 +175,30 @@ fn api_piece_op<O: op::Complex>(form: Json<ApiPiece<O>>)
     }
   };
 
+  if let Some(unprepared) = if_chain! {
+    let g = &mut *ig;
+    if let Some(was_held) = was_held;
+    if let Some(gpc) = g.gs.pieces.get_mut(piece);
+    if gpc.held != was_held;
+    if let Some(ipc) = &g.ipieces.get(piece);
+    if let Ok(unprepared) = ipc.direct_trait_access().held_change_hook(
+      &mut g.gs.pieces,
+      was_held,
+    ).map_err(|e| error!("internal error on change hook: {:?}", e));
+    then { unprepared }
+    else { None }
+  } {
+    let mut prepub = PrepareUpdatesBuffer::new(&mut ig, None, None);
+    unprepared(&mut prepub);
+    prepub.finish();
+  }
+
       Ok::<(),OE>(())
     })();
 
     let g = &mut *ig;
     let gs = &mut g.gs;
+
     (r, to_permute.implement(&mut gs.players,
                              &mut gs.pieces,
                              &mut gs.occults,
index c20bde3aa7c3ebea58388a6ace3c07958b2724f7..548f862deced3f4ab97a91ca0f5c52151ee48784 100644 (file)
@@ -142,6 +142,14 @@ pub trait PieceTrait: OutlineTrait + Send + Debug + 'static {
 
   fn describe_html(&self, gpc: &GPiece) -> Result<Html,IE>;
 
+  #[throws(IE)]
+  /// Piece is responsible for dealing with the possibility that they
+  /// may be occulted!
+  fn held_change_hook(&self,
+                      _gpieces: &mut GPieces,
+                      _was_held: Option<PlayerId>)
+                      -> UnpreparedUpdates { None }
+
   fn delete_hook(&self, _p: &GPiece, _gs: &mut GameState)
                  -> ExecuteGameChangeUpdates { 
     ExecuteGameChangeUpdates{ pcs: vec![], log: vec![], raw: None }
index 9365bba1375bbd6dae5dcfa6efcffa2d10460431..47497751bd921d1c155fa145b1f16afce50e16f7 100644 (file)
@@ -245,6 +245,10 @@ impl IPieceTraitObj {
   }
 
   pub fn into_inner(self) -> Box<dyn PieceTrait> { self.0 }
+
+  pub fn direct_trait_access(&self) -> &Box<dyn PieceTrait> {
+    &self.0
+  }
 }
 
 impl IPiece {