chiark / gitweb /
Plumb &GameState through into svg_piece
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Wed, 17 Mar 2021 18:11:22 +0000 (18:11 +0000)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Fri, 19 Mar 2021 20:05:30 +0000 (20:05 +0000)
This is quite a lot of plumbing.

Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
daemon/session.rs
src/bin/otterlib.rs
src/clock.rs
src/gamestate.rs
src/hand.rs
src/pcrender.rs
src/pieces.rs
src/shapelib.rs
src/updates.rs

index 8a8214e74d41c0c38666ebafe4250e235e0fedfe..04b64b53bfc65e0e96125c7307c30099c686c6a6 100644 (file)
@@ -109,6 +109,7 @@ fn session_inner(form: Json<SessionForm>,
     }
     let layout = gpl.layout;
     let mut pieces: Vec<_> = ig.gs.pieces.iter().collect();
+    let nick = gpl.nick.clone();
 
     pieces.sort_by_key(|(_,pr)| &pr.zlevel);
 
@@ -116,11 +117,14 @@ fn session_inner(form: Json<SessionForm>,
       let ipc = if let Some(pto) = ig.ipieces.get(piece) { pto }
       else { continue /* was deleted */ };
 
-      let pri = piece_pri(ioccults, &ig.gs.occults, player, gpl,
+      let pri = piece_pri(ioccults, &ig.gs.occults, player,
+                          // we need to re-obtain gpl, because
+                          // make_defs needs to borrow the whole of &gs
+                          ig.gs.players.byid_mut(player)?,
                           piece, gpc, ipc);
       let pri = if let Some(pri) = pri { pri } else { continue /*invisible*/};
 
-      let defs = pri.make_defs(ioccults, gpc, ipc)?;
+      let defs = pri.make_defs(ioccults, &ig.gs, gpc, ipc)?;
       alldefs.push((pri.vpid, defs));
       let desc = pri.describe(ioccults, &gpc, ipc);
 
@@ -203,7 +207,7 @@ fn session_inner(form: Json<SessionForm>,
       defs: alldefs,
       uses,
       scale: SVG_SCALE,
-      nick: gpl.nick.clone(),
+      nick,
       sse_url_prefix,
       player_info_pane,
       ptoken: form.ptoken.clone(),
index b3400384b7360290cf5410e08eea16f398b1f239..19a623606721231213ecf4775d9e87eaee85a402 100644 (file)
@@ -173,7 +173,7 @@ fn preview(items: Vec<ItemForOutput>) {
         }
         let mut html = Html("".into());
         let gpc = GPiece { face: face.into(), ..GPiece::dummy() };
-        p.svg_piece(&mut html, &gpc, default())?;
+        p.svg_piece(&mut html, &gpc, &GameState::dummy(), default())?;
         println!("{}</svg>", html.0);
       }
       println!("</td>");
index 0a1bb70765e18d00fa16b625452f0655c18729f7..8d859e67b5faa75690a20f3833f88cf1f2aed358 100644 (file)
@@ -47,7 +47,7 @@ impl PieceTrait for Clock {
   fn nfaces(&self) -> RawFaceId { 1 }
 
   #[throws(IE)]
-  fn svg_piece(&self, f: &mut Html, _gpc: &GPiece, id: VisiblePieceId) {
+  fn svg_piece(&self, f: &mut Html, _gpc: &GPiece, _gs: &GameState, id: VisiblePieceId) {
     dbgc!("rendering", id);
     write!( &mut f.0, r##"
         <rect fill="black" width="10" height="10"/>
index 073e68e1eddd94cde00a20af8771ed6e4509081a..7768107be4fba8986ddf275626ca790bb5a6c344 100644 (file)
@@ -137,7 +137,7 @@ pub trait PieceTrait: OutlineTrait + Send + Debug + 'static {
   }
 
   // #[throws] doesn't work here - fehler #todo
-  fn svg_piece(&self, f: &mut Html, gpc: &GPiece,
+  fn svg_piece(&self, f: &mut Html, gpc: &GPiece, gs: &GameState,
                id: VisiblePieceId) -> Result<(),IE>;
 
   fn describe_html(&self, gpc: &GPiece) -> Result<Html,IE>;
index 484c97665b416b72c7608ef8bd144b2968614545..755a95d821d20a590f714c5a6a651665e5ec4596 100644 (file)
@@ -89,7 +89,7 @@ impl Hand {
 impl PieceTrait for Hand {
   fn nfaces(&self) -> RawFaceId { 1 }
   #[throws(IE)]
-  fn svg_piece(&self, f: &mut Html, gpc: &GPiece, _vpid: VisiblePieceId) {
+  fn svg_piece(&self, f: &mut Html, gpc: &GPiece, _gs: &GameState, _vpid: VisiblePieceId) {
     self.shape.svg_piece_raw(f, gpc.face, &mut |f: &mut String| {
       if_chain!{
         if let Some(xdata) = gpc.xdata.get::<HandState>()?;
index 933f744ace139158d8ca403dcd02fac1deeb43b8..869786385c767ef154109b10ed58b157a167e4b6 100644 (file)
@@ -79,7 +79,7 @@ impl<P,Z> PriOccultedGeneral<P,Z> {
 
 impl PieceRenderInstructions {
   #[throws(IE)]
-  pub fn map_piece_update_op(&self, ioccults: &IOccults,
+  pub fn map_piece_update_op(&self, ioccults: &IOccults, gs: &GameState,
                              gpc: &GPiece, ipc: &IPiece,
                              op: PieceUpdateOp<(),()>
   ) -> Option<PieceUpdateOp<PreparedPieceState, ZLevel>>
@@ -99,7 +99,7 @@ impl PieceRenderInstructions {
 
     let op = op.try_map(
       |()|{
-        let ns = self.prep_piecestate(ioccults, gpc, ipc)?;
+        let ns = self.prep_piecestate(ioccults, gs, gpc, ipc)?;
         <Result<_,InternalError>>::Ok(ns)
       },
       |()|{
@@ -110,7 +110,7 @@ impl PieceRenderInstructions {
   }
   
   #[throws(IE)]
-  pub fn prep_piecestate(&self, ioccults: &IOccults,
+  pub fn prep_piecestate(&self, ioccults: &IOccults, gs: &GameState,
                          gpc: &GPiece, ipc: &IPiece)
                          -> PreparedPieceState {
     let pri = self;
@@ -118,7 +118,7 @@ impl PieceRenderInstructions {
     let r = PreparedPieceState {
       pos        : pos,
       held       : gpc.held,
-      svg        : pri.make_defs(ioccults, gpc, ipc)?,
+      svg        : pri.make_defs(ioccults, gs, gpc, ipc)?,
       z          : zlevel.z.clone(),
       zg         : zlevel.zg,
       angle      : pri.angle(gpc).to_compass(),
@@ -145,7 +145,7 @@ impl PieceRenderInstructions {
   }
 
   #[throws(IE)]
-  pub fn make_defs<'p>(&self, ioccults: &IOccults,
+  pub fn make_defs<'p>(&self, ioccults: &IOccults, gs: &GameState,
                          gpc: &GPiece, ipc: &IPiece) -> Html
   {
     let pri = self;
@@ -173,7 +173,7 @@ impl PieceRenderInstructions {
 
     match instead {
       Left(y) => {
-        ipc.show(y).svg_piece(&mut defs, gpc, pri.vpid)?;
+        ipc.show(y).svg_piece(&mut defs, gpc, gs, pri.vpid)?;
       },
       Right(i) => {
         i.svg(&mut defs, pri.vpid)?;
index 038fa56fc6420349e35abd0387ed04a71986bb2d..6ed3846c3541990ee92101d7975da4712ddbd69c 100644 (file)
@@ -129,7 +129,7 @@ impl<Desc, Outl:'static> OutlineTrait for GenericSimpleShape<Desc, Outl>
 #[typetag::serde]
 impl PieceTrait for SimpleShape {
   #[throws(IE)]
-  fn svg_piece(&self, f: &mut Html, gpc: &GPiece, _vpid: VisiblePieceId) {
+  fn svg_piece(&self, f: &mut Html, gpc: &GPiece, _gs: &GameState, _vpid: VisiblePieceId) {
     self.svg_piece_raw(f, gpc.face, &mut |_|Ok(()))?;
   }
   #[throws(IE)]
index c180b9b482412b0a47274f7eb3111d9485c156e0..9e5d5dd5ab9323746f2587efa682d8a74471cf50 100644 (file)
@@ -216,7 +216,7 @@ impl PieceTrait for Item {
   }
 
   #[throws(IE)]
-  fn svg_piece(&self, f: &mut Html, gpc: &GPiece, _vpid: VisiblePieceId) {
+  fn svg_piece(&self, f: &mut Html, gpc: &GPiece, _gs: &GameState, _vpid: VisiblePieceId) {
     let face = &self.faces[gpc.face];
     let svgd = &self.svgs[face.svg];
     face.xform.write_svgd(f, svgd)?;
index d93ee0ca7b9f7b943fd397c819273cd06637e7d6..25be6382b9a78f4411e1c7f88a5d1346dc437b30 100644 (file)
@@ -499,7 +499,8 @@ impl<'r> PrepareUpdatesBuffer<'r> {
 
   #[throws(InternalError)]
   fn piece_update_player(ioccults: &IOccults,
-                         gpc: &mut GPiece,
+                         gs: &GameState,
+                         gpc: &GPiece,
                          ipc: &IPiece,
                          op: PieceUpdateOp<(),()>,
                          pri: &Option<PieceRenderInstructions>)
@@ -508,7 +509,7 @@ impl<'r> PrepareUpdatesBuffer<'r> {
     let pri = match pri { Some(pri) => pri, None => return None };
 
 
-    let op = pri.map_piece_update_op(ioccults, gpc, ipc, op)?;
+    let op = pri.map_piece_update_op(ioccults, gs, gpc, ipc, op)?;
     op.map(|op| PreparedPieceUpdate {
       piece: pri.vpid,
       op,
@@ -533,8 +534,17 @@ impl<'r> PrepareUpdatesBuffer<'r> {
     if let Some(ref mut gpc) = gpc {
       gen_update(gpc, gen, &self.by_client);
     }
+    let gpc = gs.pieces.byid(piece).ok();
+
     let mut out: SecondarySlotMap<PlayerId, PreparedPieceUpdate> = default();
-    for (player, gpl) in &mut gs.players {
+    for player in self.g.iplayers.keys() {
+      // Iterate via iplayers because we want to borrow each gpl
+      // mutably and also gs immutably, at different times.  The naive
+      // approach fails because the iterator must borrow the whole
+      // thing, and mutably to produce mut references, so ties everything
+      // in a knot.
+      let gpl = match gs.players.get_mut(player) { Some(v)=>v, _=>continue };
+
       let ops = match ops {
         PUOs::Simple(update) => update,
         PUOs::PerPlayer(ref ops) => match ops.get(player) {
@@ -542,13 +552,14 @@ impl<'r> PrepareUpdatesBuffer<'r> {
           None => continue,
         }
       };
-      let op = match (&mut gpc, ipc) {
+      let op = match (gpc, ipc) {
         (Some(gpc), Some(ipc)) => {
           let pri = piece_pri(ioccults, &gs.occults, player,
-                              gpl, piece, *gpc, ipc);
+                              gpl, piece, gpc, ipc);
           gs.max_z.update_max(&gpc.zlevel.z);
+          drop(gpl);
           Self::piece_update_player(
-            ioccults, gpc, ipc, ops, &pri
+            ioccults, gs, gpc, ipc, ops, &pri
           )?
         }
         _ => gpl.idmap.fwd(piece).map(