fix(rust): protocol 13 step 2 — expiry, plugin loads, the loading hold, NPC names, the link fleet (F2 F5 F6 F7 F8 F13 F14)
The module's half of PLAN_FIXES §6 step 2 (decisions D181-D185, docs#288). - F13/F14 (D170, D183): `world.expired`, recognisable from protocol 13 by its `what`, is handed to core as the resource the zone step ledgered (`world`, `<serverId>:<id>`) through ctx.events.expired, which records it `expired`. coreApi moves to ^1.11.0 (website#209). - F8 (D184): `plugin.loaded` / `plugin.unloaded` mark the permission sync dirty when the plugin added or removed permissions, so an unresolved grant lands on the next tick instead of the fifteen-minute audit. - Catalogue: plugin.loaded/unloaded, world.expired and lease.expired are staff kinds. The last two were never classified (default deny kept them off public pages); the test now covers every event kind through protocol 13. - F7: permission and title pushes hold while the stored hello says `worldReady: false` (a human's "sync now" does not); a failed or refused permission sync now logs at warn. - F2 (D185): the killfeed names an NPC attacker — a family (Scientist, Bandit guard, Bradley APC…) or the prefab without its variant digits (wolf2 → Wolf). - F5/F6: a link code is asked of the servers that minted one in the last six minutes first, then of the rest, each group in parallel; "unsure" only when one of the minting servers is unreachable. - D182: the admin server list carries the ZoneManager helper's state from the hello, and the servers page says what a missing or failed helper costs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
This commit is contained in:
@@ -8,6 +8,7 @@ const core = require('../../core')
|
||||
const LINKS = 'rust_account_links'
|
||||
const PLAYERS = 'rust_players'
|
||||
const STATS = 'rust_player_wipe_stats'
|
||||
const EVENTS = 'rust_events'
|
||||
|
||||
/**
|
||||
* The link for one Steam id, or undefined.
|
||||
@@ -165,7 +166,27 @@ async function userIdsForSteamIds(steamIds) {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* The servers that handed out a link code in the last `windowSec` (PLAN_FIXES F5).
|
||||
*
|
||||
* Every `/link` in game emits `account.link.requested`, which ingest stores like
|
||||
* any frame — without the code, which travels through the player. So the site
|
||||
* cannot know WHICH server minted a code, but it does know which servers minted
|
||||
* one at all. Read on the database's clock (`created_at`, set at ingest) rather
|
||||
* than the frame's `t`, which is the game host's clock.
|
||||
*/
|
||||
async function recentLinkIssuers(windowSec) {
|
||||
const rows = await core.query(
|
||||
`SELECT DISTINCT server_id AS serverId FROM ${EVENTS}
|
||||
WHERE kind = 'account.link.requested'
|
||||
AND created_at >= NOW() - INTERVAL ? SECOND`,
|
||||
[Number(windowSec)],
|
||||
)
|
||||
return rows.map((row) => String(row.serverId))
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
recentLinkIssuers,
|
||||
getBySteamId,
|
||||
listForUser,
|
||||
listForUserWithPlayer,
|
||||
|
||||
Reference in New Issue
Block a user