Files
healer-man/src/game/DungeonRunCheckpointBridge.tsx
T
2026-09-13 11:07:56 -04:00

57 lines
2.2 KiB
TypeScript

import { useEffect, useRef } from "react";
import { useShellStore } from "../app/shellStore";
import {
exportDungeonEncounterCheckpointSnapshots,
subscribeDungeonEncounterSnapshots,
} from "./dungeonEncounterRuntime";
import { DUNGEON_RUN_CHECKPOINT_VERSION } from "./dungeonRunCheckpoint";
import { useGameStore } from "./store";
import { useDungeonRunStore } from "./dungeonRunStore";
function checkpointSignature(dungeonId: string): string {
const game = useGameStore.getState();
const encounters = exportDungeonEncounterCheckpointSnapshots(dungeonId, 0);
return JSON.stringify({
dungeonId,
difficultyId: game.activeDifficultyId,
spawn: game.activeSpawn,
encounters,
run: useDungeonRunStore.getState().progress,
});
}
/** Persists only reset-projected state when encounter progress reaches a new stable revision. */
export function DungeonRunCheckpointBridge() {
const phase = useShellStore((state) => state.phase);
const activeCharacterId = useShellStore((state) => state.activeCharacter?.id ?? null);
const lastSignature = useRef("");
useEffect(() => {
if (phase !== "game" || !activeCharacterId) return undefined;
const save = () => {
const game = useGameStore.getState();
if (game.gameMode !== "dungeon" || game.gmTestMode) return;
const signature = checkpointSignature(game.activeDungeonId);
if (signature === lastSignature.current) return;
lastSignature.current = signature;
const encounters = exportDungeonEncounterCheckpointSnapshots(game.activeDungeonId, 0);
useShellStore.getState().saveActiveDungeonRunCheckpoint({
version: DUNGEON_RUN_CHECKPOINT_VERSION,
dungeonId: game.activeDungeonId,
difficultyId: game.activeDifficultyId,
checkpointId: encounters.find((entry) => entry.checkpointId)?.checkpointId ?? "entrance",
spawn: game.activeSpawn,
encounters,
savedAt: Date.now(),
run: useDungeonRunStore.getState().progress ?? undefined,
});
};
save();
const unsubscribeEncounters = subscribeDungeonEncounterSnapshots(save);
const unsubscribeRun = useDungeonRunStore.subscribe(save);
return () => { unsubscribeEncounters(); unsubscribeRun(); };
}, [activeCharacterId, phase]);
return null;
}