Merge pull request 'docs(runicnpc): stage 0 as built, D229–D230' (#299) from docs/runicnpc-stage0 into main

Reviewed-on: #299
This commit is contained in:
2026-09-30 02:05:26 +00:00
2 changed files with 35 additions and 2 deletions

View File

@@ -8,7 +8,7 @@ they can be read together. **Built so far:** §1, walked 2026-09-28 (§1.9); §5
rig walk still to come (§5.8, D209); §3, built and walked on the rigs and the site 2026-09-29, its in-game rig walk still to come (§5.8, D209); §3, built and walked on the rigs and the site 2026-09-29, its in-game
rows still to come (§3.4); §4, built 2026-09-29 (§4.1). **§6 was spiked on 2026-09-30, and the org lead rows still to come (§3.4); §4, built 2026-09-29 (§4.1). **§6 was spiked on 2026-09-30, and the org lead
chose neither route: Runic Gateway writes its own NPC plugin, RunicNPC, planned in chose neither route: Runic Gateway writes its own NPC plugin, RunicNPC, planned in
[`../../runicnpc/PLAN.md`](../../runicnpc/PLAN.md) (D214–D228), and the rest of this plan waits for it.** [`../../runicnpc/PLAN.md`](../../runicnpc/PLAN.md) (D214–D230), and the rest of this plan waits for it.**
This is a companion to [`PLAN_FIXES.md`](PLAN_FIXES.md) and [`PLAN.md`](PLAN.md). Where they disagree, this This is a companion to [`PLAN_FIXES.md`](PLAN_FIXES.md) and [`PLAN.md`](PLAN.md). Where they disagree, this
document is later and wins. Its decisions continue PLAN_FIXES' numbering at **D188**. document is later and wins. Its decisions continue PLAN_FIXES' numbering at **D188**.

View File

@@ -1,6 +1,8 @@
# RunicNPC — the plan # RunicNPC — the plan
**Status:** plan, written 2026-09-30. No code yet. **Its eight questions (§11) were answered the same day: D221–D228 (§0).** **Status:** plan, written 2026-09-30. Its eight questions (§11) were answered the same day: D221–D228 (§0).
**Stage 0 built 2026-09-30** (runicnpc-rust#1, §9): an empty plugin that loads on both rigs. It is closed by the
first release, v0.1.0, at the `edge`→`main` cutover. D229–D230 were decided with it.
RunicNPC is Runic Gateway's own NPC plugin for Rust servers, in its own repository, RunicNPC is Runic Gateway's own NPC plugin for Rust servers, in its own repository,
[`RunicGateway/runicnpc-rust`](https://gitea.whitlocktech.com/RunicGateway/runicnpc-rust). It runs on Oxide and [`RunicGateway/runicnpc-rust`](https://gitea.whitlocktech.com/RunicGateway/runicnpc-rust). It runs on Oxide and
@@ -38,6 +40,8 @@ architectural or design decision is implemented.
| **D226** | **`edge` → `main`**, like the other Rust repositories (Q5, D18). | PRs straight to `main`. | | **D226** | **`edge` → `main`**, like the other Rust repositories (Q5, D18). | PRs straight to `main`. |
| **D227** | **No default caps.** Instead, a realistic warning of what a number of NPCs costs and its impact on the server, measured in stage 1, shown wherever NPCs are added (Q7). Caps exist only when an admin sets them. | 100 / 50 / 10 per second by default. | | **D227** | **No default caps.** Instead, a realistic warning of what a number of NPCs costs and its impact on the server, measured in stage 1, shown wherever NPCs are added (Q7). Caps exist only when an admin sets them. | 100 / 50 / 10 per second by default. |
| **D228** | **`RunicNPC.cs`, console name `RunicNPC`, chat command `/rnpc`, permissions `runicnpc.*`** (Q8). | — | | **D228** | **`RunicNPC.cs`, console name `RunicNPC`, chat command `/rnpc`, permissions `runicnpc.*`** (Q8). | — |
| **D229** | **The empty repository was seeded by one `chore:` commit straight to `main`** (the licence and a stub README), `edge` was branched from it, and everything after goes by PR (stage 0). It is the only direct push. | You seeding it in the Gitea UI; the whole scaffold straight to `main`, unreviewed. |
| **D230** | **The layout is `plugin/RunicNPC.cs` and a root `plugin.toml`**: `api`, the framework floors, `requires_plugins` (stage 0). RunicNPC is one file, not an overlay of a server tree. | Mirroring Rust-Plugins' `overlay/oxide/plugins/` and `overlay.toml`. |
**Borrowing, not copying.** NpcSpawn states no licence at all, so its source grants us nothing and is read only as a **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 description of *what* can be done in Rust. HumanNPC is MIT on uMod, which is GPL-compatible, but §1.2 rules out its
@@ -332,6 +336,35 @@ needs a player in game writes that walk down, and it is done before the stage cl
**Done when** an empty plugin releases through CI and loads on both rigs. **Done when** an empty plugin releases through CI and loads on both rigs.
**As built (2026-09-30, runicnpc-rust#1):**
- **The plugin** has `// Requires: Kits` and `[Info("RunicNPC", "Runic Gateway", "0.0.0")]`, whose version the
release replaces. It answers `RunicNpc_ApiVersion()` (API 1) and `rnpc.status` (version, API version, which
hooks have fired). It spawns nothing.
- **`plugin.toml`** (D230) declares `api = 1`, `requires_plugins = ["Kits"]` and the floors it was loaded on:
**Oxide 2.0.7726** and **Carbon 2.0.259**. The Oxide floor is newer than the bridge's 2.0.7585, because the rig
runs 7726 and RunicNPC has never run on anything older.
- **`scripts/checkPlugin.js`** runs the bridge's checks (every hook listed in `ExpectedHooks` and void unless
listed in `ANSWERS_DELIBERATELY`; chat-command signatures). It adds three of its own:
- no `RunicNpc_*` call may be public without `[HookMethod]`, because `Call` cannot reach it (the trap in §1.2);
- `// Requires:` must equal `requires_plugins`, and Kits must be in it;
- there must be exactly one `[Info]` line, because the release stamps that line.
It has 23 self-tests, including the real plugin and a CRLF checkout: on Windows, an attribute pattern that
only knew `\n` stopped seeing `[HookMethod]`.
- **The release** reuses Rust-Plugins' release engine unchanged. Its packaging step ships
`runicnpc-<ver>.tar.gz`, holding `runicnpc/RunicNPC.cs` and `manifest.json`, whose fields are component,
version, commit, repo, **`api`**, the floors, `requires_plugins` and `files` with each file's sha256. It ships
`SHA256SUMS` beside it. It does not ask the installer to rebuild its bundle until stage 4 makes RunicNPC part of
that bundle.
- **`tools/`**: `rig.js` and **`console.js`**, not `con.js`. `CON` is a reserved device name on Windows, so git
there cannot open a file of that name, even with an extension. The panel address and server ids moved into
a git-ignored `tools/rigs.json`.
- **Loaded from the branch on both rigs:** `rnpc.status` answered `api=1 hooks=1 fired=1` on Oxide and on Carbon
(Carbon compiled it in 217 ms).
- Also updated: the workspace `CLAUDE.md` repository table, which now lists every org repository, and the org
landing page (`.profile#7`).
### Stage 1 — The spike ### Stage 1 — The spike
A harness plugin (`tools/RunicNpcHarness.cs`) answers, on **both** rigs, what stage 2 depends on: A harness plugin (`tools/RunicNpcHarness.cs`) answers, on **both** rigs, what stage 2 depends on: