forked from phenom/healer-man
Update Healer Man server
This commit is contained in:
1 parent
f8314e7de1
commit
1fedb9368d
76 files changed
+20556
-2523
No files matched your search
@@ -8,6 +8,14 @@ import {
|
||||
normalizeManastormAdminConfig,
|
||||
stampManastormReviewMetadata,
|
||||
} from "./manastorm-config.mjs";
|
||||
import {
|
||||
cloneDefaultCompanionCooldownPolicy,
|
||||
normalizeCompanionCooldownPolicy,
|
||||
} from "./companion-cooldown-policy.mjs";
|
||||
import {
|
||||
cloneDefaultCompanionSpecReadinessPolicy,
|
||||
normalizeCompanionSpecReadinessPolicy,
|
||||
} from "./companion-spec-readiness.mjs";
|
||||
import { arenaRatingBand, calculateArenaRating, clampArenaRating } from "./arena-rules.mjs";
|
||||
import { arenaRoleForSpecialization } from "./arena-specializations.mjs";
|
||||
import { createDungeonReportRepository } from "./dungeon-reports.mjs";
|
||||
@@ -93,6 +101,24 @@ export function openGameDatabase(options = {}) {
|
||||
updated_by_username TEXT,
|
||||
updated_at INTEGER
|
||||
) STRICT;
|
||||
CREATE TABLE IF NOT EXISTS companion_cooldown_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,
|
||||
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 online_groups (
|
||||
id TEXT PRIMARY KEY,
|
||||
leader_account_id TEXT NOT NULL REFERENCES accounts(id) ON DELETE CASCADE,
|
||||
@@ -184,6 +210,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(cloneDefaultManastormAdminConfig()));
|
||||
database.prepare(`
|
||||
INSERT OR IGNORE INTO companion_cooldown_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(cloneDefaultCompanionCooldownPolicy()));
|
||||
database.prepare(`
|
||||
INSERT OR IGNORE INTO companion_spec_readiness (
|
||||
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(cloneDefaultCompanionSpecReadinessPolicy()));
|
||||
|
||||
const statements = {
|
||||
accountByUsername: database.prepare("SELECT * FROM accounts WHERE username_key = ?"),
|
||||
@@ -215,6 +251,22 @@ export function openGameDatabase(options = {}) {
|
||||
WHERE id = 1 AND revision = ?
|
||||
RETURNING revision, updated_at
|
||||
`),
|
||||
companionCooldownPolicy: database.prepare("SELECT * FROM companion_cooldown_policy WHERE id = 1"),
|
||||
updateCompanionCooldownPolicy: database.prepare(`
|
||||
UPDATE companion_cooldown_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
|
||||
`),
|
||||
companionSpecReadiness: database.prepare("SELECT * FROM companion_spec_readiness WHERE id = 1"),
|
||||
updateCompanionSpecReadiness: database.prepare(`
|
||||
UPDATE companion_spec_readiness
|
||||
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
|
||||
`),
|
||||
arenaLoadouts: database.prepare(`
|
||||
SELECT * FROM arena_loadouts WHERE account_id = ? AND character_id = ? ORDER BY slot
|
||||
`),
|
||||
@@ -364,6 +416,74 @@ export function openGameDatabase(options = {}) {
|
||||
};
|
||||
}
|
||||
|
||||
function getCompanionCooldownPolicy() {
|
||||
const row = statements.companionCooldownPolicy.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: normalizeCompanionCooldownPolicy(JSON.parse(row?.config_json ?? "null")),
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("Healer Man companion cooldown policy is corrupt; using safe defaults", error);
|
||||
return { revision: 0, updatedAt: null, updatedBy: null, config: cloneDefaultCompanionCooldownPolicy() };
|
||||
}
|
||||
}
|
||||
|
||||
function putCompanionCooldownPolicy(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 = normalizeCompanionCooldownPolicy(config);
|
||||
} catch (error) {
|
||||
throw new GameDatabaseError(error instanceof Error ? error.message : "Invalid companion cooldown policy.", 400, "invalid_companion_cooldown_policy");
|
||||
}
|
||||
const now = Date.now();
|
||||
const row = statements.updateCompanionCooldownPolicy.get(
|
||||
JSON.stringify(normalized), account.id, account.username, now, expectedRevision,
|
||||
);
|
||||
if (!row) throw new GameDatabaseError("The companion cooldown 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 {
|
||||
return {
|
||||
revision: Number(row?.revision ?? 0),
|
||||
updatedAt: row?.updated_at == null ? null : Number(row.updated_at),
|
||||
updatedBy: row?.updated_by_username ?? null,
|
||||
config: normalizeCompanionSpecReadinessPolicy(JSON.parse(row?.config_json ?? "null")),
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("Healer Man companion readiness policy is corrupt; using shipped defaults", error);
|
||||
return { revision: 0, updatedAt: null, updatedBy: null, config: cloneDefaultCompanionSpecReadinessPolicy() };
|
||||
}
|
||||
}
|
||||
|
||||
function putCompanionSpecReadiness(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 = normalizeCompanionSpecReadinessPolicy(config);
|
||||
} catch (error) {
|
||||
throw new GameDatabaseError(error instanceof Error ? error.message : "Invalid companion readiness policy.", 400, "invalid_companion_spec_readiness");
|
||||
}
|
||||
const now = Date.now();
|
||||
const row = statements.updateCompanionSpecReadiness.get(
|
||||
JSON.stringify(normalized), account.id, account.username, now, expectedRevision,
|
||||
);
|
||||
if (!row) throw new GameDatabaseError("The companion readiness 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 pruneExpiredGroupInvites() {
|
||||
database.prepare(`
|
||||
UPDATE online_group_invites SET status = 'expired'
|
||||
@@ -620,6 +740,9 @@ export function openGameDatabase(options = {}) {
|
||||
throw new GameDatabaseError("Every player must select a character and party role before the group can start.", 409, "group_not_ready");
|
||||
}
|
||||
const fillWithAi = input?.fillWithAi !== false;
|
||||
if (input?.includeBetaSpecs !== undefined && typeof input.includeBetaSpecs !== "boolean") {
|
||||
throw new GameDatabaseError("includeBetaSpecs must be boolean.", 400, "invalid_beta_preference");
|
||||
}
|
||||
const requestedSize = Math.max(1, Math.min(5, Math.trunc(Number(input?.partySize) || 5)));
|
||||
const partySize = fillWithAi ? Math.max(members.length, requestedSize) : members.length;
|
||||
const activity = {
|
||||
@@ -628,6 +751,7 @@ export function openGameDatabase(options = {}) {
|
||||
contentId,
|
||||
...(type === "dungeon" ? { difficultyId: input?.difficultyId, bossDifficulty: input?.bossDifficulty ?? 1 } : {}),
|
||||
fillWithAi,
|
||||
includeBetaSpecs: input?.includeBetaSpecs === true,
|
||||
partySize,
|
||||
startingLevel: type === "manastorm"
|
||||
? Math.max(1, Math.trunc(Number(input?.startingLevel) || 1))
|
||||
@@ -921,6 +1045,10 @@ export function openGameDatabase(options = {}) {
|
||||
isGameMaster,
|
||||
getManastormConfig,
|
||||
putManastormConfig,
|
||||
getCompanionCooldownPolicy,
|
||||
putCompanionCooldownPolicy,
|
||||
getCompanionSpecReadiness,
|
||||
putCompanionSpecReadiness,
|
||||
onlineGroupState,
|
||||
inviteOnlineGroupMember,
|
||||
respondToOnlineGroupInvite,
|
||||
|
||||
Reference in new issue
Block a user