feat: add sync new content debug tool
CI / Lint, Build & Test (push) Failing after 51s
Security Scan and Upload / Security & DefectDojo Upload (push) Successful in 1m9s

Adds a new debug panel button that injects any adventurers, quests,
bosses, equipment, upgrades, achievements, zones, and exploration areas
that exist in the current game data but are missing from an existing
player save (e.g. content added after the save was first created).
This commit is contained in:
2026-03-23 18:10:39 -07:00
committed by Naomi Carrigan
parent 26d30c271d
commit e92cf3c9a1
6 changed files with 356 additions and 2 deletions
+90 -2
View File
@@ -10,7 +10,50 @@ import { type JSX, useState } from "react";
import { useGame } from "../../context/gameContext.js";
import { ConfirmationModal } from "../ui/confirmationModal.js";
type ActiveModal = "force-unlocks" | "hard-reset" | null;
type ActiveModal = "force-unlocks" | "hard-reset" | "sync-new-content" | null;
interface SyncNewContentResult {
achievementsAdded: number;
adventurersAdded: number;
bossesAdded: number;
equipmentAdded: number;
explorationAreasAdded: number;
questsAdded: number;
upgradesAdded: number;
zonesAdded: number;
}
/**
* Builds a human-readable summary of what the sync-new-content operation added.
* @param result - The counts returned by the operation.
* @returns A message string describing what was added, or a confirmation nothing was needed.
*/
const buildSyncNewContentMessage = (result: SyncNewContentResult): string => {
const entries: Array<[ number, string ]> = [
[ result.zonesAdded, "zone(s)" ],
[ result.questsAdded, "quest(s)" ],
[ result.bossesAdded, "boss(es)" ],
[ result.explorationAreasAdded, "exploration area(s)" ],
[ result.adventurersAdded, "adventurer tier(s)" ],
[ result.upgradesAdded, "upgrade(s)" ],
[ result.equipmentAdded, "equipment item(s)" ],
[ result.achievementsAdded, "achievement(s)" ],
];
const parts = entries.
filter(([ count ]) => {
return count > 0;
}).
map(([ count, label ]) => {
return `${String(count)} ${label}`;
});
if (parts.length === 0) {
return "Your save is already up to date — no new content was found.";
}
const total = entries.reduce((sum, [ count ]) => {
return sum + count;
}, 0);
return `Added ${String(total)} new item(s) to your save: ${parts.join(", ")}.`;
};
interface ForceUnlocksResult {
adventurersUnlocked: number;
@@ -60,15 +103,21 @@ const buildForceUnlocksMessage = (result: ForceUnlocksResult): string => {
* @returns The JSX element.
*/
const DebugPanel = (): JSX.Element => {
const { forceUnlocks, debugHardReset, isLoading } = useGame();
const { forceUnlocks, debugHardReset, syncNewContent, isLoading } = useGame();
const [ activeModal, setActiveModal ] = useState<ActiveModal>(null);
const [ forceUnlocksResult, setForceUnlocksResult ] = useState<string | null>(null);
const [ syncNewContentResult, setSyncNewContentResult ] = useState<string | null>(null);
function handleOpenForceUnlocks(): void {
setForceUnlocksResult(null);
setActiveModal("force-unlocks");
}
function handleOpenSyncNewContent(): void {
setSyncNewContentResult(null);
setActiveModal("sync-new-content");
}
function handleOpenHardReset(): void {
setActiveModal("hard-reset");
}
@@ -85,6 +134,14 @@ const DebugPanel = (): JSX.Element => {
})();
}
function handleConfirmSyncNewContent(): void {
setActiveModal(null);
void (async(): Promise<void> => {
const result = await syncNewContent();
setSyncNewContentResult(buildSyncNewContentMessage(result));
})();
}
function handleConfirmHardReset(): void {
setActiveModal(null);
void debugHardReset();
@@ -120,6 +177,26 @@ const DebugPanel = (): JSX.Element => {
}
</div>
<div className="debug-action-card">
<h3>{"🔄 Sync New Content"}</h3>
<p>
{
"If the game has been updated since your save was created, this will add any missing adventurers, quests, bosses, equipment, upgrades, and more to your save without affecting your existing progress."
}
</p>
<button
className="action-button"
disabled={isLoading}
onClick={handleOpenSyncNewContent}
type="button"
>
{"Sync New Content"}
</button>
{syncNewContentResult !== null
&& <p className="debug-result-message">{syncNewContentResult}</p>
}
</div>
<div className="debug-action-card">
<h3>{"💀 Hard Reset"}</h3>
<p>
@@ -149,6 +226,17 @@ const DebugPanel = (): JSX.Element => {
/>
}
{activeModal === "sync-new-content"
&& <ConfirmationModal
confirmLabel="Yes, Sync New Content"
description="This will scan for any adventurers, quests, bosses, equipment, upgrades, achievements, and zones added to the game after your save was created, and add them to your save. This operation is safe and non-destructive — your existing progress will not be affected."
isLoading={isLoading}
onCancel={handleCancel}
onConfirm={handleConfirmSyncNewContent}
title="Sync New Content"
/>
}
{activeModal === "hard-reset"
&& <ConfirmationModal
confirmLabel="Yes, Wipe Everything"