feat(rust): RunicNPC profiles, placements, event NPCs and per-profile kills (runicnpc stage 4) #29

Merged
whitlocktech merged 4 commits from feat/runicnpc-stage4 into edge 2026-09-30 19:52:14 +00:00
Member

What

This is the site's part of RunicNPC stage 4 (docs/runicnpc/PLAN.md, D243–D252).

  • Admin → Rust NPC profiles. Profiles in the shape RunicNPC reads (D238), for one server, several or every server, checked as RunicNPC checks them. Kits are checked live against each covered server.
    • Each server's push state and RunicNPC's refusals are shown.
    • Each profile has a "kills count" setting (D247).
    • Replaced profiles are listed, with Restore.
  • The push loop (npcSync.js). Before the first push to a server, its own profiles are adopted as profiles for that server alone (D244). One whose name a site profile already has there is kept as replaced (D251).
  • Admin → Rust NPC placements. The server's placements, read live (D222), on the live map: click to place (D245, D246), plus edit, rename, respawn and remove. The live map takes a pick handler and pins; the public page is unchanged.
  • Events. The Place NPCs step offers the site's profiles first, then Rust's own, grouped (D243), and sends profile. It is refused on a server without RunicNPC. The triggers rust.npc.died and rust.npc.health carry profile, byEvent, runId and placement, which a phase gate filters on.
  • Kills. The tally's npcProfileKills is stored per profile and credited to the site profile pushed under that name (D247). They appear in three places:
    • the leaderboard's "Rank by" a profile (D250);
    • an opened leaderboard row, with the player's kills by profile (D252);
    • Player → Rust.
  • Titles and feed. A title category "Kills of an NPC profile" (D250). The killfeed shows attackerNpc as typed.
  • Other. Schema: rust_npc_profiles, _profile_servers, _sync, _kills, and rust_title_rules.profile_id. npc.died, npc.health and npc.placement.changed are staff kinds. The swagger fragment (+13 paths), the engagement manifest and routes.manifest.json are regenerated. npcSync.js is in ci/bundle.json.

Tested

  • 481 server and 66 client tests pass (test/npcs.test.js is new), plus check:imports, check:bundle, check:swagger and check:engagement.
  • The frozen manifest was regenerated against the pinned core.
  • Walked in the browser on both rigs as a signed-in admin, row by row in docs PLAN.md stage 4.

Pairs with

runicnpc-rust feat/stage-4-api3, Rust-Plugins, Rust-Link and installer feat/runicnpc-stage4, plus the docs PR.

Checklist

  • I have read CONTRIBUTING.md.
  • The change builds and existing tests/checks pass locally.
  • I have added or updated tests/docs where it makes sense.
  • My commits are reasonably scoped with clear messages.
  • AI tools were used. Tool(s): Claude Code (Claude Opus 5.5). Commits carry the Co-Authored-By trailer.
  • I agree that my contribution is licensed under GPL-3.0-or-later.

🤖 Generated with Claude Code

https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY

## What This is the site's part of RunicNPC stage 4 (docs/runicnpc/PLAN.md, D243–D252). - **Admin → Rust NPC profiles.** Profiles in the shape RunicNPC reads (D238), for one server, several or every server, checked as RunicNPC checks them. Kits are checked live against each covered server. - Each server's push state and RunicNPC's refusals are shown. - Each profile has a **"kills count"** setting (D247). - Replaced profiles are listed, with Restore. - **The push loop** (`npcSync.js`). Before the first push to a server, its own profiles are adopted as profiles for that server alone (D244). One whose name a site profile already has there is kept as **replaced** (D251). - **Admin → Rust NPC placements.** The server's placements, read live (D222), on the live map: **click to place** (D245, D246), plus edit, rename, respawn and remove. The live map takes a pick handler and pins; the public page is unchanged. - **Events.** The Place NPCs step offers the site's profiles first, then Rust's own, grouped (D243), and sends `profile`. It is refused on a server without RunicNPC. The triggers `rust.npc.died` and `rust.npc.health` carry `profile`, `byEvent`, `runId` and `placement`, which a phase gate filters on. - **Kills.** The tally's `npcProfileKills` is stored per profile and credited to the site profile pushed under that name (D247). They appear in three places: - the leaderboard's "Rank by" a profile (D250); - an opened leaderboard row, with the player's kills by profile (D252); - Player → Rust. - **Titles and feed.** A title category "Kills of an NPC profile" (D250). The killfeed shows `attackerNpc` as typed. - **Other.** Schema: `rust_npc_profiles`, `_profile_servers`, `_sync`, `_kills`, and `rust_title_rules.profile_id`. `npc.died`, `npc.health` and `npc.placement.changed` are staff kinds. The swagger fragment (+13 paths), the engagement manifest and `routes.manifest.json` are regenerated. `npcSync.js` is in `ci/bundle.json`. ## Tested - 481 server and 66 client tests pass (`test/npcs.test.js` is new), plus `check:imports`, `check:bundle`, `check:swagger` and `check:engagement`. - The frozen manifest was regenerated against the pinned core. - **Walked in the browser on both rigs** as a signed-in admin, row by row in docs PLAN.md stage 4. ## Pairs with runicnpc-rust `feat/stage-4-api3`, Rust-Plugins, Rust-Link and installer `feat/runicnpc-stage4`, plus the docs PR. ## Checklist - [x] I have read CONTRIBUTING.md. - [x] The change builds and existing tests/checks pass locally. - [x] I have added or updated tests/docs where it makes sense. - [x] My commits are reasonably scoped with clear messages. - [x] AI tools were used. Tool(s): `Claude Code (Claude Opus 5.5)`. Commits carry the `Co-Authored-By` trailer. - [x] I agree that my contribution is licensed under GPL-3.0-or-later. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
wtclaude added 4 commits 2026-09-30 13:46:50 +00:00
Schema for site NPC profiles (per server, shared or fleet), the per-server
push record, and kills by profile. The push adopts a server's own profiles
before its first push (D244), keeping one whose name a site profile already
has as replaced (D251). The tally's npcProfileKills are stored per profile
and credited to the site profile pushed under that name (D247).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
Admin: /admin/rust/npcs for profiles (create, change, delete, restore a
replaced one, push now) and each server's placements (list, add from a map
point, change, remove, rename, respawn). Public: the profiles a leaderboard
ranks by, one profile's ranking counted as the profile says (D247, D250), and
one player's kills by profile (D252). Player: your own kills by profile.

The Place NPCs step offers the site's profiles first, then Rust's own
(D243). rust.npc.died and rust.npc.health are triggers a phase can wait on.
A title rule can rank a profile's kills. Swagger fragment, engagement and
route manifests regenerated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
Admin: Rust NPC profiles (the form RunicNPC reads, per server, shared or
fleet, each server's push state and refusals, replaced profiles with
Restore) and Rust NPC placements (the live map: click to place, pins for
every placement; edit, rename, respawn, remove). The live map takes a pick
handler and pins, unchanged for the public page.

Public: the leaderboard ranks by a profile's kills (D250), and opening a
row shows that player's kills by profile (D252); the killfeed names a
RunicNPC NPC by its own name. Player: your own kills by profile. Titles: a
rule on a profile's kills picks the profile. npcs.test.js covers the
profile checks, adoption, the push, the picker and verb, the triggers, kill
crediting, titles and placements (481 server tests).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
fix(rust): name the servers in a refused restore
All checks were successful
PR Checks / client-build (pull_request) Successful in 27s
PR Checks / server-tests (pull_request) Successful in 34s
PR Checks / frozen-manifest (pull_request) Successful in -1m12s
a5b9bf434f
The walk read "is on rust-oxide"; it now reads the server's name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
whitlocktech merged commit b83fa8174c into edge 2026-09-30 19:52:14 +00:00
whitlocktech deleted branch feat/runicnpc-stage4 2026-09-30 19:52:16 +00:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: RunicGateway/Module-Rust#29
No description provided.