import { create } from 'zustand'; import { type GamePrefs, getPrefs, setPrefs as persistPrefs } from './prefs'; import type { GameView } from './viewModel'; /** * The view store. The runtime owns the authoritative engine state and pushes a * fresh view snapshot here at ~10 fps; React components subscribe to slices of * it. The store is a dumb mirror plus an event log — no game logic lives here. */ const MAX_LOG_LINES = 50; export interface StoryLogEntry { nodeId: string; prose: string; choiceLabel?: string; } export type ActivePanel = 'play' | 'story' | 'settings' | 'about'; export interface GameStoreState extends GameView { log: string[]; storyHasUnread: boolean; storyLog: StoryLogEntry[]; prefs: GamePrefs; activePanel: ActivePanel; selectedStoryNodeId: string | null; setView: (view: GameView) => void; appendLog: (line: string) => void; appendStoryLog: (entry: StoryLogEntry) => void; setStoryHasUnread: (unread: boolean) => void; setPrefs: (partial: Partial) => void; setActivePanel: (panel: ActivePanel) => void; setSelectedStoryNodeId: (id: string | null) => void; toggleActionGroupCollapsed: (groupKey: string) => void; } export const useGameStore = create((set, get) => ({ resources: [], activeActionId: null, actionName: null, actionProgress: 0, queuedActionIds: [], queuedActionNames: [], actions: [], story: { currentProse: null, atBootIntro: false, choices: [], tree: [] }, actionColumns: [], log: [], storyHasUnread: false, storyLog: [], prefs: getPrefs(), activePanel: 'play', selectedStoryNodeId: null, setView: (view) => set((state) => ({ ...state, ...view })), appendLog: (line) => set((state) => ({ log: [...state.log, line].slice(-MAX_LOG_LINES) })), appendStoryLog: (entry) => set((state) => ({ storyLog: [...state.storyLog, entry] })), setStoryHasUnread: (unread) => set({ storyHasUnread: unread }), setPrefs: (partial) => { const prefs = persistPrefs(partial); set({ prefs }); }, setActivePanel: (panel) => set({ activePanel: panel }), setSelectedStoryNodeId: (id) => set({ selectedStoryNodeId: id }), toggleActionGroupCollapsed: (groupKey) => { const currentPrefs = get().prefs; const nextCollapsed = { ...currentPrefs.collapsedActionGroups, [groupKey]: !currentPrefs.collapsedActionGroups[groupKey], }; const prefs = persistPrefs({ collapsedActionGroups: nextCollapsed }); set({ prefs }); }, }));