fix: Fixing the MP power bonus + seed maintenance
This commit is contained in:
+58
-51
@@ -26,13 +26,12 @@ import {
|
||||
getCellAttackCount,
|
||||
setTileOwner,
|
||||
getTeamActionsRow,
|
||||
resetTeamActions,
|
||||
decrementTeamActions,
|
||||
decrementTeamActionsBy,
|
||||
checkTeamVisibility,
|
||||
insertTeamVisibility,
|
||||
getTeamVisibleCells,
|
||||
getRoundHistory,
|
||||
getSettingsSnapshot,
|
||||
} from "../db/gameDb.js";
|
||||
import {
|
||||
nextResetUtc,
|
||||
@@ -53,7 +52,26 @@ router.get("/config", async (req, res) => {
|
||||
const worldSeed = await ensureSeedEpoch();
|
||||
const cfg = getConfig();
|
||||
const rot = cfg.databaseWipeoutIntervalSeconds;
|
||||
const ws = computeWorldSeedState(rot);
|
||||
const epoch = cfg.timingEpochSec ?? 0;
|
||||
const ws = computeWorldSeedState(rot, epoch);
|
||||
|
||||
// If in-memory config lost its worth tables (e.g. file-read failure),
|
||||
// fall back to the last persisted snapshot stored in the DB.
|
||||
let elementWorth = cfg.elementWorth ?? {};
|
||||
let resourceWorth = cfg.resourceWorth ?? { common: {}, rare: {} };
|
||||
let militaryPower = cfg.militaryPower ?? {};
|
||||
const worthEmpty = Object.keys(elementWorth).length === 0
|
||||
&& Object.keys(resourceWorth.common ?? {}).length === 0;
|
||||
if (worthEmpty) {
|
||||
try {
|
||||
const snap = await getSettingsSnapshot();
|
||||
if (snap) {
|
||||
elementWorth = snap.elementWorth ?? elementWorth;
|
||||
resourceWorth = snap.resourceWorth ?? resourceWorth;
|
||||
militaryPower = snap.militaryPower ?? militaryPower;
|
||||
}
|
||||
} catch { /* best effort */ }
|
||||
}
|
||||
|
||||
let actionsRemaining = null;
|
||||
let teamActionsRemaining = null;
|
||||
@@ -77,19 +95,8 @@ router.get("/config", async (req, res) => {
|
||||
}
|
||||
|
||||
// Team-wide quota: compute current remaining without consuming
|
||||
const now = new Date();
|
||||
const teamRow = await getTeamActionsRow(team);
|
||||
if (!teamRow || new Date(teamRow.quota_reset_at) <= now) {
|
||||
// Expired or unset: compute what it would be when refreshed
|
||||
const rows = await getGridCells(worldSeed);
|
||||
const milPower = computeTeamMilitaryPower(team, rows, cfg.militaryPower ?? {});
|
||||
const milDeductions = await getMilitaryDeductions(worldSeed);
|
||||
const milNet = milPower - (milDeductions[team] ?? 0);
|
||||
const milBonus = Math.floor(Math.max(0, milNet) / 10000);
|
||||
teamActionsRemaining = cfg.teamActionQuota + milBonus;
|
||||
} else {
|
||||
teamActionsRemaining = teamRow.actions_remaining;
|
||||
}
|
||||
teamActionsRemaining = teamRow?.actions_remaining ?? cfg.teamActionQuota;
|
||||
}
|
||||
|
||||
res.json({
|
||||
@@ -101,13 +108,35 @@ router.get("/config", async (req, res) => {
|
||||
seedPeriodStartsAtUtc: ws.seedPeriodStartsAtUtc,
|
||||
actionsRemaining,
|
||||
teamActionsRemaining,
|
||||
actionsResetIntervalHours: cfg.actionsResetIntervalHours ?? 12,
|
||||
resourceWorth: cfg.resourceWorth ?? { common: {}, rare: {} },
|
||||
elementWorth: cfg.elementWorth ?? {},
|
||||
militaryPower: cfg.militaryPower ?? {},
|
||||
actionsResetIntervalSeconds: cfg.actionsResetIntervalSeconds ?? 3600,
|
||||
timingEpochSec: epoch,
|
||||
resourceWorth,
|
||||
elementWorth,
|
||||
militaryPower,
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
// On error, try to return a meaningful fallback from the DB snapshot
|
||||
try {
|
||||
const snap = await getSettingsSnapshot();
|
||||
if (snap && snap.worldSeed) {
|
||||
return res.json({
|
||||
dailyActionQuota: snap.dailyActionQuota ?? 100,
|
||||
databaseWipeoutIntervalSeconds: snap.databaseWipeoutIntervalSeconds ?? 21600,
|
||||
configReloadIntervalSeconds: snap.configReloadIntervalSeconds ?? 30,
|
||||
worldSeed: snap.worldSeed,
|
||||
seedPeriodEndsAtUtc: snap.seedPeriodEndsAtUtc,
|
||||
seedPeriodStartsAtUtc: snap.seedPeriodStartsAtUtc,
|
||||
actionsRemaining: null,
|
||||
teamActionsRemaining: null,
|
||||
actionsResetIntervalSeconds: snap.actionsResetIntervalSeconds ?? 3600,
|
||||
timingEpochSec: snap.timingEpochSec ?? 0,
|
||||
resourceWorth: snap.resourceWorth ?? { common: {}, rare: {} },
|
||||
elementWorth: snap.elementWorth ?? {},
|
||||
militaryPower: snap.militaryPower ?? {},
|
||||
});
|
||||
}
|
||||
} catch { /* fall through to error */ }
|
||||
res.status(500).json({ error: "config_error" });
|
||||
}
|
||||
});
|
||||
@@ -122,7 +151,8 @@ router.get("/grid/:seed", async (req, res) => {
|
||||
error: "seed_expired",
|
||||
worldSeed,
|
||||
seedPeriodEndsAtUtc: computeWorldSeedState(
|
||||
getConfig().databaseWipeoutIntervalSeconds
|
||||
getConfig().databaseWipeoutIntervalSeconds,
|
||||
getConfig().timingEpochSec ?? 0
|
||||
).seedPeriodEndsAtUtc,
|
||||
});
|
||||
}
|
||||
@@ -172,7 +202,7 @@ router.post("/cell/reveal", authMiddleware, async (req, res) => {
|
||||
const now = new Date();
|
||||
const quotaRow = await getUserActionsRow(userId);
|
||||
if (!quotaRow || new Date(quotaRow.quota_reset_at) <= now) {
|
||||
await resetUserActions(userId, effectiveQuota - 1, nextResetUtc(cfg.actionsResetIntervalHours ?? 12).toISOString());
|
||||
await resetUserActions(userId, effectiveQuota - 1, nextResetUtc(cfg.actionsResetIntervalSeconds ?? 3600, cfg.timingEpochSec ?? 0).toISOString());
|
||||
} else {
|
||||
const updated = await decrementUserActions(userId);
|
||||
if (!updated) {
|
||||
@@ -234,26 +264,14 @@ router.post("/cell/capture", authMiddleware, async (req, res) => {
|
||||
const isOpponentControlled = existing.discovered_by !== null && existing.discovered_by !== team;
|
||||
const cost = isOpponentControlled ? baseCost * 2 : baseCost;
|
||||
|
||||
// Consume team actions
|
||||
// Consume team actions — team quota is epoch-scoped, never time-refreshed here.
|
||||
const cfg = getConfig();
|
||||
const now = new Date();
|
||||
const teamRow = await getTeamActionsRow(team);
|
||||
if (!teamRow || new Date(teamRow.quota_reset_at) <= now) {
|
||||
// Compute fresh quota
|
||||
const rows = await getGridCells(worldSeed);
|
||||
const milPower = computeTeamMilitaryPower(team, rows, cfg.militaryPower ?? {});
|
||||
const milDeductions = await getMilitaryDeductions(worldSeed);
|
||||
const milNet = milPower - (milDeductions[team] ?? 0);
|
||||
const milBonus = Math.floor(Math.max(0, milNet) / 10000);
|
||||
const totalActions = cfg.teamActionQuota + milBonus;
|
||||
if (totalActions < cost) {
|
||||
return res.status(429).json({ error: "team_quota_exhausted", cost, teamActionsRemaining: totalActions });
|
||||
}
|
||||
await resetTeamActions(team, totalActions - cost, nextResetUtc(cfg.actionsResetIntervalHours ?? 12).toISOString());
|
||||
} else {
|
||||
if (teamRow.actions_remaining < cost) {
|
||||
return res.status(429).json({ error: "team_quota_exhausted", cost, teamActionsRemaining: teamRow.actions_remaining });
|
||||
}
|
||||
const currentTeamActions = teamRow?.actions_remaining ?? cfg.teamActionQuota;
|
||||
if (currentTeamActions < cost) {
|
||||
return res.status(429).json({ error: "team_quota_exhausted", cost, teamActionsRemaining: currentTeamActions });
|
||||
}
|
||||
if (teamRow) {
|
||||
const updated = await decrementTeamActionsBy(team, cost);
|
||||
if (!updated) {
|
||||
return res.status(429).json({ error: "team_quota_exhausted", cost, teamActionsRemaining: 0 });
|
||||
@@ -308,19 +326,8 @@ router.get("/team-quota", async (req, res) => {
|
||||
try {
|
||||
const worldSeed = await ensureSeedEpoch();
|
||||
const cfg = getConfig();
|
||||
const now = new Date();
|
||||
const teamRow = await getTeamActionsRow(team);
|
||||
let actionsRemaining;
|
||||
if (!teamRow || new Date(teamRow.quota_reset_at) <= now) {
|
||||
const rows = await getGridCells(worldSeed);
|
||||
const milPower = computeTeamMilitaryPower(team, rows, cfg.militaryPower ?? {});
|
||||
const milDeductions = await getMilitaryDeductions(worldSeed);
|
||||
const milNet = milPower - (milDeductions[team] ?? 0);
|
||||
const milBonus = Math.floor(Math.max(0, milNet) / 10000);
|
||||
actionsRemaining = cfg.teamActionQuota + milBonus;
|
||||
} else {
|
||||
actionsRemaining = teamRow.actions_remaining;
|
||||
}
|
||||
const actionsRemaining = teamRow?.actions_remaining ?? cfg.teamActionQuota;
|
||||
res.json({ team, actionsRemaining });
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
|
||||
Reference in New Issue
Block a user