Merge main into docs/rust-title-conditions: §3's docs
PROTOCOL.md: §19.10 (titles) and §19.11 (zones) both kept, in order. PLAN_REDESIGNS: the D210-D212 table moved from the end of the file, where docs#296 appended it by mistake, into §10 after D209. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
This commit is contained in:
@@ -1436,7 +1436,7 @@ five routes.
|
||||
| Command | Answers | |
|
||||
|---|---|---|
|
||||
| `world.monuments` | `world.monuments` | This map's monuments in one stable order (grouped by prefab short name, then by position). Each has `value` (`kind`, or `kind#n` when the kind repeats), `kind`, `instance`, `of`, `label` (the game's display phrase), `x`, `z` and `grid`. Also `worldSize`, the placeable `prefabs` (`key`, `kind`, `label`), `eventsEnabled`, `maxCrates`, `maxNpcs` and `zoneManager` |
|
||||
| `world.zone` | `world.ok` or `world.error` | Opens a ZoneManager temporary zone owned by the bridge. Needs `runId`, `key`, a location, `radius` (5–150 m) and `holdMs` (1 minute to 7 days); `name` is optional |
|
||||
| `world.zone` | `world.ok` or `world.error` | Opens a ZoneManager temporary zone owned by the bridge. Needs `runId`, `key`, a location, `radius` (5–150 m) and `holdMs` (1 minute to 7 days); `name` is optional. Protocol 13 adds `flags`, `settings`, `enterMessage`, `leaveMessage`, `delivery`, `format` and `dome` (§19.11) |
|
||||
| `world.place` | `world.ok` or `world.error` | Places `count` of one allowlisted `prefab` at a location, scattered within `spread` m (0–50, 10 by default for a group). All or nothing: if the game refuses one, the ones already made are killed |
|
||||
| `world.revert` | `world.ok` | Gives back what a run owns: the named `ids`, or else everything under `key`, or else everything the run owns. The answer lists `removed`, `gone` and `refused` |
|
||||
| `world.owned` | `world.owned` | What the world still holds of what events made, **looked for** by net id or zone id, narrowed by `runId`. Anything gone is pruned from the registry as the walk passes it |
|
||||
@@ -2281,3 +2281,105 @@ frame from an older plugin has none:
|
||||
are in `ExpectedHooks`, so a framework that stops raising one shows as zero in `rg.hooks`.
|
||||
|
||||
No sidecar change: the sidecar stores and forwards `player.tally` whole, as it does every frame.
|
||||
|
||||
### 19.11 A zone's options, its messages and its dome (PLAN_REDESIGNS §3)
|
||||
|
||||
**`world.zone` gains seven optional fields.** A zone that sends none of them is opened exactly as before.
|
||||
|
||||
```json
|
||||
{"cmd":"world.zone","reqId":"r-4","runId":"13","key":"9c1e…","monument":"airfield_1","radius":40,
|
||||
"holdMs":1800000,"name":"Arena",
|
||||
"flags":["NoBuild","PvpGod"],"settings":{"radiation":10,"safezone":false},
|
||||
"enterMessage":"You entered the arena.","leaveMessage":"You left the arena.",
|
||||
"delivery":"chat","format":"<color=#ffb400>[Event]</color> {message}",
|
||||
"dome":{"type":1,"stack":2}}
|
||||
```
|
||||
|
||||
- **`flags`** is a list of ZoneManager flag names, at most 80. Each is checked against the flags **this
|
||||
server's ZoneManager** declares, case-insensitively, and passed on as ZoneManager spells it. An unknown
|
||||
one is refused **`bad-option`**, never dropped: a zone that quietly lacks the "no building" its author
|
||||
chose is worse than a step that fails and says why.
|
||||
- **`settings`** is an object of five allowlisted keys: `radiation` (0–500), `comfort` (0–1), `temperature`
|
||||
(−100–100), `safezone` (true/false) and `permission` (1–32 of `a–z`, `0–9`, `_`; ZoneManager registers it
|
||||
as `zonemanager.<name>`). Anything else is `bad-option`, and a value out of range is `bad-option` with the
|
||||
range. Every other ZoneManager field (rotation, parent, size, eject spawns) stays out, because each one
|
||||
changes what the bridge believes the zone is.
|
||||
- Both are passed to **`CreateOrUpdateTemporaryZone` as ZoneManager's own key/value arguments** (a setting
|
||||
by its key, a flag as `"<Flag>", "true"`), kept on the zone's registry entry, and passed again whenever the
|
||||
bridge re-creates the zone: at a restart, a hot reload of the bridge, and a ZoneManager reload. A flag a
|
||||
newer ZoneManager no longer has is ignored by ZoneManager on re-creation rather than failing the zone.
|
||||
- **`enterMessage` and `leaveMessage`** (up to 256 characters each) are said **by the bridge**, never given
|
||||
to ZoneManager (D193): ZoneManager says a zone's messages as popups only when its own config turns
|
||||
popups on for every zone on the server. The bridge handles `OnEnterZone(zoneId, player)` and
|
||||
`OnExitZone(zoneId, player)` and speaks only for zones in its registry. A zone it has just re-created says
|
||||
nothing for 5 s, because ZoneManager (with the zone helper, §19.6) re-enters whoever is standing in it.
|
||||
- **`delivery`** is `chat` (the default) or `popup`. **A popup where PopupNotifications is missing falls back
|
||||
to chat**; the zone is not refused for it, because the moment the message is said can be days after the
|
||||
step ran. **`format`** is the chat voice (§33.2 of PLAN.md), one `{message}`, used only for chat.
|
||||
- **`dome`** asks ZoneDomes for a dome over the zone: `type` is ZoneDomes' own sphere type (0 Standard,
|
||||
1 Red, 2 Blue, 3 Green, 4 Purple; **0 when absent**, the one full dome, D212) and `stack` 1–10 spheres (1 when
|
||||
absent). The coloured types show only where they meet terrain or a structure. It is refused
|
||||
**`dome-unavailable`**, with which piece is missing, unless ZoneDomes is loaded and the domes helper has
|
||||
patched it and seen ZoneDomes finish starting. A dome ZoneDomes does not make takes its zone with it:
|
||||
the zone is erased and the step refused.
|
||||
|
||||
**The dome's lifecycle is the bridge's.** It adds the dome after the zone, because ZoneDomes reads the
|
||||
zone's place and radius from ZoneManager. At expiry and at `world.revert` it calls `RemoveExistingDome`
|
||||
**before** erasing the zone, so a dome never outlives its zone in ZoneDomes' data file. After re-creating
|
||||
zones it calls `AddNewDome` again for each zone that had one; ZoneDomes answers false for a dome it
|
||||
already has, so this is safe to repeat.
|
||||
|
||||
**The domes helper, `RunicGatewayDomes.cs`** (D194, D168), ships beside the bridge like the zone helper.
|
||||
It does two things, both by Harmony:
|
||||
|
||||
- A **prefix on ZoneDomes' `TranslateMessage(BasePlayer, string, string)`** skips the message when the
|
||||
player is null. ZoneDomes 2.0.2's `AddNewDome` and `RemoveExistingDome` end with that message and no null
|
||||
check, so a call from a plugin made the dome, saved it, and then threw (PLAN_REDESIGNS §0.5).
|
||||
- A **postfix on `InitializeDomes`**, ZoneDomes' own start, raises **`OnRgDomesReady`**. ZoneDomes' start
|
||||
drops every dome whose zone does not exist yet and draws every one that does. A dome added **before**
|
||||
it is drawn twice, and the first set of spheres stays in the world with nothing able to remove it. So the
|
||||
bridge puts domes back only once the helper says ZoneDomes has started. A helper or ZoneDomes loaded into
|
||||
a running server is ready on the next tick.
|
||||
|
||||
It patches at load (and when ZoneDomes loads), so at a real start the patch is in before ZoneDomes'
|
||||
`OnServerInitialized`. `rgd.status` prints its state.
|
||||
|
||||
**Hello and status.** `server.hello` gains, wherever ZoneManager is loaded:
|
||||
|
||||
```json
|
||||
"zoneManager": { "version": "3.1.14", "flags": ["AutoLights", "AlwaysLights", "NoKits", "…"] }
|
||||
```
|
||||
|
||||
`flags` comes from ZoneManager's own API call **`ZoneFieldListRaw()`**, less the leading field names
|
||||
(`name`, `radius`, `enter_message`, …). **Plan §0.6 said only a plugin that references ZoneManager's types
|
||||
could read the list; that was wrong for 3.1.14** (D211), so the bridge reads it and a server without the
|
||||
zone helper still reports every flag. It is in hello rather than every status frame because it changes only
|
||||
when ZoneManager does, and **the bridge sends hello again when ZoneManager, ZoneDomes, or either helper
|
||||
loads or unloads**.
|
||||
|
||||
`integrations` on `server.status` (and so on hello) gains `zoneDomes`:
|
||||
|
||||
```json
|
||||
"zoneDomes": { "loaded": true, "version": "2.0.2",
|
||||
"helper": { "state": "patched", "version": "0.1.0" }, "ready": true }
|
||||
```
|
||||
|
||||
`helper.state` is `patched`, `unsupported` (with `reason`), `no-zonedomes` or `missing`, as §19.6's are.
|
||||
|
||||
**Hooks.** `OnEnterZone`, `OnExitZone` and `OnRgDomesReady` join `rg.hooks`' list.
|
||||
|
||||
**The sidecar** forwards `world.zone` whole, as before; nothing in it changed.
|
||||
|
||||
**The website** (Module-Rust): the zone step `rust.zone.open` gains `options` (one line, `NoBuild,
|
||||
NoPlayerLoot, radiation=10`, read into `flags` and `settings`), `enterMessage`, `leaveMessage`, `delivery`,
|
||||
`dome` (`standard`, `red`, `blue`, `green`, `purple`) and `domeStack`. Core's step editor holds single values
|
||||
only, so the flags are ticked on a new page, **Admin → Rust zone presets**, and saved by name for one server,
|
||||
several, or every server (D195, D210). The step's `options` field offers the presets (option source
|
||||
`rust.options.zone_presets`); **a row's value is the preset's line itself**, so picking one copies it and a
|
||||
preset edited later changes no published event. The step checks the line and the dome against the server's
|
||||
last hello when it is saved and in a dry run; `bad-option` and `dome-unavailable` are permanent refusals.
|
||||
|
||||
**Compiled on both rigs and walked without a player, 2026-09-29** (PLAN_REDESIGNS §3.4): every refusal,
|
||||
ZoneManager and ZoneDomes reloads, a server restart and the forced opposite boot order (exactly one set of
|
||||
spheres each time), revert and expiry removing the dome, and a dome refused without the helper. The
|
||||
in-game rows (flags on a player, the messages) wait for the later in-game walk.
|
||||
|
||||
Reference in New Issue
Block a user