Update Healer Man server
This commit is contained in:
1 parent
9c5fb4c614
commit
bd073fb00f
113 files changed
+4902
-273
No files matched your search
@@ -12,6 +12,8 @@ import {
|
||||
cloneDefaultCompanionCooldownPolicy,
|
||||
normalizeCompanionCooldownPolicy,
|
||||
} from "./companion-cooldown-policy.mjs";
|
||||
import { DEFAULT_PARTY_BUFF_POLICY, normalizePartyBuffPolicy } from "./party-buff-policy.mjs";
|
||||
import { DEFAULT_DUNGEON_QUEUE_POLICY, normalizeDungeonQueuePolicy } from "./dungeon-queue-policy.mjs";
|
||||
import {
|
||||
cloneDefaultCompanionSpecReadinessPolicy,
|
||||
normalizeCompanionSpecReadinessPolicy,
|
||||
@@ -20,6 +22,7 @@ import { arenaRatingBand, calculateArenaRating, clampArenaRating } from "./arena
|
||||
import { arenaRoleForSpecialization } from "./arena-specializations.mjs";
|
||||
import { createDungeonReportRepository } from "./dungeon-reports.mjs";
|
||||
import { createDungeonLeaderboardRepository } from "./dungeon-leaderboards.mjs";
|
||||
import { createDungeonRaceRepository } from "./dungeon-races.mjs";
|
||||
import { createDungeonSimulationRepository } from "./dungeon-simulation.mjs";
|
||||
import dungeonLeaderboardCatalog from "../src/game/generated/dungeonLeaderboardCatalog.generated.json" with { type: "json" };
|
||||
|
||||
@@ -110,6 +113,24 @@ export function openGameDatabase(options = {}) {
|
||||
updated_by_username TEXT,
|
||||
updated_at INTEGER
|
||||
) STRICT;
|
||||
CREATE TABLE IF NOT EXISTS party_buff_policy (
|
||||
id INTEGER PRIMARY KEY CHECK (id = 1),
|
||||
schema_version INTEGER NOT NULL,
|
||||
revision INTEGER NOT NULL,
|
||||
config_json TEXT NOT NULL,
|
||||
updated_by_account_id TEXT REFERENCES accounts(id) ON DELETE SET NULL,
|
||||
updated_by_username TEXT,
|
||||
updated_at INTEGER
|
||||
) STRICT;
|
||||
CREATE TABLE IF NOT EXISTS dungeon_queue_policy (
|
||||
id INTEGER PRIMARY KEY CHECK (id = 1),
|
||||
schema_version INTEGER NOT NULL,
|
||||
revision INTEGER NOT NULL,
|
||||
config_json TEXT NOT NULL,
|
||||
updated_by_account_id TEXT REFERENCES accounts(id) ON DELETE SET NULL,
|
||||
updated_by_username TEXT,
|
||||
updated_at INTEGER
|
||||
) STRICT;
|
||||
CREATE TABLE IF NOT EXISTS companion_spec_readiness (
|
||||
id INTEGER PRIMARY KEY CHECK (id = 1),
|
||||
schema_version INTEGER NOT NULL,
|
||||
@@ -215,6 +236,16 @@ export function openGameDatabase(options = {}) {
|
||||
id, schema_version, revision, config_json, updated_by_account_id, updated_by_username, updated_at
|
||||
) VALUES (1, 1, 0, ?, NULL, NULL, NULL)
|
||||
`).run(JSON.stringify(cloneDefaultCompanionCooldownPolicy()));
|
||||
database.prepare(`
|
||||
INSERT OR IGNORE INTO party_buff_policy (
|
||||
id, schema_version, revision, config_json, updated_by_account_id, updated_by_username, updated_at
|
||||
) VALUES (1, 1, 0, ?, NULL, NULL, NULL)
|
||||
`).run(JSON.stringify(DEFAULT_PARTY_BUFF_POLICY));
|
||||
database.prepare(`
|
||||
INSERT OR IGNORE INTO dungeon_queue_policy (
|
||||
id, schema_version, revision, config_json, updated_by_account_id, updated_by_username, updated_at
|
||||
) VALUES (1, 1, 0, ?, NULL, NULL, NULL)
|
||||
`).run(JSON.stringify(DEFAULT_DUNGEON_QUEUE_POLICY));
|
||||
database.prepare(`
|
||||
INSERT OR IGNORE INTO companion_spec_readiness (
|
||||
id, schema_version, revision, config_json, updated_by_account_id, updated_by_username, updated_at
|
||||
@@ -252,6 +283,22 @@ export function openGameDatabase(options = {}) {
|
||||
RETURNING revision, updated_at
|
||||
`),
|
||||
companionCooldownPolicy: database.prepare("SELECT * FROM companion_cooldown_policy WHERE id = 1"),
|
||||
partyBuffPolicy: database.prepare("SELECT * FROM party_buff_policy WHERE id = 1"),
|
||||
dungeonQueuePolicy: database.prepare("SELECT * FROM dungeon_queue_policy WHERE id = 1"),
|
||||
updateDungeonQueuePolicy: database.prepare(`
|
||||
UPDATE dungeon_queue_policy
|
||||
SET schema_version = 1, revision = revision + 1, config_json = ?,
|
||||
updated_by_account_id = ?, updated_by_username = ?, updated_at = ?
|
||||
WHERE id = 1 AND revision = ?
|
||||
RETURNING revision, updated_at
|
||||
`),
|
||||
updatePartyBuffPolicy: database.prepare(`
|
||||
UPDATE party_buff_policy
|
||||
SET schema_version = 1, revision = revision + 1, config_json = ?,
|
||||
updated_by_account_id = ?, updated_by_username = ?, updated_at = ?
|
||||
WHERE id = 1 AND revision = ?
|
||||
RETURNING revision, updated_at
|
||||
`),
|
||||
updateCompanionCooldownPolicy: database.prepare(`
|
||||
UPDATE companion_cooldown_policy
|
||||
SET schema_version = 1, revision = revision + 1, config_json = ?,
|
||||
@@ -450,6 +497,74 @@ export function openGameDatabase(options = {}) {
|
||||
return { revision: Number(row.revision), updatedAt: Number(row.updated_at), updatedBy: account.username, config: normalized };
|
||||
}
|
||||
|
||||
function getPartyBuffPolicy() {
|
||||
const row = statements.partyBuffPolicy.get();
|
||||
try {
|
||||
return {
|
||||
revision: Number(row?.revision ?? 0),
|
||||
updatedAt: row?.updated_at == null ? null : Number(row.updated_at),
|
||||
updatedBy: row?.updated_by_username ?? null,
|
||||
config: normalizePartyBuffPolicy(JSON.parse(row?.config_json ?? "null")),
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("Healer Man party buff policy is corrupt; using safe defaults", error);
|
||||
return { revision: 0, updatedAt: null, updatedBy: null, config: DEFAULT_PARTY_BUFF_POLICY };
|
||||
}
|
||||
}
|
||||
|
||||
function getDungeonQueuePolicy() {
|
||||
const row = statements.dungeonQueuePolicy.get();
|
||||
try {
|
||||
return {
|
||||
revision: Number(row?.revision ?? 0),
|
||||
updatedAt: row?.updated_at == null ? null : Number(row.updated_at),
|
||||
updatedBy: row?.updated_by_username ?? null,
|
||||
config: normalizeDungeonQueuePolicy(JSON.parse(row?.config_json ?? "null")),
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("Healer Man dungeon queue policy is corrupt; using defaults", error);
|
||||
return { revision: 0, updatedAt: null, updatedBy: null, config: DEFAULT_DUNGEON_QUEUE_POLICY };
|
||||
}
|
||||
}
|
||||
|
||||
function putDungeonQueuePolicy(account, expectedRevision, config) {
|
||||
if (!isGameMaster(account)) throw new GameDatabaseError("Game Master access is required.", 403, "gm_required");
|
||||
if (!Number.isInteger(expectedRevision) || expectedRevision < 0) {
|
||||
throw new GameDatabaseError("A valid expected revision is required.", 400, "invalid_revision");
|
||||
}
|
||||
let normalized;
|
||||
try {
|
||||
normalized = normalizeDungeonQueuePolicy(config);
|
||||
} catch (error) {
|
||||
throw new GameDatabaseError(error instanceof Error ? error.message : "Invalid dungeon queue policy.", 400, "invalid_dungeon_queue_policy");
|
||||
}
|
||||
const now = Date.now();
|
||||
const row = statements.updateDungeonQueuePolicy.get(
|
||||
JSON.stringify(normalized), account.id, account.username, now, expectedRevision,
|
||||
);
|
||||
if (!row) throw new GameDatabaseError("The dungeon queue policy changed. Reload and try again.", 409, "revision_conflict");
|
||||
return { revision: Number(row.revision), updatedAt: Number(row.updated_at), updatedBy: account.username, config: normalized };
|
||||
}
|
||||
|
||||
function putPartyBuffPolicy(account, expectedRevision, config) {
|
||||
if (!isGameMaster(account)) throw new GameDatabaseError("Game Master access is required.", 403, "gm_required");
|
||||
if (!Number.isInteger(expectedRevision) || expectedRevision < 0) {
|
||||
throw new GameDatabaseError("A valid expected revision is required.", 400, "invalid_revision");
|
||||
}
|
||||
let normalized;
|
||||
try {
|
||||
normalized = normalizePartyBuffPolicy(config);
|
||||
} catch (error) {
|
||||
throw new GameDatabaseError(error instanceof Error ? error.message : "Invalid party buff policy.", 400, "invalid_party_buff_policy");
|
||||
}
|
||||
const now = Date.now();
|
||||
const row = statements.updatePartyBuffPolicy.get(
|
||||
JSON.stringify(normalized), account.id, account.username, now, expectedRevision,
|
||||
);
|
||||
if (!row) throw new GameDatabaseError("The party buff policy changed. Reload and try again.", 409, "revision_conflict");
|
||||
return { revision: Number(row.revision), updatedAt: Number(row.updated_at), updatedBy: account.username, config: normalized };
|
||||
}
|
||||
|
||||
function getCompanionSpecReadiness() {
|
||||
const row = statements.companionSpecReadiness.get();
|
||||
try {
|
||||
@@ -1066,6 +1181,21 @@ export function openGameDatabase(options = {}) {
|
||||
databasePath,
|
||||
...createDungeonReportRepository(database, { isGameMaster, ErrorType: GameDatabaseError }),
|
||||
...createDungeonLeaderboardRepository(database, { ErrorType: GameDatabaseError }),
|
||||
...(() => {
|
||||
const races = createDungeonRaceRepository(database, { ErrorType: GameDatabaseError });
|
||||
return {
|
||||
getDungeonRaceMatch: races.getMatch,
|
||||
createDungeonRaceMatch: races.createMatch,
|
||||
readyDungeonRace: races.ready,
|
||||
startDungeonRace: races.start,
|
||||
settleDungeonRace: races.settleMatch,
|
||||
completeDungeonRaceRun: races.completeRaceRun,
|
||||
replaceDungeonRaceWithBot: races.replaceWithBot,
|
||||
voidDungeonRace: races.void,
|
||||
dungeonRaceRecordForAccount: races.recordForAccount,
|
||||
listDungeonRaceLeaderboard: races.leaderboard,
|
||||
};
|
||||
})(),
|
||||
...createDungeonSimulationRepository(database, { isGameMaster, ErrorType: GameDatabaseError }),
|
||||
register,
|
||||
login,
|
||||
@@ -1078,6 +1208,10 @@ export function openGameDatabase(options = {}) {
|
||||
putManastormConfig,
|
||||
getCompanionCooldownPolicy,
|
||||
putCompanionCooldownPolicy,
|
||||
getPartyBuffPolicy,
|
||||
putPartyBuffPolicy,
|
||||
getDungeonQueuePolicy,
|
||||
putDungeonQueuePolicy,
|
||||
getCompanionSpecReadiness,
|
||||
putCompanionSpecReadiness,
|
||||
onlineGroupState,
|
||||
|
||||
Reference in new issue
Block a user