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

@@ -48,6 +48,7 @@ const eventsDb = require('./model/events/events.db')
const eventWorld = require('./eventWorld')
const ingest = require('./ingest')
const mapImages = require('./mapImages')
const npcSync = require('./npcSync')
const permSync = require('./permSync')
const permissionsDb = require('./model/permissions/permissions.db')
const titleSync = require('./titleSync')
@@ -275,6 +276,9 @@ async function onBoot() {
permSync.start()
// The chat titles have a loop of their own for the same reason (phase 17).
titleSync.start()
// So do the NPC profiles, adopted and pushed to each server's RunicNPC
// (runicnpc stage 4, D244): a first push reads a server before it writes it.
npcSync.start()
refreshTimer = setInterval(refresh, REFRESH_MS)
ingestTimer = setInterval(ingestAll, INGEST_MS)
pruneTimer = setInterval(prune, PRUNE_MS)
@@ -300,6 +304,7 @@ async function onBoot() {
async function onShutdown() {
permSync.stop()
titleSync.stop()
npcSync.stop()
for (const timer of [refreshTimer, ingestTimer, pruneTimer, sweepTimer]) {
if (timer) clearInterval(timer)