feat(rust): Guarded Crate — feed, map, Warden, Place a guarded crate (PLAN_REDESIGNS §14.3.5)
All checks were successful
PR Checks / client-build (pull_request) Successful in 30s
PR Checks / server-tests (pull_request) Successful in 34s
PR Checks / frozen-manifest (pull_request) Successful in -1m34s

Stage 6 of the §14.3 integration plan, on protocol 14. Spec: docs
rust-link/PROTOCOL.md §20.9.

- gc.started and gc.ended public, gc.failed staff's; guardedCrate.js reads
  each row per viewer (the clearer's name for the presence audience, Steam id,
  position and key for staff, `won` for everyone).
- Triggers rust.gc.started and rust.gc.ended (a crate a player cleared only).
- The step rust.gc.place: an event from rust.options.gc_events and a world
  call's location; refused at verify for Guarded Crate absent, NpcSpawn missing
  (D364), console unavailable, or an unknown event. Kept (D373); the run log's
  success line says so (D380). Budget rust.gc.crates.
- Warden (D375): guarded_won, title category guardedwon, Crates cleared column.
- Map marker, server settings line, swagger, engagement manifest, bundle, README.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
This commit is contained in:
2026-10-15 12:26:50 -05:00
parent 140bc67fe1
commit da1d74bdff
28 changed files with 1230 additions and 24 deletions

View File

@@ -669,7 +669,50 @@ const DANGEROUS_TREASURES = [
},
]
const TRIGGERS = Object.freeze([RAID, ...BROADCASTS, ACCOUNT, REWARD, ...CLANS, ...MODERATION, ...NPCS, ...BOSSES, ...WORLD, ...DANGEROUS_TREASURES])
// ── Guarded Crate (protocol 14, PLAN_REDESIGNS §14.3.5, §14.3.9) ────────────
//
// A guarded crate landing and being cleared are triggers, as Dangerous
// Treasures' are: public news, the server the cooldown subject. `player` is the
// clearer's in-game name only. A crate whose guards went with nobody killing
// the last (NpcSpawn reloaded under it) and one that timed out raise nothing:
// neither is news.
const GC_BY_EVENT = { name: 'byEvent', type: 'boolean', required: true, example: false,
description: 'Whether one of this site\'s events placed it (a Place a guarded crate step).' }
const GUARDED_CRATE = [
{
id: 'rust.gc.started',
label: 'A guarded crate landed',
description: 'Guarded Crate dropped a locked crate ringed by guards on a server: on its own schedule, by an admin, or by an event.',
kind: 'event',
subjectKey: 'subject',
audience: 'subscribers',
ceiling: 'everyone',
version: V1,
variables: [...SERVER, ...HEADLINE, { ...DT_SUBJECT, example: 'main:gc.started' }, WORLD_GRID, GC_BY_EVENT],
},
{
id: 'rust.gc.ended',
label: 'A guarded crate was cleared',
description: 'A player killed the last guard of a guarded crate on a server.',
kind: 'event',
subjectKey: 'subject',
audience: 'subscribers',
ceiling: 'everyone',
version: V1,
variables: [
...SERVER,
...HEADLINE,
{ ...DT_SUBJECT, example: 'main:gc.ended' },
WORLD_GRID,
{ name: 'player', type: 'string', required: true, example: 'Marisol',
description: 'Who killed the last guard, by in-game name.' },
],
},
]
const TRIGGERS = Object.freeze([RAID, ...BROADCASTS, ACCOUNT, REWARD, ...CLANS, ...MODERATION, ...NPCS, ...BOSSES, ...WORLD, ...DANGEROUS_TREASURES, ...GUARDED_CRATE])
const TRIGGER_IDS = Object.freeze(Object.fromEntries(TRIGGERS.map((t) => [t.id, t.id])))