docs(rust): stage 3 built — TruePVE in the zone step (PROTOCOL §20.6, PLAN_REDESIGNS §14.3.16) #350
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user