// ── Guarded Crate, with NpcSpawn (protocol 14, PLAN_REDESIGNS §14.3.5) ───── // // Bazz3l's Guarded Crate drops a locked crate from a cargo plane and rings it // with NpcSpawn's scientists; whoever kills the last guard has cleared it. Its // events reach this module as three kinds: `gc.started` (public), `gc.ended` // (public) and `gc.failed` (staff's, the timeout). The crate cleared is // *Warden*'s count, from the tally's `guardedWon` (D375). A run's step places // one (`eventGuardedCrate.js`). // // ── Who may read what ────────────────────────────────────────────────────── // // As Dangerous Treasures' are (`dangerousTreasures.js`, D376): the event and its // grid are public; the clearer's name shows only to the operator's presence // audience, so with presence left at staff a signed-out visitor reads "The // guarded crate was cleared · M4"; the Steam id, the position and a step's key // are staff's. Whether a player cleared it at all is public (`won`), since an // ending with nobody named (NpcSpawn reloaded under it) names nobody either. const { gridOf } = require('./worldEvents') const KINDS = Object.freeze(['gc.started', 'gc.ended', 'gc.failed']) const STEAM_ID = /^\d{17}$/ function isKind(kind) { return KINDS.includes(kind) } /** * One `gc.*` frame for one viewer: `{ staff, presence, geometry }`. Passes the * envelope, adds `grid`; an ending adds `won`, and `name` for the presence * audience. Staff also get `x`, `z`, the step's `key` and the clearer's * `steamId`. Any other frame is returned as is. */ function shapeFor(frame, { staff = false, presence = false, geometry = null } = {}) { if (!frame || !isKind(frame.kind)) return frame const out = {} for (const key of ['kind', 'type', 't', 'serverId', 'wipeId']) { if (frame[key] !== undefined) out[key] = frame[key] } const grid = gridOf(geometry, frame.x, frame.z) if (grid) out.grid = grid if (frame.kind === 'gc.ended') { out.won = STEAM_ID.test(String(frame.steamId || '')) if (out.won && (presence || staff) && typeof frame.name === 'string' && frame.name) out.name = frame.name if (out.won && staff) out.steamId = String(frame.steamId) } if (staff) { for (const key of ['x', 'z', 'key']) { if (frame[key] !== undefined) out[key] = frame[key] } } return out } /** * A server's last report about Guarded Crate and its console, from * `servers.db.gcReportFor`: `{ guardedCrate, consolePlugins }`, each null where * the plugin never said (no state yet, or a plugin before protocol 14). * `guardedCrate` is `{ loaded, version, npcSpawn: { loaded, version }, events }`; * `npcSpawn` is null where it was not said, and `events` null where the * plugin could not read Guarded Crate's data file. */ function reportOf(row) { const parse = (value) => { if (value === null || value === undefined) return null if (typeof value !== 'string') return value try { return JSON.parse(value) } catch { return null } } const integration = (body) => body && typeof body === 'object' ? { loaded: body.loaded === true, version: typeof body.version === 'string' ? body.version : null } : null const gc = row ? parse(row.guardedCrate) : null const probe = row ? parse(row.console) : null return { guardedCrate: gc && typeof gc === 'object' ? { ...integration(gc), npcSpawn: integration(gc.npcSpawn), events: Array.isArray(gc.events) ? gc.events.filter((e) => typeof e === 'string' && e.trim()) : null, } : null, consolePlugins: probe && typeof probe === 'object' && typeof probe.plugins === 'boolean' ? probe.plugins : null, } } module.exports = { KINDS, isKind, shapeFor, reportOf }