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 3d69b32b50
commit e31f9f1f93

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 | | 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 | | 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 | | 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 | | 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 **Protocol.** §1, §3, §4 and §5 joined **protocol 13**, which shipped on 2026-10-09 with RunicNPC v1.0.0
@@ -1095,6 +1095,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 | | **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 | | **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 | | **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) ## 11. First-class optional plugins (D199–D202)
@@ -2061,8 +2062,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 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): 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* **TruePVE, Dynamic PVP, Dangerous Treasures, Guarded Crate, ZLevels Remastered and Server Rewards.** **Server
means D199's pattern: each is detected at hello, a step or screen that needs one refuses with a reason when it is 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. absent, and the installer never requires it.
Two rules from the org lead govern every one of them (D351): Two rules from the org lead govern every one of them (D351):
@@ -2091,7 +2093,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** | | **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` | | **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 | | **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:** **Not included:**
- **Duelist:** left out entirely by the org lead. Its name also clashes with §5's blade-kill title. - **Duelist:** left out entirely by the org lead. Its name also clashes with §5's blade-kill title.
@@ -2274,6 +2276,8 @@ above fires for it too. §13 must not count a plugin's crate as Rust's own (the
##### Server Rewards 2.0.9 ##### 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` - **`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)`** overloads. `TakePoints` refuses (false) more than the balance. **`OnPointsUpdated(ulong, int balance)`**
follows every change. follows every change.
@@ -2652,54 +2656,25 @@ dropped. D369 still holds in what remains: nothing is done at a wipe.
**Walk rows.** Lend `vip2` from a run and see the XP rate change at once, and back at the run's end. **Walk rows.** Lend `vip2` from a run and see the XP rate change at once, and back at the run's end.
#### 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 **Taken off the plan on 2026-10-16 (D381), before anything was built.** It would have mirrored Economics
are the same. (§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.
**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.
#### 14.3.8 The wire, all together #### 14.3.8 The wire, all together
| Kind | New in protocol 14 | | 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` | | 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` | | Commands | `world.call`; `dt.start`; `gc.place`; `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) | | 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 | | `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. `PROTOCOL_VERSION` stays 14 (D332); `overlay.toml` already says 14.
@@ -2716,8 +2691,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 - **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. 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. - **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 - ~~**Server Rewards' wire is `points.*`, beside `economics.*`**~~: void, Server Rewards was dropped (D381).
is unreleased, but Economics' verbs are built and specified, and two names keep each plugin's refusals its own.
#### 14.3.10 Questions for the org lead #### 14.3.10 Questions for the org lead
@@ -2775,7 +2749,7 @@ until the end (D331, D359). The org lead is asked before each stage starts.
5. **Dangerous Treasures**, on stage 2's `retryAfterMs`. 5. **Dangerous Treasures**, on stage 2's `retryAfterMs`.
6. **Guarded Crate**. 6. **Guarded Crate**.
7. **ZLevels** (hello only, D374). 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, 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. 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. Module-Rust needs no code for it, because the world events are already triggers.