Compare commits
3 Commits
main
...
docs/rust-
| Author | SHA1 | Date | |
|---|---|---|---|
| baef8f27eb | |||
| 4056e5a14d | |||
| 7f9026c9e7 |
@@ -42,7 +42,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 |
|
||||
@@ -424,6 +424,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)
|
||||
@@ -916,3 +1030,11 @@ The org lead answered §11.4.4's three questions the same day:
|
||||
These are new verbs, events and hello fields. If they are built before the cutover they join the unreleased
|
||||
protocol 13 like everything else here; if the cutover comes first, they open protocol 14. Which one is decided
|
||||
when §9 reaches item 7.
|
||||
|
||||
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 |
|
||||
|
||||
@@ -159,7 +159,9 @@ history, and the token is unchanged.
|
||||
`oxide/plugins/` or `carbon/plugins/`, and every other `.cs` the tarball's `manifest.json` lists
|
||||
in `files` beside it — from protocol 13 that is `RunicGatewayZones.cs`, which lets ZoneManager count a
|
||||
player already standing in a zone when it opens or comes back after a restart. It is optional: leave
|
||||
it out and events still score everybody, but ZoneManager's own flags miss that player. To name the server, create its config first —
|
||||
it out and events still score everybody, but ZoneManager's own flags miss that player. The second is
|
||||
`RunicGatewayDomes.cs`, which lets the bridge ask ZoneDomes for a dome over an event zone; leave it
|
||||
out and zones open without one. To name the server, create its config first —
|
||||
`oxide/config/RunicGateway.json` or `carbon/configs/RunicGateway.json` — holding
|
||||
`{ "ServerId": "<id>", "Port": 7799 }`. Without it, the plugin calls the server `main`.
|
||||
4. **The sidecar:** put the binary somewhere stable and give it a config:
|
||||
|
||||
@@ -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 |
|
||||
@@ -2245,3 +2245,105 @@ logs its summary instead of replying.
|
||||
Walked on both rigs, 2026-09-27/28. Oxide gave 85 permissions, every one owned (`RustCore` owns
|
||||
`oxide.*`), in 148 ms over four ticks. Carbon gave 104, the 30 `adminmodule.*` unowned, in 204 ms. On
|
||||
both, **`zonemanager.ignoreflag.nokits` belongs to ZoneManager**.
|
||||
|
||||
### 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