From 4e0936ab05c285ca43665c6eb42ff4fdd630821b Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Tue, 5 Jan 2021 01:12:02 +0000 Subject: [PATCH] represent and display angles Signed-off-by: Ian Jackson --- daemon/cmdlistener.rs | 3 ++- daemon/session.rs | 7 +++++-- specs/demo.game.toml | 1 + src/bin/otter.rs | 3 ++- src/gamestate.rs | 12 +++++++++++ src/spec.rs | 46 +++++++++++++++++++++++++++++++++++++++++++ templates/macros.tera | 1 + 7 files changed, 69 insertions(+), 4 deletions(-) diff --git a/daemon/cmdlistener.rs b/daemon/cmdlistener.rs index 09af0f6c..582f2211 100644 --- a/daemon/cmdlistener.rs +++ b/daemon/cmdlistener.rs @@ -576,7 +576,7 @@ fn execute_game_insn<'cs, 'igr, 'ig: 'igr>( Fine, ig) }, - AddPieces(PiecesSpec{ pos,posd,count,face,pinned,info }) => { + AddPieces(PiecesSpec{ pos,posd,count,face,pinned,angle,info }) => { let (ig_g, modperm, _) = cs.check_acl_modify_pieces(ag, ig)?; let ig = &mut **ig_g; let gs = &mut ig.gs; @@ -615,6 +615,7 @@ fn execute_game_insn<'cs, 'igr, 'ig: 'igr>( lastclient: Default::default(), gen_before_lastclient: Generation(0), pinned: pinned.unwrap_or(false), + angle, gen: gs.gen, pos, face, }; diff --git a/daemon/session.rs b/daemon/session.rs index e52bf99a..37ef11ff 100644 --- a/daemon/session.rs +++ b/daemon/session.rs @@ -31,6 +31,7 @@ struct SessionFormattedLogEntry { struct SessionPieceContext { id: VisiblePieceId, pos: Pos, + transform: VisibleAngleTransform, info: String, // SessionPieceLoadJson as JSON } @@ -110,6 +111,7 @@ fn session_inner(form : Json, else { continue /* was deleted */ }; let defs = p.make_defs(&pri)?; alldefs.push((pri.id, defs)); + let transform = make_angle_visible(pr.angle, pr.pos); let for_info = SessionPieceLoadJson { held : &pr.held, @@ -120,9 +122,10 @@ fn session_inner(form : Json, }; let for_piece = SessionPieceContext { + transform, id: pri.id, - pos : pr.pos, - info : serde_json::to_string(&for_info) + pos: pr.pos, + info: serde_json::to_string(&for_info) .map_err(|e| InternalError::JSONEncode(e))?, }; uses.push(for_piece); diff --git a/specs/demo.game.toml b/specs/demo.game.toml index dd5bfe19..64b7cbd6 100644 --- a/specs/demo.game.toml +++ b/specs/demo.game.toml @@ -25,5 +25,6 @@ item = "chess-w-B" [[pieces]] pos = [160,40] type = "Lib" +angle.Compass = 1 lib = "wikimedia" item = "chess-b-N" diff --git a/src/bin/otter.rs b/src/bin/otter.rs index a9a5f1f5..5ba2951b 100644 --- a/src/bin/otter.rs +++ b/src/bin/otter.rs @@ -1194,6 +1194,7 @@ mod library_add { count: Some(to_add as u32), face: None, pinned: Some(false), + angle: default(), info: Box::new(spec), }; Poor(vec![ MGI::AddPieces(spec) ], @@ -1346,7 +1347,7 @@ mod library_add { let spec = PiecesSpec { pos: Some(pos), posd: None, count: Some(1), face: None, pinned: Some(false), - info: Box::new(spec), + angle: default(), info: Box::new(spec), }; let insn = MGI::AddPieces(spec); insns.push(insn); diff --git a/src/gamestate.rs b/src/gamestate.rs index 7ac57e15..d68be53e 100644 --- a/src/gamestate.rs +++ b/src/gamestate.rs @@ -23,6 +23,11 @@ pub struct Generation(pub u64); visible_slotmap_key!{ VisiblePieceId('.') } +#[derive(Clone,Debug)] +#[derive(Serialize,Deserialize)] +#[serde(transparent)] +pub struct VisibleAngleTransform(String); + #[derive(Clone,Serialize,Deserialize,Hash,Eq,Ord,PartialEq,PartialOrd)] #[serde(transparent)] pub struct Html(pub String); @@ -67,6 +72,7 @@ pub struct PieceState { pub held: Option, pub zlevel: ZLevel, pub pinned: bool, + #[serde(default)] pub angle: PieceAngle, pub gen: Generation, pub lastclient: ClientId, pub gen_before_lastclient: Generation, @@ -321,3 +327,9 @@ pub fn make_pieceid_visible(p: PieceId) -> VisiblePieceId { let kd: slotmap::KeyData = p.into(); VisiblePieceId(kd) } + +pub fn make_angle_visible(angle: PieceAngle, pos: Pos) + -> VisibleAngleTransform { + // todo-lens need to do censorship mapping here + VisibleAngleTransform(angle.to_transform(pos)) +} diff --git a/src/spec.rs b/src/spec.rs index 5b33af9b..23712b37 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -72,6 +72,7 @@ pub enum SpecError { InconsistentPieceCount, BadUrlSyntax, UrlTooLong, + CompassAngleInvalid, } display_as_debug!{SpecError} @@ -168,10 +169,23 @@ pub struct PiecesSpec { pub count: Option, pub face: Option, pub pinned: Option, + #[serde(default)] pub angle: PieceAngle, #[serde(flatten)] pub info: Box, } +#[derive(Debug,Copy,Clone,Serialize,Deserialize)] +pub enum PieceAngle { + Compass(CompassAngle), +} + +#[derive(Debug,Copy,Clone,Eq,PartialEq)] +#[derive(Default,Serialize,Deserialize)] +#[serde(try_from="u8")] +#[serde(into="u8")] +/// 0 = unrotated, +ve is anticlockwise, units of 45deg +pub struct CompassAngle(u8); + //---------- Piece specs ---------- // the implementations are in pieces.rs @@ -282,6 +296,38 @@ pub mod implementation { type SE = SpecError; type TPS = TablePlayerSpec; + impl Default for PieceAngle { + fn default() -> Self { PieceAngle::Compass(default()) } + } + + impl TryFrom for CompassAngle { + type Error = SpecError; + #[throws(SpecError)] + fn try_from(v: u8) -> Self { + if v < 8 { Self(v) } + else { throw!(SE::CompassAngleInvalid) } + } + } + + impl From for u8 { + fn from(a: CompassAngle) -> u8 { + a.0 + } + } + + impl PieceAngle { + pub fn to_transform(self, pos: Pos) -> String { + match self { + PieceAngle::Compass(CompassAngle(angle)) => { + if angle == 0 { default() } + else { format!("rotate({}, {}, {})", + -45 * (angle as i16), + pos.0[0], pos.0[1]) } + } + } + } + } + impl Default for Acl

{ fn default() -> Self { Acl { ents: default() } } } diff --git a/templates/macros.tera b/templates/macros.tera index 48dfa885..32f8eac5 100644 --- a/templates/macros.tera +++ b/templates/macros.tera @@ -61,6 +61,7 @@ Hi {{nick | escape}} {%- for piece in uses %} {%- endfor %} -- 2.30.2