Release Healer Man 0.1.21

This commit is contained in:
phenom committed 2026-09-08 10:40:26 -04:00
1 parent 699fc858c9
commit f6f2375145
210 files changed
+976039 -6247

No files matched your search

+73
View File
@@ -0,0 +1,73 @@
import { create, type StoreApi, type UseBoundStore } from "zustand";
import {
createDungeonEncounterSnapshot,
reduceDungeonEncounter,
registerDungeonEncounterProvider,
resetDungeonEncounterSnapshot,
validateDungeonEncounterDefinition,
} from "./dungeonEncounterRuntime";
import type {
DungeonEncounterDefinition,
DungeonEncounterEffect,
DungeonEncounterEvent,
DungeonEncounterResetScope,
DungeonEncounterSnapshot,
} from "./dungeonEncounterTypes";
export interface DungeonEncounterStoreState extends DungeonEncounterSnapshot {
readonly dispatch: (event: DungeonEncounterEvent) => readonly DungeonEncounterEffect[];
readonly reset: (scope?: DungeonEncounterResetScope, now?: number) => void;
}
function serializableSnapshot(state: DungeonEncounterStoreState): DungeonEncounterSnapshot {
return {
schemaVersion: state.schemaVersion,
encounterId: state.encounterId,
phase: state.phase,
phaseStartedAt: state.phaseStartedAt,
flags: state.flags,
counters: state.counters,
timers: state.timers,
worldObjectStates: state.worldObjectStates,
transitionStates: state.transitionStates,
activeSpawnGroupIds: state.activeSpawnGroupIds,
completedObjectiveIds: state.completedObjectiveIds,
consumedActionIds: state.consumedActionIds,
checkpointId: state.checkpointId,
revision: state.revision,
};
}
export function createDungeonEncounterStore(
definition: DungeonEncounterDefinition,
): UseBoundStore<StoreApi<DungeonEncounterStoreState>> {
validateDungeonEncounterDefinition(definition);
const useStore = create<DungeonEncounterStoreState>((set, get) => ({
...createDungeonEncounterSnapshot(definition),
dispatch: (event) => {
const snapshot = serializableSnapshot(get());
const result = reduceDungeonEncounter(definition, snapshot, event);
if (result.snapshot !== snapshot) set(result.snapshot);
return result.effects;
},
reset: (scope = "dungeon", now = 0) => {
set(resetDungeonEncounterSnapshot(definition, serializableSnapshot(get()), scope, now));
},
}));
const provider = {
definition,
encounterId: definition.id,
dungeonId: definition.dungeonId,
getSnapshot: () => serializableSnapshot(useStore.getState()),
dispatch: (event: DungeonEncounterEvent) => useStore.getState().dispatch(event),
reset: (scope: DungeonEncounterResetScope, now = 0) => useStore.getState().reset(scope, now),
replaceSnapshot: (snapshot: DungeonEncounterSnapshot) => {
if (snapshot.encounterId !== definition.id) {
throw new Error(`Cannot hydrate ${definition.id} from ${snapshot.encounterId}`);
}
useStore.setState(snapshot);
},
};
registerDungeonEncounterProvider(provider);
return useStore;
}