chiark / gitweb /
delete piece
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 22 Aug 2020 21:09:40 +0000 (22:09 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 22 Aug 2020 21:09:40 +0000 (22:09 +0100)
src/api.rs
src/cmdlistener.rs
src/commands.rs
src/gamestate.rs
src/pieces.rs
src/updates.rs

index 3edf31d5fdb26db5e09eade85918f321d120a31b..7f574dae344f05ddf71d2d5bce36b7e86afa433a 100644 (file)
@@ -131,7 +131,7 @@ impl ApiPieceOp for ApiPieceGrab {
     let logent = LogEntry {
       html : format!("{} grasped {}",
                      &htmlescape::encode_minimal(&pl.nick),
-                     pc.describe_html(&lens.log_pri(piece, pc))?),
+                     pc.describe_html(&lens.log_pri(piece, pc))),
     };
 
     (update, vec![logent])
@@ -163,7 +163,7 @@ impl ApiPieceOp for ApiPieceUngrab {
     let logent = LogEntry {
       html : format!("{} released {}",
                      &htmlescape::encode_minimal(&pl.nick),
-                     pc.describe_html(&lens.log_pri(piece, pc))?),
+                     pc.describe_html(&lens.log_pri(piece, pc))),
     };
 
     (update, vec![logent])
index 444a668bc9bdaee7deefeb5eaf7354a587c36488..077bde0088025396131c4ed8f9c01abb0db5cedb 100644 (file)
@@ -283,13 +283,12 @@ impl UpdateHandler {
 
   #[throws(SVGProcessingError)]
   fn accumulate(&mut self, g: &mut Instance,
-                upieces: Vec<(PieceId,PieceUpdateOp<()>)>,
-                ulogs: Vec<LogEntry>,
-                mut raw: Vec<PreparedUpdateEntry>) {
+                updates: ExecuteGameChangeUpdates) {
+    let mut raw = updates.raw.unwrap_or_default();
     use UpdateHandler::*;
     match self {
       Bulk(bulk) => {
-        for (upiece, uuop) in upieces {
+        for (upiece, uuop) in updates.pcs {
           use PieceUpdateOp::*;
           let ne = match (bulk.pieces.get(upiece), uuop) {
             ( None               , e        ) => Some( e          ),
@@ -303,17 +302,17 @@ impl UpdateHandler {
             None     => { bulk.pieces.remove(upiece); },
           };
         }
-        bulk.logs |= ulogs.len() != 0;
+        bulk.logs |= updates.log.len() != 0;
         bulk.raw.append(&mut raw);
       },
       Online => {
-        let estimate = upieces.len() + ulogs.len();
+        let estimate = updates.pcs.len() + updates.log.len();
         let mut buf = PrepareUpdatesBuffer::new(g, None, Some(estimate));
-        for (upiece, uuop) in upieces {
+        for (upiece, uuop) in updates.pcs {
           let lens = TransparentLens { };
           buf.piece_update(upiece, uuop, &lens);
         }
-        buf.log_updates(ulogs);
+        buf.log_updates(updates.log);
         buf.raw_updates(raw);
       },
     }
@@ -352,8 +351,8 @@ fn execute_for_game(cs: &CommandStream, ig: &mut InstanceGuard,
   let mut responses = Vec::with_capacity(insns.len());
   let ok = (||{
     for insn in insns.drain(0..) {
-      let (upieces, ulogs, raw, resp) = execute_game_insn(cs, ig, insn)?;
-      uh.accumulate(ig, upieces, ulogs, raw.unwrap_or_default())?;
+      let (updates, resp) = execute_game_insn(cs, ig, insn)?;
+      uh.accumulate(ig, updates)?;
       responses.push(resp);
     }
     uh.complete(cs,ig)?;
@@ -371,9 +370,7 @@ const XXX_DEFAULT_POSD : Pos = [5,5];
 const CREATE_PIECES_MAX : u32 = 300;
 
 type ExecuteGameInsnResults = (
-  Vec<(PieceId,PieceUpdateOp<()>)>,
-  Vec<LogEntry>,
-  Option<Vec<PreparedUpdateEntry>>,
+  ExecuteGameChangeUpdates,
   MgmtGameResponse,
 );
 
@@ -381,48 +378,46 @@ type ExecuteGameInsnResults = (
 fn execute_game_insn(cs: &CommandStream,
                      ig: &mut InstanceGuard, update: MgmtGameInstruction)
                      -> ExecuteGameInsnResults {
+  type U = ExecuteGameChangeUpdates;
   use MgmtGameInstruction::*;
   use MgmtGameResponse::*;
   type Insn = MgmtGameInstruction;
   type Resp = MgmtGameResponse;
   fn readonly(_ig: &InstanceGuard, resp: Resp) -> ExecuteGameInsnResults {
-    (vec![], vec![], None, resp)
+    (U{ pcs: vec![], log: vec![], raw: None }, resp)
   }
 
   match update {
     Noop { } => readonly(ig, Fine),
 
-    Insn::DeletePiece(_) => panic!(),//xxx
-
-    MgmtGameInstruction::SetTableSize(size) => {
+    Insn::SetTableSize(size) => {
       ig.gs.table_size = size;
-      (vec![],
-       vec![ LogEntry {
-         html: format!("The table was resized to {}x{}", size[0], size[1]),
-       }],
-       Some(vec![ PreparedUpdateEntry::SetTableSize(size) ]),
+      (U{ pcs: vec![],
+          log: vec![ LogEntry {
+            html: format!("The table was resized to {}x{}", size[0], size[1]),
+          }],
+          raw: Some(vec![ PreparedUpdateEntry::SetTableSize(size) ]) },
        Fine)
     }
 
-    MgmtGameInstruction::AddPlayer(pl) => {
+    Insn::AddPlayer(pl) => {
       if ig.gs.players.values().any(|p| p.nick == pl.nick) {
         Err(ME::AlreadyExists)?;
       }
       let player = ig.player_new(pl)?;
       #[allow(clippy::useless_format)] // xxx below
-      (vec![],
-       vec![ LogEntry {
-         html: format!("The facilitator added a player xxx"),
-       } ],
-       None,
-       MgmtGameResponse::AddPlayer(player))
+      (U{ pcs: vec![],
+          log: vec![ LogEntry {
+            html: format!("The facilitator added a player xxx"),
+          } ],
+          raw: None },
+       Resp::AddPlayer(player))
     },
 
     Insn::ListPieces => readonly(ig, {
       let pieces = ig.gs.pieces.iter().map(|(piece,p)|{
         let &PieceState { pos, face, .. } = p;
-        let desc_html = p.p.describe_html(None)
-          .unwrap_or_else(|_|"[html formatting failed!]".to_string());
+        let desc_html = p.p.describe_html(None);
         MgmtGamePieceInfo { piece, pos, face, desc_html }
       }).collect();
       Resp::Pieces(pieces)
@@ -430,26 +425,38 @@ fn execute_game_insn(cs: &CommandStream,
 
     RemovePlayer(player) => {
       ig.player_remove(player)?;
-      (vec![], vec![], None, Fine)
+      #[allow(clippy::useless_format)] // xxx below
+      (U{ pcs: vec![],
+          log: vec![ LogEntry {
+            html: format!("The facilitator removed a player xxx"),
+          }],
+          raw: None},
+       Fine)
     },
 
-    MgmtGameInstruction::Info { } => {
+    Insn::Info => readonly(ig, {
       let players = ig.gs.players.clone();
       let table_size = ig.gs.table_size;
       let info = MgmtGameResponseGameInfo { table_size, players };
-      (vec![], vec![], None, Resp::Info(info))
-    },
+      Resp::Info(info)
+    }),
 
     ResetPlayerAccesses { players } => {
       let tokens = ig.players_access_reset(&players)?
         .drain(0..).map(|token| vec![token]).collect();
-      (vec![], vec![], None, PlayerAccessTokens(tokens))
+      (U{ pcs: vec![],
+          log: vec![],
+          raw: None },
+       PlayerAccessTokens(tokens))
     }
 
     ReportPlayerAccesses { players } => {
       let tokens = ig.players_access_report(&players)?;
-      (vec![], vec![], None, PlayerAccessTokens(tokens))
-    }
+      (U{ pcs: vec![],
+          log: vec![],
+          raw: None },
+       PlayerAccessTokens(tokens))
+    },
 
     SetFixedPlayerAccess { player, token } => {
       let authorised : AuthorisedSatisfactory =
@@ -461,9 +468,26 @@ fn execute_game_insn(cs: &CommandStream,
       ig.player_access_register_fixed(
         player, token, authorised
       )?;
-      (vec![], vec![], None, Fine)
+      (U{ pcs: vec![],
+          log: vec![],
+          raw: None},
+       Fine)
     }
 
+    DeletePiece(piece) => {
+      let gs = &mut ig.gs;
+      let p = gs.pieces.remove(piece).ok_or(ME::PieceNotFound)?;
+      let desc_html = p.p.describe_html(Some(Default::default()));
+      p.p.delete_hook(&p, gs);
+      (U{ pcs: vec![(piece, PieceUpdateOp::Delete())],
+          log: vec![ LogEntry {
+            html: format!("A piece {} was removed from the game",
+                          desc_html),
+          }],
+          raw: None },
+       Fine)
+    },
+
     AddPieces(PiecesSpec{ pos,posd,count,face,info }) => {
       let gs = &mut ig.gs;
       let count = count.unwrap_or(1);
@@ -490,13 +514,12 @@ fn execute_game_insn(cs: &CommandStream,
         pos[1] += posd[1];
       }
 
-      (updates,
-       vec![ LogEntry {
-         html: format!("The facilitaror added {} pieces", count),
-       }],
-       None,
-       Fine
-      )
+      (U{ pcs: updates,
+          log: vec![ LogEntry {
+            html: format!("The facilitaror added {} pieces", count),
+          }],
+          raw: None },
+       Fine)
     },
   }
 }
index a61b6ae3c1faafbfccb45f375811155ea7205ca6..b594ef0330d5f06682af0f51308dc46c5697f42d 100644 (file)
@@ -79,6 +79,7 @@ pub enum MgmtError {
   GameNotFound,
   GameCorrupted,
   PlayerNotFound,
+  PieceNotFound,
   LimitExceeded,
   SVGProcessingFailed(#[from] SVGProcessingError),
   GameError(#[from] GameError),
index 905f5cb6825029be977f7aee670397bbca6200c9..b9ad1171111693cc504edd05975bb0243e5b22f5 100644 (file)
@@ -92,7 +92,12 @@ pub trait Piece : Send + Debug {
   fn thresh_dragraise(&self, pri : &PieceRenderInstructions)
                       -> Option<Coord>;
 
-  fn describe_html(&self, face : Option<FaceId>) -> Result<String,SE>;
+  fn describe_html(&self, face : Option<FaceId>) -> String;
+
+  fn delete_hook(&self, _p: &PieceState, _gs: &mut GameState)
+                 -> ExecuteGameChangeUpdates { 
+    ExecuteGameChangeUpdates{ pcs: vec![], log: vec![], raw: None }
+  }
 }
 
 #[derive(Debug,Copy,Clone)]
@@ -180,9 +185,8 @@ impl PieceState {
     }
   }
 
-  #[throws(SE)]
   pub fn describe_html(&self, pri : &PieceRenderInstructions) -> String {
-    self.p.describe_html(Some(pri.face))?
+    self.p.describe_html(Some(pri.face))
   }
 }
 
index 1013e2b8e063f1ccd0634bec91113cd7fdc9f6cf..facaad9e9139427e787f9e7d513fc24beef7f5ce 100644 (file)
@@ -98,7 +98,6 @@ impl Piece for SimpleShape {
   #[throws(SE)]
   fn svg_x_defs(&self, _f: &mut String, _pri : &PieceRenderInstructions) {
   }
-  #[throws(SE)]
   fn describe_html(&self, face : Option<FaceId>) -> String {
     if let Some(face) = face {
       format!("a {} {}", self.colours[face], self.desc)
index 910d3274c10dcfa3f2c60992a0053fbe142a5ecb..494d03668fb54883c648fd9baebea6175c55a466 100644 (file)
@@ -10,6 +10,15 @@ pub struct ClientSequence(u64);
 
 const RECENT_BUFFER : usize = 50;
 
+// ---------- from manamgenet operations ----------
+
+#[derive(Debug)] // not Default
+pub struct ExecuteGameChangeUpdates {
+  pub pcs: Vec<(PieceId,PieceUpdateOp<()>)>,
+  pub log: Vec<LogEntry>,
+  pub raw: Option<Vec<PreparedUpdateEntry>>,
+}
+
 // ---------- prepared updates, queued in memory ----------
 
 pub type PlayerUpdatesLog =