docs(runicnpc): stage 0 as built, D229–D230 #299
@@ -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
|
||||
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
|
||||
[`../../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
|
||||
document is later and wins. Its decisions continue PLAN_FIXES' numbering at **D188**.
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# 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,
|
||||
[`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`. |
|
||||
| **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). | — |
|
||||
| **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
|
||||
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.
|
||||
|
||||
**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
|
||||
|
||||
A harness plugin (`tools/RunicNpcHarness.cs`) answers, on **both** rigs, what stage 2 depends on:
|
||||
|
||||
Reference in New Issue
Block a user