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:
2026-09-29 11:36:45 -05:00
3 changed files with 229 additions and 3 deletions

View File

@@ -43,7 +43,7 @@ probe plugin that wrote one data file. It was unloaded and deleted afterwards on
| 0.3 | Do groups carry anything the site does not model? | **Parents.** `GetGroupParent` answers on both. The site's `rust_perm_groups` has no parent column. | §1.4 |
| 0.4 | Is there a framework hook for a finished Rust mission (D173)? | **Yes: option 1 of D173's spike.** Oxide's patched `Assembly-CSharp.dll` raises `OnMissionSucceeded`, `OnMissionFailed`, `OnMissionStarted` and `OnMissionAssigned`, and `Carbon.Hooks.Oxide.dll` patches the same four names onto `BaseMission`. Rust's own methods are `BaseMission.MissionSuccess(MissionInstance, BasePlayer assignee)` and `MissionFailed(MissionInstance, BasePlayer, MissionFailReason, bool)`. The catalogues [`HOOKS.md`](HOOKS.md) and [`CARBON.md`](CARBON.md) predate them. The exact hook arguments are confirmed when a person finishes a mission (§5.7). | §5.7 |
| 0.5 | Is ZoneDomes' API safe with a null player (PLAN_FIXES §4.4, §7)? | **No.** `AddNewDome` and `RemoveExistingDome` end with `player.ChatMessage(...)` and no null check. With a null player the dome is made and saved, and then the call throws. On boot, ZoneDomes also drops every dome whose zone does not exist yet, and the bridge's temporary zones are re-created after that. | §3.2 |
| 0.6 | Can ZoneManager's flag list be read at run time? | **Only from inside.** The list is `ZoneManager.ZoneFlags.NameToIndex`, a public static on a nested type. No hook or `Call` method returns it. The zone helper (`RunicGatewayZones.cs`) already references ZoneManager's types, and the bridge may not (R2, D168). | §3.1 |
| 0.6 | Can ZoneManager's flag list be read at run time? | **Only from inside.** The list is `ZoneManager.ZoneFlags.NameToIndex`, a public static on a nested type. No hook or `Call` method returns it. The zone helper (`RunicGatewayZones.cs`) already references ZoneManager's types, and the bridge may not (R2, D168). **Wrong, found at the build (D211):** ZoneManager 3.1.14's API region has `ZoneFieldListRaw()`, which returns the zone field names followed by every `NameToIndex` key, and the bridge calls it by name. | §3.1, §3.4 |
| 0.7 | What does the map actually show? | **85 markers on the rigs' map (world 3000, seed 1234): 31 substations in four prefab kinds, 7 caves in six, 7 train-tunnel entrances in four, and 5 water wells in three.** The label (`Substation`) groups the variants. Rust also classifies monuments itself (`MonumentInfo`'s `MonumentType`: Cave, WaterWell, Lake, Mountain, Radtown, Building, Town, Airport, Lighthouse). | §4 |
| 0.8 | Can the site see how much of a kit players have used? | **One player at a time.** `kits.list` already returns each kit's `max` (MaximumUses) and `cooldown`, and the module ignores `cooldown`. Per-player use is read only during a credit settle (`GetPlayerKitUses`). | §2.6 |
| 0.9 | Where do the Ultima Online examples a Rust admin sees come from (U-3)? | **Core's own actions.** `core.lease` gives `uo.rate.skillgain` as its example, and the announcement actions talk about Britain and Cove. | §2.1 |
@@ -425,6 +425,120 @@ for one with it; the enter and leave messages arrive as chat and then as popups;
reload and a ZoneDomes reload all keep the flags and the dome; expiry and teardown remove the dome from the
world and from ZoneDomes' data file; and with the domes helper removed, the step stops offering a dome.
### 3.4 As built (2026-09-29; not yet walked on a rig)
Built on `edge` as Rust-Plugins `feat/zones-domes`, Module-Rust `feat/zones-domes` and installer
`feat/rust-domes-helper`; the wire is PROTOCOL §19.11. The build changed §3.1 and §3.2 in four places.
- **Where the flags are ticked (D210).** Core's step editor holds one value per field: a text box, a number,
a yes/no, a date, or one dropdown. It has no checkbox list and no slot for a module's own button, and
MODULE_API 1.12.0 (§8) adds neither. So the checkboxes are on a new page, **Admin → Rust zone presets**,
and the step's **Options** field is one line of text (`NoBuild, NoPlayerLoot, radiation=10`). The field's
dropdown lists the presets, and **each row's value is the preset's line**, so picking one writes that
line into the field. Core already writes a dropdown's pick into the free-text field beside it, so this
needed no core change. It keeps §3.1's promise: the step holds its own copy, and editing a preset
changes no published event. There is no **Save as preset** button in the step; a preset is made on its
page. Presets are `rust_zone_presets` (`name`, `flags`, `settings`, `all_servers`) and
`rust_zone_preset_servers`. As with a group (D189), the same name may be used on two servers but not
twice on one.
- **Who reads the flag list (D211).** The bridge does, with `ZoneFieldListRaw()` (§0.6 corrected). The zone
helper gained nothing, and a server without it still offers every flag, so there is no
"name, radius and duration only" mode. The list is in hello, and the bridge sends hello again when
ZoneManager, ZoneDomes or either helper loads or unloads.
- **The dome must wait for ZoneDomes' own start.** ZoneDomes' `InitializeDomes` also re-draws every dome
in its data file whose zone exists. A dome the bridge added before that is drawn twice, and the first
set of spheres is left in the world with nothing able to remove it. The domes helper therefore
postfixes `InitializeDomes` and raises `OnRgDomesReady`, and the bridge puts domes back only after it.
The helper's patch goes in at load, before ZoneDomes' `OnServerInitialized`.
- **A popup falls back to chat at the moment of speaking**, as §2.4 says, and the zone is not refused for
it: a zone's messages are said long after the step ran. (`rust.announce` still refuses a popup without
PopupNotifications, because its line is said at once.)
**Chosen in the build, within the plan:**
- **Settings bounds:** radiation 0–500, comfort 0–1, temperature −100–100 °C.
- **Permission:** up to 32 of `a–z0–9_`.
- **Dome stack:** 1–10. ZoneDomes itself has no limit, and each sphere is an entity.
- **The 5 s quiet:** after re-creating a zone, the bridge stays silent to anyone already inside it.
- **The flag groups:** in `server/model/zones/zoneOptions.js`. `NoTp` and ZoneManager's `Custom1`–`5`
are under Other.
**The default dome (D212).** ZoneDomes 2.0.2 has five types, and only **Standard** (type 0, Rust's shaded
`sphere.prefab`) is a whole dome: a dark, see-through sphere that each stacked copy makes darker. Red, Blue,
Green and Purple are the Twitch battle-royale spheres, which ZoneDomes itself says show only where they meet
terrain or an object, so they read as a ring at the zone's edge. **The org lead chose the full dome as the
default:** the step lists Standard first as "Full dome (shaded)", labels each colour for what it shows, and
a `dome` sent without a `type` is Standard. The default stack is still 1, until it is chosen by eye.
**Compiled on both rigs, and the rig rows walked, 2026-09-29** (no player; the "file API outage" that
morning was a Git Bash path-rewriting bug in the walk's own helper, not the rigs):
- **Both rigs:** the bridge and both helpers compiled and loaded (Oxide; Carbon with 0 failed plugins).
Both helpers reported `patched`, and the domes helper `ready`.
- **Hello (Oxide, read from the sidecar's board):**
- `zoneManager` carried all **69** flags of ZoneManager 3.1.14 (64 named and `Custom1`–`5`), with no zone
helper involved (D211).
- `integrations.zoneDomes` was `{ loaded, patched, ready }`.
- It was re-sent within a second each time ZoneDomes or a helper loaded or unloaded.
- **Refusals:** an unknown flag (`NoFlying`), a setting outside the allowlist (`rotation`) and radiation 900
were each refused `bad-option`, with the reason.
- **A full zone:** `nobuild, PvpGod, NoPlayerLoot`, radiation 5, safezone off, a popup enter/leave message and a
stacked dome.
- ZoneManager held exactly those flags and settings (read through a throwaway probe calling
`ZoneFieldList`).
- ZoneManager held no enter message of its own: the bridge says it (D193).
- The registry stored the flags as ZoneManager spells them.
- ZoneDomes' data file held the dome.
- **ZoneManager reload:** the zone came back ("1 re-created") with all its flags. The dome's data was
untouched.
- **ZoneDomes reload:** the helper re-patched and was ready again. The dome was redrawn from ZoneDomes' own
data.
- **Server restart:**
- The zone was re-created with its flags.
- On this boot the bridge's zones existed before ZoneDomes started, so ZoneDomes drew the dome itself,
and the bridge's restore added nothing.
- **Exactly 2 sphere entities for a stack of 2**, so the dome was not drawn twice.
- **The other order, forced:**
- The bridge was unloaded (ZoneManager erased the zone), then ZoneDomes reloaded and dropped the dome's
data.
- The bridge was loaded again: "domes after load: 1 put back", and again exactly 2 spheres. §0.5's
boot fault is handled whichever plugin starts first.
- **Teardown (`world.revert`):** the zone was erased, 0 spheres were left, and ZoneDomes' data was empty.
- **Expiry:** a 1-minute domed zone was erased at its deadline, and its dome went with it (0 spheres, data
empty).
- **Without the domes helper:** a dome was refused `dome-unavailable`, "RunicGatewayDomes.cs is not
installed beside the bridge…". Hello said `missing`, then `patched`/`ready` once the helper was loaded
again.
**The site half, walked 2026-09-29** on a local core (website `main` `f0e7d2a`) with this branch's module,
against `rust-carbon`. `rust-oxide`'s fresh egg installed the last released sidecar, which speaks protocol 12,
so the site refuses it until protocol 13 ships:
- **The page, in the browser as an admin:**
- Each server's line: Carbon's ZoneManager 3.1.14 with 69 flags, and "domes available".
- The edit form: the flags in their groups with the preset's ticked, the servers, and the settings with
their bounds.
- A save with comfort 3 was refused under the form ("comfort is 0 to 1, not "3""). Corrected, it saved,
and the preset's line updated.
- The sidebar row. No console errors.
- **The API:** a flag Carbon does not have was refused, naming the server. So were an out-of-range setting,
a preset for no server, and a second "arena" on the same server (409).
- **The step:**
- The Options dropdown's row value is the preset's line (D210).
- After the preset was edited, the published step still held its own old line. Picking the preset in the
editor wrote the new one.
- The dome dropdown carries D212's labels.
- A draft with `NoFlying` failed its dry run with that reason.
- **A run through the whole path:**
- The site opened the zone on Carbon: the preset's flags and settings, the popup messages, and ZoneDomes'
Standard dome at stack 2.
- The run's cleanup removed it, leaving ZoneDomes' data empty.
**Still to walk:**
- **The in-game rows, deferred by the org lead (2026-09-29) to the later in-game walk, with §5.7's:**
- The flags hold for a player without the exemption and not for one with it.
- The enter and leave messages arrive as chat and as a popup.
- The default stack is chosen by eye, in daylight and at night.
---
## 4. The live map's marker types (§4.5; D165)
@@ -702,6 +816,14 @@ The §5 build raised one more, answered on 2026-09-28:
|---|---|---|---|
| **D209** | **A title rule's "NPC kills" ranks human NPCs only** (scientists and bandits): every NPC kill less the animals, which Beastbane ranks. The public leaderboard's NPC column still counts both (§5.2). | Keeping the old all-NPC count as a 25th category beside Exterminator. | 5.8 |
The §3 build raised two more, answered on 2026-09-29:
| # | Decision | Rejected | § |
|---|---|---|---|
| **D210** | **A zone's flags and settings are ticked on an Admin → Rust zone presets page**, and the zone step's Options field copies a preset's line when it is picked. Core is unchanged. | A list param type in core (MODULE_API) drawn as grouped checkboxes; a module-supplied step editor. | 3.4 |
| **D211** | **The bridge reads ZoneManager's flag list** through its API call `ZoneFieldListRaw()` and sends it in hello. A server without the zone helper still offers every flag. | Keeping the read in the zone helper, with a name/radius/minutes-only mode without it. | 3.4 |
| **D212** | **A zone's dome defaults to ZoneDomes' Standard type, the full shaded dome.** The coloured types show only where they meet the ground or a building, and the step says so. | A coloured default. | 3.4 |
## 11. First-class optional plugins (D199–D202)
The org lead named four plugins the module supports as first-class integrations. Kits already is one. The other