From 47ed629d26f9aa64ca2c8c780762bf04be2ef7a1 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Wed, 7 Apr 2021 19:19:57 +0100 Subject: [PATCH] Prevent occultation by rotated pieces * Add a OcculterRotationChecked proof token to create_occultation * Make a function to get the proof token from the GPiece * In ui_operation (do the thing) functions, check it and plumb it through * In the load functions, set rotateable to false Signed-off-by: Ian Jackson --- src/deck.rs | 8 +++++--- src/error.rs | 1 + src/hand.rs | 7 +++++-- src/hidden.rs | 11 +++++++++++ 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/deck.rs b/src/deck.rs index 26020797..505bd522 100644 --- a/src/deck.rs +++ b/src/deck.rs @@ -59,6 +59,7 @@ impl PieceSpec for piece_specs::Deck { throw!(SpE::WrongNumberOfFaces); } gpc.moveable = PieceMoveable::IfWresting; + gpc.rotateable = false; let p = Box::new(Deck { shape, label: self.label.load()?, @@ -161,7 +162,7 @@ impl PieceTrait for Deck { } #[throws(ApiPieceOpError)] - fn ui_operation(&self, _: ShowUnocculted, + fn ui_operation(&self, vis: ShowUnocculted, a: ApiPieceOpArgs<'_>, opname: &str, wrc: WhatResponseToClientOp) -> UpdateFromOpComplex { @@ -177,7 +178,8 @@ impl PieceTrait for Deck { let nick = gpl.nick.to_html(); dbgc!("ui op k entry", &opname); - + + let rot_checked = gpc.occulter_check_unrotated(vis)?; let old_state = self.state(gpc, &goccults)?; let (new_state, did) = match opname { @@ -222,7 +224,7 @@ impl PieceTrait for Deck { xupdates.extend( create_occultation(&mut gen.unique_gen(), &mut gs.max_z, gplayers, gpieces, goccults, ipieces, ioccults, - to_recalculate, + to_recalculate, rot_checked, region, piece, views)? ); dbgc!("creating occ done", &xupdates); diff --git a/src/error.rs b/src/error.rs index 784465b8..c515b370 100644 --- a/src/error.rs +++ b/src/error.rs @@ -181,6 +181,7 @@ pub enum PieceOpError { PieceGone, Occultation, PieceUnrotateable, + OcculterAlreadyRotated, OrganisedPlacementOverfull, } display_as_debug!{PieceOpError} diff --git a/src/hand.rs b/src/hand.rs index e09b1173..2b10686a 100644 --- a/src/hand.rs +++ b/src/hand.rs @@ -123,6 +123,7 @@ impl PieceSpec for piece_specs::Hand { _pcaliases: &PieceAliases, _ir: &InstanceRef) -> PieceSpecLoaded { gpc.moveable = PieceMoveable::IfWresting; + gpc.rotateable = false; self.c.load(Behaviour::Hand)? } } @@ -217,7 +218,7 @@ impl PieceTrait for Hand { } #[throws(ApiPieceOpError)] - fn ui_operation(&self, _: ShowUnocculted, mut a: ApiPieceOpArgs<'_>, + fn ui_operation(&self, vis: ShowUnocculted, mut a: ApiPieceOpArgs<'_>, opname: &str, wrc: WhatResponseToClientOp) -> UpdateFromOpComplex { if let Some(r) = { @@ -237,6 +238,7 @@ impl PieceTrait for Hand { let goccults = &mut gs.occults; let gpc = gpieces.byid_mut(piece)?; + let rot_checked = gpc.occulter_check_unrotated(vis); let xdata = gpc.xdata.get_mut::(default)?; let old_desc = self.behaviour.describe_html_inner(Some(xdata)); let old_player = xdata.player(); @@ -261,6 +263,7 @@ impl PieceTrait for Hand { let xupdates = match self.behaviour.views() { None => default(), Some((mk_owner, mk_defview)) => { + let rot_checked = rot_checked?; let (region, views) = (||{ dbgc!("claiming region"); let rect = self.shape.outline.rect (gpc.pos)?; @@ -281,7 +284,7 @@ impl PieceTrait for Hand { create_occultation(&mut gen.unique_gen(), &mut gs.max_z, gplayers, gpieces, goccults, ipieces, ioccults, - to_recalculate, + to_recalculate, rot_checked, region, piece, views)?; xupdates } diff --git a/src/hidden.rs b/src/hidden.rs index 74397d3e..01a0227d 100644 --- a/src/hidden.rs +++ b/src/hidden.rs @@ -19,6 +19,9 @@ visible_slotmap_key!{ OccId(b'H') } #[derive(Copy,Clone,Debug)] pub struct ShowUnocculted(()); +#[derive(Copy,Clone,Debug)] +pub struct OcculterRotationChecked(()); + #[derive(Debug,Serialize,Deserialize)] #[serde(transparent)] pub struct IPieceTraitObj(Box); @@ -414,6 +417,13 @@ impl GPiece { } } + pub fn occulter_check_unrotated(&self, _:ShowUnocculted) + -> Result { + if self.angle.is_rotated() { Err(POE::OcculterAlreadyRotated) } + else { Ok(OcculterRotationChecked(())) } + } + + pub fn fully_visible_to(&self, goccults: &GameOccults, player: PlayerId) -> Option { @@ -871,6 +881,7 @@ pub fn create_occultation( ipieces: &IPieces, ioccults: &IOccults, to_recalculate: &mut ToRecalculate, + _: OcculterRotationChecked, region: Region, occulter: PieceId, views: OccultationViews, -- 2.30.2