diff --git a/modules/rust/PLAN.md b/modules/rust/PLAN.md index 9b49164..a0b16f4 100644 --- a/modules/rust/PLAN.md +++ b/modules/rust/PLAN.md @@ -1,7 +1,7 @@ # `module-rust` — the plan **Before the Module-Rust cutover (phase 19):** the first player walk's fixes and the org lead's -decisions from it (D159–D168) are planned in [`PLAN_FIXES.md`](PLAN_FIXES.md), 2026-09-26. +decisions from it (D159–D172) are planned in [`PLAN_FIXES.md`](PLAN_FIXES.md), 2026-09-26. **Status:** phases 0 and 1 done, 2026-09-15. **Twenty-two decisions of record, no open questions.** Audited against the whole contract, not just the game-facing chapters (§7); the event and engagement catalogues are §9 and §10; §11 is a second pass over `MODULE_API.md` @@ -6989,13 +6989,13 @@ line, `confirms it connected.` (installer#34). The first walk of [`PLAYER_WALK.md`][pw] with a real player (the Oxide pass, org lead in game) found fifteen places where the bridge or the site does something other than this plan and [`PROTOCOL.md`][protocol] say, and the -org lead took ten decisions on the spot (D159–D168) — among them **D160, which reverses D31**: the site now owns every +org lead took fourteen decisions on it (D159–D172) — among them **D160, which reverses D31**: the site now owns every permission and group, not only those it authored. They are planned in their own document, [`PLAN_FIXES.md`](PLAN_FIXES.md), so this one stays a record of the phases as built. -**Its recommended gate:** the fixes (its §6 steps 1–2, protocol 13) land before Module-Rust's cutover in phase 19; -the redesigns it describes — the permission manager, the event step editor, zone options and domes — follow the -cutover as phases of their own. The Carbon pass is still to be walked and may add to it. +**All of it lands before Module-Rust's cutover in phase 19 (D169)** — the fixes (protocol 13) and the redesigns it +describes: the permission manager, the event step editor, zone options and domes, the map's marker types and the +chat title conditions. The Carbon pass is still to be walked and may add to it. [kit]: https://gitea.whitlocktech.com/RunicGateway/Integration-kit [protocol]: ../../rust-link/PROTOCOL.md diff --git a/modules/rust/PLAN_FIXES.md b/modules/rust/PLAN_FIXES.md index df4daa6..b74d07e 100644 --- a/modules/rust/PLAN_FIXES.md +++ b/modules/rust/PLAN_FIXES.md @@ -1,14 +1,15 @@ # `module-rust` — plan fixes -**Status:** plan, awaiting the org lead's approval, 2026-09-26. **The gate before Module-Rust's cutover -(phase 19, [`PLAN.md`](PLAN.md) §34, D145).** Everything here comes from the first walk of +**Status:** plan, awaiting the org lead's approval, 2026-09-26; its four open questions were answered the same +day (D169–D172). **Everything in it — fixes and redesigns alike — lands before Module-Rust's cutover +(phase 19, [`PLAN.md`](PLAN.md) §34, D145; D169).** Everything here comes from the first walk of [`PLAYER_WALK.md`](../../rust-link/PLAYER_WALK.md) with a real player in the game — the Oxide pass, walked by the org lead on the `rust-oxide` rig with every frame checked on the console, the sidecar and the site's database. The Carbon pass has not been walked yet and may add to this document. This is a companion to [`PLAN.md`](PLAN.md), not a replacement: its decisions continue PLAN.md's numbering (D159 onward), and where the two disagree this one is later and wins. It has three kinds of content, and -they gate the cutover differently (§6): +all of it lands before the cutover (D169, §6): - **Fixes** (§2) — the plugin, the sidecar or the site does something other than what the plan and the protocol say. Fifteen, F1–F15. @@ -51,8 +52,10 @@ Taken by the org lead during and straight after the walk. | **D166** | **The zone step offers ZoneManager's own flags and settings**, read from the installed ZoneManager, not a hard-coded list. | | **D167** | **ZoneDomes is an optional dependency.** The zone step gains a "show a dome" option; the bridge adds the dome and removes it with the zone. | | **D168** | **When a plugin we depend on does not expose what we need, we may write a small helper plugin for it.** It ships from Rust-Plugins beside the bridge, is optional, and is detected at hello like the other integrations. The bridge keeps calling only public APIs (R2); the helper is where a gap in someone else's plugin gets bridged. | - -**One more, leaning but not yet decided:** Steam as a first-class sign-in provider on the website (§4.8). +| **D169** | **Every fix and every redesign in this document lands before Module-Rust's cutover (phase 19).** Rejected: cutting over after the fixes and following with the redesigns. | +| **D170** | **An expired zone is marked expired on the site.** Once F13 makes `world.expired` recognisable, ingest marks the run's resource row `expired`. This amends D96's "the website maps it to nothing". F14. | +| **D171** | **Steam sign-in belongs to the website's own plan and is part of the base website**, exposed to modules however they need it. It leaves this document (§4.8). | +| **D172** | **Chat titles use all twenty-three conditions the org lead listed, under new names** (§4.6). Rejected: a first subset. | ## 2. Fixes @@ -155,13 +158,11 @@ or map prefab to label on the site — whichever the killfeed page already expec empty for players other plugins spawn; the plugin already avoids it for `entity.destroyed`. Use `((ulong)player.userID).ToString()` at all 13 sites. Real connected players are unaffected. -### 2.4 By design — a question, not a fix - -**F14 — the site never learns that a zone expired.** Expired zones stayed `confirmed` on the run console until -the runs were cancelled, when teardown found them "already gone" and counted that a success. PROTOCOL.md §15 -says this is intended: "The website maps it to nothing. Core learns about it through `reconcile` and `revert`" -(D96). **The question:** should ingest mark the row `expired` once F13 makes the frame recognisable, so the -console stops showing a live zone that is gone? Recommended: yes. +**F14 — the site never learns that a zone expired.** *(Module-Rust)* Expired zones stayed `confirmed` on the run +console until the runs were cancelled, when teardown found them "already gone" and counted that a success. This +was the design — PROTOCOL.md §15: "The website maps it to nothing. Core learns about it through `reconcile` and +`revert`" (D96) — and D170 changes it. *Fix:* after F13, ingest maps `world.expired` to the run's resource row +and marks it `expired`; teardown treats `expired` as already reverted; amend PROTOCOL.md §15. ## 3. Interface and walk-doc corrections @@ -257,15 +258,50 @@ A per-type marker setting for staff, defaulting to the major monuments. Decide i monument sweep or the site does the filtering; the type (`monument_substation`, cave, …) is already in the monument data. -### 4.6 Chat titles: more conditions +### 4.6 Chat titles: twenty-three conditions (D172) -The org lead's list, as inspiration (the names are examples): animal, bow, melee, blade, revolver, NPC, APC and -helicopter kills; headshots; players killed; PvP and PvE kill distance; wood, ore and plants gathered; clothes -and weapons crafted; structures built and repaired; players healed; rockets fired; explosives thrown; quests -completed. Most need new counters in the plugin — the weapon class on a kill, headshots, crafting by category, -heals, building and repair, explosives — each a hook, a tally field and a leaderboard column. D159's gathering -counters feed the gathering titles. Quests need a quest plugin, and none is installed. The plan picks the first -set; the rest follow. +All of the conditions the org lead listed, each under a new title. The titles are proposals; the conditions are +decided. Every hook below is in uMod's catalogue ([`HOOKS.md`](HOOKS.md)); each is declared `void`, as the read +path requires (PROTOCOL.md §8.7), and each must be checked on Carbon, whose catalogue renames some. + +| Condition | Title | Where the count comes from | +|---|---|---| +| Animal kills | **Beastbane** | `OnEntityDeath`, victim a `BaseAnimalNPC` — today folded into `npcKills`; split it | +| NPC kills | **Exterminator** | `OnEntityDeath`, victim a human NPC (scientists, bandits) — the other half of that split | +| Players killed | **Reaper** | the existing `kills` column (`player.death` with a player attacker) | +| Bow kills | **Fletcher** | a kill whose weapon is a bow or crossbow — the weapon shortname the killfeed already carries | +| Melee kills | **Brawler** | a kill with any `BaseMelee` weapon | +| Blade kills | **Duelist** | a kill with a bladed melee weapon (machete, swords, knives) — a named list | +| Revolver kills | **Outlaw** | a kill with the revolver or the python | +| Headshots | **Crownbreaker** | a killing blow with `HitInfo.isHeadshot` | +| PvP kill distance | **Longshot** | the *longest* single player kill — the `distance` the killfeed already carries | +| PvE kill distance | **Marksman** | the longest single NPC or animal kill | +| APC kills | **Tankbreaker** | `OnEntityDeath`, victim a `BradleyAPC`, credited to the killing player | +| Helicopter kills | **Rotorbane** | `OnEntityDeath`, victim a patrol helicopter (and the CH47), credited to the killing player | +| Wood gathered | **Timberwright** | `gathered.wood`, all three sources (D159) | +| Ore gathered | **Prospector** | `gathered` metal, sulfur and high-quality ore, all three sources | +| Plants gathered | **Greenhand** | `OnGrowableGathered` plus picked-up plants (hemp, berries, mushrooms, corn, potatoes, pumpkins) | +| Clothes crafted | **Seamster** | `OnItemCraftFinished`, item category attire | +| Weapons crafted | **Armorer** | `OnItemCraftFinished`, item category weapon | +| Structures built | **Mason** | `OnEntityBuilt` placing a building block | +| Structures repaired | **Tinkerer** | `OnStructureRepair` | +| Players healed | **Mender** | healing *another* player — `OnHealingItemUse` on someone else, and `OnPlayerRevive` | +| Rockets fired | **Artillerist** | `OnRocketLaunched` | +| Explosives thrown | **Demolitionist** | `OnExplosiveThrown` and `OnExplosiveDropped` | +| Quests completed | **Wayfarer** | a quest plugin — none is installed; choose one, or a D168 helper | + +What the detailed plan has to settle before building: + +- **Two kinds of column.** Every existing leaderboard column is a sum; the two distance titles need a *best* (the + largest single value). The tally carries the interval's maximum, and the site keeps the running best. +- **What a weapon-class kill counts.** Recommended: any kill the player is credited with — players, NPCs and + animals — so Fletcher rewards a hunter as well as a raider. The weapon lists (bow, blade, revolver) are named + sets in one place, so a Rust update adds a weapon by editing a list. +- **Credit for a vehicle kill.** The APC and the helicopter are usually killed by several people. Credit the player + who dealt the killing blow (`HitInfo.InitiatorPlayer`) — simple, and the rule the killfeed already uses. +- **Healing someone else**, never yourself — otherwise Mender is earned by bandaging after every fight. +- **Counters are aggregates** (rule 2): all of these ride on `player.tally`, never one frame per shot, craft or swing. +- **Quests** wait on a quest plugin; the other twenty-two do not. ### 4.7 NPCs @@ -273,12 +309,12 @@ Research before deciding: which free uMod NPC plugins are maintained and expose name and a behaviour, against extending `rust.npc.place` to dress the stock scientist from a Kits kit and give it a display name. The goal the org lead named is server customisation — NPCs with different kits and names. -### 4.8 Steam sign-in (website, not this module) +### 4.8 Steam sign-in (moved to the website's plan, D171) -Steam as a provider beside Google and Discord. It is OpenID 2.0, not OAuth2/OIDC, so it needs its own adapter. -Leaning toward both halves: link-only sign-in (SSO never provisions an account), and linking Steam also creates -the Rust link, since it proves the Steam id more strongly than a code does. Belongs in `website/` with its own -plan; noted here because it changes R1's identity story. +Steam as a sign-in provider beside Google and Discord is part of the base website and is planned there, not +here. What this module needs from it: a way to learn a signed-in account's verified Steam id, so linking by +Steam can stand beside the in-game code (R1). Steam is OpenID 2.0, not OAuth2/OIDC, so the website needs its +own adapter. ## 5. Protocol @@ -290,20 +326,23 @@ once: - A plugin-loaded / unloaded frame (F8). - The permission inventory verb and its reply (§4.1). - ZoneManager's flags at hello, zone options on `world.zone`, the dome option (§4.4). -- New tally fields for D159 and the first title counters (§4.6). +- New tally fields: D159's gathering sources, the animal / NPC split, weapon-class kills, headshots, crafting, + building, repairs, heals, rockets, explosives, and the two per-interval maxima for kill distance (§4.6). +- `world.expired` handled by the site (F14, D170) — no wire change beyond F13's. F15 changes no message shape and ships ahead of the bump. ## 6. Order, and what gates the cutover -1. **Before anything else:** F15 (data corruption), and F9 + F10 (it throws away edits). Small, no protocol change - for F15. -2. **Protocol 13 with the remaining fixes:** F13, F12, F1, F3, F8, F7, F2, F4, and F5/F6 in the module. -3. **The redesigns** (§4.1, §4.3, §4.4) — each its own phase, planned in detail before code. +**All of it lands before Module-Rust's cutover (D169).** The order inside that: -**Recommended gate:** steps 1 and 2 land before Module-Rust's cutover (phase 19); the redesigns follow it. -Nobody outside the org runs module-rust yet, so the cutover should not carry known corruption or silent -rollbacks, but it need not wait for the new screens. Open for the org lead. +1. **First:** F15 (data corruption), and F9 + F10 (they throw away edits). Small; F15 changes no message shape. +2. **Protocol 13 with the remaining fixes:** F13, F14, F12, F1, F3, F8, F7, F2, F4 in the bridge and the module, + and F5/F6 in the module. +3. **The redesigns**, each planned in detail before code and walked on both frameworks: the permission manager + (§4.1), the event step editor with the kit-weekend template (§4.2, §4.3), zones and domes (§4.4), the map's + marker types (§4.5), the chat title conditions (§4.6), and the NPC research (§4.7). +4. **The cutover**, once the re-walk (§8) passes on Oxide and Carbon. ## 7. Helper plugins (D168) @@ -327,12 +366,19 @@ After step 2 of §6, on both frameworks: - A zone restarted with a player standing in it, and a zone opened around a player (F12). - A zone left to expire, checked by `kind=world.expired` (F13). - A plugin unloaded, a grant made, the plugin loaded again — the grant lands within a minute (F8). +- An expired zone reads `expired` on the run console (F14). +- Each redesign's own walk, and every title condition earned at least once. - Then the steps still owed: the Carbon subset, player step 8 and the map walk with a second player, events step 7 with several players, the phone walks. -## 9. Open questions for the org lead +## 9. Answered, and what stays open -1. The cutover gate in §6 — fixes before phase 19, redesigns after? -2. F14 — should ingest mark an expired zone `expired` (recommended), or keep D96's "maps it to nothing"? -3. Steam sign-in (§4.8) — both halves, and does it belong to this workstream or to `website/`? -4. Which title conditions form the first set (§4.6)? +The four questions this plan first asked were answered on 2026-09-26: the gate (D169), F14 (D170), Steam sign-in +(D171) and the title conditions (D172). + +Left for the detailed plans of §6 step 3, none of them blocking the fixes: + +1. The quest plugin behind Wayfarer — or a D168 helper. +2. Whether the plugin or the site filters monument types (§4.5). +3. The ZoneDomes default type and stack, chosen by looking at each on the rig (§4.4). +4. The NPC route — a plugin, or extending `rust.npc.place` (§4.7). diff --git a/modules/rust/README.md b/modules/rust/README.md index c03301f..396b4ee 100644 --- a/modules/rust/README.md +++ b/modules/rust/README.md @@ -24,7 +24,7 @@ differ. for actually building `module-rust`. Everything else in this directory is copied from uMod; those two are written by this project and are where the phases, the settled decisions and the local test rig are recorded. [`PLAN_FIXES.md`](PLAN_FIXES.md) is its companion: the first player walk's fixes and decisions -D159–D168, planned to land before the Module-Rust cutover. +D159–D172, all to land before the Module-Rust cutover. > **This is a mirror, not a specification we own.** uMod is upstream and wins any disagreement; the > point of copying it is availability and grep-ability, not authority. Nothing here may be cited as a