Merge remote-tracking branch 'origin/edge' into feat/spawn-atlas-parse

This commit is contained in:
2026-07-28 16:45:56 -05:00
17 changed files with 677 additions and 0 deletions

View File

@@ -259,6 +259,25 @@ async function latestPresence() {
return rows[0] || null
}
// ── Shard ruleset (Protocol 3.0 world.ruleset) ─────────────────────────────
// Singleton, same shape as shard_presence: the shard re-emits the whole frame on
// every connect, so there is nothing to merge — the latest one wins outright.
async function setRuleset({ rev, expansion, payload, t }) {
await query(
`INSERT INTO shard_ruleset (id, rev, expansion, payload, t) VALUES (1, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE rev = VALUES(rev), expansion = VALUES(expansion),
payload = VALUES(payload), t = VALUES(t)`,
[rev ?? null, expansion ?? null, payload, Number.isFinite(t) ? t : null],
)
}
async function getRuleset() {
const rows = await query(
'SELECT rev, expansion, payload, t, updated_at FROM shard_ruleset WHERE id = 1',
)
return rows[0] || null
}
module.exports = {
upsertOnline,
removeOnline,
@@ -290,6 +309,8 @@ module.exports = {
listGovernorTerms,
setPresence,
latestPresence,
setRuleset,
getRuleset,
upsertChamp,
removeChamp,
clearChamps,

View File

@@ -508,6 +508,35 @@ async function latestPresence() {
}
}
// ── Shard ruleset (Protocol 3.0 world.ruleset) ─────────────────────────────
//
// The whole frame is stored in `payload` and served back whole. Nothing is
// normalized out of it: it is a flat description of config read as one page, and
// splitting it into columns would mean a schema change every time the shard grows
// a new block. `rev` and `expansion` are hoisted only because they are cheap to
// index/display, following shard_champs' payload-plus-hoisted-columns pattern.
async function setRuleset(ev) {
if (!ev) return
await db.setRuleset({
rev: ev.rev ?? null,
expansion: ev.expansion ?? null,
payload: JSON.stringify(ev),
t: ev.t,
})
}
// The stored ruleset, or null when the shard has never published one (an old
// plugin, or Bridge.RulesetEnabled=false). Null is a real answer here — the page
// says "not published yet" rather than rendering an empty ruleset as if the shard
// had no rules — so it is deliberately not smoothed into {}.
async function getRuleset() {
const r = await db.getRuleset()
if (!r) return null
const payload = typeof r.payload === 'string' ? safeJson(r.payload) : r.payload
if (!payload) return null
return { ...payload, updatedAt: r.updated_at }
}
function safeJson(s) {
try {
return JSON.parse(s)
@@ -557,4 +586,6 @@ module.exports = {
replaceGovernors,
setPresence,
latestPresence,
setRuleset,
getRuleset,
}