diff --git a/sidecar/src/main.rs b/sidecar/src/main.rs index 0b4ee34..b2850a2 100644 --- a/sidecar/src/main.rs +++ b/sidecar/src/main.rs @@ -192,6 +192,12 @@ use tracing_subscriber::EnvFilter; /// one player's backpack, read live. The plugin never writes a backpack, and a bigger one an event /// lends is a `backpacks.size.N` permission in an ordinary `perm.sync`, so it needs nothing here. /// +/// Rust's own world events (§20.5, the module's PLAN_REDESIGNS.md §14.3.1) add one forward, +/// `POST /world/call`: run one of the game's own world events now, for a run. It is kept, so the +/// plugin remembers only the call's key and its run, and this process nothing. The `world.event` +/// frames (24 of them, told apart by `event`) ride the feed like any other event, and hello's +/// `console` like any other field. +/// /// `docs/rust-link/PROTOCOL.md` is the specification — §8 the read path, §9 identity, §10 the /// mirror, §11 configuration, §12 clans, §13 the raid frame, §14 the leases, §15 the world verbs, /// §16 the rewards, §17 the map, §18 the optional mods, §19 the walk's fixes, §20 the step editor; diff --git a/sidecar/src/web.rs b/sidecar/src/web.rs index ad0872b..299d690 100644 --- a/sidecar/src/web.rs +++ b/sidecar/src/web.rs @@ -123,6 +123,8 @@ pub async fn serve(addr: &str, state: AppState) -> anyhow::Result<()> { .route("/world/zone", post(world_zone)) .route("/world/place", post(world_place)) .route("/world/revert", post(world_revert)) + // Protocol 14 (§20.5): one of the game's own world events, now. Kept, never reverted. + .route("/world/call", post(world_call)) // Protocol 10 (§29): who took part, what they may redeem, and a line in chat. The tally // is counted and held by the plugin, the kit catalogue is Kits' own, and whether a chat // line was already said is the plugin's memory. These move lines, like everything above. @@ -554,6 +556,13 @@ async fn world_revert(State(st): State, Json(body): Json) -> Re forward_object(&st, body, "world.revert", "a revert").await } +/// Run one of the game's own world events for a run (protocol 14): a patrol helicopter, a cargo +/// ship, an airdrop and the rest. `world.called` (`called`, and `repeat` for a key already seen) +/// or `world.error` with a reason. What it starts is kept, so nothing is remembered here. +async fn world_call(State(st): State, Json(body): Json) -> Response { + forward_object(&st, body, "world.call", "a world event call").await +} + /// Start counting who takes part in a run. `tally.ok` or `tally.error` with a reason. async fn tally_open(State(st): State, Json(body): Json) -> Response { forward_object(&st, body, "tally.open", "a tally").await @@ -1270,6 +1279,22 @@ mod tests { assert!(stamp(json!("76561198000000001"), "backpacks.read", "r-41").is_none()); } + /// Protocol 14, world events: a call is stamped `world.call` whatever its body names, so the + /// route cannot place, revert or zone anything, and its params pass through untouched. + #[test] + fn protocol_14_world_call_is_stamped() { + let body = json!({ "cmd": "world.revert", "reqId": "theirs", "runId": "9", "key": "9:2", + "event": "airdrop", "count": 3, "x": -412.0, "z": 1180.5 }); + let stamped = stamp(body, "world.call", "r-50").expect("an object is stamped"); + + assert_eq!(stamped["cmd"], "world.call"); + assert_eq!(stamped["reqId"], "r-50"); + assert_eq!(stamped["event"], "airdrop"); + assert_eq!(stamped["count"], 3); + assert_eq!(stamped["x"], -412.0); + assert!(stamp(json!("airdrop"), "world.call", "r-51").is_none()); + } + /// Protocol 12: a title set is forwarded whole. The markup inside each `text` is the module's /// and the plugin's business, so it must arrive byte for byte as the website composed it. #[test]