feat(save): persist story flags and node progress in v1

This commit is contained in:
ginnoir
2026-06-11 18:52:16 -05:00
parent 51d3ec1a4b
commit 9196c77e25
4 changed files with 33 additions and 3 deletions
+11
View File
@@ -58,6 +58,17 @@ describe('createSave()', () => {
state.actionQueue.push('forage');
expect(save.state.actionQueue).toEqual(['forage', 'forage']);
});
it('snapshots story fields in the save payload', () => {
const state = sampleState();
state.storyFlags = { route_a: true };
state.currentStoryNodeId = 'route_a_beat';
state.seenStoryNodeIds = ['boot_intro', 'route_a_beat'];
const save = createSave(state, 1700);
expect(save.state.storyFlags).toEqual({ route_a: true });
expect(save.state.currentStoryNodeId).toBe('route_a_beat');
expect(save.state.seenStoryNodeIds).toHaveLength(2);
});
});
describe('serialize / deserialize round-trip', () => {
+6
View File
@@ -29,6 +29,9 @@ export const gameStateSchema = z.object({
activeActionId: z.string().nullable(),
actionElapsedMs: z.number().nonnegative(),
actionQueue: z.array(z.string()).default([]),
storyFlags: z.record(z.string(), z.boolean()).default({}),
currentStoryNodeId: z.string().default(''),
seenStoryNodeIds: z.array(z.string()).default([]),
});
export const saveSchema = z.object({
@@ -49,6 +52,9 @@ export function createSave(state: GameState, now: number): SaveData {
activeActionId: state.activeActionId,
actionElapsedMs: state.actionElapsedMs,
actionQueue: [...state.actionQueue],
storyFlags: { ...state.storyFlags },
currentStoryNodeId: state.currentStoryNodeId,
seenStoryNodeIds: [...state.seenStoryNodeIds],
},
};
}