chiark / gitweb /
Move game spec parsing from client to server
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Thu, 29 Apr 2021 00:43:38 +0000 (01:43 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Thu, 29 Apr 2021 00:56:20 +0000 (01:56 +0100)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
daemon/cmdlistener.rs
src/bin/otter.rs
src/commands.rs

index 92bc1f6ef2adb2fe0a3e8c1743b7d64e27be6df1..baa99474d923672665c8d61a88cd54dfa6237162 100644 (file)
@@ -451,6 +451,35 @@ fn execute_game_insn<'cs, 'igr, 'ig: 'igr>(
       no_updates(ig, MGR::Fine)
     },
 
+    MGI::ResetFromGameSpec { spec_toml: spec } => {
+      let ig = cs.check_acl(&ag, ig, PCH::Instance, &[TP::ChangePieces])?.0;
+      let spec: toml::Value = spec.parse()
+        .map_err(|e: toml::de::Error| ME::TomlSyntaxError(e.to_string()))?;
+      let GameSpec {
+        pieces, table_size, table_colour, pcaliases,
+      } = toml_de::from_value(&spec)
+        .map_err(|e: toml_de::Error| ME::TomlStructureError(e.to_string()))?;
+      let mut insns = vec![];
+      for piece in ig.gs.pieces.keys() {
+        insns.push(MGI::DeletePiece(piece));
+      }
+      for (alias, target) in pcaliases.into_iter() {
+        insns.push(MGI::DefinePieceAlias{ alias, target });
+      }
+      insns.push(MGI::ClearLog);
+      insns.push(MGI::SetTableSize(table_size));
+      insns.push(MGI::SetTableColour(table_colour));
+      for pspec in pieces.into_iter() {
+        insns.push(MGI::AddPieces(pspec));
+      }
+      let html = hformat!("{} reset the game", &who);
+      (U{ pcs: vec![],
+          log: vec![ LogEntry { html } ],
+          raw: None },
+       MGR::InsnExpanded,
+       None, insns, ig)
+    }
+
     MGI::InsnMark(token) => {
       let (ig, _) = cs.check_acl(&ag,ig,PCH::Instance, &[TP::TestExistence])?;
       no_updates(ig, MGR::InsnMark(token))
index 91cae8bb49966e16adf9ad16eb3170049cade449..e10ee880bf07929c36a54c90453a3b2802593b89 100644 (file)
@@ -575,7 +575,6 @@ impl<T:DeserializeOwned+SomeSpec> SpecParse for SpecParseToml<T> {
   }
 }
 impl<T> SpecParseToml<T> { pub fn new() -> Self { Self(default()) } }
-#[allow(dead_code)]
 struct SpecRaw<T>(pub PhantomData<T>);
 impl<T:SomeSpec> SpecParse for SpecRaw<T> {
   type T = String;
@@ -583,7 +582,6 @@ impl<T:SomeSpec> SpecParse for SpecRaw<T> {
   #[throws(AE)]
   fn parse(buf: String) -> String { buf }
 }
-#[allow(dead_code)]
 impl<T> SpecRaw<T> { pub fn new() -> Self { Self(default()) } }
 
 #[throws(AE)]
@@ -696,12 +694,8 @@ mod reset_game {
       instance_name.clone(),
       MgmtGameUpdateMode::Bulk,
     );
-    let GameSpec {
-      table_size,
-      pieces,
-      table_colour,
-      pcaliases,
-    } = read_spec(&ma, &args.game_file, SpecParseToml::new())?;
+    let spec_toml = read_spec(&ma, &args.game_file,
+                              SpecRaw::<GameSpec>::new())?;
 
     let mut insns = vec![];
 
@@ -721,25 +715,7 @@ mod reset_game {
       insns.extend(setup_table(&ma, &instance_name, &table_spec)?);
     }
 
-    let (pcs, aliases) = chan.list_pieces()?;
-    for p in pcs {
-      insns.push(MgmtGameInstruction::DeletePiece(p.piece));
-    }
-    for p in aliases {
-      insns.push(MgmtGameInstruction::DeletePieceAlias(p));
-    }
-
-    for (alias, target) in pcaliases.into_iter() {
-      insns.push(MGI::DefinePieceAlias{ alias, target });
-    }
-
-    insns.push(MGI::ClearLog);
-    insns.push(MGI::SetTableSize(table_size));
-    insns.push(MGI::SetTableColour(table_colour));
-
-    for pspec in pieces.into_iter() {
-      insns.push(MGI::AddPieces(pspec));
-    }
+    insns.push(MGI::ResetFromGameSpec { spec_toml });
 
     chan.alter_game(insns, None)?;
 
index 92fcdfe9207e5f1dd4d55920aac92028c94be8c0..1618b27d3d40480beb0983954a8e8f1bbd86e8df 100644 (file)
@@ -95,6 +95,8 @@ pub enum MgmtGameInstruction {
   DeletePieceAlias(String),
   DefinePieceAlias { alias: String, target: Box<dyn PieceSpec> },
 
+  ResetFromGameSpec { spec_toml: String },
+
   ResetPlayerAccess(PlayerId),
   RedeliverPlayerAccess(PlayerId),
 
@@ -203,6 +205,8 @@ pub enum MgmtError {
   BadSpec(#[from] SpecError),
   TokenDeliveryFailed(#[from] TokenDeliveryError),
   CoordinateOverflow(#[from] CoordinateOverflow),
+  TomlSyntaxError(String),
+  TomlStructureError(String),
   RngIsReal,
 }
 impl Display for MgmtError {