From: Ian Jackson Date: Sun, 1 May 2022 00:31:56 +0000 (+0100) Subject: Introduce OpHookThunk X-Git-Tag: otter-1.1.0~383 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=90d8d2beda59671621c22119249a75a09faa2415;p=otter.git Introduce OpHookThunk Currency merge needs this so that it can reborrow ipieces to delete one of the merged notes. Signed-off-by: Ian Jackson --- diff --git a/daemon/api.rs b/daemon/api.rs index 6752fcd4..eda86336 100644 --- a/daemon/api.rs +++ b/daemon/api.rs @@ -190,12 +190,19 @@ fn api_piece_op(form: Json>) 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); } diff --git a/src/clock.rs b/src/clock.rs index 0743db7d..be445a53 100644 --- a/src/clock.rs +++ b/src/clock.rs @@ -717,7 +717,7 @@ impl PieceTrait for Clock { gpieces: &mut GPieces, piece: PieceId, was_held: Option) - -> 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)] diff --git a/src/dice.rs b/src/dice.rs index 658e199b..8ea6c85d 100644 --- a/src/dice.rs +++ b/src/dice.rs @@ -411,7 +411,7 @@ impl PieceTrait for Die { gpieces: &mut GPieces, piece: PieceId, _was_held: Option) - -> UnpreparedUpdates { + -> OpHookThunk { self.cooldown_cleanup_hook(gpieces, piece)?; default() } diff --git a/src/gamestate.rs b/src/gamestate.rs index 512db5ff..cdd9aed0 100644 --- a/src/gamestate.rs +++ b/src/gamestate.rs @@ -229,7 +229,7 @@ pub trait PieceTrait: PieceBaseTrait + Downcast + Send + Debug + 'static { _gpieces: &mut GPieces, _piece: PieceId, _was_held: Option) - -> Result { Ok(default()) } + -> Result { Ok(default()) } fn loaded_hook(&self, _piece: PieceId, _gs: &mut GameState, _ig: &InstanceRef) -> Result<(),IE> { diff --git a/src/updates.rs b/src/updates.rs index b6ef2774..216ca07c 100644 --- a/src/updates.rs +++ b/src/updates.rs @@ -180,6 +180,23 @@ pub enum OpOutcomeThunk { -> Result>), } +#[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 Result>), +} + pub type UpdateFromOpComplex = ( PieceUpdate, UnpreparedUpdates,