feat(rust): RunicNPC profiles, their push and adoption, per-profile kills (runicnpc stage 4, WIP)

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
This commit is contained in:
2026-09-30 04:21:46 -05:00
parent b0143801a2
commit 564a234890
12 changed files with 1200 additions and 0 deletions

View File

@@ -490,6 +490,19 @@ const mapRender = (server, body) => request(server, '/map/render', { method: 'PO
/** Everything that moves on one server's map, every layer, unfiltered. The caller filters (§8.5). */
const mapLive = (server) => request(server, '/map/live')
/**
* RunicNPC (runicnpc PLAN.md stage 4, protocol 13). The server's own profiles as
* RunicNPC holds them (`npc.profiles`: `managed`, `profiles`, `refused`), read
* before the site's first push so it can adopt them (D244); a push, which
* replaces them whole and marks the server managed (`npc.ok` lists what
* RunicNPC refused); every placement; and one change to one placement, by `op`.
* Each refusal is `data.kind` `npc.error` with a `reason` and RunicNPC's own sentence.
*/
const npcProfiles = (server) => request(server, '/npc/profiles')
const npcProfilesSet = (server, profiles) => request(server, '/npc/profiles', { method: 'POST', body: { profiles } })
const npcPlacements = (server) => request(server, '/npc/placements')
const npcPlacement = (server, body) => request(server, '/npc/placement', { method: 'POST', body })
module.exports = {
TIMEOUT_MS,
LEASE_TIMEOUT_MS,
@@ -528,5 +541,9 @@ module.exports = {
mapChunk,
mapRender,
mapLive,
npcProfiles,
npcProfilesSet,
npcPlacements,
npcPlacement,
joinUrl,
}