feat: stage 3, the /rnpc commands in game
All checks were successful
PR Checks / plugin-checks (pull_request) Successful in 7s

The chat command /rnpc and the same verbs as rnpc.<verb> in a console
(PLAN.md §5), behind runicnpc.place and runicnpc.admin:

- place / here with key=value options in any order (D242); placements
  made in game are named <profile>-<n> and renamable (D241).
- remove, rename, near, info (the NPC you look at), profiles, tp,
  respawn, clear, and rnpc.profile create|show|set|delete for a
  standalone server (refused while the site manages profiles, D221).
- path record / point / undo / save [loop|back] / cancel / list /
  delete (D240). A point an NPC cannot walk to from the last one is
  refused, as is a loop that cannot close: Rust's path query says so.
- A roamer may stand on a player-built floor, with a warning (D239).
  If the floor is destroyed under a live NPC, Rust leaves it standing
  in the air, so the brain puts it on the nearest navmesh within 2 s;
  a placement whose spot is off the mesh respawns on the nearest.
- The API's SetPlacement now refuses a roamer off the navmesh, as the
  command does; placements report a note while they fall back.
- Pos.V and Profile.IsSentry no longer leak into the JSON files.

The harness gains the cmd and floor groups. Both rigs: 134/134 in one
rnt.run all, rnpc reload 5/5, server restart 5/5.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
This commit is contained in:
2026-09-30 03:17:43 -05:00
parent 15120ef80d
commit 0a57d783ca
3 changed files with 1460 additions and 21 deletions

View File

@@ -7,9 +7,8 @@ works on its own, and on a [Runic Gateway](https://gitea.whitlocktech.com/RunicG
website authors its NPC profiles and events use its NPCs. The plan of record, stage by stage, is
[`docs/runicnpc/PLAN.md`](https://gitea.whitlocktech.com/RunicGateway/docs/src/branch/main/runicnpc/PLAN.md).
> **Status: stage 2.** The NPC, its profiles, placements and routes, and the API other plugins call.
> The in-game `/rnpc` commands arrive in stage 3; until then profiles are edited in
> `data/RunicNPC/profiles.json` (then `rnpc.reload`), and placements and routes are made through the API.
> **Status: stage 3.** The NPC, its profiles, placements and routes, the API other plugins call, and
> the `/rnpc` commands admins use in game. Runic Gateway's website takes over the profiles in stage 4.
## Requirements
@@ -44,6 +43,26 @@ Answers at the server console and over RCON: the version, the API version, and w
plugin's hooks have fired. A hook that never fires is the first sign a Rust or framework update has
renamed it, because neither framework reports a hook that matches nothing.
## In game
`/rnpc` in chat, and the same verbs as `rnpc.<verb>` in a console (F1, the server console or RCON).
`/rnpc` alone lists the ones you may use. Grant `runicnpc.place` to place and manage NPCs, and
`runicnpc.admin` for everything (it includes `runicnpc.place`); the server console has both.
```
/rnpc place bandit count=3 respawn=300 mode=group move=route:gate
> Placed bandit-1: 3 × 'bandit' (roamer, route:gate), respawn 300 s, group.
/rnpc path record gate then walk, and at each point: /rnpc path point
/rnpc path save loop (or back, to walk it back and forth)
/rnpc near · /rnpc info · /rnpc rename bandit-1 gateguards · /rnpc remove
```
`place` uses the spot you look at, `here` the spot you stand on; the server console gives
`at=x,y,z`. A roamer must stand on Rust's navmesh; only a sentry may stand off it. Every placement
answers with what the server's NPCs cost. On a standalone server, profiles are made from a console
with `rnpc.profile create|set|delete`. The full list is in
[PLAN.md §5](https://gitea.whitlocktech.com/RunicGateway/docs/src/branch/main/runicnpc/PLAN.md).
## For other plugins
Every call is prefixed `RunicNpc_` and reached through `Call`:
@@ -66,7 +85,7 @@ The API version moves when a call or a raised hook changes shape, not on every r
| `plugin/RunicNPC.cs` | The plugin. The only file a server gets. |
| `plugin.toml` | Its declarations: API version, framework floors, required plugins. The release copies them into the manifest. |
| `scripts/checkPlugin.js` | The static checks run on every pull request and again before a release (see its header). |
| `tools/` | Developer scaffolding for the test rigs, never shipped: the panel scripts (see `tools/rigs.example.json`); `RunicNpcHarness.cs`, the stage 1 measurement plugin; `RunicNpcTest.cs`, the stage 2 test harness (`rnt.run all`, then `rnt.after` after a reload or restart); and `fieldlist/` with `managed.js`, which regenerate the swap's field list (below). |
| `tools/` | Developer scaffolding for the test rigs, never shipped: the panel scripts (see `tools/rigs.example.json`); `RunicNpcHarness.cs`, the stage 1 measurement plugin; `RunicNpcTest.cs`, the stage 2 and 3 test harness (`rnt.run all`, then `rnt.after` after a reload or restart); and `fieldlist/` with `managed.js`, which regenerate the swap's field list (below). |
## After a Rust update: the swap's field list