docs(rust): take Server Rewards off the plan (D381)

The org lead does not want Server Rewards. D381 records it and amends
D350, D369, D375 and D377; §14.3.7 becomes a dropped note, the wire
table loses points.*, the tally's points and the sidecar's /points/*
routes, and stage 8 of §14.3.11 is struck. Nothing had been built.
§14.2.1's test findings stay as a record.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
This commit is contained in:
2026-10-16 01:11:23 -05:00
parent 03f572121a
commit 58167ccac8

View File

@@ -28,7 +28,7 @@ document is later and wins. Its decisions continue PLAN_FIXES' numbering at **D1
| 11 | First-class optional plugins: Economics, Backpacks, RaidableBases (Kits stays required) | — (added 2026-09-28) | Rust-Plugins, Module-Rust, installer, Android-app |
| 12 | Permissions as event rewards: until the event ends, or for good | — (added 2026-10-12) | **core** (website `main`, MODULE_API 1.14.0), Module-Rust |
| 13 | Rust's own world events (helicopter, Bradley, cargo, Chinook, airdrops, locked crates) in the base module | — (added 2026-10-14) | Rust-Plugins, Rust-Link, Module-Rust |
| 14 | Six more optional plugins: TruePVE, Dynamic PVP, Dangerous Treasures, Guarded Crate, ZLevels, Server Rewards | — (added 2026-10-14) | Rust-Plugins, Rust-Link, Module-Rust, Android-app |
| 14 | Five more optional plugins: TruePVE, Dynamic PVP, Dangerous Treasures, Guarded Crate, ZLevels (Server Rewards dropped, D381) | — (added 2026-10-14) | Rust-Plugins, Rust-Link, Module-Rust, Android-app |
| 15 | Steam sign-in: a link to the website's own plan, [`website/STEAM_SIGNIN.md`](../../website/STEAM_SIGNIN.md) | §4.8, D171 | **core** (website), Android-app, Module-Rust |
**Protocol.** §1, §3, §4 and §5 joined **protocol 13**, which shipped on 2026-10-09 with RunicNPC v1.0.0
@@ -930,7 +930,8 @@ 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).** **Stage 3, TruePVE in the zone step, was built on 2026-10-15 (§14.3.16)**, and **stage 4, Dynamic PVP, the same day (§14.3.17)**, and **stage 5, Dangerous Treasures, the same day (§14.3.18)**, and **stage 6, Guarded Crate, the same day (§14.3.19)**, and **stage 7, ZLevels, the same day (§14.3.20).**
2026-10-15 (§14.3.15).** **Stage 3, TruePVE in the zone step, was built on 2026-10-15 (§14.3.16)**, and **stage 4, Dynamic PVP, the same day (§14.3.17)**, and **stage 5, Dangerous Treasures, the same day (§14.3.18)**, and **stage 6, Guarded Crate, the same day (§14.3.19)**, and **stage 7, ZLevels, the same day (§14.3.20).** **Stage 8, Server Rewards, was taken off the plan on
2026-10-16 (D381).**
**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
@@ -1095,6 +1096,7 @@ The org lead answered §14.3's Q26–Q32 on 2026-10-14:
| **D378** | **The Chinook is called with no position.** It drops only at the map's own drop zones (seven on the rigs' map, all at monuments), and the one route that sends it to a chosen zone borrows the Airfield call terminal's shared state, so a player at the real terminal and a step calling at once would race for one Chinook (stage 1's spike, org lead 2026-10-15). The airdrop and the patrol helicopter take a position. | A position snapped to the nearest drop zone through the terminal's state, refused while a real Airfield call is active. | 14.3.1, 14.3.14 |
| **D379** | **`chinook.downed` is a 24th world event**, with the credit block and the operator's rule, and counts toward *Rotorbane*: D174 counted Chinook kills there, and the plan's first draft would have dropped them (org lead, 2026-10-15). | Counting Chinook kills through the old tally, with no line; patrol helicopters only. | 14.3.1, 14.3.14 |
| **D380** | **A guarded crate left standing is noted in the run log when it is placed, not when the run ends:** the *Place a guarded crate* step's success line says the crate is kept when the run ends and how it ends (org lead, 2026-10-15). Core gives a module no hook at a run's end for a step that is kept, so D373's note at the end would need new core work. | A run-end hook in core now (a MODULE_API minor, with the Module-uo proof), or filed for later. | 14.3.5, 14.3.19 |
| **D381** | **Server Rewards is taken off the plan** (org lead, 2026-10-16: *"I do not want it"*). Stage 8 is not built. Gone with it: `integrations.serverRewards`, `points.pay` / `balances` / `adjust` and the sidecar's three routes, the tally's `points`, the step `rust.points.pay` and its budget, the `rust_player_points` table, staff add and take, the app's RP balance, and the *Hoarder* title and its column. It amends D350 (five plugins, not six), D369 (its wipe half now covers ZLevels only), D375 and D377 (no *Hoarder*). Nothing had been built. §14.2.1's test findings stay as a record. | Building §14.3.7 as planned. | 14, 14.3.7, 14.3.11 |
## 11. First-class optional plugins (D199–D202)
@@ -2061,8 +2063,9 @@ Kill credit reuses D174's rule, so the feed and *Rotorbane* never disagree about
The same survey read the org lead's two old plugin folders and uMod's Rust catalogue (446 plugins, by downloads
and 57 searches). The org lead chose **six free plugins as first-class optional integrations** (D350):
**TruePVE, Dynamic PVP, Dangerous Treasures, Guarded Crate, ZLevels Remastered and Server Rewards.** *Optional*
means D199's pattern: each is detected at hello, a step or screen that needs one refuses with a reason when it is
**TruePVE, Dynamic PVP, Dangerous Treasures, Guarded Crate, ZLevels Remastered and Server Rewards.** **Server
Rewards was taken off the plan on 2026-10-16 (D381)**, so five remain; what this section says of it is kept as a
record. *Optional* means D199's pattern: each is detected at hello, a step or screen that needs one refuses with a reason when it is
absent, and the installer never requires it.
Two rules from the org lead govern every one of them (D351):
@@ -2091,7 +2094,7 @@ the rigs.
| **Dangerous Treasures** (nivex) | 3.0.0, 2026-10-07, GPL-3 | Feed and map for a treasure event, a *treasures won* column and title, and a step that starts one | Hooks `OnDangerousEventStarted(pos)`, `Won(looter, invaders)`, `Ended(pos)`, `OnPlayerEntered/ExitedDangerousEvent`. Console `dtevent [difficulty] [count]`; **it picks the spot** |
| **Guarded Crate** (Bazz3l) | 2.0.17, 2026-08-09, MIT | Feed and map, and a step that places a guarded crate at a spot | Hooks `OnGuardedCrateEventStart(pos)`, `Ended(player, instance)`, `Failed(pos)`. Console `gcrate start <event>` and `gcrate position <event> x y z`. **`gcrate stop` clears every one**, and the handler checks `arg.IsRcon` |
| **ZLevels Remastered** (nivex) | 3.3.1, 2026-09-10, MIT | Skill levels as leaderboard columns and title conditions. **XP boosts need no code:** its VIP XP multipliers are keyed by permission name, so §12's `rust.perm.lend` already lends one | `GetLevel(userId, skill)`, `api_GetPlayerInfo(userId)`. **No level-up hook**, so the level is read at tally time. Its only write, `api_SetPlayerInfo`, replaces the whole record and is not used |
| **Server Rewards** (k1lly0u) | 2.0.9, 2026-09-27, MIT | The second common currency (RP). It mirrors §11.2: a pay step, balances on the site and app, staff adjust, and a column | `AddPoints` / `TakePoints` / `CheckPoints` (by Steam id), and `OnPointsUpdated(userId, balance)` |
| **Server Rewards** (k1lly0u), **dropped (D381)** | 2.0.9, 2026-09-27, MIT | The second common currency (RP). It mirrors §11.2: a pay step, balances on the site and app, staff adjust, and a column | `AddPoints` / `TakePoints` / `CheckPoints` (by Steam id), and `OnPointsUpdated(userId, balance)` |
**Not included:**
- **Duelist:** left out entirely by the org lead. Its name also clashes with §5's blade-kill title.
@@ -2274,6 +2277,8 @@ above fires for it too. §13 must not count a plugin's crate as Rust's own (the
##### Server Rewards 2.0.9
*Kept as a record: Server Rewards was taken off the plan on 2026-10-16 (D381).*
- **`AddPoints`, `TakePoints` and `CheckPoints` work for an offline player**, through both the `ulong` and `string`
overloads. `TakePoints` refuses (false) more than the balance. **`OnPointsUpdated(ulong, int balance)`**
follows every change.
@@ -2654,54 +2659,25 @@ dropped. D369 still holds in what remains: nothing is done at a wipe.
> **Built on 2026-10-15** (§14.3.20), specified in PROTOCOL.md §20.10, as planned here.
#### 14.3.7 Server Rewards (D369)
#### 14.3.7 Server Rewards — dropped (D381)
It mirrors §11.2.2 (Economics) wherever Server Rewards allows, and the code shares Economics' path where the two
are the same.
**Hello.** `integrations.serverRewards`: `{ loaded, version }`. Server Rewards has no starting balance, so a new
player is at 0.
**The wire.**
- **`points.pay`** `{ key, amount, steamIds[], message, delivery }`, answered by `points.paid` with `paid` (before
and after) and `failed`, the key remembered seven days, the message told once, exactly as `economics.pay`.
**Whole numbers only, 1 to 1,000,000.** The bridge refuses anything else itself, because the id overloads
accept a negative amount and invert it (§14.2.1).
- **`points.balances`** `{ steamIds[] }` → `{ balances: [{ steamId, points }] }`, bounded like `economics.balances`.
- **`points.adjust`** `{ key, steamId, op: add | take, amount }` → `{ before, after }`. There is no `set`, because
Server Rewards has no call for it. `take` above the balance is refused with `insufficient`, as Server Rewards
refuses it.
- The tally gains **`points`**, a value, read at connect and from `OnPointsUpdated(ulong, int)`.
- The sidecar adds `POST /points/pay`, `/points/balances`, `/points/adjust`.
**The website.**
- **The step `rust.points.pay`**, *"Pay RP"*: kept like coins (D335's reasoning), the same recipient modes, a new
budget `rust.points`.
- **Balances** in a new table, **`rust_player_points`** (`server_id`, `steam_id`, `points`),
per server and not per wipe (D369). The player's Rust page, the user's admin page and the app (R10) show it beside
the coins.
- **Staff add and take** from the user's admin page, each an activity row, like Economics.
- **A column and a title**, `points`, default *Hoarder*, a value like the richest (D375): ranked only above 0, on
servers that report Server Rewards, and shown for every wipe view because the points do not belong to one
(D369).
**Tests.** The same set as Economics': the amount bounds (0, negative, fractional), a repeat key, `insufficient`,
the value ingest, the admin route and its activity row, the app's screen.
**Walk rows.** Pay three players, one offline, and see the popup on wake; retry the step and see no second
payment; add and take from the admin page, including more than the balance; read the balance on the site and
in the app; wipe and see the points stay.
**Taken off the plan on 2026-10-16 (D381), before anything was built.** It would have mirrored Economics
(§11.2.2) with `points.pay` / `balances` / `adjust`, a *Pay RP* step, a `rust_player_points` table, staff add and
take, the app's balance and a *Hoarder* title and column. None of it is built, and none of it is on the wire.
#### 14.3.8 The wire, all together
| Kind | New in protocol 14 |
|---|---|
| Hello | `console.plugins`; `integrations.truePve`, `dynamicPvp`, `dangerousTreasures`, `guardedCrate` (with `npcSpawn`, `events`), `zLevels`, `serverRewards` |
| Hello | `console.plugins`; `integrations.truePve`, `dynamicPvp`, `dangerousTreasures`, `guardedCrate` (with `npcSpawn`, `events`), `zLevels` |
| Events | `world.event` (24 types with `chinook.downed`, D379; the type in `event`, §14.3.14); `pvp.zone.created` / `deleted`; `dt.started` / `won` / `ended`; `gc.started` / `ended` / `failed` |
| Commands | `world.call`; `dt.start`; `gc.place`; `points.pay` / `balances` / `adjust`; `world.zone`'s `truePve` |
| Tally | `cratesHacked`, `dropsLooted`, `treasuresWon`, `guardedWon`; `points` (a value). **`heliKills` and `apcKills` leave the tally**: the site counts them from `world.event`'s `credit` (D372) |
| Commands | `world.call`; `dt.start`; `gc.place`; `world.zone`'s `truePve` |
| Tally | `cratesHacked`, `dropsLooted`, `treasuresWon`, `guardedWon`. **`heliKills` and `apcKills` leave the tally**: the site counts them from `world.event`'s `credit` (D372) |
| `map.live` | `world` kinds `treasure` and `guarded`; the `pvp` layer |
| Sidecar | `POST /world/call`, `/dt/start`, `/gc/place`, `/points/pay`, `/points/balances`, `/points/adjust`, thin forwards that keep nothing |
| Sidecar | `POST /world/call`, `/dt/start`, `/gc/place`, thin forwards that keep nothing |
Server Rewards' `points.*` verbs, its hello field, the tally's `points` and the sidecar's `/points/*` routes were
planned here and dropped with it (D381).
`PROTOCOL_VERSION` stays 14 (D332); `overlay.toml` already says 14.
@@ -2718,8 +2694,7 @@ in the app; wipe and see the points stay.
- **A run's DT or guarded crate is told from the plugin's own** by the first start within ten seconds of our
command, which is the only join the hooks allow.
- **The DT and GC steps refuse on a server whose `console.plugins` is false**, rather than being hidden.
- **Server Rewards' wire is `points.*`, beside `economics.*`**, not one verb with a currency field: protocol 14
is unreleased, but Economics' verbs are built and specified, and two names keep each plugin's refusals its own.
- ~~**Server Rewards' wire is `points.*`, beside `economics.*`**~~: void, Server Rewards was dropped (D381).
#### 14.3.10 Questions for the org lead
@@ -2777,7 +2752,7 @@ until the end (D331, D359). The org lead is asked before each stage starts.
5. **Dangerous Treasures**, on stage 2's `retryAfterMs`.
6. **Guarded Crate**.
7. **ZLevels** (hello only, D374).
8. **Server Rewards**.
8. ~~**Server Rewards**~~: dropped on 2026-10-16 (D381), not built.
9. **Core: starting a run from a trigger** (§14.3.12, D370), a website PR of its own with the Module-uo proof,
as §2 was. It can be built alongside any stage after 1; it is last here only because nothing else waits on it.
Module-Rust needs no code for it, because the world events are already triggers.