chiark / gitweb /
Introduce OpHookThunk
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 1 May 2022 00:31:56 +0000 (01:31 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 1 May 2022 00:31:56 +0000 (01:31 +0100)
Currency merge needs this so that it can reborrow ipieces to delete
one of the merged notes.

Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
daemon/api.rs
src/clock.rs
src/dice.rs
src/gamestate.rs
src/updates.rs

index 6752fcd402db912b89c8e9d69ba56ca0199858a0..eda863367ee71b1b0dfcd63b16282f153eb2c5b1 100644 (file)
@@ -190,12 +190,19 @@ fn api_piece_op<O: op::Complex>(form: Json<ApiPiece<O>>)
     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(
+    let thunk = ipc.direct_trait_access().held_change_hook(
       &iad.gref,
       &mut g.gs.pieces,
       piece,
       was_held,
-    ).map_err(|e| error!("internal error on change hook: {:?}", e));
+    );
+    let unprepared = match thunk {
+      Err(e) => Err(e),
+      Ok(OpHookThunk::Immediate(uu)) => Ok(uu),
+      Ok(OpHookThunk::Reborrow(f)) => f(&mut ig, player),
+    };
+    if let Ok(unprepared) = unprepared.map_err(
+      |e| error!("internal error on change hook: {:?}", e));
     then {
       PrepareUpdatesBuffer::only_unprepared(&mut ig, unprepared);
     }
index 0743db7d2d6b683b480f67389a8bf9fbf65b94ea..be445a53e3c7604ad934006bd36488bcb278969a 100644 (file)
@@ -717,7 +717,7 @@ impl PieceTrait for Clock {
                       gpieces: &mut GPieces,
                       piece: PieceId,
                       was_held: Option<PlayerId>)
-                      -> UnpreparedUpdates {
+                      -> OpHookThunk {
     let gpc = gpieces.get_mut(piece);
     let gpc = if let Some(gpc) = gpc { gpc } else { return default() };
     let now_held = gpc.held;
@@ -736,7 +736,7 @@ impl PieceTrait for Clock {
 
     state.do_start_or_stop(piece, was_current, was_running,
                            now_held, &self.spec, ig)?;
-    unprepared_update(piece)
+    unprepared_update(piece).into()
   }
 
   #[throws(IE)]
index 658e199bd54edb14af7502ff8b6854543c836e20..8ea6c85d45f629bf8ce449ce9c4df88ddd9fe16a 100644 (file)
@@ -411,7 +411,7 @@ impl PieceTrait for Die {
                       gpieces: &mut GPieces,
                       piece: PieceId,
                       _was_held: Option<PlayerId>)
-                      -> UnpreparedUpdates {
+                      -> OpHookThunk {
     self.cooldown_cleanup_hook(gpieces, piece)?;
     default()
   }
index 512db5ffcf148b4a32a70b4f5776af1e6ac64a75..cdd9aed05f71fcbdaeba7dbacfaa11db7268f4dc 100644 (file)
@@ -229,7 +229,7 @@ pub trait PieceTrait: PieceBaseTrait + Downcast + Send + Debug + 'static {
                       _gpieces: &mut GPieces,
                       _piece: PieceId,
                       _was_held: Option<PlayerId>)
-                      -> Result<UnpreparedUpdates,IE> { Ok(default()) }
+                      -> Result<OpHookThunk,IE> { Ok(default()) }
 
   fn loaded_hook(&self, _piece: PieceId,
                  _gs: &mut GameState, _ig: &InstanceRef) -> Result<(),IE> {
index b6ef27748092c4d60ab19dc87fd5c9d3920ed24d..216ca07cf1d5cfef6e961b08ae2231a50c7ba737 100644 (file)
@@ -180,6 +180,23 @@ pub enum OpOutcomeThunk {
                    -> Result<UpdateFromOpComplex, ApiPieceOpError>>),
 }
 
+#[derive(From,Educe)]
+#[educe(Default)]
+pub enum OpHookThunk {
+  #[educe(Default)]
+  Immediate(UnpreparedUpdates),
+  /// Allows a UI operation full mutable access to the whole Instance.
+  ///
+  /// Use with care!  Eg, you might have to call save_game_and_aux_late.r
+  ///
+  /// Adding and removing pieces during play (rather than management)
+  /// is complicated, because we want to avoid having to rewrite the aux.
+  /// file during routine game saves.  `fastsplit.rs` has machinery that
+  /// can achieve this.
+  Reborrow(Box<dyn FnOnce(&mut InstanceGuard, PlayerId)
+                   -> Result<UnpreparedUpdates, InternalError>>),
+}
+
 pub type UpdateFromOpComplex = (
   PieceUpdate,
   UnpreparedUpdates,