feat(rust): the world verbs, their budgets and the reconcile watch (phase 13a, protocol 9)
- registerEventActions: rust.zone.open and rust.prefab.place, both reversible 'ledger' with revert() and reconcile(), budgetMs 15000 above the client's 12 s. A location is a monument (kind + instance, carrying its server) or raw coordinates, exactly one (D87, D93); bounds mirrored from the plugin so a bad step is refused on the form (D95); zone minutes required and held by the game (D96). - registerEventBudgets: rust.prefabs, rust.npcs and rust.zone.minutes, each beside the verb that spends it (D79, D89). - Option sources rust.options.monuments (live, searchable) and rust.options.prefabs (mirrored, answers with every server off), registered in the one batch core accepts alongside the lease sources. - Refs are <serverId>:<id>, since revert and reconcile get no params. The undo sends no idempotency key; a lost answer is reverted by key on every server. reconcile asks the plugin, and a server that cannot be asked keeps its rows. - The refresh's bootId/wipeId watch calls ctx.events.reconcile() on a restart or a wipe, never on a first sighting or a reconnect (§11.1). - The permission mirror keeps the plugin's new notLanded grants out of what it records as pushed, and the admin page says so (D85). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
This commit is contained in:
@@ -60,7 +60,10 @@ const TIMEOUT_MS = 12000
|
||||
* walls and the cupboard and names who is authorised there, which is what the
|
||||
* raid alert is sent to (PLAN.md §25); **8** adds the leases — `GET /lease`,
|
||||
* `POST /lease` and `POST /lease/release` — which is what lets an event borrow
|
||||
* a value on a server and give it back (PLAN.md §27). The bump lands here in the same change as the emitters,
|
||||
* a value on a server and give it back (PLAN.md §27); **9** adds the world
|
||||
* verbs — `/world/monuments`, `/world/owned`, `/world/zone`, `/world/place` and
|
||||
* `/world/revert` — what an event places in the world and gives back (PLAN.md
|
||||
* §28). The bump lands here in the same change as the emitters,
|
||||
* because the sidecar refuses a client declaring a different version with a
|
||||
* `409`: a module left on 2 would stop being able to read the server board it
|
||||
* has been reading all along. A constant that lags the deployment is not a safe
|
||||
@@ -70,7 +73,7 @@ const TIMEOUT_MS = 12000
|
||||
* deployment into a `409` naming both numbers instead of a parse failure three
|
||||
* layers further in.
|
||||
*/
|
||||
const PROTOCOL_VERSION = 8
|
||||
const PROTOCOL_VERSION = 9
|
||||
|
||||
/** What a caller gets back. Shaped once so every call site reads the same. */
|
||||
function reply(ok, status, data = null) {
|
||||
@@ -331,6 +334,34 @@ const leaseApply = (server, body) =>
|
||||
const leaseRelease = (server, body) =>
|
||||
request(server, '/lease/release', { method: 'POST', body, timeoutMs: LEASE_TIMEOUT_MS })
|
||||
|
||||
/**
|
||||
* This wipe's monuments, the plugin's placeable allowlist and its bounds
|
||||
* (protocol 9). Live, because a map changes at every wipe.
|
||||
*/
|
||||
const worldMonuments = (server) => request(server, '/world/monuments')
|
||||
|
||||
/**
|
||||
* What the world still holds of what events made, looked for by net id on the
|
||||
* game (a restart is not proof a crate is gone, §28.1). One run, or all.
|
||||
*/
|
||||
const worldOwned = (server, { runId } = {}) =>
|
||||
request(server, `/world/owned${runId ? `?runId=${encodeURIComponent(runId)}` : ''}`)
|
||||
|
||||
/**
|
||||
* Open a zone, or place crates or NPCs, for a run. `data.kind` is `world.ok`
|
||||
* (with `placed`) or `world.error` (with `reason`); a repeated idempotency key
|
||||
* is answered with the first call's ids and `repeat: true`.
|
||||
*/
|
||||
const worldZone = (server, body) => request(server, '/world/zone', { method: 'POST', body })
|
||||
const worldPlace = (server, body) => request(server, '/world/place', { method: 'POST', body })
|
||||
|
||||
/**
|
||||
* Give back what a run owns: named ids, else everything under a key, else the
|
||||
* whole run. `data` lists `removed`, `gone` (already not there — a success)
|
||||
* and `refused` (there, and not this run's to erase).
|
||||
*/
|
||||
const worldRevert = (server, body) => request(server, '/world/revert', { method: 'POST', body })
|
||||
|
||||
module.exports = {
|
||||
TIMEOUT_MS,
|
||||
LEASE_TIMEOUT_MS,
|
||||
@@ -352,5 +383,10 @@ module.exports = {
|
||||
leaseList,
|
||||
leaseApply,
|
||||
leaseRelease,
|
||||
worldMonuments,
|
||||
worldOwned,
|
||||
worldZone,
|
||||
worldPlace,
|
||||
worldRevert,
|
||||
joinUrl,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user