From 2f91319e786ce8f57eded5f4b9d3f042efa0e6bc Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Wed, 19 May 2021 23:19:49 +0100 Subject: [PATCH] specs: Support ResetFromNamesSpec And the associated config. Signed-off-by: Ian Jackson --- apitest/apitest.rs | 1 + daemon/cmdlistener.rs | 16 ++++++++++++++++ server-test-zealot.toml | 1 + src/bundles.rs | 28 ++++++++++++++++++++++++++++ src/commands.rs | 3 +++ src/config.rs | 7 +++++-- 6 files changed, 54 insertions(+), 2 deletions(-) diff --git a/apitest/apitest.rs b/apitest/apitest.rs index 04aeaef1..49aded72 100644 --- a/apitest/apitest.rs +++ b/apitest/apitest.rs @@ -615,6 +615,7 @@ public_url = "@url@" save_dir = "." command_socket = "@command_socket@" template_dir = "@src@/templates" +specs_dir = "@src@/specs" nwtemplate_dir = "@src@/nwtemplates" bundled_sources = "@target@/bundled-sources" wasm_dir = "@target@/packed-wasm" diff --git a/daemon/cmdlistener.rs b/daemon/cmdlistener.rs index 22cebb71..3ad736b8 100644 --- a/daemon/cmdlistener.rs +++ b/daemon/cmdlistener.rs @@ -690,6 +690,22 @@ fn execute_game_insn<'cs, 'igr, 'ig: 'igr>( Ok(LogEntry { html }) }))? } + + MGI::ResetFromNamedSpec { spec } => { + reset_game_from_spec(cs,ag,ig,who, Box::new(move |ig| { + let (mut spec_f, what) = bundles::load_spec_to_read(ig,&spec)?; + let mut buf = String::new(); + spec_f.read_to_string(&mut buf).map_err(|e| match e.kind() { + ErrorKind::InvalidData => ME::GameSpecInvalidData, + ErrorKind::UnexpectedEof => ME::BadBundle(e.to_string()), + _ => IE::from( + AE::from(e).context(what).context("read spec") + ).into() + })?; + Ok::<_,ME>(buf) + }))? + } + MGI::ResetFromGameSpec { spec_toml: spec } => { reset_game_from_spec(cs,ag,ig,who, Box::new(|_| Ok::<_,ME>(spec)))? } diff --git a/server-test-zealot.toml b/server-test-zealot.toml index e78230f6..af0776b3 100644 --- a/server-test-zealot.toml +++ b/server-test-zealot.toml @@ -12,6 +12,7 @@ save_dir = "/home/rustcargo/Rustup/Game/server" command_socket = "/home/rustcargo/Rustup/Game/server/command.socket" template_dir = "/home/ian/Rustup/Game/server/templates" nwtemplate_dir = "/home/ian/Rustup/Game/server/nwtemplates" +specs_dir = "/home/ian/Rustup/Game/server/specs" bundled_sources = "/home/rustcargo/Rustup/Game/server/target/bundled-sources" wasm_dir = "/home/rustcargo/Rustup/Game/server/target/packed-wasm" libexec_dir = "/home/rustcargo/Rustup/Game/server/target/debug" diff --git a/src/bundles.rs b/src/bundles.rs index c7bc2c9b..30a9b755 100644 --- a/src/bundles.rs +++ b/src/bundles.rs @@ -708,6 +708,34 @@ fn make_usvg(za: &mut IndexedZip, progress_count: &mut usize, } } +//---------- specs ---------- + +#[throws(MgmtError)] +pub fn load_spec_to_read(ig: &Instance, spec_name: &str) + -> (Box, String) +{ + let spec_leaf = format!("{}.game.toml", spec_name); + + // todo: game specs from bundles + + if spec_name.chars().all( + |c| c.is_ascii_alphanumeric() || c=='-' || c =='_' + ) { + let path = format!("{}/{}", config().specs_dir, &spec_leaf); + debug!("{}: trying to loading builtin spec from {}", + &ig.name, &path); + match File::open(&path) { + Ok(f) => return (Box::new(f) as _, path), + Err(e) if e.kind() == ErrorKind::NotFound => { }, + Err(e) => throw!(IE::from( + AE::from(e).context(path).context("try open game spec") + )), + } + } + + Err(ME::GameSpecNotFound)? +} + //---------- scanning/incorporating/uploading ---------- #[throws(InternalError)] diff --git a/src/commands.rs b/src/commands.rs index a3901244..056ce1a2 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -119,6 +119,7 @@ pub enum MgmtGameInstruction { DefinePieceAlias { alias: String, target: Box }, ClearGame { }, + ResetFromNamedSpec { spec: String }, ResetFromGameSpec { spec_toml: String }, ResetPlayerAccess(PlayerId), @@ -249,6 +250,8 @@ pub enum MgmtError { #[error("bad bundle: {0}")] BadBundle(String), #[error("bundle not found")] BundleNotFound, #[error("bundle(s) in use, cannot clear ({0})")] BundlesInUse(String), + #[error("game spec not found")] GameSpecNotFound, + #[error("game contains invalid UTF-8")] GameSpecInvalidData, #[error("idle timeout waiting for mgmt command")] IdleTimeout, #[error("upload took too long (timed out)")] UploadTimeout, } diff --git a/src/config.rs b/src/config.rs index b8041ab2..ce97d696 100644 --- a/src/config.rs +++ b/src/config.rs @@ -36,6 +36,7 @@ pub struct ServerConfigSpec { pub log: Option, pub bundled_sources: Option, pub shapelibs: Option>, + pub specs_dir: Option, pub sendmail: Option, pub debug_js_inject_file: Option, #[serde(default)] pub fake_rng: FakeRngSpec, @@ -65,6 +66,7 @@ pub struct ServerConfig { pub usvg_bin: String, pub bundled_sources: String, pub shapelibs: Vec, + pub specs_dir: String, pub sendmail: String, pub debug_js_inject: Arc, pub check_bundled_sources: bool, @@ -115,7 +117,7 @@ impl ServerConfigSpec { let ServerConfigSpec { change_directory, base_dir, save_dir, command_socket, debug, http_port, public_url, sse_wildcard_url, rocket_workers, - template_dir, nwtemplate_dir, wasm_dir, libexec_dir, usvg_bin, + template_dir, specs_dir, nwtemplate_dir, wasm_dir, libexec_dir, usvg_bin, log, bundled_sources, shapelibs, sendmail, debug_js_inject_file, check_bundled_sources, fake_rng, } = self; @@ -139,6 +141,7 @@ impl ServerConfigSpec { }; let save_dir = defpath(save_dir, "save" ); + let specs_dir = defpath(specs_dir, "specs" ); let command_socket = defpath(command_socket, "var/command.socket"); let template_dir = defpath(template_dir, "assets" ); let wasm_dir = defpath(wasm_dir, "assets" ); @@ -228,7 +231,7 @@ impl ServerConfigSpec { let server = ServerConfig { save_dir, command_socket, debug, http_port, public_url, sse_wildcard_url, rocket_workers, - template_dir, nwtemplate_dir, wasm_dir, libexec_dir, + template_dir, specs_dir, nwtemplate_dir, wasm_dir, libexec_dir, bundled_sources, shapelibs, sendmail, usvg_bin, debug_js_inject, check_bundled_sources, game_rng, prctx, }; -- 2.30.2