From 65c57cec363ec2234f5300d4cdead64c5ef4e14b Mon Sep 17 00:00:00 2001 From: wtclaude Date: Thu, 15 Oct 2026 05:47:27 -0500 Subject: [PATCH] =?UTF-8?q?docs(rust):=20stage=203=20built=20=E2=80=94=20T?= =?UTF-8?q?ruePVE=20in=20the=20zone=20step=20(PROTOCOL=20=C2=A720.6,=20PLA?= =?UTF-8?q?N=5FREDESIGNS=20=C2=A714.3.16)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - rust-link/PROTOCOL.md §20.6: hello's integrations.truePve, world.zone's truePve (exactly one of exclude and ruleset, all or nothing, the refusals), the unmapping on every erase path with truepve.json for while TruePVE is away, rg.world's two fields, and the website's two params. The §15 command table points at it. - modules/rust/PLAN_REDESIGNS.md §14.3.16: the stage-3 record, ten points settled in code (all overrulable), TruePVE's one-second save, the tests and the rig compile. Pointers from §9's summary and §14.3.2. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY --- modules/rust/PLAN_REDESIGNS.md | 45 +++++++++++++++++++++++++- rust-link/PROTOCOL.md | 58 +++++++++++++++++++++++++++++++++- 2 files changed, 101 insertions(+), 2 deletions(-) diff --git a/modules/rust/PLAN_REDESIGNS.md b/modules/rust/PLAN_REDESIGNS.md index 263ac71..b06ec30 100644 --- a/modules/rust/PLAN_REDESIGNS.md +++ b/modules/rust/PLAN_REDESIGNS.md @@ -930,7 +930,7 @@ pulls) is research, not a walk, so it still comes first: answered before code: **written on 2026-10-14 as §14.3**, from D361–D369, and answered as D370–D376. Then the build, in §14.3.11's nine stages (two of them core), §13 first. **Stage 1, §13, was built on 2026-10-15 (§14.3.14)**, with D378 and D379. **Stage 2, core's `retryAfterMs` (MODULE_API 1.15.0), was built on - 2026-10-15 (§14.3.15).** + 2026-10-15 (§14.3.15).** **Stage 3, TruePVE in the zone step, was built on 2026-10-15 (§14.3.16).** **Then one walk, on Oxide and Carbon, of everything still owed (D331):** §2.7; §11's rows; §12.9; §13's and §14's rows; the in-game rows @@ -2501,6 +2501,8 @@ helicopter from a run, then cancel the run and see both stay; a Guarded Crate cr #### 14.3.2 TruePVE in the zone step (D362, D368) +> **Built on 2026-10-15** (§14.3.16), specified in PROTOCOL.md §20.6. + **Hello.** `integrations.truePve`: `{ loaded, version }`. **The wire.** `world.zone` gains an optional **`truePve`**: `{ "exclude": true }` or `{ "ruleset": "pvp-arena" }` @@ -2933,6 +2935,47 @@ machine's installed `modules/`; client 422/422 and the build. **No walk rows of its own.** Stage 5's Dangerous Treasures rows exercise it: a step answering *"not ready"* shows *"retrying at …"* and runs then. +#### 14.3.16 Stage 3, built: TruePVE in the zone step (2026-10-15) + +Built in Rust-Plugins and Module-Rust as §14.3.2 planned it, specified in +[PROTOCOL.md](../../rust-link/PROTOCOL.md) §20.6. **No Rust-Link change**: the sidecar forwards `world.zone` +whole. `PROTOCOL_VERSION` stays 14. Builds: Rust 25902425, Oxide 2.0.7830, Carbon 2.0.262, TruePVE 2.4.6 on both +rigs. + +**Settled in the code, and overrulable:** + +1. **A ruleset name is trimmed and 1–64 characters**, checked by the site and the plugin alike; past that it + is passed as written, because TruePVE compares names case-sensitively (`r.name == ruleset` in 2.4.6). +2. **A server whose hello has not said whether it has TruePVE is left to the plugin** (a plugin before + protocol 14, or never reached), as a dome is, and the plugin answers `truepve-missing`. Only a hello that + says `loaded: false` is refused at verify. +3. **`exclude` refused by TruePVE answers `refused`, not `truepve-ruleset`.** It happens only when TruePVE has + not read its config or data yet; the zone is erased all the same. +4. **The mapping comes after the dome**, so a refusal erases both, as a failed dome erases its zone. +5. **Re-creation maps nothing again.** TruePVE keeps the mapping in its own data file, keyed by the zone id, + which re-creation keeps. +6. **Two erase paths beyond the plan's three are covered:** a zone `world.owned` finds ZoneManager no longer + holds, and a new wipe dropping the old map's entries. TruePVE's table outlives a wipe. +7. **Leftovers are also flushed at the bridge's own load**, not only at `OnPluginLoaded(TruePVE)`, so a bridge + reloaded after TruePVE came back does not wait for TruePVE's next reload. `truepve.json` is deleted when empty. +8. **Hello is sent again when TruePVE loads or unloads**, so the site's verify reads the current answer. +9. **`truepve-missing` and `truepve-ruleset` are permanent failures**, as `no-zone` is. +10. **Server settings' plugin line names TruePVE**: *"TruePVE 2.4.6 is loaded — a zone step may turn off PvP + protection or name a ruleset."* + +**One thing TruePVE does that we cannot change:** it saves its data file one second after a change, on its +own timer. A restart inside that second loses the change. For a removal that leaves a mapping for an `rg-…` id +no zone will have again, which changes nothing in game; D362's cleanup is otherwise complete. + +**Tests.** Module-Rust: five new in `test/zones.test.js` (exclude, `"true"` and a trimmed ruleset on the wire; +unset, off and blank send nothing; both, a long name and no TruePVE refused for good at verify and perform; a +hello that has not said is left to the plugin; `truepve-ruleset` and `truepve-missing` fail for good with the +plugin's words). Full suites: server 603/603 and every check (imports, bundle, swagger, engagement); client +84/84, the build and externals. The plugin compiled and loaded on both rigs, and `rg.world` read +`truePve=True truePveLeftover=0` on each; both rigs were put back on the protocol-13 bridge after. + +**Walk rows** are §14.3.2's, at the end walk (D331, D359). + ### 14.4 Questions for the org lead **Answered on 2026-10-14:** Q17 as proposed, out (D358). **Q18 against the proposal: the end walk waits for diff --git a/rust-link/PROTOCOL.md b/rust-link/PROTOCOL.md index ab148ec..ac95e50 100644 --- a/rust-link/PROTOCOL.md +++ b/rust-link/PROTOCOL.md @@ -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. Protocol 13 adds `flags`, `settings`, `enterMessage`, `leaveMessage`, `delivery`, `format` and `dome` (§19.11) | +| `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); protocol 14 adds `truePve` (§20.6) | | `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. Protocol 13 adds `profile`, a RunicNPC profile in place of a prefab (§19.12), and for a profile `escort`, `ally` and `tether` (§19.13) | | `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 | @@ -3019,3 +3019,59 @@ is every website command's path. On both rigs it reads `true`. Hello is sent aga - **The tally's two counts** in `rust_player_wipe_stats.crates_hacked` and `.drops_looted`; title categories `crateshacked` (*Safecracker*) and `dropslooted` (*Scavenger*); leaderboard columns *Crates hacked* and *Drops looted*, sortable (`sort=cratesHacked`, `sort=dropsLooted`). + +### 20.6 TruePVE in a zone — `world.zone`'s `truePve` (§14.3.2, D362, D368) + +nivex's **TruePVE** (2.4.6, uMod), optional like Economics (D199) and not in `overlay.toml`. A zone an event +opens may ask TruePVE to leave it alone, or to use one of the operator's rulesets inside it. The design is +[`PLAN_REDESIGNS.md`](../modules/rust/PLAN_REDESIGNS.md) §14.3.2, and what §14.2's test found, which shapes it, +is §14.2 there. None of TruePVE's hooks is used. + +**Hello and status.** `integrations` gains `truePve`: + +```json +"truePve": { "loaded": true, "version": "2.4.6" } +``` + +Hello is sent again when TruePVE loads or unloads. + +**`world.zone` gains an optional `truePve`** (the rest of the zone is §15 and §19.11): + +```json +{"cmd":"world.zone","reqId":"r-4","runId":"13","key":"9c1e…","monument":"airfield_1","radius":40, + "holdMs":1800000,"truePve":{"exclude":true}} +{"cmd":"world.zone","reqId":"r-5","runId":"13","key":"0b7d…","monument":"launch_site_1","radius":60, + "holdMs":1800000,"truePve":{"ruleset":"pvp-arena"}} +``` + +- **Exactly one of `exclude` and `ruleset`.** `exclude` is `true` or left out; `ruleset` is 1–64 characters + after trimming, passed as written, because TruePVE matches its names case-sensitively. Both, neither, a + non-object or a blank name is **`malformed`**. +- **TruePVE not loaded** is **`truepve-missing`**, before anything is made. +- **All or nothing.** The bridge makes the zone, and its dome when asked, then calls + **`AddOrUpdateMapping(zoneId, "exclude" | ruleset)`**. TruePVE answers false for a ruleset it does not have, + and nothing else lists the names, so the call is the check (D368). A false erases the dome and the zone + just made and answers **`truepve-ruleset`** with the name, or **`refused`** for `exclude` (TruePVE not ready). +- The registry entry keeps the mapping it was given (`TruePve`), so a mapping is only ever removed for a zone + this plugin mapped. **Re-creating a zone** (a restart, a hot reload, a ZoneManager reload, §19.11) maps + nothing again: TruePVE keeps its table in its own data file, and the zone keeps its id. + +**The unmapping lives with the zone (D362).** TruePVE prunes a mapping whose zone is gone only when the zone +id is a number, and ours are `rg-…`. So every path that erases one of our zones calls **`RemoveMapping`** +first: its deadline (checked every second, with the site down too, §15.3), `world.revert`, a zone that +`world.owned` finds ZoneManager no longer holds, and a new wipe dropping the old map's entries. When TruePVE is not loaded at +that moment, the id goes into **`data/RunicGateway/truepve.json`**, and the bridge removes each one at +`OnPluginLoaded(TruePVE)` (TruePVE has read its table in `Init` by then) and at its own load. The file is +deleted when it is empty. + +**Status.** `rg.world` prints `truePve=` (loaded) and `truePveLeftover=` (ids waiting in `truepve.json`). + +**The sidecar** forwards `world.zone` whole, as before; nothing in it changed. + +**The website (Module-Rust).** `rust.zone.open` gains **`noPvpProtection`** (a boolean, *"No PvP protection in +this zone"*) and **`pvpRuleset`** (a string, *"or this TruePVE ruleset"*). Setting both is refused, as is a +name over 64 characters, and either one is refused where the server's last hello said TruePVE is not loaded +(*"TruePVE is not installed on this server"*); all three at verify too. A server whose hello has not said +(a plugin before protocol 14, or never reached) is left to the plugin. `truepve-missing` and +`truepve-ruleset` fail the step for good, with the plugin's words. Server settings' plugin line says whether +TruePVE is loaded. -- 2.49.1