diff --git a/README.md b/README.md index 247c50c..a2465fd 100644 --- a/README.md +++ b/README.md @@ -511,7 +511,7 @@ PostgreSQL data lives in bind-mount directories on the host: | `./data/postgres` | Game DB (`star_wars_grid`) | | `./data/postgres_users` | Users DB (`star_wars_users`) | -A **world wipe** only cleans epoch-scoped tables when the UTC period slot changes; it does not touch the host data directories. User accounts, `user_action_quota`, `team_action_quota`, `victory_points`, and `db_metadata` survive all wipes. +A **world wipe** only cleans epoch-scoped tables when the UTC period slot changes; it does not touch the host data directories. Only user accounts (`users`), `victory_points`, and `db_metadata` survive all wipes. Both `user_action_quota` and `team_action_quota` are truncated and reset to config defaults on wipe. To fully reset the game state (including all user accounts), stop the stack and delete both data directories, then start again: diff --git a/server/db/gameDb.js b/server/db/gameDb.js index 8b28ca4..66ea245 100644 --- a/server/db/gameDb.js +++ b/server/db/gameDb.js @@ -1,7 +1,7 @@ import { pool } from "./pools.js"; import { loadConfigFile, getConfig } from "../configLoader.js"; import { computeWorldSeedState } from "../worldSeed.js"; -import { nextResetUtc, resetAllUserActions, getUsersByIds } from "./usersDb.js"; +import { nextResetUtc, truncateUserActionQuota, getUsersByIds } from "./usersDb.js"; let lastSeedSlot = null; @@ -94,18 +94,8 @@ export async function initGameSchema() { `); await pool.query(` ALTER TABLE grid_cells ADD COLUMN IF NOT EXISTS discovered_by TEXT; - UPDATE grid_cells SET discovered_by = 'blue' WHERE discovered_by IS NULL; - ALTER TABLE grid_cells ALTER COLUMN discovered_by SET DEFAULT 'blue'; - DO $$ - BEGIN - IF NOT EXISTS ( - SELECT 1 FROM pg_constraint WHERE conname = 'grid_cells_discovered_by_check' - ) THEN - ALTER TABLE grid_cells ADD CONSTRAINT grid_cells_discovered_by_check - CHECK (discovered_by IN ('blue', 'red')); - END IF; - END $$; - ALTER TABLE grid_cells ALTER COLUMN discovered_by SET NOT NULL; + ALTER TABLE grid_cells ALTER COLUMN discovered_by DROP NOT NULL; + ALTER TABLE grid_cells ALTER COLUMN discovered_by SET DEFAULT NULL; `); await pool.query(` CREATE TABLE IF NOT EXISTS team_action_quota ( @@ -189,14 +179,12 @@ export async function ensureSeedEpoch() { const cfg = getConfig(); const nextNoon = nextResetUtc(cfg.actionsResetIntervalHours ?? 12).toISOString(); await pool.query( - `INSERT INTO team_action_quota (team, actions_remaining, quota_reset_at) - VALUES ('blue', $1, $2), ('red', $1, $2) - ON CONFLICT (team) DO UPDATE - SET actions_remaining = $1, - quota_reset_at = $2`, + `TRUNCATE team_action_quota; + INSERT INTO team_action_quota (team, actions_remaining, quota_reset_at) + VALUES ('blue', $1, $2), ('red', $1, $2)`, [cfg.teamActionQuota, nextNoon] ); - await resetAllUserActions(cfg.dailyActionQuota, nextNoon); + await truncateUserActionQuota(); console.log(`[world] Slot ${lastSeedSlot} → ${seedSlot}; grid wiped, old cooldowns cleared.`); lastSeedSlot = seedSlot; } diff --git a/server/db/usersDb.js b/server/db/usersDb.js index f26d0a2..a11c7d8 100644 --- a/server/db/usersDb.js +++ b/server/db/usersDb.js @@ -151,4 +151,9 @@ export async function resetAllUserActions(actionsRemaining, quotaResetAt) { quota_reset_at = $2`, [actionsRemaining, quotaResetAt] ); +} + +/** Removes all rows from user_action_quota (used on world-seed wipeout). */ +export async function truncateUserActionQuota() { + await usersPool.query(`TRUNCATE user_action_quota`); } \ No newline at end of file