chiark / gitweb /
prevent modifying which pieces exist without a modperm
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 27 Sep 2020 01:04:12 +0000 (02:04 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 27 Sep 2020 01:04:12 +0000 (02:04 +0100)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
src/cmdlistener.rs
src/gamestate.rs
src/global.rs

index 6267bcf9aa4a996d37082212ec15faf0d482a0a0..3eb53d16d0fa3334ef298452454ef61d96ad07e0 100644 (file)
@@ -227,7 +227,7 @@ fn execute_game_insn(cs: &CommandStream,
       let p = ig.pieces.as_mut(modperm)
         .remove(piece).ok_or(ME::PieceNotFound)?;
       let gs = &mut ig.gs;
-      let pc = gs.pieces.remove(piece);
+      let pc = gs.pieces.as_mut(modperm).remove(piece);
       let desc_html = p.describe_html(Some(Default::default()));
       if let Some(pc) = pc { p.delete_hook(&pc, gs); }
       (U{ pcs: vec![(piece, PieceUpdateOp::Delete())],
@@ -264,7 +264,7 @@ fn execute_game_insn(cs: &CommandStream,
         if let (_, true) = pc.pos.clamped(gs.table_size) {
           throw!(SpecError::PosOffTable);
         }
-        let piece = gs.pieces.insert(pc);
+        let piece = gs.pieces.as_mut(modperm).insert(pc);
         ig.pieces.as_mut(modperm).insert(piece, p);
         updates.push((piece, PieceUpdateOp::Insert(())));
         pos[0] += posd[0];
index 9cabc5aa7e9159daf8e58471c01d0075bf94a065..54231352721226cd5d87c2fa2c6aca35f5eefbe7 100644 (file)
@@ -44,7 +44,7 @@ pub struct ZLevel {
 #[derive(Debug,Serialize,Deserialize)]
 pub struct GameState {
   pub table_size : Pos,
-  pub pieces : DenseSlotMap<PieceId,PieceState>,
+  pub pieces : Pieces,
   pub players : PlayerMap,
   pub gen : Generation,
   pub log : Vec<(Generation,Arc<LogEntry>)>,
@@ -196,6 +196,7 @@ impl Debug for Html {
 
 // ---------- game state - rendering etc. ----------
 
+
 impl PieceState {
   #[throws(IE)]
   pub fn prep_piecestate(&self, p: &dyn Piece, pri : &PieceRenderInstructions)
index f6986e081be42610f86a4d0259cf77413fb20f0c..341008d6d0219d3a8963c7655bc641dcb51b287e 100644 (file)
@@ -7,6 +7,7 @@
 use crate::imports::*;
 
 use std::sync::PoisonError;
+use slotmap::dense as sm;
 
 // ---------- newtypes and type aliases ----------
 
@@ -49,6 +50,11 @@ pub type ActualPiecesLoaded = SecondarySlotMap<PieceId,Box<dyn Piece>>;
 #[derive(Copy,Clone,Debug)]
 pub struct ModifyingPieces(());
 
+#[derive(Debug,Serialize,Deserialize,Default)]
+#[serde(transparent)]
+pub struct Pieces (pub(in crate::global) ActualPieces);
+type ActualPieces = DenseSlotMap<PieceId,PieceState>;
+
 #[derive(Debug,Clone,Deserialize,Serialize)]
 #[derive(Eq,PartialEq,Ord,PartialOrd,Hash)]
 pub enum ManagementScope {
@@ -408,7 +414,9 @@ impl InstanceGuard<'_> {
       }
     }
     undo.push(Box::new(|ig| for &piece in &updated_pieces {
-      ig.c.g.gs.pieces[piece].held = Some(oldplayer)
+      (||Some({
+        ig.c.g.gs.pieces.get_mut(piece)?.held = Some(oldplayer);
+      }))();
     }));
 
     // Handle gs.log:
@@ -433,7 +441,9 @@ impl InstanceGuard<'_> {
 
     (||{
       for &piece in &updated_pieces {
-        self.c.g.gs.pieces[piece].gen = self.c.g.gs.gen;
+        (||Some({
+          self.c.g.gs.pieces.get_mut(piece)?.gen = self.c.g.gs.gen;
+        }))();
       }
 
       let lens = TransparentLens { };
@@ -730,8 +740,8 @@ impl InstanceGuard<'_> {
       for mut p in gs.pieces.values_mut() {
         p.lastclient = Default::default();
       }
-      gs.pieces.retain(|k,_v| pieces.contains_key(k));
-      pieces.retain(|k,_v| gs.pieces.contains_key(k));
+      gs.pieces.0.retain(|k,_v| pieces.contains_key(k));
+      pieces.retain(|k,_v| gs.pieces.0.contains_key(k));
 
       gs
     };
@@ -908,6 +918,50 @@ impl PiecesLoaded {
   }
 }
 
+// ---------- gamestate pieces table ----------
+
+impl Deref for Pieces {
+  type Target = ActualPieces;
+  fn deref(&self) -> &ActualPieces { &self.0 }
+}
+
+impl Pieces {
+  pub fn get_mut(&mut self, piece: PieceId) -> Option<&mut PieceState> {
+    self.0.get_mut(piece)
+  }
+  pub fn values_mut(&mut self) -> sm::ValuesMut<PieceId, PieceState> {
+    self.0.values_mut()
+  }
+  pub fn as_mut(&mut self, _: ModifyingPieces) -> &mut ActualPieces {
+    &mut self.0
+  }
+}
+
+impl ById for Pieces {
+  type Id = PieceId;
+  type Entry = PieceState;
+  type Error = OnlineError;
+  #[throws(OE)]
+  fn byid(&self, piece: PieceId) -> &PieceState {
+    self.get(piece).ok_or(OE::PieceGone)?
+  }
+  #[throws(OE)]
+  fn byid_mut(&mut self, piece: PieceId) -> &mut PieceState {
+    self.get_mut(piece).ok_or(OE::PieceGone)?
+  }
+}
+
+/*impl<'p> IntoIterator for &'p Pieces {
+  type Item = (PieceId, &'p PieceState);
+  type IntoIter = sm::Iter<'p, PieceId, PieceState>;
+  fn into_iter(self) -> Self::IntoIter { (&self.0).into_iter() }
+}*/
+impl<'p> IntoIterator for &'p mut Pieces {
+  type Item = (PieceId, &'p mut PieceState);
+  type IntoIter = sm::IterMut<'p, PieceId, PieceState>;
+  fn into_iter(self) -> Self::IntoIter { (&mut self.0).into_iter() }
+}
+
 // ========== background maintenance ==========
 
 // ---------- delayed game save ----------