diff --git a/runicnpc/API.md b/runicnpc/API.md index d0a2e7f..bb1cf85 100644 --- a/runicnpc/API.md +++ b/runicnpc/API.md @@ -407,6 +407,11 @@ route is walked back and forth. An NPC joins the route at its nearest point. (D324). On a server no site manages it also adds the four example profiles (`raider`, `campguard`, `sniper`, `juggernaut`). Then it reloads Kits, which reloads RunicNPC with it. **Nothing is written again, even if you delete them** (D280, D284, D289). + The kits written are then **owed a Kits reload** (`kitsReloadOwed`, `kitsReloadTries`; D329) until Kits knows + them all. Every load, and Kits coming back, settles the debt: it is cleared once Kits has the kits, and otherwise + the reload is asked for again. So a load interrupted inside that one second still ends with working examples. After + three reloads RunicNPC stops asking and warns with the command to run (`c.reload Kits` / `oxide.reload Kits`). + A `state.json` from before D329 has neither field and owes nothing. - **A Kits reload reloads RunicNPC** on both frameworks, because RunicNPC requires Kits, and the NPCs it had spawned are lost: placements come back, an event's NPCs do not. **Do not reload Kits while an event runs** (D283). - `config/RunicNPC.json`: diff --git a/runicnpc/PLAN.md b/runicnpc/PLAN.md index dfd313b..9e186ae 100644 --- a/runicnpc/PLAN.md +++ b/runicnpc/PLAN.md @@ -151,6 +151,7 @@ architectural or design decision is implemented. | **D326** | **An event zone's dome stacks 3 spheres when its step leaves the stack blank, not 1.** The org lead chose it by eye at noon in the 9d player session. It changes in `module-rust` only, so steps saved with a blank stack draw 3 from their next run. The wire is unchanged: the bridge still gives a `dome` sent without a `stack` 1, and the module always sends one (2026-10-09). | The bridge's default too, which changes a message's meaning and needs a plugin release. | | **D327** | **A recommended PopupNotifications look ships three ways:** a banner across the top of the screen (left 0.15, bottom 0.87, width 0.7, height 0.07, spacing 0.005), no close button, Roboto Condensed Bold at 18, panel transparency 0.8. It is a block to paste in `rust-link/INTEGRATION.md` §2.4, and both the installer (`install` and `update`) and the Pterodactyl egg's install write it. Each writes it with PopupNotifications' `Version`, because the plugin resets a config without one. PopupNotifications stays optional and is the operator's to install (D141). The org lead: whether `update` also writes it "does not matter", since no host outside the test rigs is installed yet. | Writing it on a first install only; writing it once per host and recording that. | | **D328** | **"Still at the plugin's defaults" means every setting, all or nothing.** The installer and the egg write the banner only where `PopupNotifications.json` is missing, or where every setting equals PopupNotifications 0.2.1's own defaults (its `Version` aside; numbers compared as numbers). A config with any one setting changed, or one that does not parse, is kept whole and never merged into. | Field by field: our values only where that one field is still at its default, which mixes two looks nobody chose. | +| **D329** | **The Kits reload the first load asks for is owed until Kits has the example kits.** The reload ran on a one-second timer, and a timer dies with its plugin. In the 9d session RunicNPC was loaded again inside that second on Carbon, the reload was lost, and since `examplesWritten` was already set the examples stayed refused until Kits was reloaded by hand. Now `state.json` holds `kitsReloadOwed`: every load, and Kits coming back, clears it once Kits knows every kit owed, and otherwise asks for the reload again, at most three times, then warns with the command to run. Oxide never showed it, because loading RunicNPC recompiles and reloads Kits there (`// Requires: Kits`). The org lead chose the fix over recording it (2026-10-09). | Record it as a hot-load artifact, with the remedy in INSTALL.md. | **Borrowing, not copying.** NpcSpawn states no licence at all, so its source grants us nothing and is read only as a description of *what* can be done in Rust. HumanNPC is MIT on uMod, which is GPL-compatible, but §1.2 rules out its @@ -1845,6 +1846,24 @@ since no host outside the test rigs is installed yet, so both verbs apply the ru not JSON and a directory that cannot be made. - **Left for step 3:** both paths from a real bundle (the installer on a rig, the egg by a panel reinstall). +**9e step 2, as built (2026-10-09; D329).** On Rust 25797215 with Oxide 2.0.7815 and Carbon 2.0.262: + +- **A real first boot does not meet it.** The Carbon rig was stopped, the four example kits were taken out of Kits' + file, `examplesWritten` was reset, and the server was booted. The first load wrote the kits, `s6bossc` was refused + for a moment, and Kits reloaded by itself 25 s later (boot timers run late), bringing RunicNPC back with `refused: -`. + A `c.load` and the file landing on a running server, each with Kits reloaded first so it had never seen the + examples, healed the same way within 8 s. +- **The cause, from the rig's own Carbon log of the session (04:49):** the first load wrote the kits and set a + one-second timer for `c.reload Kits`; RunicNPC was loaded again one second later, and the timer died with it. + `examplesWritten` was already set, so the examples stayed refused until the manual reload at 04:51. +- **Why only Carbon:** on Oxide, loading RunicNPC recompiles and reloads Kits as well ("Kits and RunicNPC were + compiled"), because RunicNPC requires it. Carbon reloads only the plugin it was asked to. +- **The org lead chose the fix (D329):** runicnpc-rust#17. Walked on both rigs: a first install landing on a running + server; the interrupted state (kits in Kits' file but not its memory, the reload owed), which now heals on the next + load; and a debt for a kit that never exists, which gives three reloads, the warning, and no loop. Both rigs were + restored afterwards (their own kits files, `examplesWritten` true) and run the fix's build. The harness gains + `s6.examples.reloadSettled` (0.7.3; compiled, not run, while the walk site pushes profiles). + **Then the Rust plan resumes** at PLAN_REDESIGNS §9 item 6 (the step editor and the kit weekend) and §11. ### Stage 10 — Custom navigation (only if needed)