docs(rust): protocol 14 — kits.uses and reward notices (PROTOCOL §20, PLAN_REDESIGNS §2.9)
The wire half of PLAN_REDESIGNS §2 (D332, D333): PROTOCOL.md §2 says 14, and §20 specifies kits.uses (counts only, bounded by the sync's bound, POST /kits/uses) and perm.sync notices (the whole untold set, told once when the player is awake, told keys kept on disk, noticesTold in the report). PLAN_REDESIGNS §2.9 records the Rust half as built and its compile on both rigs. Stacked on docs/event-step-editor (docs#335) for §2.8. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
This commit is contained in:
@@ -50,7 +50,7 @@ it is listening without one.
|
||||
|
||||
## 2. Versioning
|
||||
|
||||
The wire version is a single integer — **13** as of the first player walk's fixes (§19) — declared in
|
||||
The wire version is a single integer — **14** as of the step editor (§20) — declared in
|
||||
**four** places that must agree:
|
||||
|
||||
| Where | Repo |
|
||||
@@ -2638,3 +2638,66 @@ unaffected. The refusal is checked before anything is spawned, with the two reas
|
||||
The site checks the same thing first, from the hello's `integrations.runicNpc`, and refuses the step before it
|
||||
is sent; the bridge's check is for a site that missed the hello. `rg.npc` says the same when RunicNPC is not
|
||||
loaded.
|
||||
|
||||
---
|
||||
|
||||
## 20. Protocol 14 — the step editor
|
||||
|
||||
Opened by [`PLAN_REDESIGNS.md`](../modules/rust/PLAN_REDESIGNS.md) §2 after protocol 13 shipped with RunicNPC
|
||||
v1.0.0 (D332). It is built on `edge` in Rust-Plugins, Rust-Link and Module-Rust and released once, after the
|
||||
end-of-plan walk (D331); the first-class optional plugins (§11 there) join it. **This section grows as the
|
||||
pieces land.** `PROTOCOL_VERSION` becomes 14 in all four places (§2).
|
||||
|
||||
### 20.1 `kits.uses` — how many have used a kit up (§2.6)
|
||||
|
||||
The warning beside a kit weekend: *"Kit vip: 2 uses, 24 h cooldown — 9 of 41 linked players have used it up."*
|
||||
The website asks about the players it already knows — the linked players of the server — and the answer is
|
||||
**counts, never a list**.
|
||||
|
||||
```json
|
||||
{"cmd":"kits.uses","reqId":"r-12","kit":"vip","steamIds":["76561190000000001","76561190000000002"]}
|
||||
{"kind":"kits.uses","type":"reply","reqId":"r-12","kit":"vip","max":2,"cooldown":86400,"asked":2,"exhausted":1,"onCooldown":0}
|
||||
```
|
||||
|
||||
- **Main thread**, two Kits reads per player (`GetPlayerKitUses`, `GetPlayerKitCooldown`), plus `GetKitMaxUses` and
|
||||
`GetKitCooldown` once. `exhausted` counts players whose uses have reached `max`; a kit with no use limit
|
||||
(`max` 0) is never used up. `onCooldown` counts players with any cooldown remaining. `asked` is how many ids
|
||||
parsed.
|
||||
- **Bounded by the sync's own bound** (`PermMaxOps`, 20,000): the site sends no more players than a sync
|
||||
carries.
|
||||
- Refusals are `kits.error`, as for `kits.list`: `kits-missing` (Kits is not loaded), `unknown-kit`,
|
||||
`too-large`.
|
||||
- **The sidecar route is `POST /kits/uses`**, a thin forward like `/kits`; the list rides in the body because it
|
||||
can be as long as a server's linked players. Nothing is kept.
|
||||
- **The website** asks once per kit that a permission gates, per server, at most 25 kits, and keeps the answer
|
||||
a minute. It attaches the sentence as the `note` of every `rust.options.grouppermissions` row whose
|
||||
permission is that kit's (core's option note, MODULE_API 1.13.0). A failure is no note.
|
||||
|
||||
### 20.2 `notices` on `perm.sync` — the reward's message (§2.4, D333)
|
||||
|
||||
"You earned kit vip — type /kit vip", said once to the player a reward step picked. `rust.kit.entitle` gains an
|
||||
optional `message` and `delivery`; the site writes them on each grant row, and every sync carries the rows'
|
||||
**whole untold set** for that server, beside `credits`:
|
||||
|
||||
```json
|
||||
{"cmd":"perm.sync", …, "notices":[{"key":"7:3:11","steamId":"76561190000000001","message":"You earned kit vip — type /kit vip","delivery":"popup"}]}
|
||||
```
|
||||
|
||||
- **`key`** is `<runId>:<stepId>:<userId>`: one reward step tells one person once, whichever of their linked
|
||||
accounts it picked. **`steamId`** is that account, while it is still linked to the person.
|
||||
- **When it is said is the plugin's.** At the end of the sync, to a player who is connected and **awake** —
|
||||
a sleeping or loading player sees no popup and reads no chat — and otherwise on `OnPlayerSleepEnded`, the
|
||||
next time they wake on this server. A popup goes through PopupNotifications when `delivery` is `popup` and
|
||||
the plugin is loaded, and chat otherwise; the reward was granted long before this moment, so the player is
|
||||
told either way. At most 2,000 notices per sync; a message is cut at the chat bound (`EventsMaxChat`).
|
||||
- **Told keys are kept on disk** (`data/RunicGateway/notices.json`) until the site stops sending them, so a
|
||||
reload between telling a player and the report that says so cannot tell them twice. Each sync forgets every
|
||||
told key the set no longer carries.
|
||||
- **The report lists them back**: `perm.report` gains `noticesTold`, every key of this sync's set that has been
|
||||
told — at this sync or before it. Present only when the sync carried `notices`, like the credit counts. The
|
||||
site marks those rows told, and they leave the next sync's set.
|
||||
- **A withdrawn reward takes its message with it.** Teardown deletes the grant row, so the notice leaves the set
|
||||
untold, and nobody is told about a reward that is no longer theirs.
|
||||
- **Absent is not empty**, as for `credits`: a sync with no `notices` field leaves the plugin's set alone. The
|
||||
site sends the field on every sync from protocol 14, empty when there is nothing to say. The notices are part
|
||||
of the sync's digest, so a new one is pushed at once.
|
||||
|
||||
Reference in New Issue
Block a user