docs(runicnpc): 9e step 1 — dome stack 3 and the PopupNotifications banner (D326-D328)
D326: a blank dome stack is 3 (module only; the wire still defaults to 1). D327: the recommended PopupNotifications banner ships as a paste block (rust-link/INTEGRATION.md §2.4), from the installer (install and update) and from the egg's install. D328: "at the plugin's defaults" is all or nothing. PLAN_REDESIGNS §3's "until it is chosen by eye" closes; rust-link/INSTALL.md says what the installer and the egg write, and that uninstall leaves it. Code: Module-Rust#36, installer#39, Rust-Link#22. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
This commit is contained in:
@@ -470,7 +470,10 @@ Built on `edge` as Rust-Plugins `feat/zones-domes`, Module-Rust `feat/zones-dome
|
||||
Green and Purple are the Twitch battle-royale spheres, which ZoneDomes itself says show only where they meet
|
||||
terrain or an object, so they read as a ring at the zone's edge. **The org lead chose the full dome as the
|
||||
default:** the step lists Standard first as "Full dome (shaded)", labels each colour for what it shows, and
|
||||
a `dome` sent without a `type` is Standard. The default stack is still 1, until it is chosen by eye.
|
||||
a `dome` sent without a `type` is Standard. **The default stack is 3** (D326, `runicnpc/PLAN.md`): the org
|
||||
lead chose it by eye at noon in RunicNPC's 9d player session, and the module sends it when the step's stack
|
||||
is blank. Steps saved with a blank stack draw 3 from their next run. The wire is unchanged: a `dome` sent
|
||||
without a `stack` still gets 1 from the bridge, and the module always sends one.
|
||||
|
||||
**Compiled on both rigs, and the rig rows walked, 2026-09-29** (no player; the "file API outage" that
|
||||
morning was a Git Bash path-rewriting bug in the walk's own helper, not the rigs):
|
||||
@@ -540,7 +543,8 @@ so the site refuses it until protocol 13 ships:
|
||||
- **The in-game rows, deferred by the org lead (2026-09-29) to the later in-game walk, with §5.7's:**
|
||||
- The flags hold for a player without the exemption and not for one with it.
|
||||
- The enter and leave messages arrive as chat and as a popup.
|
||||
- The default stack is chosen by eye, in daylight and at night.
|
||||
- ~~The default stack is chosen by eye, in daylight and at night.~~ Chosen at noon in RunicNPC's 9d
|
||||
player session: 3 (D326).
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -148,6 +148,9 @@ architectural or design decision is implemented.
|
||||
| **D323** | **Each example profile wears its own outfit; the weapons of D289 stay.** The raider wears scrap armour (coffee-can helmet, roadsign jacket and kilt, hoodie, pants, boots, leather gloves); the camp guard metal (metal facemask and chest plate, long-sleeve shirt, pants, boots, roadsign gloves); the sniper hide (boonie hat, balaclava, hide poncho, pants and boots); the Juggernaut heavy plate, as before. Three shared one hoodie, pants and boots, so they read alike in game. Only a first load writes them (D284): no live server has RunicNPC yet, and the test rigs were given them by resetting `examplesWritten` (9d player walk, 2026-10-09). | One outfit for all; replacing a server's kits that still match the old ones. |
|
||||
| **D324** | **An example kit's items are written at full durability, read from this Rust's item definitions when the kits are written.** Kits sets an item's condition and maximum straight from its file. The writer put 0 on armour (a metal facemask 0 of 320, heavy plate 0 of 1,000, so it barely protected) and 100 on every weapon whatever its real maximum (an M249's is 500). Now an item with a condition gets the definition's maximum and one without gets 0. The harness checks it (`s6.examples.fullCondition`). | A fixed table of maximums, which a Rust update would make stale. |
|
||||
| **D325** | **`/rnpc here` stands the NPC 1 m in front of the admin, facing them, not at their feet.** At their feet it spawned inside the admin, looking away (9d player walk). The spot must fit: nothing at chest height in the way, ground no more than 2 m below, and navmesh for one that walks. Otherwise it falls back to the admin's own spot and the reply says so. The harness checks the distance (`cmd.chat.here`). | 1.5 m or 3 m in front; refusing when the spot does not fit. |
|
||||
| **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. |
|
||||
|
||||
**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
|
||||
@@ -1825,6 +1828,23 @@ put three steps in 9e, in this order (2026-10-09), each ending in its PRs:
|
||||
`module-rust` `edge` → `main` with RunicNPC required. Each release is checked (checksums, the bundle composing)
|
||||
before the next merge. The row the walk left for it: the installer's RunicNPC path from a real bundle.
|
||||
|
||||
**9e step 1, as built (2026-10-09; D326–D328).** Before building, the org lead answered three questions. The dome change
|
||||
is in the module only. "At defaults" means all settings or none. Whether `update` also writes the banner "does not matter",
|
||||
since no host outside the test rigs is installed yet, so both verbs apply the rule.
|
||||
|
||||
- **Dome stack 3:** Module-Rust#36. A blank stack sends 3, and the field's hint says so. 505/505 tests pass.
|
||||
- **The banner, three ways:** the paste block in `rust-link/INTEGRATION.md` §2.4; installer#39 (`popup.rs`; a
|
||||
`popup look` row in the plan; `install` and `update`; 188 tests pass, 5 of them new); Rust-Link#22 (`rg_popup` in
|
||||
`egg/install.sh`; a failure there is said in the console and does not fail the install). Both write PopupNotifications'
|
||||
`Version`, because the plugin resets a config without one, and keep a later version they find.
|
||||
- **How it was checked:**
|
||||
- **The installer:** run against two scratch roots. No published bundle carries RunicNPC yet, so the run bypassed its
|
||||
check in the working tree only. Oxide with no config got the banner. Carbon at the rig's defaults got the walk's
|
||||
banner file exactly. On `update`, a hand-changed config and an existing banner were both kept.
|
||||
- **The egg's function:** run in `ghcr.io/ptero-eggs/installers:debian` over the same cases, plus a config that is
|
||||
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).
|
||||
|
||||
**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)
|
||||
|
||||
@@ -77,6 +77,12 @@ What a run does:
|
||||
The plugin fills in every other key on its first load. An existing config is never rewritten,
|
||||
and one that names a different server stops the run and says so — the website locks a server's
|
||||
id once it has seen it.
|
||||
It also writes the **recommended PopupNotifications banner** (`PopupNotifications.json` beside it;
|
||||
[`INTEGRATION.md` §2.4](INTEGRATION.md#24-the-recommended-popupnotifications-look-optional)), but
|
||||
only where that file is missing or still exactly the plugin's own defaults. A config with any
|
||||
setting changed is kept whole. `install` and `update` both apply this rule, and the plan names
|
||||
which case it found (`popup look … banner written` or `kept`). PopupNotifications itself stays
|
||||
optional and yours to install. One that is already running shows the banner after its next reload.
|
||||
4. **Installs the sidecar**, writes its config with this server's ports, and registers its service.
|
||||
5. **Places the plugin** in `oxide/plugins/` or `carbon/plugins/`. Both frameworks load a plugin
|
||||
the moment it lands, so on a running server the bridge comes up at once; on a stopped one, at
|
||||
@@ -125,7 +131,10 @@ When you create a server from it:
|
||||
against the bundle's checksum, and only then places them: the sidecar in `rust-link/`, the plugin in
|
||||
`oxide/plugins/` or `carbon/plugins/`. `RunicNPC.cs` goes beside the plugin (its data directory is left for RunicNPC to make); a bundle
|
||||
without RunicNPC is refused. Any mismatch fails the install with the reason, before
|
||||
anything is placed.
|
||||
anything is placed. It then writes the recommended PopupNotifications banner by the installer's
|
||||
rule: only where `PopupNotifications.json` is missing or still the plugin's defaults, so a look
|
||||
you chose survives a reinstall. If that write fails, the console says so and the install still
|
||||
succeeds, because it only affects how popups look.
|
||||
|
||||
**The first boot** prints, in the console, the token the sidecar generated — **once** — and a line
|
||||
with what the website needs:
|
||||
@@ -230,7 +239,7 @@ With the installer:
|
||||
|---|---|
|
||||
| `doctor --game rust [--server-id <id>]` | Per server: the framework; whether the plugin file is still the one deployed; each helper deployed beside it, as a **warning** when missing or edited (the bridge runs without one, and the row says what that costs); RunicNPC as a **failure** when it is missing or was never installed (it is required: without it every NPC an event places is refused), and a warning when edited by hand; that the plugin's config names this server; the required uMod plugins; the service; and `/health` through to **plugin connected**. A stopped server is a warning; a running one whose plugin never connected is a failure, printed with the framework versions the plugin is known good on |
|
||||
| `update --game rust` | Moves the sidecar and every server's plugin to the current bundle, and restarts the sidecars. Always all servers together — they share one binary |
|
||||
| `uninstall --game rust [--server-id <id>] [--purge]` | Removes the service, the plugin file, its helpers and RunicNPC. **Keeps the plugin's config** and RunicNPC's `data/RunicNPC/` (an admin's placements and routes) — it is the website's, and it names the server. `--purge` also removes the sidecar config (the token) and the database. Removing the last server removes the shared binary too |
|
||||
| `uninstall --game rust [--server-id <id>] [--purge]` | Removes the service, the plugin file, its helpers and RunicNPC. **Keeps the plugin's config** and RunicNPC's `data/RunicNPC/` (an admin's placements and routes) — it is the website's, and it names the server. `--purge` also removes the sidecar config (the token) and the database. Removing the last server removes the shared binary too. `PopupNotifications.json` is never touched: it belongs to PopupNotifications |
|
||||
|
||||
With the egg: reinstall to update (above); the console is the diagnosis.
|
||||
|
||||
|
||||
@@ -137,6 +137,50 @@ Then press **Test**, which probes the sidecar and reports what came back:
|
||||
|
||||
Within a poll interval the server appears at `/rust/servers`.
|
||||
|
||||
### 2.4 The recommended PopupNotifications look (optional)
|
||||
|
||||
PopupNotifications is optional (D141). Where it is installed, news, events and zone messages can
|
||||
arrive as popups, and its stock look is a small grey box at the right of the screen, sized for one
|
||||
short line. The look we recommend is a **banner across the top of the screen**: no close button,
|
||||
Roboto Condensed Bold at 18 (chosen in RunicNPC's 9d player session, D327). Paste this over
|
||||
`oxide/config/PopupNotifications.json` (Carbon: `carbon/configs/PopupNotifications.json`), then
|
||||
`oxide.reload PopupNotifications` (Carbon: `c.reload PopupNotifications`):
|
||||
|
||||
```json
|
||||
{
|
||||
"Notification duration (in seconds)": 8,
|
||||
"Maximum notifications shown at any time": 6,
|
||||
"UI Positioning": {
|
||||
"Position of the left side of notification (0.0 - 1.0)": 0.15,
|
||||
"Position of the bottom of noticiation (0.0 - 1.0)": 0.87,
|
||||
"Width (0.0 - 1.0)": 0.7,
|
||||
"Height (0.0 - 1.0)": 0.07,
|
||||
"Space between notification (0.0 - 1.0)": 0.005
|
||||
},
|
||||
"UI Options": {
|
||||
"Show close button": false,
|
||||
"Panel color (hex)": "#2b2b2b",
|
||||
"Panel transparency (0.0 - 1.0)": 0.8,
|
||||
"Close button color (hex)": "#d85540",
|
||||
"Close button transparency (0.0 - 1.0)": 0.5,
|
||||
"Font": "robotocondensed-bold.ttf",
|
||||
"Font size": 18
|
||||
},
|
||||
"Version": {
|
||||
"Major": 0,
|
||||
"Minor": 2,
|
||||
"Patch": 1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- **Keep the `Version` block.** PopupNotifications resets a config with no version (or one below
|
||||
0.2.0) to its defaults when it loads, which would undo the banner.
|
||||
- The key `noticiation` is PopupNotifications' own spelling. Leave it as it is.
|
||||
- **The installer and the Pterodactyl egg write this for you**, but only where the file is missing
|
||||
or is still exactly the plugin's own defaults (D328). A config with any setting changed is kept
|
||||
whole, so a look you chose is never replaced. See [`INSTALL.md`](INSTALL.md).
|
||||
|
||||
---
|
||||
|
||||
## 3. When it does not work
|
||||
|
||||
Reference in New Issue
Block a user