From: Ian Jackson Date: Sat, 13 Feb 2021 23:44:23 +0000 (+0000) Subject: hand: Track claiming and unclaiming X-Git-Tag: otter-0.4.0~497 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=88e4ac01d07dd4cfe62ed68760798fe1534a0914;p=otter.git hand: Track claiming and unclaiming Signed-off-by: Ian Jackson --- diff --git a/src/imports.rs b/src/imports.rs index 2154cd74..39097f2f 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -130,6 +130,7 @@ pub type AS = AccountScope; pub type ME = MgmtError; // error.rs +pub type APOE = ApiPieceOpError; pub type ESVU = ErrorSignaledViaUpdate; pub type IE = InternalError; pub type OE = OnlineError; diff --git a/src/pieces.rs b/src/pieces.rs index 3854aade..a04fd01f 100644 --- a/src/pieces.rs +++ b/src/pieces.rs @@ -283,11 +283,25 @@ impl PieceSpec for piece_specs::Square { fn load(&self, _: usize) -> Box { SimplePieceSpec::load(self)? } } +#[derive(Debug,Clone,Serialize,Deserialize)] +struct MagicOwner { + player: PlayerId, + dasharray: Html, +} + #[derive(Debug,Serialize,Deserialize)] struct Hand { shape: SimpleShape, } +#[derive(Debug,Clone,Default,Serialize,Deserialize)] +struct HandState { + owner: Option, +} + +#[typetag::serde(name="Hand")] +impl PieceXData for HandState { } + #[typetag::serde] impl Outline for Hand { delegate!{ @@ -301,20 +315,6 @@ impl Outline for Hand { } } -#[typetag::serde] -impl Piece for Hand { - delegate!{ - to self.shape { - fn svg_piece(&self, f: &mut Html, gpc: &PieceState, - pri: &PieceRenderInstructions) -> Result<(),IE>; - fn describe_html(&self, face: Option, _gpc: &PieceState) - -> Result; - fn itemname(&self) -> &str; - } - } - fn nfaces(&self) -> RawFaceId { 1 } -} - #[typetag::serde] impl PieceSpec for piece_specs::Hand { #[throws(SpecError)] @@ -328,7 +328,104 @@ impl PieceSpec for piece_specs::Hand { } shape.itemname = "magic-hand".to_string(); Box::new(Hand { - shape + shape, }) as Box } } + +#[typetag::serde] +impl Piece for Hand { + fn nfaces(&self) -> RawFaceId { 1 } + #[throws(IE)] + fn svg_piece(&self, f: &mut Html, gpc: &PieceState, + pri: &PieceRenderInstructions) { + self.shape.svg_piece_raw(f, pri, &mut |f: &mut String| { + if_chain!{ + if let Some(xdata) = gpc.xdata.get::()?; + if let Some(owned) = &xdata.owner; + then { write!(f, " dasharray={} ", &owned.dasharray.0)?; } + } + Ok(()) + })?; + } + + delegate!{ + to self.shape { + fn describe_html(&self, face: Option, _gpc: &PieceState) + -> Result; + fn itemname(&self) -> &str; + } + } + + #[throws(InternalError)] + fn add_ui_operations(&self, upd: &mut Vec, + gpc: &PieceState) { + upd.push(if_chain! { + if let Some(xdata) = gpc.xdata.get::()?; + if let Some(_owner) = &xdata.owner; + then { UoDescription { + kind: UoKind:: GlobalExtra, + def_key: 'C', + opname: "claim".to_owned(), + desc: Html::lit("Claim this as your hand"), + wrc: WRC::Unpredictable, + }} + else { UoDescription { + kind: UoKind:: GlobalExtra, + def_key: 'C', + opname: "deactivate".to_owned(), + desc: Html::lit("Deactivate hand"), + wrc: WRC::Unpredictable, + }} + }) + } + + fn ui_operation(&self, gs: &mut GameState, player: PlayerId, + piece: PieceId, opname: &str, wrc: WhatResponseToClientOp) + -> PieceUpdateResult { + let gplayers = &mut gs.players; + let gpc = gs.pieces.byid_mut(piece)?; + let xdata = gpc.xdata.get_mut::() + .map_err(|e| APOE::ReportViaResponse(e.into()))?; + let previous_owner = (||{ + let owner = xdata.owner.as_ref()?; + let owner_gpl = gplayers.get(owner.player)?; + Some(Html(htmlescape::encode_minimal(&owner_gpl.nick))) + })(); + + let dasharray = player_dasharray(gplayers, player); + let gpl = gplayers.byid_mut(player)?; + let occults = &mut gs.occults; + + let did; + match (opname, &previous_owner) { + ("claim", None) => { + xdata.owner = Some(MagicOwner { + player, + dasharray, + }); + // xxx recalculate occultations + did = format!("claimed a hand repository"); + } + ("deactivate", Some(prev)) => { + xdata.owner = None; + // xxx recalculate occultations + did = format!("deactivated {}'s a hand", &prev.0); + } + ("claim", Some(_)) | + ("deactivate", None) => { + throw!(OE::PieceHeld); + } + _ => { + throw!(OE::BadOperation); + } + } + + let log = log_did_to_piece(occults,player,gpl,piece,gpc,self,&did); + Ok(PieceUpdate { + wrc, log, + ops: PUOs::Simple(PUO::Modify(())), // xxx + // xxx want PUU::RecalculateOccultations + }) + } +}