steamsheep-ts-game-engine 3.0.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../core/messages.ts","../core/constants.ts","../core/utils.ts","../systems/events.ts","../state/history.ts","../state/store.ts","../systems/query.ts","../systems/flow.ts","../ui/Layout.tsx","../ui/LogStream.tsx","../ui/OverlaySystem.tsx"],"names":["create","persist","get","createJSONStorage","jsxs","jsx","Fragment","useRef","useEffect","useState"],"mappings":"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","file":"index.js","sourcesContent":["// src/engine/core/messages.ts\n\n/**\n * 系统消息常量\n * \n * 使用特殊的标识符(sys: 前缀),让 UI 层知道这需要翻译。\n * 这些常量用于系统级别的提示消息,应该在 UI 层进行本地化处理。\n */\nexport const SystemMessages = {\n /** 资源不足提示 */\n NOT_ENOUGH_RESOURCES: 'sys:not_enough_resources',\n /** 条件不满足提示 */\n REQUIREMENT_NOT_MET: 'sys:requirement_not_met',\n /** 操作成功提示 */\n ACTION_SUCCESS: 'sys:action_success',\n /** 时间回溯成功提示 */\n UNDO_SUCCESS: 'sys:undo_success',\n} as const;","// src/engine/core/constants.ts\n/**\n * 全局常量定义\n */\n\n/**\n * 引擎版本\n */\nexport const ENGINE_VERSION = '1.0.0';\n\n/**\n * 默认配置\n */\nexport const DEFAULT_CONFIG = {\n /** 默认存档键名 */\n DEFAULT_SAVE_KEY: 'game-save',\n /** 最大日志条数 */\n MAX_LOG_ENTRIES: 50,\n /** 最大历史快照数 */\n MAX_HISTORY_SNAPSHOTS: 20,\n /** 飘字显示时长(毫秒) */\n TOAST_DURATION: 3000,\n} as const;\n\n/**\n * 日志类型颜色映射\n */\nexport const LOG_TYPE_COLORS = {\n info: '#3b82f6',\n success: '#10b981',\n warn: '#f59e0b',\n error: '#ef4444',\n result: '#6366f1',\n} as const;\n\n/**\n * 默认属性值\n */\nexport const DEFAULT_STATS = {\n /** 默认生命值 */\n DEFAULT_HP: 100,\n /** 默认金币 */\n DEFAULT_GOLD: 0,\n} as const;\n\n/**\n * 游戏时间常量\n */\nexport const TIME_CONSTANTS = {\n /** 一天的小时数 */\n HOURS_PER_DAY: 24,\n /** 早晨开始时间 */\n MORNING_START: 6,\n /** 中午开始时间 */\n NOON_START: 12,\n /** 傍晚开始时间 */\n EVENING_START: 18,\n /** 夜晚开始时间 */\n NIGHT_START: 22,\n} as const;\n\n/**\n * UI 常量\n */\nexport const UI_CONSTANTS = {\n /** 侧边栏宽度 */\n SIDEBAR_WIDTH: 288, // 72 * 4 = 288px (w-72)\n /** 日志栏宽度 */\n LOG_WIDTH: 320, // 80 * 4 = 320px (w-80)\n /** Toast 容器 z-index */\n TOAST_Z_INDEX: 1000,\n /** Modal 容器 z-index */\n MODAL_Z_INDEX: 2000,\n} as const;\n\n/**\n * 验证常量\n */\nexport const VALIDATION = {\n /** 最小属性值 */\n MIN_STAT_VALUE: 0,\n /** 最大属性值 */\n MAX_STAT_VALUE: 9999,\n /** 最大背包容量 */\n MAX_INVENTORY_SIZE: 100,\n /** 最小动作 ID 长度 */\n MIN_ACTION_ID_LENGTH: 1,\n /** 最大动作 ID 长度 */\n MAX_ACTION_ID_LENGTH: 50,\n} as const;","// src/engine/core/utils.ts\n/**\n * 工具函数集合\n */\n\nimport type { GameState } from './types';\nimport { TIME_CONSTANTS } from './constants';\n\n/**\n * 生成唯一 ID\n * \n * @returns 唯一标识符字符串\n * \n * @example\n * ```typescript\n * const id = generateId(); // \"1234567890-abc123\"\n * ```\n */\nexport function generateId(): string {\n return `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;\n}\n\n/**\n * 深拷贝对象\n * \n * 使用 JSON 序列化实现深拷贝,注意会丢失函数、Symbol 等特殊类型\n * \n * @param obj - 要拷贝的对象\n * @returns 深拷贝后的对象\n * \n * @example\n * ```typescript\n * const copy = deepClone(originalObject);\n * ```\n */\nexport function deepClone<T>(obj: T): T {\n return JSON.parse(JSON.stringify(obj));\n}\n\n/**\n * 限制数值在指定范围内\n * \n * @param value - 要限制的值\n * @param min - 最小值\n * @param max - 最大值\n * @returns 限制后的值\n * \n * @example\n * ```typescript\n * clamp(150, 0, 100); // 100\n * clamp(-10, 0, 100); // 0\n * clamp(50, 0, 100); // 50\n * ```\n */\nexport function clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n\n/**\n * 格式化数字,添加千位分隔符\n * \n * @param num - 要格式化的数字\n * @returns 格式化后的字符串\n * \n * @example\n * ```typescript\n * formatNumber(1234567); // \"1,234,567\"\n * ```\n */\nexport function formatNumber(num: number): string {\n return num.toString().replace(/\\B(?=(\\d{3})+(?!\\d))/g, ',');\n}\n\n/**\n * 获取时间段描述\n * \n * @param hour - 小时数 (0-23)\n * @returns 时间段描述\n * \n * @example\n * ```typescript\n * getTimeOfDay(8); // \"早晨\"\n * getTimeOfDay(14); // \"下午\"\n * getTimeOfDay(20); // \"傍晚\"\n * ```\n */\nexport function getTimeOfDay(hour: number): string {\n if (hour >= TIME_CONSTANTS.MORNING_START && hour < TIME_CONSTANTS.NOON_START) {\n return '早晨';\n } else if (hour >= TIME_CONSTANTS.NOON_START && hour < TIME_CONSTANTS.EVENING_START) {\n return '下午';\n } else if (hour >= TIME_CONSTANTS.EVENING_START && hour < TIME_CONSTANTS.NIGHT_START) {\n return '傍晚';\n } else {\n return '夜晚';\n }\n}\n\n/**\n * 计算百分比\n * \n * @param current - 当前值\n * @param max - 最大值\n * @returns 百分比 (0-100)\n * \n * @example\n * ```typescript\n * getPercentage(75, 100); // 75\n * getPercentage(0, 100); // 0\n * ```\n */\nexport function getPercentage(current: number, max: number): number {\n if (max === 0) return 0;\n return Math.round((current / max) * 100);\n}\n\n/**\n * 随机整数\n * \n * @param min - 最小值(包含)\n * @param max - 最大值(包含)\n * @returns 随机整数\n * \n * @example\n * ```typescript\n * randomInt(1, 6); // 1-6 之间的随机整数(模拟骰子)\n * ```\n */\nexport function randomInt(min: number, max: number): number {\n return Math.floor(Math.random() * (max - min + 1)) + min;\n}\n\n/**\n * 从数组中随机选择一个元素\n * \n * @param array - 数组\n * @returns 随机选择的元素,如果数组为空则返回 undefined\n * \n * @example\n * ```typescript\n * randomChoice(['剑', '盾', '药水']); // 随机返回一个\n * ```\n */\nexport function randomChoice<T>(array: T[]): T | undefined {\n if (array.length === 0) return undefined;\n return array[Math.floor(Math.random() * array.length)];\n}\n\n/**\n * 打乱数组顺序(Fisher-Yates 算法)\n * \n * @param array - 要打乱的数组\n * @returns 打乱后的新数组\n * \n * @example\n * ```typescript\n * shuffle([1, 2, 3, 4, 5]); // [3, 1, 5, 2, 4]\n * ```\n */\nexport function shuffle<T>(array: T[]): T[] {\n const result = [...array];\n for (let i = result.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1));\n [result[i], result[j]] = [result[j], result[i]];\n }\n return result;\n}\n\n/**\n * 延迟执行\n * \n * @param ms - 延迟毫秒数\n * @returns Promise\n * \n * @example\n * ```typescript\n * await delay(1000); // 延迟 1 秒\n * ```\n */\nexport function delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * 检查对象是否为空\n * \n * @param obj - 要检查的对象\n * @returns 是否为空\n * \n * @example\n * ```typescript\n * isEmpty({}); // true\n * isEmpty({ a: 1 }); // false\n * ```\n */\nexport function isEmpty(obj: object): boolean {\n return Object.keys(obj).length === 0;\n}\n\n/**\n * 安全地获取嵌套属性\n * \n * @param obj - 对象\n * @param path - 属性路径,用点分隔\n * @param defaultValue - 默认值\n * @returns 属性值或默认值\n * \n * @example\n * ```typescript\n * const obj = { a: { b: { c: 123 } } };\n * get(obj, 'a.b.c', 0); // 123\n * get(obj, 'a.x.y', 0); // 0\n * ```\n */\nexport function get<T>(obj: unknown, path: string, defaultValue?: T): T {\n const keys = path.split('.');\n let result: unknown = obj;\n\n for (const key of keys) {\n if (result && typeof result === 'object' && key in result) {\n result = (result as Record<string, unknown>)[key];\n } else {\n return defaultValue as T;\n }\n }\n\n return result as T;\n}\n\n/**\n * 防抖函数\n * \n * @param fn - 要防抖的函数\n * @param wait - 等待时间(毫秒)\n * @returns 防抖后的函数\n * \n * @example\n * ```typescript\n * const debouncedSave = debounce(() => saveGame(), 1000);\n * debouncedSave(); // 1秒内多次调用只执行最后一次\n * ```\n */\nexport function debounce<T extends (...args: never[]) => unknown>(\n fn: T,\n wait: number\n): (...args: Parameters<T>) => void {\n let timeout: ReturnType<typeof setTimeout> | null = null;\n\n return function (this: unknown, ...args: Parameters<T>) {\n if (timeout) clearTimeout(timeout);\n timeout = setTimeout(() => fn.apply(this, args), wait);\n };\n}\n\n/**\n * 节流函数\n * \n * @param fn - 要节流的函数\n * @param wait - 等待时间(毫秒)\n * @returns 节流后的函数\n * \n * @example\n * ```typescript\n * const throttledUpdate = throttle(() => updateUI(), 100);\n * throttledUpdate(); // 100ms 内只执行一次\n * ```\n */\nexport function throttle<T extends (...args: never[]) => unknown>(\n fn: T,\n wait: number\n): (...args: Parameters<T>) => void {\n let lastTime = 0;\n\n return function (this: unknown, ...args: Parameters<T>) {\n const now = Date.now();\n if (now - lastTime >= wait) {\n lastTime = now;\n fn.apply(this, args);\n }\n };\n}\n\n/**\n * 格式化游戏时间\n * \n * @param day - 天数\n * @param time - 小时数\n * @returns 格式化的时间字符串\n * \n * @example\n * ```typescript\n * formatGameTime(5, 14); // \"第 5 天 下午 2:00\"\n * ```\n */\nexport function formatGameTime(day: number, time: number): string {\n const hour = time % TIME_CONSTANTS.HOURS_PER_DAY;\n const period = getTimeOfDay(hour);\n const displayHour = hour === 0 ? 12 : hour > 12 ? hour - 12 : hour;\n return `第 ${day} 天 ${period} ${displayHour}:00`;\n}\n\n/**\n * 计算两个状态之间的差异\n * \n * @param oldState - 旧状态\n * @param newState - 新状态\n * @returns 差异对象\n * \n * @example\n * ```typescript\n * const diff = getStateDiff(oldState, newState);\n * console.log(diff.stats); // { hp: -10, gold: 5 }\n * ```\n */\nexport function getStateDiff<S extends string, I extends string, F extends string, X>(\n oldState: GameState<S, I, F, X>,\n newState: GameState<S, I, F, X>\n): {\n stats: Partial<Record<S, number>>;\n itemsAdded: I[];\n itemsRemoved: I[];\n flagsChanged: Partial<Record<F, boolean>>;\n} {\n const diff = {\n stats: {} as Partial<Record<S, number>>,\n itemsAdded: [] as I[],\n itemsRemoved: [] as I[],\n flagsChanged: {} as Partial<Record<F, boolean>>,\n };\n\n // 计算属性差异\n for (const key in newState.stats) {\n const oldValue = oldState.stats[key] || 0;\n const newValue = newState.stats[key] || 0;\n if (oldValue !== newValue) {\n diff.stats[key] = newValue - oldValue;\n }\n }\n\n // 计算物品差异\n const oldItems = new Set(oldState.inventory);\n const newItems = new Set(newState.inventory);\n\n for (const item of newState.inventory) {\n if (!oldItems.has(item)) {\n diff.itemsAdded.push(item);\n }\n }\n\n for (const item of oldState.inventory) {\n if (!newItems.has(item)) {\n diff.itemsRemoved.push(item);\n }\n }\n\n // 计算标记差异\n for (const key in newState.flags) {\n if (oldState.flags[key] !== newState.flags[key]) {\n diff.flagsChanged[key] = newState.flags[key];\n }\n }\n\n return diff;\n}","// src/engine/systems/events.ts\n\n/**\n * 类型安全的事件监听器回调函数\n * 使用 `unknown` 作为默认类型以强制类型安全\n * @template T - 监听器期望接收的数据类型\n */\ntype Listener<T = unknown> = (data: T) => void;\n\n/**\n * EventBus - 类型安全的发布-订阅事件系统\n *\n * 提供了一个集中式机制,让组件通过事件进行通信而无需紧密耦合。\n * 支持泛型类型参数以实现类型安全的载荷数据。\n *\n * @example\n * ```typescript\n * // 订阅事件并保证类型安全\n * const unsubscribe = eventBus.on<{ count: number }>('update', (data) => {\n * console.log(data.count); // TypeScript 知道 data 有 count 属性\n * });\n *\n * // 发射事件\n * eventBus.emit('update', { count: 42 });\n *\n * // 取消订阅\n * unsubscribe();\n * ```\n */\nexport class EventBus {\n /**\n * 事件监听器的内部存储\n * 将事件名映射到监听器回调函数数组\n * 使用 Listener[](默认为 Listener<unknown>[])以允许同一事件名有不同类型的监听器\n * 类型安全在订阅/发射时强制执行\n */\n private listeners: Map<string, Listener[]> = new Map();\n\n /**\n * 订阅事件\n *\n * @template T - 事件载荷的预期类型\n * @param event - 要订阅的事件名称\n * @param callback - 事件触发时调用的监听器函数\n * @returns 取消订阅的函数\n *\n * @example\n * ```typescript\n * const handler = (data: { count: number }) => console.log(data.count);\n * const unsubscribe = eventBus.on('update', handler);\n * // 稍后取消订阅\n * unsubscribe();\n * ```\n */\n on<T>(event: string, callback: Listener<T>): () => void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, []);\n }\n this.listeners.get(event)!.push(callback as Listener);\n\n // 返回 unsubscribe 函数\n return () => this.off(event, callback);\n }\n\n /**\n * 取消订阅事件\n *\n * @template T - 事件载荷的预期类型\n * @param event - 要取消订阅的事件名称\n * @param callback - 要移除的监听器函数\n *\n * @example\n * ```typescript\n * const handler = (data: number) => console.log(data);\n * eventBus.on('count', handler);\n * eventBus.off('count', handler); // 移除监听器\n * ```\n */\n off<T>(event: string, callback: Listener<T>) {\n const callbacks = this.listeners.get(event);\n if (callbacks) {\n this.listeners.set(\n event,\n callbacks.filter((cb) => cb !== (callback as Listener))\n );\n }\n }\n\n /**\n * 发射事件并携带可选的类型化载荷数据\n * 该事件的所有已注册监听器都将被调用并传入数据\n * 单个监听器中的错误会被捕获并记录,不会影响其他监听器\n *\n * @template T - 事件载荷的类型\n * @param event - 要发射的事件名称\n * @param data - 传递给监听器的可选载荷数据\n *\n * @example\n * ```typescript\n * eventBus.emit<{ userId: string }>('login', { userId: '123' });\n * eventBus.emit('logout'); // 无载荷\n * ```\n */\n emit<T>(event: string, data?: T) {\n const callbacks = this.listeners.get(event);\n if (callbacks) {\n callbacks.forEach((cb) => {\n try {\n cb(data);\n } catch (error) {\n console.error(`Error in event listener for \"${event}\":`, error);\n }\n });\n }\n }\n\n /**\n * 清空所有事件的所有监听器\n * 用于清理或重置事件系统\n *\n * @example\n * ```typescript\n * eventBus.clear(); // 所有监听器被移除\n * ```\n */\n clear() {\n this.listeners.clear();\n }\n}\n\n/**\n * 全局单例 EventBus 实例,用于游戏范围内的事件通信\n * 在整个应用中使用此实例以保持一致的事件处理\n *\n * @example\n * ```typescript\n * import { gameEvents, EngineEvents } from './events';\n *\n * gameEvents.on(EngineEvents.STAT_CHANGE, (data) => {\n * console.log(`属性 ${data.stat} 变化了 ${data.delta}`);\n * });\n * ```\n */\nexport const gameEvents = new EventBus();\n\n/**\n * 预定义的系统事件名称常量,用于常见的游戏引擎事件\n * 使用这些常量而不是字符串字面量,以保证类型安全和一致性\n *\n * 事件载荷类型:\n * - STAT_CHANGE: { stat: string, delta: number, current: number }\n * - ITEM_ADD: { item: string }\n * - ITEM_REMOVE: { item: string }\n * - FLAG_CHANGE: { flag: string, value: boolean }\n * - ACTION_EXECUTED: { actionId: string }\n * - TIME_PASS: { day: number, time: number }\n * - NOTIFICATION: { text: string, type: string, notificationType: string, timestamp: number }\n * - CUSTOM: { id: string } (对应 effects.triggerEvent)\n */\nexport const EngineEvents = {\n /** 当角色属性变化时触发 */\n STAT_CHANGE: \"engine:stat_change\",\n /** 当物品添加到背包时触发 */\n ITEM_ADD: \"engine:item_add\",\n /** 当物品从背包移除时触发 */\n ITEM_REMOVE: \"engine:item_remove\",\n /** 当游戏标志变化时触发 */\n FLAG_CHANGE: \"engine:flag_change\",\n /** 当动作执行时触发 */\n ACTION_EXECUTED: \"engine:action_exec\",\n /** 当游戏时间推进时触发 */\n TIME_PASS: \"engine:time_pass\",\n /** 当需要显示瞬时通知时触发(Toast/Modal,不持久化) */\n NOTIFICATION: \"engine:notification\",\n /** 用于自定义触发事件 */\n CUSTOM: \"engine:custom_trigger\",\n} as const;\n","// src/engine/state/history.ts\nimport type { GameState } from \"../core/types\";\nimport { DEFAULT_CONFIG } from \"../core/constants\";\n\n/**\n * 快照信息接口\n * \n * 包含快照的元数据和实际状态数据\n */\nexport interface SnapshotInfo<\n S extends string,\n I extends string,\n F extends string,\n X = Record<string, unknown>\n> {\n /** 快照的唯一标识符(自动生成的时间戳) */\n id: string;\n /** 快照名称(可选,用于命名快照) */\n name?: string;\n /** 快照创建时间 */\n timestamp: number;\n /** 快照描述(可选) */\n description?: string;\n /** 实际的游戏状态数据 */\n state: GameState<S, I, F, X>;\n}\n\n/**\n * 历史管理器 - 管理游戏状态的历史快照\n * \n * ⚠️ 增强功能:支持命名快照和多级撤销\n * \n * 提供撤销/重做功能,通过保存游戏状态的快照来实现时间旅行。\n * \n * 功能特性:\n * - 多级撤销:支持撤销多个步骤\n * - 命名快照:可以保存和恢复命名的快照\n * - 快照列表:查看所有保存的快照\n * - 自动管理:超过限制时自动清理旧快照\n * \n * @template S - 属性名称的字符串字面量类型\n * @template I - 物品名称的字符串字面量类型\n * @template F - 标志名称的字符串字面量类型\n * @template X - 扩展数据的类型\n * \n * @example\n * ```typescript\n * const history = new HistoryManager<'health' | 'mana', 'sword', 'hasKey'>(20);\n * \n * // 保存匿名快照\n * history.push(currentState);\n * \n * // 保存命名快照\n * history.pushNamed(currentState, 'before_boss_fight', '挑战Boss前');\n * \n * // 撤销到上一个状态\n * const previousState = history.pop();\n * \n * // 恢复到命名快照\n * const savedState = history.restoreNamed('before_boss_fight');\n * \n * // 查看所有快照\n * const snapshots = history.listSnapshots();\n * ```\n */\nexport class HistoryManager<\n S extends string,\n I extends string,\n F extends string,\n X = Record<string, unknown>\n> {\n /** 存储的状态快照数组(按时间顺序) */\n private snapshots: SnapshotInfo<S, I, F, X>[] = [];\n /** 命名快照映射表(name -> snapshot) */\n private namedSnapshots: Map<string, SnapshotInfo<S, I, F, X>> = new Map();\n /** 最大快照数量限制(不包括命名快照) */\n private maxSnapshots: number;\n\n /**\n * 创建历史管理器实例\n * @param maxSnapshots - 最大保存的快照数量,默认使用配置中的值\n */\n constructor(maxSnapshots = DEFAULT_CONFIG.MAX_HISTORY_SNAPSHOTS) {\n this.maxSnapshots = maxSnapshots;\n }\n\n /**\n * 保存当前状态快照(匿名快照)\n * \n * 通过深拷贝保存状态,防止后续修改影响历史记录。\n * 当快照数量超过最大限制时,自动移除最旧的快照。\n * \n * 匿名快照用于常规的撤销操作,会受到数量限制。\n * \n * @param state - 要保存的游戏状态\n * @param description - 快照描述(可选)\n * \n * @example\n * ```typescript\n * history.push(gameState);\n * history.push(gameState, '攻击哥布林前');\n * ```\n */\n push(state: GameState<S, I, F, X>, description?: string) {\n // 深拷贝状态,防止引用污染\n const stateCopy = JSON.parse(JSON.stringify(state)) as GameState<S, I, F, X>;\n \n const snapshot: SnapshotInfo<S, I, F, X> = {\n id: `snapshot_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n timestamp: Date.now(),\n description,\n state: stateCopy\n };\n \n this.snapshots.push(snapshot);\n\n // 限制历史记录长度(只清理匿名快照)\n if (this.snapshots.length > this.maxSnapshots) {\n this.snapshots.shift();\n }\n }\n\n /**\n * 保存命名快照\n * \n * ⚠️ 新功能:保存可以通过名称访问的快照\n * \n * 命名快照不受数量限制,不会被自动清理。\n * 适用于重要的游戏节点,如Boss战前、章节开始等。\n * \n * 如果已存在同名快照,会被覆盖。\n * \n * @param state - 要保存的游戏状态\n * @param name - 快照名称(唯一标识符)\n * @param description - 快照描述(可选)\n * \n * @example\n * ```typescript\n * // 保存Boss战前的状态\n * history.pushNamed(gameState, 'before_boss_fight', '挑战最终Boss前');\n * \n * // 保存章节开始的状态\n * history.pushNamed(gameState, 'chapter_2_start', '第二章开始');\n * ```\n */\n pushNamed(state: GameState<S, I, F, X>, name: string, description?: string) {\n // 深拷贝状态\n const stateCopy = JSON.parse(JSON.stringify(state)) as GameState<S, I, F, X>;\n \n const snapshot: SnapshotInfo<S, I, F, X> = {\n id: `named_${name}_${Date.now()}`,\n name,\n timestamp: Date.now(),\n description,\n state: stateCopy\n };\n \n this.namedSnapshots.set(name, snapshot);\n }\n\n /**\n * 回退到上一个状态(撤销操作)\n * \n * 移除并返回最近的一个匿名快照。\n * 如果没有可用的快照,返回 undefined。\n * \n * 注意:此操作不会影响命名快照。\n * \n * @returns 上一个状态快照,如果历史为空则返回 undefined\n * \n * @example\n * ```typescript\n * const previousState = history.pop();\n * if (previousState) {\n * // 恢复到上一个状态\n * restoreState(previousState);\n * }\n * ```\n */\n pop(): GameState<S, I, F, X> | undefined {\n const snapshot = this.snapshots.pop();\n return snapshot?.state;\n }\n\n /**\n * 恢复到命名快照\n * \n * ⚠️ 新功能:通过名称恢复到指定的快照\n * \n * 返回指定名称的快照状态,但不从历史记录中删除它。\n * 这允许多次恢复到同一个命名快照。\n * \n * @param name - 快照名称\n * @returns 指定名称的状态快照,如果不存在则返回 undefined\n * \n * @example\n * ```typescript\n * // 恢复到Boss战前\n * const savedState = history.restoreNamed('before_boss_fight');\n * if (savedState) {\n * restoreState(savedState);\n * } else {\n * console.log('快照不存在');\n * }\n * ```\n */\n restoreNamed(name: string): GameState<S, I, F, X> | undefined {\n const snapshot = this.namedSnapshots.get(name);\n return snapshot?.state;\n }\n\n /**\n * 删除命名快照\n * \n * 从历史记录中删除指定名称的快照。\n * \n * @param name - 要删除的快照名称\n * @returns 是否成功删除\n * \n * @example\n * ```typescript\n * history.deleteNamed('before_boss_fight');\n * ```\n */\n deleteNamed(name: string): boolean {\n return this.namedSnapshots.delete(name);\n }\n\n /**\n * 检查命名快照是否存在\n * \n * @param name - 快照名称\n * @returns 是否存在指定名称的快照\n * \n * @example\n * ```typescript\n * if (history.hasNamed('before_boss_fight')) {\n * console.log('可以恢复到Boss战前');\n * }\n * ```\n */\n hasNamed(name: string): boolean {\n return this.namedSnapshots.has(name);\n }\n\n /**\n * 列出所有快照\n * \n * ⚠️ 新功能:获取所有快照的信息列表\n * \n * 返回所有快照(包括匿名和命名快照)的元数据。\n * 不包含实际的状态数据,只包含快照信息。\n * \n * @returns 快照信息数组,按时间倒序排列(最新的在前)\n * \n * @example\n * ```typescript\n * const snapshots = history.listSnapshots();\n * snapshots.forEach(snap => {\n * console.log(`${snap.name || '匿名'}: ${snap.description || '无描述'}`);\n * console.log(` 时间: ${new Date(snap.timestamp).toLocaleString()}`);\n * });\n * ```\n */\n listSnapshots(): Array<Omit<SnapshotInfo<S, I, F, X>, 'state'>> {\n const allSnapshots: Array<Omit<SnapshotInfo<S, I, F, X>, 'state'>> = [];\n \n // 添加匿名快照\n this.snapshots.forEach(snap => {\n allSnapshots.push({\n id: snap.id,\n name: snap.name,\n timestamp: snap.timestamp,\n description: snap.description\n });\n });\n \n // 添加命名快照\n this.namedSnapshots.forEach(snap => {\n allSnapshots.push({\n id: snap.id,\n name: snap.name,\n timestamp: snap.timestamp,\n description: snap.description\n });\n });\n \n // 按时间倒序排列\n return allSnapshots.sort((a, b) => b.timestamp - a.timestamp);\n }\n\n /**\n * 列出所有命名快照\n * \n * 只返回命名快照的信息列表。\n * \n * @returns 命名快照信息数组\n * \n * @example\n * ```typescript\n * const namedSnaps = history.listNamedSnapshots();\n * console.log(`共有 ${namedSnaps.length} 个命名快照`);\n * ```\n */\n listNamedSnapshots(): Array<Omit<SnapshotInfo<S, I, F, X>, 'state'>> {\n const result: Array<Omit<SnapshotInfo<S, I, F, X>, 'state'>> = [];\n \n this.namedSnapshots.forEach(snap => {\n result.push({\n id: snap.id,\n name: snap.name,\n timestamp: snap.timestamp,\n description: snap.description\n });\n });\n \n return result.sort((a, b) => b.timestamp - a.timestamp);\n }\n\n /**\n * 查看最近的快照但不移除\n * \n * 返回最新的匿名快照但不从历史记录中删除它。\n * 用于预览上一个状态而不实际执行撤销操作。\n * \n * @returns 最近的状态快照,如果历史为空则返回 undefined\n * \n * @example\n * ```typescript\n * const lastState = history.peek();\n * if (lastState) {\n * console.log('上一个状态:', lastState);\n * }\n * ```\n */\n peek(): GameState<S, I, F, X> | undefined {\n const snapshot = this.snapshots[this.snapshots.length - 1];\n return snapshot?.state;\n }\n\n /**\n * 清空所有历史记录\n * \n * 移除所有保存的快照(包括匿名和命名快照),释放内存。\n * 通常在开始新游戏或重置时使用。\n * \n * @param includeNamed - 是否同时清空命名快照(默认为 false)\n * \n * @example\n * ```typescript\n * // 只清空匿名快照\n * history.clear();\n * \n * // 清空所有快照(包括命名快照)\n * history.clear(true);\n * ```\n */\n clear(includeNamed = false) {\n this.snapshots = [];\n \n if (includeNamed) {\n this.namedSnapshots.clear();\n }\n }\n\n /**\n * 获取当前匿名快照数量\n * \n * @returns 当前保存的匿名快照数量\n * \n * @example\n * ```typescript\n * console.log(`历史记录数量: ${history.size}`);\n * if (history.size > 0) {\n * // 可以执行撤销操作\n * }\n * ```\n */\n get size() {\n return this.snapshots.length;\n }\n\n /**\n * 获取命名快照数量\n * \n * @returns 当前保存的命名快照数量\n * \n * @example\n * ```typescript\n * console.log(`命名快照数量: ${history.namedSize}`);\n * ```\n */\n get namedSize() {\n return this.namedSnapshots.size;\n }\n\n /**\n * 获取总快照数量\n * \n * @returns 所有快照的总数量(匿名 + 命名)\n * \n * @example\n * ```typescript\n * console.log(`总快照数量: ${history.totalSize}`);\n * ```\n */\n get totalSize() {\n return this.snapshots.length + this.namedSnapshots.size;\n }\n}\n","// src/engine/state/store.ts\n// ============================================================================\n// 游戏状态管理 - 使用Zustand实现全局状态管理和持久化\n// ============================================================================\n//\n// 这个文件提供了游戏引擎的状态管理解决方案,基于Zustand库实现。\n// 主要功能:\n// - 全局状态管理:统一管理游戏的所有状态数据\n// - 状态持久化:自动保存到localStorage,支持游戏存档\n// - 类型安全:完全的TypeScript类型支持\n// - 原子操作:提供细粒度的状态更新方法\n//\n// ============================================================================\n\nimport { create } from 'zustand';\nimport { persist, createJSONStorage } from 'zustand/middleware';\nimport type { GameState, LogEntry, NotificationPayload } from '../core/types';\nimport { gameEvents, EngineEvents } from '../systems/events';\nimport { HistoryManager } from './history';\nimport { SystemMessages } from '../core/messages';\nimport { DEFAULT_CONFIG } from '../core/constants';\nimport { generateId } from '../core/utils';\n\n/**\n * 游戏Store操作方法接口 - 定义所有可用的状态操作\n * \n * 这个接口定义了修改游戏状态的所有方法。所有方法都是原子操作,\n * 确保状态更新的一致性和可预测性。\n * \n * @template S - 数值属性键的联合类型\n * @template I - 物品ID的联合类型\n * @template F - 标记键的联合类型\n * \n * @example\n * ```typescript\n * const useStore = createGameEngineStore(initialState);\n * \n * // 在组件中使用\n * function GameComponent() {\n * const updateStat = useStore(state => state.updateStat);\n * const addItem = useStore(state => state.addItem);\n * \n * const handleAction = () => {\n * updateStat('hp', -10); // 减少10点生命值\n * addItem('potion'); // 获得药水\n * };\n * }\n * ```\n */\nexport interface GameStoreActions<\n S extends string,\n I extends string,\n F extends string,\n X = Record<string, unknown>\n> {\n // ========== 数值属性操作 ==========\n \n /**\n * 更新单个数值属性\n * \n * 对指定属性进行增量更新(正数增加,负数减少)。\n * 这是最常用的属性修改方法。\n * \n * @param stat - 要更新的属性键\n * @param delta - 变化量(正数增加,负数减少)\n * \n * @example\n * ```typescript\n * updateStat('hp', 20); // 恢复20点生命值\n * updateStat('gold', -50); // 花费50金币\n * ```\n */\n updateStat: (stat: S, delta: number) => void;\n\n /**\n * 批量更新多个数值属性\n * \n * 一次性更新多个属性,所有更新在同一个状态变更中完成。\n * 适用于需要同时修改多个属性的场景。\n * \n * @param stats - 属性变化的部分记录\n * \n * @example\n * ```typescript\n * setStats({ hp: 10, mp: -5, gold: 100 });\n * // 同时增加10点生命值,减少5点魔法值,增加100金币\n * ```\n */\n setStats: (stats: Partial<Record<S, number>>) => void;\n\n setExtra: (updater: Partial<X> | ((prev: X) => Partial<X>)) => void;\n\n // ========== 物品操作 ==========\n\n /**\n * 添加物品到库存\n * \n * 将指定物品添加到玩家的库存中。\n * 同一物品可以多次添加(如多个药水)。\n * \n * @param item - 要添加的物品ID\n * \n * @example\n * ```typescript\n * addItem('health_potion');\n * addItem('health_potion'); // 可以添加多个相同物品\n * ```\n */\n addItem: (item: I) => void;\n\n /**\n * 从库存移除物品\n * \n * 从玩家库存中移除指定物品的一个实例。\n * 如果有多个相同物品,只移除第一个匹配的。\n * \n * @param item - 要移除的物品ID\n * \n * @example\n * ```typescript\n * removeItem('health_potion'); // 移除一个生命药水\n * ```\n */\n removeItem: (item: I) => void;\n\n // ========== 标记操作 ==========\n\n /**\n * 设置布尔标记\n * \n * 设置或清除游戏标记,用于追踪任务进度、解锁状态等。\n * 标记是游戏逻辑的重要组成部分。\n * \n * @param flag - 标记键\n * @param value - 标记值(true或false)\n * \n * @example\n * ```typescript\n * setFlag('quest_completed', true); // 标记任务完成\n * setFlag('door_locked', false); // 解锁门\n * ```\n */\n setFlag: (flag: F, value: boolean) => void;\n\n // ========== 系统操作 ==========\n\n /**\n * 添加日志条目\n * \n * ⚠️ 重要:日志是持久化的历史记录\n * \n * 向游戏日志中添加新的消息,用于记录游戏事件。\n * 日志会:\n * - 被保存到 localStorage\n * - 在页面刷新后重新加载\n * - 永久显示在日志面板中\n * - 自动限制在最近50条\n * \n * @param text - 日志文本内容\n * @param type - 日志类型(默认为'info')\n * \n * @example\n * ```typescript\n * addLog('你进入了森林', 'info');\n * addLog('击败了哥布林', 'result');\n * addLog('获得了传说武器', 'success');\n * ```\n */\n addLog: (text: string, type?: LogEntry['type']) => void;\n\n /**\n * 显示飘字通知\n * \n * ⚠️ 重要:飘字是瞬时通知,不会被持久化\n * \n * 显示一个轻量级的飘字提示,会自动消失。\n * 飘字通知:\n * - 不会被保存到 localStorage\n * - 不会在页面刷新后重新出现\n * - 仅在当前会话中显示\n * - 适用于轻量级反馈\n * \n * @param text - 通知文本\n * @param type - 通知类型(默认为'info')\n * \n * @example\n * ```typescript\n * showToast('获得 10 金币', 'success');\n * showToast('体力不足', 'warn');\n * ```\n */\n showToast: (text: string, type?: LogEntry['type']) => void;\n\n /**\n * 显示弹窗通知\n * \n * ⚠️ 重要:弹窗是瞬时通知,不会被持久化\n * \n * 显示一个模态弹窗,需要用户确认才能关闭。\n * 弹窗通知:\n * - 不会被保存到 localStorage\n * - 不会在页面刷新后重新出现\n * - 仅在当前会话中显示\n * - 适用于重要信息和阻塞式交互\n * \n * @param text - 通知文本\n * @param type - 通知类型(默认为'info')\n * \n * @example\n * ```typescript\n * showModal('任务完成!获得传说装备', 'success');\n * showModal('警告:此操作不可撤销', 'warn');\n * ```\n */\n showModal: (text: string, type?: LogEntry['type']) => void;\n\n /**\n * 推进游戏时间\n * \n * 增加游戏内的天数,用于时间相关的游戏机制。\n * \n * @param amount - 要增加的天数(默认为1)\n * \n * @example\n * ```typescript\n * advanceTime(); // 推进1天\n * advanceTime(7); // 推进7天\n * ```\n */\n advanceTime: (amount?: number) => void;\n\n /**\n * 传送到指定地点\n * \n * 将玩家传送到指定的地点ID。\n * 这是改变玩家位置的主要方法。\n * \n * @param locationId - 目标地点的ID\n * \n * @example\n * ```typescript\n * teleport('town_square'); // 传送到城镇广场\n * teleport('dungeon_1'); // 传送到地牢\n * ```\n */\n teleport: (locationId: string) => void;\n\n // ========== 存档操作 ==========\n\n /**\n * 重置游戏状态\n * \n * 将游戏状态重置为初始状态,清空所有日志。\n * 用于开始新游戏或重置当前进度。\n * \n * @example\n * ```typescript\n * reset(); // 开始新游戏\n * ```\n */\n reset: () => void;\n\n // ========== 历史记录操作 ==========\n\n /**\n * 保存当前状态快照(匿名快照)\n * \n * 将当前游戏状态保存到历史记录中,用于后续的撤销操作。\n * 快照会自动排除日志数据以节省内存。\n * \n * 匿名快照用于常规的撤销操作,会受到数量限制。\n * \n * @param description - 快照描述(可选)\n * \n * @example\n * ```typescript\n * saveSnapshot(); // 在重要操作前保存快照\n * saveSnapshot('攻击Boss前'); // 带描述的快照\n * ```\n */\n saveSnapshot: (description?: string) => void;\n\n /**\n * 保存命名快照\n * \n * ⚠️ 新功能:保存可以通过名称访问的快照\n * \n * 命名快照不受数量限制,不会被自动清理。\n * 适用于重要的游戏节点,如Boss战前、章节开始等。\n * \n * @param name - 快照名称(唯一标识符)\n * @param description - 快照描述(可选)\n * \n * @example\n * ```typescript\n * saveNamedSnapshot('before_boss_fight', '挑战最终Boss前');\n * saveNamedSnapshot('chapter_2_start', '第二章开始');\n * ```\n */\n saveNamedSnapshot: (name: string, description?: string) => void;\n\n /**\n * 撤销到上一个状态\n * \n * 恢复到上一个保存的匿名快照状态。\n * 如果没有可用的历史记录,操作失败并返回false。\n * \n * @returns 是否成功撤销\n * \n * @example\n * ```typescript\n * if (undo()) {\n * console.log('撤销成功');\n * } else {\n * console.log('没有可撤销的历史记录');\n * }\n * ```\n */\n undo: () => boolean;\n\n /**\n * 恢复到命名快照\n * \n * ⚠️ 新功能:通过名称恢复到指定的快照\n * \n * 返回指定名称的快照状态,但不从历史记录中删除它。\n * 这允许多次恢复到同一个命名快照。\n * \n * @param name - 快照名称\n * @returns 是否成功恢复\n * \n * @example\n * ```typescript\n * if (restoreSnapshot('before_boss_fight')) {\n * console.log('已恢复到Boss战前');\n * } else {\n * console.log('快照不存在');\n * }\n * ```\n */\n restoreSnapshot: (name: string) => boolean;\n\n /**\n * 删除命名快照\n * \n * 从历史记录中删除指定名称的快照。\n * \n * @param name - 要删除的快照名称\n * @returns 是否成功删除\n * \n * @example\n * ```typescript\n * deleteSnapshot('before_boss_fight');\n * ```\n */\n deleteSnapshot: (name: string) => boolean;\n\n /**\n * 列出所有快照\n * \n * ⚠️ 新功能:获取所有快照的信息列表\n * \n * 返回所有快照(包括匿名和命名快照)的元数据。\n * \n * @returns 快照信息数组\n * \n * @example\n * ```typescript\n * const snapshots = listSnapshots();\n * snapshots.forEach(snap => {\n * console.log(`${snap.name || '匿名'}: ${snap.description || '无描述'}`);\n * });\n * ```\n */\n listSnapshots: () => Array<{\n id: string;\n name?: string;\n timestamp: number;\n description?: string;\n }>;\n\n /**\n * 检查命名快照是否存在\n * \n * @param name - 快照名称\n * @returns 是否存在指定名称的快照\n * \n * @example\n * ```typescript\n * if (hasSnapshot('before_boss_fight')) {\n * console.log('可以恢复到Boss战前');\n * }\n * ```\n */\n hasSnapshot: (name: string) => boolean;\n}\n\n/**\n * 游戏Store类型 - 组合数据和操作方法\n * \n * 这是完整的Store类型,包含游戏状态数据和所有操作方法。\n * 使用交叉类型将GameState和GameStoreActions合并。\n * \n * @template S - 数值属性键的联合类型\n * @template I - 物品ID的联合类型\n * @template F - 标记键的联合类型\n * \n * @example\n * ```typescript\n * const useGameStore: GameStore<'hp' | 'mp', 'sword', 'quest_done'>;\n * ```\n */\nexport type GameStore<\n S extends string,\n I extends string,\n F extends string,\n X = Record<string, unknown>\n> = GameState<S, I, F, X> & GameStoreActions<S, I, F, X>;\n\n/**\n * 创建游戏引擎Store的工厂函数\n * \n * 这是创建游戏状态管理Store的核心函数。它使用Zustand创建一个\n * 带有持久化功能的状态管理器,自动将游戏状态保存到localStorage。\n * \n * 工厂模式的优势:\n * - 可以创建多个独立的游戏实例\n * - 每个实例有自己的初始状态和存档名称\n * - 完全的类型安全和泛型支持\n * \n * @template S - 数值属性键的联合类型\n * @template I - 物品ID的联合类型\n * @template F - 标记键的联合类型\n * \n * @param initialState - 游戏的初始状态\n * @param persistName - localStorage中的存档键名(默认:'generic-rpg-save')\n * \n * @returns Zustand store hook,可在React组件中使用\n * \n * @example\n * ```typescript\n * // 定义游戏类型\n * type Stats = 'hp' | 'mp' | 'gold';\n * type Items = 'sword' | 'potion';\n * type Flags = 'quest_completed';\n * \n * // 创建初始状态\n * const initialState: GameState<Stats, Items, Flags> = {\n * stats: { hp: 100, mp: 50, gold: 0 },\n * inventory: [],\n * flags: { quest_completed: false },\n * world: { currentLocationId: 'start', day: 1, time: 0 },\n * logs: []\n * };\n * \n * // 创建store\n * export const useGameStore = createGameEngineStore(\n * initialState,\n * 'my-rpg-save'\n * );\n * \n * // 在组件中使用\n * function GameUI() {\n * const hp = useGameStore(state => state.stats.hp);\n * const updateStat = useGameStore(state => state.updateStat);\n * \n * return <button onClick={() => updateStat('hp', -10)}>受伤</button>;\n * }\n * ```\n */\nexport const createGameEngineStore = <\n S extends string,\n I extends string,\n F extends string,\n X = Record<string, unknown>\n>(\n initialState: GameState<S, I, F, X>,\n persistName: string = 'generic-rpg-save'\n) => {\n // 创建历史管理器实例(闭包内,每个store独立)\n const history = new HistoryManager<S, I, F, X>(\n DEFAULT_CONFIG.MAX_HISTORY_SNAPSHOTS\n );\n\n return create<GameStore<S, I, F, X>>()(\n persist(\n (set, get) => ({\n // 展开初始状态,包含所有游戏数据\n ...initialState,\n\n // ========== 数值属性操作实现 ==========\n\n /**\n * 实现:更新单个数值属性\n * 使用增量更新,保持其他属性不变\n * 发射 STAT_CHANGE 事件通知监听器\n */\n updateStat: (stat, delta) =>\n set((state) => {\n const currentVal = state.stats[stat] || 0;\n const newVal = currentVal + delta;\n\n // 发射事件\n gameEvents.emit(EngineEvents.STAT_CHANGE, {\n stat,\n delta,\n current: newVal,\n });\n\n return {\n stats: {\n ...state.stats,\n [stat]: newVal,\n },\n };\n }),\n\n /**\n * 实现:批量更新多个数值属性\n * 遍历所有变化并应用到新的stats对象\n */\n setStats: (changes) =>\n set((state) => {\n const newStats = { ...state.stats };\n Object.entries(changes).forEach(([k, v]) => {\n newStats[k as S] = (newStats[k as S] || 0) + (v as number);\n });\n return { stats: newStats };\n }),\n\n // ========== 扩展数据操作实现 ==========\n\n /**\n * 实现:更新扩展数据\n * \n * 支持两种更新方式:\n * 1. 直接传入部分更新对象\n * 2. 传入更新函数,接收当前值返回部分更新\n * \n * @example\n * ```typescript\n * // 方式1:直接更新\n * setExtra({ reputation: 100 });\n * \n * // 方式2:基于当前值更新\n * setExtra((prev) => ({ reputation: prev.reputation + 10 }));\n * ```\n */\n setExtra: (updater) =>\n set((state) => {\n const update =\n typeof updater === 'function' ? updater(state.extra) : updater;\n return {\n extra: { ...state.extra, ...update } as X,\n };\n }),\n\n // ========== 物品操作实现 ==========\n\n /**\n * 实现:添加物品到库存\n * 创建新数组,保持不可变性\n * 发射 ITEM_ADD 事件通知监听器\n */\n addItem: (item) =>\n set((state) => {\n // 发射事件\n gameEvents.emit(EngineEvents.ITEM_ADD, { item });\n\n return {\n inventory: [...state.inventory, item],\n };\n }),\n\n /**\n * 实现:从库存移除物品\n * 使用filter移除第一个匹配的物品\n * 发射 ITEM_REMOVE 事件通知监听器\n */\n removeItem: (item) =>\n set((state) => {\n // 发射事件\n gameEvents.emit(EngineEvents.ITEM_REMOVE, { item });\n\n return {\n inventory: state.inventory.filter((i) => i !== item),\n };\n }),\n\n // ========== 标记操作实现 ==========\n\n /**\n * 实现:设置布尔标记\n * 创建新的flags对象,更新指定标记\n * 发射 FLAG_CHANGE 事件通知监听器\n */\n setFlag: (flag, value) =>\n set((state) => {\n // 发射事件\n gameEvents.emit(EngineEvents.FLAG_CHANGE, { flag, value });\n\n return {\n flags: { ...state.flags, [flag]: value },\n };\n }),\n\n // ========== 系统操作实现 ==========\n\n /**\n * 实现:添加日志条目\n * \n * 创建新日志并添加到日志数组开头。\n * 使用 MAX_LOG_ENTRIES 限制日志数量,防止内存泄漏。\n * 日志ID使用时间戳+随机数确保唯一性。\n * \n * ⚠️ 注意:日志会被持久化到 localStorage\n */\n addLog: (text, type = 'info') =>\n set((state) => {\n const newLog: LogEntry = {\n id: generateId(),\n text,\n type,\n timestamp: state.world.day,\n };\n\n return { \n logs: [newLog, ...state.logs].slice(0, DEFAULT_CONFIG.MAX_LOG_ENTRIES) \n };\n }),\n\n /**\n * 实现:显示飘字通知\n * \n * 发射 NOTIFICATION 事件,UI 层监听后显示飘字效果。\n * \n * ⚠️ 注意:通知不会被持久化,仅在当前会话中显示\n */\n showToast: (text, type = 'info') => {\n const notification: NotificationPayload = {\n text,\n type,\n notificationType: 'toast',\n timestamp: Date.now(),\n };\n gameEvents.emit(EngineEvents.NOTIFICATION, notification);\n },\n\n /**\n * 实现:显示弹窗通知\n * \n * 发射 NOTIFICATION 事件,UI 层监听后显示模态弹窗。\n * \n * ⚠️ 注意:通知不会被持久化,仅在当前会话中显示\n */\n showModal: (text, type = 'info') => {\n const notification: NotificationPayload = {\n text,\n type,\n notificationType: 'modal',\n timestamp: Date.now(),\n };\n gameEvents.emit(EngineEvents.NOTIFICATION, notification);\n },\n\n /**\n * 实现:推进游戏时间\n * 增加world.day的值\n */\n advanceTime: (amount = 1) =>\n set((state) => ({\n world: { ...state.world, day: state.world.day + amount },\n })),\n\n /**\n * 实现:传送到指定地点\n * 更新world.currentLocationId\n */\n teleport: (locationId) =>\n set((state) => ({\n world: { ...state.world, currentLocationId: locationId },\n })),\n\n // ========== 存档操作实现 ==========\n\n /**\n * 实现:重置游戏状态\n * 恢复到初始状态,清空日志\n */\n reset: () => set({ ...initialState, logs: [] }),\n\n // ========== 历史记录操作实现 ==========\n\n /**\n * 实现:保存当前状态快照(匿名快照)\n * \n * 保存除日志外的所有状态数据到历史管理器。\n * 日志通常不需要回退,因此被排除以节省内存。\n */\n saveSnapshot: (description?: string) => {\n const currentState = get();\n // 保存完整状态(HistoryManager 会通过 JSON 序列化自动过滤掉方法)\n history.push(currentState, description);\n },\n\n /**\n * 实现:保存命名快照\n * \n * 保存可以通过名称访问的快照。\n * 命名快照不受数量限制,适用于重要的游戏节点。\n */\n saveNamedSnapshot: (name: string, description?: string) => {\n const currentState = get();\n history.pushNamed(currentState, name, description);\n },\n\n /**\n * 实现:撤销到上一个状态\n * \n * 从历史管理器中恢复上一个匿名快照。\n * 恢复时保留当前的日志,并添加系统提示。\n * \n * @returns 是否成功撤销\n */\n undo: () => {\n const prev = history.pop();\n if (prev) {\n set({\n stats: prev.stats,\n inventory: prev.inventory,\n flags: prev.flags,\n world: prev.world,\n extra: prev.extra,\n // logs 保留当前的,不回退日志\n });\n get().addLog(SystemMessages.UNDO_SUCCESS, 'info');\n return true;\n }\n return false;\n },\n\n /**\n * 实现:恢复到命名快照\n * \n * 通过名称恢复到指定的快照。\n * 快照不会被删除,可以多次恢复。\n * \n * @returns 是否成功恢复\n */\n restoreSnapshot: (name: string) => {\n const saved = history.restoreNamed(name);\n if (saved) {\n set({\n stats: saved.stats,\n inventory: saved.inventory,\n flags: saved.flags,\n world: saved.world,\n extra: saved.extra,\n // logs 保留当前的,不回退日志\n });\n get().addLog(`已恢复到快照:${name}`, 'info');\n return true;\n }\n return false;\n },\n\n /**\n * 实现:删除命名快照\n * \n * 从历史记录中删除指定名称的快照。\n * \n * @returns 是否成功删除\n */\n deleteSnapshot: (name: string) => {\n return history.deleteNamed(name);\n },\n\n /**\n * 实现:列出所有快照\n * \n * 返回所有快照的元数据列表。\n */\n listSnapshots: () => {\n return history.listSnapshots();\n },\n\n /**\n * 实现:检查命名快照是否存在\n * \n * @returns 是否存在指定名称的快照\n */\n hasSnapshot: (name: string) => {\n return history.hasNamed(name);\n },\n }),\n {\n // 持久化配置\n name: persistName, // localStorage中的键名\n storage: createJSONStorage(() => localStorage), // 使用localStorage存储\n\n /**\n * 部分持久化 - 只保存数据字段,排除方法\n * \n * 这很重要,因为方法不能被序列化到JSON。\n * 我们只持久化游戏状态数据,方法会在store重新创建时自动添加。\n */\n partialize: (state) =>\n ({\n stats: state.stats,\n inventory: state.inventory,\n flags: state.flags,\n world: state.world,\n logs: state.logs,\n extra: state.extra,\n }) as GameState<S, I, F, X>,\n }\n )\n );\n};","// src/engine/systems/query.ts\n// ============================================================================\n// 查询系统 - 游戏状态查询和条件检查\n// ============================================================================\n//\n// 这个文件提供了游戏状态的查询和验证功能。\n// 主要用于:\n// - 检查动作执行的前置条件(需求检查)\n// - 验证玩家是否有足够资源支付成本\n// - 提供统一的条件判断逻辑\n//\n// 设计模式:\n// - 使用静态方法类,无需实例化\n// - 纯函数设计,不修改状态\n// - 支持复杂的条件组合(AND逻辑)\n//\n// ============================================================================\n\nimport type { GameState, RequirementDef, RequirementCheckResult } from \"../core/types\";\n\n/**\n * 查询系统类 - 提供游戏状态查询和条件检查功能\n * \n * 这是一个工具类,所有方法都是静态的,不需要实例化。\n * 主要用于在执行游戏动作前验证各种条件。\n * \n * 核心功能:\n * - checkRequirements: 检查复杂的需求条件\n * - canAfford: 检查是否有足够资源支付成本\n * \n * @example\n * ```typescript\n * // 检查是否满足开门的需求\n * const canOpenDoor = QuerySystem.checkRequirements(gameState, {\n * hasItems: ['key'],\n * stats: { strength: { min: 5 } }\n * });\n * \n * // 检查是否能支付购买成本\n * const canBuy = QuerySystem.canAfford(gameState, { gold: 100 });\n * ```\n */\nexport class QuerySystem {\n /**\n * 检查是否满足所有需求条件(带失败原因)\n * \n * ⚠️ 增强版本:返回详细的检查结果,包括失败原因\n * \n * 这是核心的条件检查方法,用于验证玩家是否满足执行某个动作的所有前置条件。\n * 内置字段使用 AND 逻辑组合,复杂逻辑使用 custom 函数实现。\n * \n * @template S - 数值属性键的联合类型\n * @template I - 物品ID的联合类型\n * @template F - 标记键的联合类型\n * \n * @param state - 当前游戏状态\n * @param reqs - 需求定义(可选,未定义时返回通过)\n * \n * @returns RequirementCheckResult 包含是否通过和失败原因\n * \n * @example\n * ```typescript\n * // 检查需求并获取失败原因\n * const result = QuerySystem.checkRequirementsWithReason(state, {\n * hasItems: ['key'],\n * stats: { strength: { min: 5 } }\n * });\n * \n * if (!result.passed) {\n * console.log(result.reason); // 显示失败原因\n * }\n * ```\n */\n static checkRequirementsWithReason<\n S extends string,\n I extends string,\n F extends string,\n X = Record<string, unknown>\n >(\n state: GameState<S, I, F, X>,\n reqs?: RequirementDef<S, I, F, X>\n ): RequirementCheckResult {\n // 如果没有定义需求,默认通过\n if (!reqs) return { passed: true };\n\n // ========== 1. 标记检查 ==========\n\n /**\n * 检查必须为true的标记\n * 使用every确保所有指定的标记都为true(AND逻辑)\n */\n if (reqs.hasFlags && reqs.hasFlags.length > 0) {\n const missingFlags = reqs.hasFlags.filter((f) => !state.flags[f]);\n if (missingFlags.length > 0) {\n return {\n passed: false,\n reason: `需要满足条件:${missingFlags.join('、')}`\n };\n }\n }\n\n /**\n * 检查必须为false的标记\n * 使用some检查是否有任何标记为true(OR逻辑)\n */\n if (reqs.noFlags && reqs.noFlags.length > 0) {\n const conflictFlags = reqs.noFlags.filter((f) => state.flags[f]);\n if (conflictFlags.length > 0) {\n return {\n passed: false,\n reason: `不能满足条件:${conflictFlags.join('、')}`\n };\n }\n }\n\n // ========== 2. 物品检查 ==========\n\n /**\n * 检查必须拥有的物品\n * 使用every确保库存中包含所有指定的物品(AND逻辑)\n */\n if (reqs.hasItems && reqs.hasItems.length > 0) {\n const missingItems = reqs.hasItems.filter((i) => !state.inventory.includes(i));\n if (missingItems.length > 0) {\n return {\n passed: false,\n reason: `缺少必需物品:${missingItems.join('、')}`\n };\n }\n }\n\n /**\n * 检查不能拥有的物品\n * 使用some检查库存中是否包含任何禁止的物品(OR逻辑)\n */\n if (reqs.noItems && reqs.noItems.length > 0) {\n const conflictItems = reqs.noItems.filter((i) => state.inventory.includes(i));\n if (conflictItems.length > 0) {\n return {\n passed: false,\n reason: `不能携带物品:${conflictItems.join('、')}`\n };\n }\n }\n\n // ========== 3. 数值属性检查 ==========\n\n /**\n * 检查数值属性是否满足条件\n * 支持两种模式:\n * - 数字模式:表示最小值要求\n * - 对象模式:支持min和max范围检查\n */\n if (reqs.stats) {\n for (const [key, condition] of Object.entries(reqs.stats)) {\n // 获取当前属性值,如果不存在则默认为0\n const currentVal = state.stats[key as S] || 0;\n const cond = condition as number | { min?: number; max?: number };\n\n if (typeof cond === \"number\") {\n /**\n * 简写模式:数字表示最小值\n * 例如:{ hp: 10 } 表示hp至少为10\n */\n if (currentVal < cond) {\n return {\n passed: false,\n reason: `${key} 不足(需要 ${cond},当前 ${currentVal})`\n };\n }\n } else {\n /**\n * 对象模式:支持区间检查\n * 例如:{ hp: { min: 10, max: 50 } } 表示hp在10-50之间\n */\n if (cond.min !== undefined && currentVal < cond.min) {\n return {\n passed: false,\n reason: `${key} 过低(需要至少 ${cond.min},当前 ${currentVal})`\n };\n }\n if (cond.max !== undefined && currentVal > cond.max) {\n return {\n passed: false,\n reason: `${key} 过高(需要最多 ${cond.max},当前 ${currentVal})`\n };\n }\n }\n }\n }\n\n // ========== 4. 自定义函数检查 ==========\n\n /**\n * 执行自定义验证函数\n * 支持返回 boolean 或 RequirementCheckResult\n */\n if (reqs.custom) {\n const customResult = reqs.custom(state);\n \n // 如果返回的是对象(RequirementCheckResult)\n if (typeof customResult === 'object') {\n if (!customResult.passed) {\n return customResult;\n }\n } \n // 如果返回的是 boolean\n else if (!customResult) {\n return {\n passed: false,\n reason: '不满足自定义条件'\n };\n }\n }\n\n // 所有检查都通过\n return { passed: true };\n }\n\n /**\n * 检查是否满足所有需求条件(简化版本)\n * \n * 这是向后兼容的简化版本,只返回 boolean。\n * 如果需要失败原因,请使用 checkRequirementsWithReason。\n * \n * @template S - 数值属性键的联合类型\n * @template I - 物品ID的联合类型\n * @template F - 标记键的联合类型\n * \n * @param state - 当前游戏状态\n * @param reqs - 需求定义(可选,未定义时返回true)\n * \n * @returns true表示满足所有条件,false表示至少有一个条件不满足\n * \n * @example\n * ```typescript\n * // 简单需求\n * const simple = QuerySystem.checkRequirements(state, {\n * hasItems: ['key'],\n * stats: { strength: { min: 5 } }\n * });\n * \n * // 复杂逻辑使用 custom\n * const complex = QuerySystem.checkRequirements(state, {\n * custom: (state) => {\n * // (有钥匙 AND 力量>=5) OR 有万能钥匙\n * const hasKeyAndStrength = \n * state.inventory.includes('key') && state.stats.strength >= 5;\n * const hasMasterKey = state.inventory.includes('master_key');\n * return hasKeyAndStrength || hasMasterKey;\n * }\n * });\n * ```\n */\n static checkRequirements<\n S extends string,\n I extends string,\n F extends string,\n X = Record<string, unknown>\n >(\n state: GameState<S, I, F, X>,\n reqs?: RequirementDef<S, I, F, X>\n ): boolean {\n return this.checkRequirementsWithReason(state, reqs).passed;\n }\n\n /**\n * 检查是否有足够资源支付成本\n * \n * 验证玩家的数值属性是否足够支付指定的成本。\n * 这是一个简化的检查,只验证数值是否足够,不实际扣除。\n * \n * 与checkRequirements的区别:\n * - canAfford只检查数值属性\n * - checkRequirements检查完整的需求(标记、物品、数值、自定义)\n * - canAfford用于成本检查,checkRequirements用于前置条件检查\n * \n * @template S - 数值属性键的联合类型\n * @template I - 物品ID的联合类型\n * @template F - 标记键的联合类型\n * \n * @param state - 当前游戏状态\n * @param costs - 成本定义(可选,未定义时返回true)\n * \n * @returns true表示有足够资源,false表示资源不足\n * \n * @example\n * ```typescript\n * // 检查是否有足够金币购买物品\n * const canBuy = QuerySystem.canAfford(state, { gold: 100 });\n * \n * // 检查是否有足够资源施放技能\n * const canCast = QuerySystem.canAfford(state, {\n * mp: 30,\n * stamina: 10\n * });\n * \n * // 在动作执行前使用\n * if (QuerySystem.canAfford(state, action.costs)) {\n * // 执行动作并扣除成本\n * executeAction(action);\n * } else {\n * addLog('资源不足!', 'error');\n * }\n * ```\n */\n static canAfford<\n S extends string,\n I extends string,\n F extends string,\n X = Record<string, unknown>\n >(\n state: GameState<S, I, F, X>,\n costs?: Partial<Record<S, number>>\n ): boolean {\n // 如果没有定义成本,默认通过\n if (!costs) return true;\n\n /**\n * 遍历所有成本项,检查每个属性是否足够\n * 只要有一个属性不足,就返回false\n */\n for (const [key, cost] of Object.entries(costs)) {\n const currentVal = state.stats[key as S] || 0;\n if (currentVal < (cost as number)) return false;\n }\n\n // 所有资源都足够\n return true;\n }\n}\n","// src/engine/systems/flow.ts\n// ============================================================================\n// 流程系统 - 游戏动作执行引擎\n// ============================================================================\n//\n// 这个文件负责执行游戏动作的完整流程,包括:\n// - 条件验证:检查是否满足执行条件\n// - 成本扣除:扣除执行动作所需的资源\n// - 效果应用:应用动作产生的所有效果\n// - 日志记录:记录动作执行结果\n//\n// 设计原则:\n// - 原子性:动作要么完全执行,要么完全不执行\n// - 安全性:执行前进行最终检查,防止非法操作\n// - 可追溯:所有操作都记录日志\n//\n// ============================================================================\n\nimport type { GameStore } from \"../state/store\";\nimport type { ActionDef, EffectDef } from \"../core/types\";\nimport { QuerySystem } from \"./query\";\nimport { SystemMessages } from '../core/messages';\nimport { gameEvents, EngineEvents } from './events';\n\n/**\n * 流程系统类 - 负责游戏动作的执行流程\n *\n * 这是一个工具类,所有方法都是静态的,不需要实例化。\n * 主要功能是协调动作执行的各个步骤,确保游戏逻辑的正确性。\n *\n * 执行流程:\n * 1. 验证条件:检查需求和成本\n * 2. 扣除成本:消耗资源\n * 3. 应用效果:修改游戏状态\n * 4. 记录日志:反馈给玩家\n *\n * @example\n * ```typescript\n * // 在游戏中执行动作\n * const success = FlowSystem.executeAction(\n * useGameStore.getState(),\n * attackAction\n * );\n *\n * if (success) {\n * console.log('动作执行成功');\n * }\n * ```\n */\nexport class FlowSystem {\n /**\n * 执行一个游戏动作\n *\n * 这是核心方法,负责完整的动作执行流程。\n * 执行过程是原子性的:要么全部成功,要么全部失败。\n *\n * 执行步骤:\n * 1. 最终验证:检查需求和成本(防止UI滞后)\n * 2. 扣除成本:消耗资源(如体力、金币)\n * 3. 应用效果:修改状态(属性、物品、标记等)\n * 4. 记录日志:生成反馈信息\n *\n * @template S - 数值属性键的联合类型\n * @template I - 物品ID的联合类型\n * @template F - 标记键的联合类型\n *\n * @param store - Zustand Store 实例(包含状态和方法)\n * @param action - 要执行的动作定义\n *\n * @returns true表示执行成功,false表示执行失败\n *\n * @example\n * ```typescript\n * // 定义一个攻击动作\n * const attackAction: ActionDef<Stats, Items, Flags> = {\n * id: 'attack_goblin',\n * label: '攻击哥布林',\n * costs: { stamina: 10 },\n * requirements: { hasItems: ['weapon'] },\n * effects: {\n * statsChange: { exp: 5 },\n * flagsSet: { goblin_defeated: true }\n * },\n * resultText: '你击败了哥布林!'\n * };\n *\n * // 执行动作\n * const store = useGameStore.getState();\n * const success = FlowSystem.executeAction(store, attackAction);\n * ```\n */\n static executeAction<\n S extends string,\n I extends string,\n F extends string,\n X = Record<string, unknown>\n >(\n store: GameStore<S, I, F, X>,\n action: ActionDef<S, I, F, X>\n ): boolean {\n // Store 本身包含 State 数据(Zustand 的设计)\n const state = store;\n\n // ========== 步骤0:保存快照(可选) ==========\n\n /**\n * 在动作执行前保存状态快照\n * \n * 这允许玩家在动作执行后撤销操作。\n * 可以根据游戏设计决定是否启用此功能。\n * \n * 建议:对于重要或不可逆的动作启用快照\n */\n // store.saveSnapshot(); // 取消注释以启用自动快照\n\n // ========== 步骤1:最终验证 ==========\n\n /**\n * 检查需求条件\n *\n * 即使UI已经检查过,这里也要再次检查,因为:\n * - UI状态可能滞后\n * - 多个动作可能同时触发\n * - 防止作弊或bug\n * \n * 使用增强版本的检查方法,可以获取失败原因并显示给玩家\n */\n const reqCheck = QuerySystem.checkRequirementsWithReason(state, action.requirements);\n if (!reqCheck.passed) {\n console.warn(`条件不满足: ${action.id}`, reqCheck.reason);\n \n // 如果有失败原因,显示给玩家\n if (reqCheck.reason) {\n store.addLog(reqCheck.reason, \"warn\");\n }\n \n return false;\n }\n\n /**\n * 检查成本\n *\n * 确保玩家有足够的资源支付成本\n */\n if (!QuerySystem.canAfford(state, action.costs)) {\n store.addLog(SystemMessages.NOT_ENOUGH_RESOURCES, \"warn\");\n return false;\n }\n\n // ========== 步骤2:扣除成本 ==========\n\n /**\n * 扣除执行动作所需的成本\n *\n * 将成本转换为负数,然后应用到状态上。\n * 例如:{ stamina: 10 } 转换为 { stamina: -10 }\n */\n if (action.costs) {\n const costsToDeduct: Partial<Record<S, number>> = {};\n for (const [key, val] of Object.entries(action.costs)) {\n costsToDeduct[key as S] = -(val as number);\n }\n store.setStats(costsToDeduct);\n }\n\n // ========== 步骤3:应用效果 ==========\n \n /**\n * 效果执行顺序说明:\n * \n * 【阶段 1:静态效果】\n * 1. statsChange - 数值属性变更\n * 2. itemsAdd - 添加物品\n * 3. itemsRemove - 移除物品\n * 4. flagsSet - 设置标记\n * 5. flagsBatch - 批量标记操作\n * 6. teleport - 传送\n * 7. timeAdvance + onTimeAdvance - 时间推进及其钩子\n * 8. triggerEvent - 触发自定义事件\n * \n * 【阶段 2:条件效果】\n * 9. conditionalEffects - 根据阶段1后的状态决定额外效果\n * \n * 【阶段 3:自定义效果】\n * 10. custom - 修改 extra 扩展数据\n * 11. customFull - 修改完整游戏状态\n * \n * 【阶段 4:后置钩子】(在 effects 之外)\n * 12. afterEffects - 基于最终状态执行副作用\n * \n * 【阶段 5:结果文本】(在 effects 之外)\n * 13. resultText - 生成反馈文本\n */\n\n const { effects } = action;\n if (effects) {\n /**\n * 辅助函数:应用单个效果定义\n * \n * 将效果应用逻辑提取为函数,以便复用于静态效果和条件效果。\n * 此函数按固定顺序执行各种效果类型。\n */\n const applyEffectDef = (effectDef: Omit<EffectDef<S, I, F, X>, 'conditionalEffects' | 'custom' | 'customFull'>) => {\n // ===== 效果类型 1:数值属性变更 =====\n if (effectDef.statsChange) {\n const statsToChange = typeof effectDef.statsChange === 'function'\n ? effectDef.statsChange(store)\n : effectDef.statsChange;\n \n store.setStats(statsToChange);\n }\n\n // ===== 效果类型 2:添加物品 =====\n effectDef.itemsAdd?.forEach((i: I) => store.addItem(i));\n \n // ===== 效果类型 3:移除物品 =====\n effectDef.itemsRemove?.forEach((i: I) => store.removeItem(i));\n\n // ===== 效果类型 4:设置标记 =====\n if (effectDef.flagsSet) {\n const flagsToSet = typeof effectDef.flagsSet === 'function'\n ? effectDef.flagsSet(store)\n : effectDef.flagsSet;\n \n Object.entries(flagsToSet).forEach(([f, v]) => {\n store.setFlag(f as F, v as boolean);\n });\n }\n\n // ===== 效果类型 5:批量标记操作 =====\n if (effectDef.flagsBatch) {\n const batchOp = typeof effectDef.flagsBatch === 'function'\n ? effectDef.flagsBatch(store)\n : effectDef.flagsBatch;\n \n if (batchOp) {\n // 步骤1:清除标记\n if (batchOp.clear) {\n const allFlags = Object.keys(store.flags) as F[];\n let flagsToClear: string[] = [];\n\n if (batchOp.clear instanceof RegExp) {\n // 正则表达式匹配\n flagsToClear = allFlags.filter(f => batchOp.clear instanceof RegExp && batchOp.clear.test(f));\n } else if (typeof batchOp.clear === 'string') {\n // 前缀字符串匹配\n flagsToClear = allFlags.filter(f => f.startsWith(batchOp.clear as string));\n } else if (Array.isArray(batchOp.clear)) {\n // 标记列表\n flagsToClear = batchOp.clear;\n }\n\n // 清除匹配的标记(设置为 false)\n flagsToClear.forEach(f => {\n store.setFlag(f as F, false);\n });\n }\n\n // 步骤2:设置标记\n if (batchOp.set) {\n Object.entries(batchOp.set).forEach(([f, v]) => {\n store.setFlag(f as F, v as boolean);\n });\n }\n }\n }\n\n // ===== 效果类型 6:传送 =====\n if (effectDef.teleport) {\n store.teleport(effectDef.teleport);\n }\n\n // ===== 效果类型 7:时间推进 + onTimeAdvance 钩子 =====\n if (effectDef.timeAdvance !== undefined) {\n const daysToAdvance = typeof effectDef.timeAdvance === 'function'\n ? effectDef.timeAdvance(store)\n : effectDef.timeAdvance;\n \n if (daysToAdvance > 0) {\n const previousDay = store.world.day;\n \n // 推进时间\n store.advanceTime(daysToAdvance);\n \n // 如果定义了 onTimeAdvance 钩子,为每一天调用一次\n if (effectDef.onTimeAdvance) {\n const actions = {\n updateStat: store.updateStat,\n setStats: store.setStats,\n setExtra: store.setExtra,\n addItem: store.addItem,\n removeItem: store.removeItem,\n setFlag: store.setFlag,\n addLog: store.addLog,\n showToast: store.showToast,\n showModal: store.showModal,\n advanceTime: store.advanceTime,\n teleport: store.teleport,\n reset: store.reset,\n saveSnapshot: store.saveSnapshot,\n undo: store.undo,\n };\n \n // 为每一天分别调用钩子\n for (let i = 1; i <= daysToAdvance; i++) {\n const currentDay = previousDay + i;\n const dayBefore = currentDay - 1;\n \n // 获取当前最新状态\n const currentState = store;\n \n effectDef.onTimeAdvance(currentDay, dayBefore, currentState, actions);\n }\n }\n }\n }\n\n // ===== 效果类型 8:触发自定义事件 =====\n if (effectDef.triggerEvent) {\n gameEvents.emit(EngineEvents.CUSTOM, { id: effectDef.triggerEvent });\n }\n };\n\n /**\n * 【阶段 1:静态效果】\n * \n * 首先应用所有静态定义的效果。\n * 这些效果按固定顺序执行(见 applyEffectDef 函数内部)。\n */\n applyEffectDef(effects);\n\n /**\n * 【阶段 2:条件效果】\n * \n * 根据当前游戏状态(包含阶段1的修改)动态决定要应用的效果。\n * conditionalEffects 返回的效果会按阶段1的顺序再次执行。\n * \n * 使用场景:\n * - 基于修改后的属性值决定额外效果\n * - 实现\"如果...则...\"的逻辑\n * - 根据不同条件产生不同效果\n */\n if (effects.conditionalEffects) {\n // 获取当前最新状态(包含静态效果的修改)\n const currentState = store;\n \n // 执行条件函数,获取要应用的效果\n const conditionalEffect = effects.conditionalEffects(currentState);\n \n // 如果返回了效果定义,应用它\n if (conditionalEffect) {\n applyEffectDef(conditionalEffect);\n }\n }\n\n /**\n * 【阶段 3.1:自定义效果 - 修改 extra 字段】\n * \n * 在所有静态效果和条件效果之后执行。\n * 用于修改扩展数据(extra 字段)。\n * \n * 使用场景:\n * - 更新游戏特定的自定义数据\n * - 记录时间戳、计数器等元数据\n * - 存储复杂的状态信息\n */\n if (effects.custom) {\n const draft = { ...state.extra };\n const result = effects.custom(draft, state);\n if (result) {\n // 如果返回了部分更新,合并到 draft\n store.setExtra({ ...draft, ...result });\n } else {\n // 如果没有返回值,使用修改后的 draft\n store.setExtra(draft);\n }\n }\n\n /**\n * 【阶段 3.2:完整自定义效果 - 修改完整游戏状态】\n * \n * ⚠️ 最强大的效果类型,在所有其他效果之后执行\n * \n * 允许修改完整的游戏状态(stats、inventory、flags、world、extra)。\n * 可以覆盖或调整之前所有效果的结果。\n * \n * 使用场景:\n * - 实现复杂的连锁反应\n * - 基于最终状态进行调整\n * - 需要同时修改多个状态字段的复杂逻辑\n * - 实现\"护盾吸收伤害\"等覆盖机制\n * \n * 注意:\n * - 这是最后的修改机会(除了 afterEffects)\n * - 可以访问原始状态和当前状态\n * - 批量应用所有修改以提高性能\n */\n if (effects.customFull) {\n // 保存原始状态(只读,供函数参考)\n const originalState = { ...state };\n \n // 获取当前最新状态(包含之前效果的修改)\n const currentState = store;\n \n // 创建可修改的状态副本(不包含 logs 和方法)\n const draft = {\n stats: { ...currentState.stats },\n inventory: [...currentState.inventory],\n flags: { ...currentState.flags },\n world: { ...currentState.world },\n extra: { ...currentState.extra },\n };\n \n // 执行自定义函数,允许修改 draft\n effects.customFull(draft, originalState);\n \n // 批量应用所有修改\n // 使用 setStats 而不是直接赋值,以保持增量更新的语义\n const statsChanges: Partial<Record<S, number>> = {};\n for (const key in draft.stats) {\n const oldVal = currentState.stats[key as S] || 0;\n const newVal = draft.stats[key as S];\n const delta = newVal - oldVal;\n if (delta !== 0) {\n statsChanges[key as S] = delta;\n }\n }\n if (Object.keys(statsChanges).length > 0) {\n store.setStats(statsChanges);\n }\n \n // 应用物品变更\n // 计算需要添加和移除的物品\n const currentItems = new Set(currentState.inventory);\n const newItems = new Set(draft.inventory);\n \n // 移除不在新清单中的物品\n currentState.inventory.forEach(item => {\n if (!newItems.has(item)) {\n store.removeItem(item);\n }\n });\n \n // 添加新清单中的新物品\n draft.inventory.forEach(item => {\n if (!currentItems.has(item)) {\n store.addItem(item);\n }\n });\n \n // 应用标记变更\n for (const key in draft.flags) {\n const oldVal = currentState.flags[key as F];\n const newVal = draft.flags[key as F];\n if (oldVal !== newVal) {\n store.setFlag(key as F, newVal);\n }\n }\n \n // 应用世界状态变更\n if (draft.world.currentLocationId !== currentState.world.currentLocationId) {\n store.teleport(draft.world.currentLocationId);\n }\n if (draft.world.day !== currentState.world.day) {\n const dayDelta = draft.world.day - currentState.world.day;\n store.advanceTime(dayDelta);\n }\n // 注意:time 字段目前没有专门的更新方法,如果需要可以扩展\n \n // 应用扩展数据变更\n store.setExtra(draft.extra);\n }\n }\n\n // ========== 步骤4:执行后置效果钩子 ==========\n\n /**\n * 【阶段 4:后置钩子】\n * \n * 在所有效果(阶段1-3)执行完成后调用。\n * 这是最后一个可以修改状态的机会。\n * \n * 与 customFull 的区别:\n * - customFull: 在 effects 内部,用于修改效果本身\n * - afterEffects: 在 effects 外部,用于基于最终状态执行副作用\n * \n * 使用场景:\n * - 检查成就解锁\n * - 触发连锁事件\n * - 清理过期数据\n * - 自动保存快照\n * - 发送通知\n * \n * 职责分离:\n * - afterEffects: 执行副作用(修改状态、触发事件等)\n * - resultText: 生成反馈文本(纯函数,不修改状态)\n */\n if (action.afterEffects) {\n // 保存原始状态用于对比\n const originalState = { ...state };\n \n // 获取当前最新状态(包含所有效果的修改)\n const currentState = store;\n \n // 提取操作方法(不包含状态数据)\n const actions = {\n updateStat: store.updateStat,\n setStats: store.setStats,\n setExtra: store.setExtra,\n addItem: store.addItem,\n removeItem: store.removeItem,\n setFlag: store.setFlag,\n addLog: store.addLog,\n showToast: store.showToast,\n showModal: store.showModal,\n advanceTime: store.advanceTime,\n teleport: store.teleport,\n reset: store.reset,\n saveSnapshot: store.saveSnapshot,\n undo: store.undo,\n };\n \n // 执行后置效果钩子\n action.afterEffects(currentState, originalState, actions);\n }\n\n // ========== 步骤5:生成结果文本并记录日志 ==========\n\n /**\n * 【阶段 5:结果文本】\n * \n * 在所有效果和钩子执行完成后生成反馈文本。\n * \n * resultText 可以是静态字符串或动态函数。\n * 动态函数可以访问最终状态(包含所有修改),\n * 因此可以生成准确的反馈信息。\n * \n * 职责分离:\n * - resultText 只负责生成文本,不应修改状态\n * - 所有状态修改应在 effects 或 afterEffects 中完成\n * \n * 使用场景:\n * - 根据最终状态生成个性化反馈\n * - 显示属性变化的具体数值\n * - 提示玩家达成的成就或触发的事件\n */\n const finalState = store; // 获取最终状态\n const resultText =\n typeof action.resultText === \"function\"\n ? action.resultText(finalState)\n : action.resultText;\n\n store.addLog(resultText, \"result\");\n\n // ========== 步骤6:发射动作完成事件 ==========\n\n /**\n * 发射 ACTION_EXECUTED 事件\n * \n * 通知系统动作已成功执行。\n * UI 层或其他系统可以监听此事件来:\n * - 播放音效\n * - 显示动画\n * - 更新成就系统\n * - 触发连锁反应\n * \n * @example\n * ```typescript\n * // 在 UI 组件中监听动作执行\n * gameEvents.on(EngineEvents.ACTION_EXECUTED, (data) => {\n * console.log(`动作 ${data.actionId} 已执行`);\n * playSound('action_success');\n * });\n * ```\n */\n gameEvents.emit(EngineEvents.ACTION_EXECUTED, { actionId: action.id });\n\n // 执行成功\n return true;\n }\n}\n","import React from \"react\";\n\ninterface LayoutProps {\n sidebar?: React.ReactNode; // 左侧:状态、背包\n main?: React.ReactNode; // 中间:地点图、动作列表\n logs?: React.ReactNode; // 右侧:日志流\n className?: string;\n}\n\nexport const Layout: React.FC<LayoutProps> = ({\n sidebar,\n main,\n logs,\n className = \"\",\n}) => {\n return (\n <div\n className={`min-h-screen bg-[#0c0c0e] text-[#a1a1aa] font-sans flex overflow-hidden ${className}`}\n >\n {/* 1. 左侧侧边栏 (固定宽度) */}\n {sidebar && (\n <aside className=\"w-72 bg-[#141417] border-r border-[#27272a] flex flex-col shrink-0 z-10\">\n {sidebar}\n </aside>\n )}\n\n {/* 2. 中间主舞台 (自适应宽度) */}\n <main className=\"flex-1 flex flex-col min-w-0 relative\">{main}</main>\n\n {/* 3. 右侧日志栏 (固定宽度) */}\n {logs && (\n <aside className=\"w-80 bg-[#0c0c0e] border-l border-[#27272a] flex flex-col shrink-0 z-10\">\n {logs}\n </aside>\n )}\n </div>\n );\n};\n\n// 同时也导出一个用于 Main 区域内部的容器组件,方便统一内边距\nexport const MainContent: React.FC<{\n header?: React.ReactNode;\n children: React.ReactNode;\n}> = ({ header, children }) => (\n <>\n {/* 顶部标题区域 */}\n {header && (\n <div className=\"p-10 border-b border-[#27272a] bg-[#0c0c0e] shrink-0\">\n <div className=\"max-w-3xl mx-auto\">{header}</div>\n </div>\n )}\n\n {/* 内容滚动区域 */}\n <div className=\"flex-1 overflow-y-auto p-10 bg-[#101012]\">\n <div className=\"max-w-3xl mx-auto\">{children}</div>\n </div>\n </>\n);\n","import React, { useEffect, useRef } from \"react\";\nimport type { LogEntry } from \"../core/types\";\n\ninterface LogStreamProps {\n logs: LogEntry[];\n className?: string;\n title?: string;\n}\n\nexport const LogStream: React.FC<LogStreamProps> = ({\n logs,\n className = \"\",\n title = \"Chronicle\",\n}) => {\n const bottomRef = useRef<HTMLDivElement>(null);\n\n // 自动滚动到底部\n useEffect(() => {\n bottomRef.current?.scrollIntoView({ behavior: \"smooth\" });\n }, [logs]);\n\n // 根据类型返回样式\n const getLogStyle = (type: LogEntry[\"type\"]) => {\n switch (type) {\n case \"warn\":\n return \"text-amber-500 border-l-2 border-amber-500/50 pl-2\";\n case \"error\":\n return \"text-red-500 border-l-2 border-red-500/50 pl-2 font-bold\";\n case \"success\":\n return \"text-green-500 border-l-2 border-green-500/50 pl-2\";\n case \"result\":\n return \"text-stone-300 border-l-2 border-stone-600/50 pl-2\"; // 行动结果\n case \"info\":\n default:\n return \"text-stone-500 border-l-2 border-transparent pl-2\"; // 普通叙事\n }\n };\n\n return (\n <div\n className={`flex flex-col bg-[#0c0c0e] border-l border-[#27272a] h-full ${className}`}\n >\n {/* 标题栏 */}\n <div className=\"p-4 border-b border-[#27272a] bg-[#141417] shrink-0\">\n <h3 className=\"text-xs font-bold text-stone-500 uppercase tracking-wider\">\n {title}\n </h3>\n </div>\n\n {/* 滚动区域 */}\n <div className=\"flex-1 overflow-y-auto p-6 space-y-4 font-serif scroll-smooth\">\n {logs.length === 0 && (\n <div className=\"text-stone-700 text-sm italic text-center mt-10\">\n 暂无记录...\n </div>\n )}\n\n {logs.map((log) => (\n <div\n key={log.id}\n className={`text-sm leading-relaxed transition-all duration-500 animate-in fade-in slide-in-from-bottom-2 ${getLogStyle(\n log.type\n )}`}\n >\n {/* 时间戳 (可选,根据需求显示) */}\n {/* <span className=\"text-[10px] opacity-50 mr-2 font-mono\">[{log.timestamp}]</span> */}\n {log.text}\n </div>\n ))}\n\n {/* 锚点 */}\n <div ref={bottomRef} />\n </div>\n </div>\n );\n};\n","// src/engine/ui/OverlaySystem.tsx\n/**\n * Overlay System - 覆盖层系统\n * \n * ⚠️ 重要架构说明:\n * \n * 这个系统处理所有瞬时的 UI 通知,与持久化的日志系统完全分离:\n * \n * 1. Logs (日志) - LogStream 组件\n * - 持久化到 localStorage\n * - 页面刷新后重新加载\n * - 永久显示在日志面板\n * - 用于回顾历史\n * \n * 2. Toasts (飘字) - 本组件处理\n * - 瞬时通知,不持久化\n * - 自动消失(3秒)\n * - 不阻塞用户操作\n * - 用于轻量级反馈\n * \n * 3. Modals (弹窗) - 本组件处理\n * - 瞬时通知,不持久化\n * - 需要用户确认\n * - 阻塞式交互\n * - 用于重要信息\n */\n\nimport { useEffect, useState } from 'react';\nimport { gameEvents, EngineEvents } from '../systems/events';\nimport type { NotificationPayload } from '../core/types';\nimport { DEFAULT_CONFIG } from '../core/constants';\n\n/**\n * Toast 通知项\n */\ninterface ToastItem extends NotificationPayload {\n id: string;\n}\n\n/**\n * Overlay System 组件\n * \n * 监听 NOTIFICATION 事件并显示对应的 UI\n */\nexport function OverlaySystem() {\n const [toasts, setToasts] = useState<ToastItem[]>([]);\n const [modal, setModal] = useState<NotificationPayload | null>(null);\n\n useEffect(() => {\n // 监听通知事件\n const unsubscribe = gameEvents.on<NotificationPayload>(\n EngineEvents.NOTIFICATION,\n (payload) => {\n switch (payload.notificationType) {\n case 'toast': {\n // 添加飘字\n const toastId = `toast-${payload.timestamp}-${Math.random()}`;\n const toast: ToastItem = { ...payload, id: toastId };\n \n setToasts((prev) => [...prev, toast]);\n \n // 自动移除(使用配置的时长)\n setTimeout(() => {\n setToasts((prev) => prev.filter((t) => t.id !== toastId));\n }, DEFAULT_CONFIG.TOAST_DURATION);\n break;\n }\n\n case 'modal': {\n // 显示弹窗\n setModal(payload);\n break;\n }\n }\n }\n );\n\n return unsubscribe;\n }, []);\n\n return (\n <>\n {/* 飘字容器 */}\n <div className=\"toast-container\">\n {toasts.map((toast) => (\n <div\n key={toast.id}\n className={`toast toast-${toast.type}`}\n role=\"alert\"\n >\n {toast.text}\n </div>\n ))}\n </div>\n\n {/* 模态弹窗 */}\n {modal && (\n <div\n className=\"modal-overlay\"\n onClick={() => setModal(null)}\n role=\"dialog\"\n aria-modal=\"true\"\n >\n <div\n className=\"modal-content\"\n onClick={(e) => e.stopPropagation()}\n >\n <div className={`modal-message modal-${modal.type}`}>\n {modal.text}\n </div>\n <button\n className=\"modal-button\"\n onClick={() => setModal(null)}\n autoFocus\n >\n 确定\n </button>\n </div>\n </div>\n )}\n\n {/* 样式 */}\n <style>{`\n /* 飘字容器 */\n .toast-container {\n position: fixed;\n top: 20px;\n right: 20px;\n z-index: 1000;\n display: flex;\n flex-direction: column;\n gap: 10px;\n pointer-events: none;\n }\n\n /* 飘字样式 */\n .toast {\n padding: 12px 20px;\n border-radius: 8px;\n background: white;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n animation: slideIn 0.3s ease-out, fadeOut 0.3s ease-in 2.7s;\n pointer-events: auto;\n max-width: 300px;\n word-wrap: break-word;\n }\n\n .toast-info {\n border-left: 4px solid #3b82f6;\n color: #1e40af;\n }\n\n .toast-success {\n border-left: 4px solid #10b981;\n color: #065f46;\n }\n\n .toast-warn {\n border-left: 4px solid #f59e0b;\n color: #92400e;\n }\n\n .toast-error {\n border-left: 4px solid #ef4444;\n color: #991b1b;\n }\n\n .toast-result {\n border-left: 4px solid #6366f1;\n color: #3730a3;\n }\n\n @keyframes slideIn {\n from {\n transform: translateX(100%);\n opacity: 0;\n }\n to {\n transform: translateX(0);\n opacity: 1;\n }\n }\n\n @keyframes fadeOut {\n from {\n opacity: 1;\n }\n to {\n opacity: 0;\n }\n }\n\n /* 模态弹窗 */\n .modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 2000;\n animation: fadeIn 0.2s ease-out;\n }\n\n .modal-content {\n background: white;\n padding: 24px;\n border-radius: 12px;\n max-width: 400px;\n min-width: 300px;\n box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1);\n animation: scaleIn 0.2s ease-out;\n }\n\n .modal-message {\n margin-bottom: 20px;\n font-size: 16px;\n line-height: 1.5;\n color: #1f2937;\n }\n\n .modal-success {\n color: #10b981;\n }\n\n .modal-warn {\n color: #f59e0b;\n }\n\n .modal-error {\n color: #ef4444;\n }\n\n .modal-button {\n width: 100%;\n padding: 10px 20px;\n background: #3b82f6;\n color: white;\n border: none;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: background 0.2s;\n }\n\n .modal-button:hover {\n background: #2563eb;\n }\n\n .modal-button:active {\n background: #1d4ed8;\n }\n\n @keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n }\n\n @keyframes scaleIn {\n from {\n transform: scale(0.9);\n opacity: 0;\n }\n to {\n transform: scale(1);\n opacity: 1;\n }\n }\n `}</style>\n </>\n );\n}\n"]}
1
+ {"version":3,"sources":["../core/messages.ts","../core/constants.ts","../core/utils.ts","../systems/events.ts","../state/history.ts","../state/store.ts","../systems/query.ts","../systems/flow.ts","../ui/Layout.tsx","../ui/LogStream.tsx","../ui/OverlaySystem.tsx"],"names":["create","persist","get","createJSONStorage","jsxs","jsx","Fragment","useRef","useEffect","useState"],"mappings":"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","file":"index.js","sourcesContent":["// src/engine/core/messages.ts\n\n/**\n * 系统消息常量\n * \n * 使用特殊的标识符(sys: 前缀),让 UI 层知道这需要翻译。\n * 这些常量用于系统级别的提示消息,应该在 UI 层进行本地化处理。\n */\nexport const SystemMessages = {\n /** 资源不足提示 */\n NOT_ENOUGH_RESOURCES: 'sys:not_enough_resources',\n /** 条件不满足提示 */\n REQUIREMENT_NOT_MET: 'sys:requirement_not_met',\n /** 操作成功提示 */\n ACTION_SUCCESS: 'sys:action_success',\n /** 时间回溯成功提示 */\n UNDO_SUCCESS: 'sys:undo_success',\n} as const;","// src/engine/core/constants.ts\n/**\n * 全局常量定义\n */\n\n/**\n * 引擎版本\n */\nexport const ENGINE_VERSION = '1.0.0';\n\n/**\n * 默认配置\n */\nexport const DEFAULT_CONFIG = {\n /** 默认存档键名 */\n DEFAULT_SAVE_KEY: 'game-save',\n /** 最大日志条数 */\n MAX_LOG_ENTRIES: 50,\n /** 最大历史快照数 */\n MAX_HISTORY_SNAPSHOTS: 20,\n /** 飘字显示时长(毫秒) */\n TOAST_DURATION: 3000,\n} as const;\n\n/**\n * 日志类型颜色映射\n */\nexport const LOG_TYPE_COLORS = {\n info: '#3b82f6',\n success: '#10b981',\n warn: '#f59e0b',\n error: '#ef4444',\n result: '#6366f1',\n} as const;\n\n/**\n * 默认属性值\n */\nexport const DEFAULT_STATS = {\n /** 默认生命值 */\n DEFAULT_HP: 100,\n /** 默认金币 */\n DEFAULT_GOLD: 0,\n} as const;\n\n/**\n * 游戏时间常量\n */\nexport const TIME_CONSTANTS = {\n /** 一天的小时数 */\n HOURS_PER_DAY: 24,\n /** 早晨开始时间 */\n MORNING_START: 6,\n /** 中午开始时间 */\n NOON_START: 12,\n /** 傍晚开始时间 */\n EVENING_START: 18,\n /** 夜晚开始时间 */\n NIGHT_START: 22,\n} as const;\n\n/**\n * UI 常量\n */\nexport const UI_CONSTANTS = {\n /** 侧边栏宽度 */\n SIDEBAR_WIDTH: 288, // 72 * 4 = 288px (w-72)\n /** 日志栏宽度 */\n LOG_WIDTH: 320, // 80 * 4 = 320px (w-80)\n /** Toast 容器 z-index */\n TOAST_Z_INDEX: 1000,\n /** Modal 容器 z-index */\n MODAL_Z_INDEX: 2000,\n} as const;\n\n/**\n * 验证常量\n */\nexport const VALIDATION = {\n /** 最小属性值 */\n MIN_STAT_VALUE: 0,\n /** 最大属性值 */\n MAX_STAT_VALUE: 9999,\n /** 最大背包容量 */\n MAX_INVENTORY_SIZE: 100,\n /** 最小动作 ID 长度 */\n MIN_ACTION_ID_LENGTH: 1,\n /** 最大动作 ID 长度 */\n MAX_ACTION_ID_LENGTH: 50,\n} as const;","// src/engine/core/utils.ts\n/**\n * 工具函数集合\n */\n\nimport type { GameState } from './types';\nimport { TIME_CONSTANTS } from './constants';\n\n/**\n * 生成唯一 ID\n * \n * @returns 唯一标识符字符串\n * \n * @example\n * ```typescript\n * const id = generateId(); // \"1234567890-abc123\"\n * ```\n */\nexport function generateId(): string {\n return `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;\n}\n\n/**\n * 深拷贝对象\n * \n * 使用 JSON 序列化实现深拷贝,注意会丢失函数、Symbol 等特殊类型\n * \n * @param obj - 要拷贝的对象\n * @returns 深拷贝后的对象\n * \n * @example\n * ```typescript\n * const copy = deepClone(originalObject);\n * ```\n */\nexport function deepClone<T>(obj: T): T {\n return JSON.parse(JSON.stringify(obj));\n}\n\n/**\n * 限制数值在指定范围内\n * \n * @param value - 要限制的值\n * @param min - 最小值\n * @param max - 最大值\n * @returns 限制后的值\n * \n * @example\n * ```typescript\n * clamp(150, 0, 100); // 100\n * clamp(-10, 0, 100); // 0\n * clamp(50, 0, 100); // 50\n * ```\n */\nexport function clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n\n/**\n * 格式化数字,添加千位分隔符\n * \n * @param num - 要格式化的数字\n * @returns 格式化后的字符串\n * \n * @example\n * ```typescript\n * formatNumber(1234567); // \"1,234,567\"\n * ```\n */\nexport function formatNumber(num: number): string {\n return num.toString().replace(/\\B(?=(\\d{3})+(?!\\d))/g, ',');\n}\n\n/**\n * 获取时间段描述\n * \n * @param hour - 小时数 (0-23)\n * @returns 时间段描述\n * \n * @example\n * ```typescript\n * getTimeOfDay(8); // \"早晨\"\n * getTimeOfDay(14); // \"下午\"\n * getTimeOfDay(20); // \"傍晚\"\n * ```\n */\nexport function getTimeOfDay(hour: number): string {\n if (hour >= TIME_CONSTANTS.MORNING_START && hour < TIME_CONSTANTS.NOON_START) {\n return '早晨';\n } else if (hour >= TIME_CONSTANTS.NOON_START && hour < TIME_CONSTANTS.EVENING_START) {\n return '下午';\n } else if (hour >= TIME_CONSTANTS.EVENING_START && hour < TIME_CONSTANTS.NIGHT_START) {\n return '傍晚';\n } else {\n return '夜晚';\n }\n}\n\n/**\n * 计算百分比\n * \n * @param current - 当前值\n * @param max - 最大值\n * @returns 百分比 (0-100)\n * \n * @example\n * ```typescript\n * getPercentage(75, 100); // 75\n * getPercentage(0, 100); // 0\n * ```\n */\nexport function getPercentage(current: number, max: number): number {\n if (max === 0) return 0;\n return Math.round((current / max) * 100);\n}\n\n/**\n * 随机整数\n * \n * @param min - 最小值(包含)\n * @param max - 最大值(包含)\n * @returns 随机整数\n * \n * @example\n * ```typescript\n * randomInt(1, 6); // 1-6 之间的随机整数(模拟骰子)\n * ```\n */\nexport function randomInt(min: number, max: number): number {\n return Math.floor(Math.random() * (max - min + 1)) + min;\n}\n\n/**\n * 从数组中随机选择一个元素\n * \n * @param array - 数组\n * @returns 随机选择的元素,如果数组为空则返回 undefined\n * \n * @example\n * ```typescript\n * randomChoice(['剑', '盾', '药水']); // 随机返回一个\n * ```\n */\nexport function randomChoice<T>(array: T[]): T | undefined {\n if (array.length === 0) return undefined;\n return array[Math.floor(Math.random() * array.length)];\n}\n\n/**\n * 打乱数组顺序(Fisher-Yates 算法)\n * \n * @param array - 要打乱的数组\n * @returns 打乱后的新数组\n * \n * @example\n * ```typescript\n * shuffle([1, 2, 3, 4, 5]); // [3, 1, 5, 2, 4]\n * ```\n */\nexport function shuffle<T>(array: T[]): T[] {\n const result = [...array];\n for (let i = result.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1));\n [result[i], result[j]] = [result[j], result[i]];\n }\n return result;\n}\n\n/**\n * 延迟执行\n * \n * @param ms - 延迟毫秒数\n * @returns Promise\n * \n * @example\n * ```typescript\n * await delay(1000); // 延迟 1 秒\n * ```\n */\nexport function delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * 检查对象是否为空\n * \n * @param obj - 要检查的对象\n * @returns 是否为空\n * \n * @example\n * ```typescript\n * isEmpty({}); // true\n * isEmpty({ a: 1 }); // false\n * ```\n */\nexport function isEmpty(obj: object): boolean {\n return Object.keys(obj).length === 0;\n}\n\n/**\n * 安全地获取嵌套属性\n * \n * @param obj - 对象\n * @param path - 属性路径,用点分隔\n * @param defaultValue - 默认值\n * @returns 属性值或默认值\n * \n * @example\n * ```typescript\n * const obj = { a: { b: { c: 123 } } };\n * get(obj, 'a.b.c', 0); // 123\n * get(obj, 'a.x.y', 0); // 0\n * ```\n */\nexport function get<T>(obj: unknown, path: string, defaultValue?: T): T {\n const keys = path.split('.');\n let result: unknown = obj;\n\n for (const key of keys) {\n if (result && typeof result === 'object' && key in result) {\n result = (result as Record<string, unknown>)[key];\n } else {\n return defaultValue as T;\n }\n }\n\n return result as T;\n}\n\n/**\n * 防抖函数\n * \n * @param fn - 要防抖的函数\n * @param wait - 等待时间(毫秒)\n * @returns 防抖后的函数\n * \n * @example\n * ```typescript\n * const debouncedSave = debounce(() => saveGame(), 1000);\n * debouncedSave(); // 1秒内多次调用只执行最后一次\n * ```\n */\nexport function debounce<T extends (...args: never[]) => unknown>(\n fn: T,\n wait: number\n): (...args: Parameters<T>) => void {\n let timeout: ReturnType<typeof setTimeout> | null = null;\n\n return function (this: unknown, ...args: Parameters<T>) {\n if (timeout) clearTimeout(timeout);\n timeout = setTimeout(() => fn.apply(this, args), wait);\n };\n}\n\n/**\n * 节流函数\n * \n * @param fn - 要节流的函数\n * @param wait - 等待时间(毫秒)\n * @returns 节流后的函数\n * \n * @example\n * ```typescript\n * const throttledUpdate = throttle(() => updateUI(), 100);\n * throttledUpdate(); // 100ms 内只执行一次\n * ```\n */\nexport function throttle<T extends (...args: never[]) => unknown>(\n fn: T,\n wait: number\n): (...args: Parameters<T>) => void {\n let lastTime = 0;\n\n return function (this: unknown, ...args: Parameters<T>) {\n const now = Date.now();\n if (now - lastTime >= wait) {\n lastTime = now;\n fn.apply(this, args);\n }\n };\n}\n\n/**\n * 格式化游戏时间\n * \n * @param day - 天数\n * @param time - 小时数\n * @returns 格式化的时间字符串\n * \n * @example\n * ```typescript\n * formatGameTime(5, 14); // \"第 5 天 下午 2:00\"\n * ```\n */\nexport function formatGameTime(day: number, time: number): string {\n const hour = time % TIME_CONSTANTS.HOURS_PER_DAY;\n const period = getTimeOfDay(hour);\n const displayHour = hour === 0 ? 12 : hour > 12 ? hour - 12 : hour;\n return `第 ${day} 天 ${period} ${displayHour}:00`;\n}\n\n/**\n * 计算两个状态之间的差异\n * \n * @param oldState - 旧状态\n * @param newState - 新状态\n * @returns 差异对象\n * \n * @example\n * ```typescript\n * const diff = getStateDiff(oldState, newState);\n * console.log(diff.stats); // { hp: -10, gold: 5 }\n * ```\n */\nexport function getStateDiff<S extends string, I extends string, F extends string, X>(\n oldState: GameState<S, I, F, X>,\n newState: GameState<S, I, F, X>\n): {\n stats: Partial<Record<S, number>>;\n itemsAdded: I[];\n itemsRemoved: I[];\n flagsChanged: Partial<Record<F, boolean>>;\n} {\n const diff = {\n stats: {} as Partial<Record<S, number>>,\n itemsAdded: [] as I[],\n itemsRemoved: [] as I[],\n flagsChanged: {} as Partial<Record<F, boolean>>,\n };\n\n // 计算属性差异\n for (const key in newState.stats) {\n const oldValue = oldState.stats[key] || 0;\n const newValue = newState.stats[key] || 0;\n if (oldValue !== newValue) {\n diff.stats[key] = newValue - oldValue;\n }\n }\n\n // 计算物品差异\n const oldItems = new Set(oldState.inventory);\n const newItems = new Set(newState.inventory);\n\n for (const item of newState.inventory) {\n if (!oldItems.has(item)) {\n diff.itemsAdded.push(item);\n }\n }\n\n for (const item of oldState.inventory) {\n if (!newItems.has(item)) {\n diff.itemsRemoved.push(item);\n }\n }\n\n // 计算标记差异\n for (const key in newState.flags) {\n if (oldState.flags[key] !== newState.flags[key]) {\n diff.flagsChanged[key] = newState.flags[key];\n }\n }\n\n return diff;\n}","// src/engine/systems/events.ts\n\n/**\n * 类型安全的事件监听器回调函数\n * 使用 `unknown` 作为默认类型以强制类型安全\n * @template T - 监听器期望接收的数据类型\n */\ntype Listener<T = unknown> = (data: T) => void;\n\n/**\n * EventBus - 类型安全的发布-订阅事件系统\n *\n * 提供了一个集中式机制,让组件通过事件进行通信而无需紧密耦合。\n * 支持泛型类型参数以实现类型安全的载荷数据。\n *\n * @example\n * ```typescript\n * // 订阅事件并保证类型安全\n * const unsubscribe = eventBus.on<{ count: number }>('update', (data) => {\n * console.log(data.count); // TypeScript 知道 data 有 count 属性\n * });\n *\n * // 发射事件\n * eventBus.emit('update', { count: 42 });\n *\n * // 取消订阅\n * unsubscribe();\n * ```\n */\nexport class EventBus {\n /**\n * 事件监听器的内部存储\n * 将事件名映射到监听器回调函数数组\n * 使用 Listener[](默认为 Listener<unknown>[])以允许同一事件名有不同类型的监听器\n * 类型安全在订阅/发射时强制执行\n */\n private listeners: Map<string, Listener[]> = new Map();\n\n /**\n * 订阅事件\n *\n * @template T - 事件载荷的预期类型\n * @param event - 要订阅的事件名称\n * @param callback - 事件触发时调用的监听器函数\n * @returns 取消订阅的函数\n *\n * @example\n * ```typescript\n * const handler = (data: { count: number }) => console.log(data.count);\n * const unsubscribe = eventBus.on('update', handler);\n * // 稍后取消订阅\n * unsubscribe();\n * ```\n */\n on<T>(event: string, callback: Listener<T>): () => void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, []);\n }\n this.listeners.get(event)!.push(callback as Listener);\n\n // 返回 unsubscribe 函数\n return () => this.off(event, callback);\n }\n\n /**\n * 取消订阅事件\n *\n * @template T - 事件载荷的预期类型\n * @param event - 要取消订阅的事件名称\n * @param callback - 要移除的监听器函数\n *\n * @example\n * ```typescript\n * const handler = (data: number) => console.log(data);\n * eventBus.on('count', handler);\n * eventBus.off('count', handler); // 移除监听器\n * ```\n */\n off<T>(event: string, callback: Listener<T>) {\n const callbacks = this.listeners.get(event);\n if (callbacks) {\n this.listeners.set(\n event,\n callbacks.filter((cb) => cb !== (callback as Listener))\n );\n }\n }\n\n /**\n * 发射事件并携带可选的类型化载荷数据\n * 该事件的所有已注册监听器都将被调用并传入数据\n * 单个监听器中的错误会被捕获并记录,不会影响其他监听器\n *\n * @template T - 事件载荷的类型\n * @param event - 要发射的事件名称\n * @param data - 传递给监听器的可选载荷数据\n *\n * @example\n * ```typescript\n * eventBus.emit<{ userId: string }>('login', { userId: '123' });\n * eventBus.emit('logout'); // 无载荷\n * ```\n */\n emit<T>(event: string, data?: T) {\n const callbacks = this.listeners.get(event);\n if (callbacks) {\n callbacks.forEach((cb) => {\n try {\n cb(data);\n } catch (error) {\n console.error(`Error in event listener for \"${event}\":`, error);\n }\n });\n }\n }\n\n /**\n * 清空所有事件的所有监听器\n * 用于清理或重置事件系统\n *\n * @example\n * ```typescript\n * eventBus.clear(); // 所有监听器被移除\n * ```\n */\n clear() {\n this.listeners.clear();\n }\n}\n\n/**\n * 全局单例 EventBus 实例,用于游戏范围内的事件通信\n * 在整个应用中使用此实例以保持一致的事件处理\n *\n * @example\n * ```typescript\n * import { gameEvents, EngineEvents } from './events';\n *\n * gameEvents.on(EngineEvents.STAT_CHANGE, (data) => {\n * console.log(`属性 ${data.stat} 变化了 ${data.delta}`);\n * });\n * ```\n */\nexport const gameEvents = new EventBus();\n\n/**\n * 预定义的系统事件名称常量,用于常见的游戏引擎事件\n * 使用这些常量而不是字符串字面量,以保证类型安全和一致性\n *\n * 事件载荷类型:\n * - STAT_CHANGE: { stat: string, delta: number, current: number }\n * - ITEM_ADD: { item: string }\n * - ITEM_REMOVE: { item: string }\n * - FLAG_CHANGE: { flag: string, value: boolean }\n * - ACTION_EXECUTED: { actionId: string }\n * - TIME_PASS: { day: number, time: number }\n * - NOTIFICATION: { text: string, type: string, notificationType: string, timestamp: number }\n * - CUSTOM: { id: string } (对应 effects.triggerEvent)\n */\nexport const EngineEvents = {\n /** 当角色属性变化时触发 */\n STAT_CHANGE: \"engine:stat_change\",\n /** 当物品添加到背包时触发 */\n ITEM_ADD: \"engine:item_add\",\n /** 当物品从背包移除时触发 */\n ITEM_REMOVE: \"engine:item_remove\",\n /** 当游戏标志变化时触发 */\n FLAG_CHANGE: \"engine:flag_change\",\n /** 当动作执行时触发 */\n ACTION_EXECUTED: \"engine:action_exec\",\n /** 当游戏时间推进时触发 */\n TIME_PASS: \"engine:time_pass\",\n /** 当需要显示瞬时通知时触发(Toast/Modal,不持久化) */\n NOTIFICATION: \"engine:notification\",\n /** 用于自定义触发事件 */\n CUSTOM: \"engine:custom_trigger\",\n} as const;\n","// src/engine/state/history.ts\nimport type { GameState } from \"../core/types\";\nimport { DEFAULT_CONFIG } from \"../core/constants\";\n\n/**\n * 快照信息接口\n * \n * 包含快照的元数据和实际状态数据\n */\nexport interface SnapshotInfo<\n S extends string,\n I extends string,\n F extends string,\n X = Record<string, unknown>\n> {\n /** 快照的唯一标识符(自动生成的时间戳) */\n id: string;\n /** 快照名称(可选,用于命名快照) */\n name?: string;\n /** 快照创建时间 */\n timestamp: number;\n /** 快照描述(可选) */\n description?: string;\n /** 实际的游戏状态数据 */\n state: GameState<S, I, F, X>;\n}\n\n/**\n * 历史管理器 - 管理游戏状态的历史快照\n * \n * ⚠️ 增强功能:支持命名快照和多级撤销\n * \n * 提供撤销/重做功能,通过保存游戏状态的快照来实现时间旅行。\n * \n * 功能特性:\n * - 多级撤销:支持撤销多个步骤\n * - 命名快照:可以保存和恢复命名的快照\n * - 快照列表:查看所有保存的快照\n * - 自动管理:超过限制时自动清理旧快照\n * \n * @template S - 属性名称的字符串字面量类型\n * @template I - 物品名称的字符串字面量类型\n * @template F - 标志名称的字符串字面量类型\n * @template X - 扩展数据的类型\n * \n * @example\n * ```typescript\n * const history = new HistoryManager<'health' | 'mana', 'sword', 'hasKey'>(20);\n * \n * // 保存匿名快照\n * history.push(currentState);\n * \n * // 保存命名快照\n * history.pushNamed(currentState, 'before_boss_fight', '挑战Boss前');\n * \n * // 撤销到上一个状态\n * const previousState = history.pop();\n * \n * // 恢复到命名快照\n * const savedState = history.restoreNamed('before_boss_fight');\n * \n * // 查看所有快照\n * const snapshots = history.listSnapshots();\n * ```\n */\nexport class HistoryManager<\n S extends string,\n I extends string,\n F extends string,\n X = Record<string, unknown>\n> {\n /** 存储的状态快照数组(按时间顺序) */\n private snapshots: SnapshotInfo<S, I, F, X>[] = [];\n /** 命名快照映射表(name -> snapshot) */\n private namedSnapshots: Map<string, SnapshotInfo<S, I, F, X>> = new Map();\n /** 最大快照数量限制(不包括命名快照) */\n private maxSnapshots: number;\n\n /**\n * 创建历史管理器实例\n * @param maxSnapshots - 最大保存的快照数量,默认使用配置中的值\n */\n constructor(maxSnapshots = DEFAULT_CONFIG.MAX_HISTORY_SNAPSHOTS) {\n this.maxSnapshots = maxSnapshots;\n }\n\n /**\n * 保存当前状态快照(匿名快照)\n * \n * 通过深拷贝保存状态,防止后续修改影响历史记录。\n * 当快照数量超过最大限制时,自动移除最旧的快照。\n * \n * 匿名快照用于常规的撤销操作,会受到数量限制。\n * \n * @param state - 要保存的游戏状态\n * @param description - 快照描述(可选)\n * \n * @example\n * ```typescript\n * history.push(gameState);\n * history.push(gameState, '攻击哥布林前');\n * ```\n */\n push(state: GameState<S, I, F, X>, description?: string) {\n // 深拷贝状态,防止引用污染\n const stateCopy = JSON.parse(JSON.stringify(state)) as GameState<S, I, F, X>;\n \n const snapshot: SnapshotInfo<S, I, F, X> = {\n id: `snapshot_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n timestamp: Date.now(),\n description,\n state: stateCopy\n };\n \n this.snapshots.push(snapshot);\n\n // 限制历史记录长度(只清理匿名快照)\n if (this.snapshots.length > this.maxSnapshots) {\n this.snapshots.shift();\n }\n }\n\n /**\n * 保存命名快照\n * \n * ⚠️ 新功能:保存可以通过名称访问的快照\n * \n * 命名快照不受数量限制,不会被自动清理。\n * 适用于重要的游戏节点,如Boss战前、章节开始等。\n * \n * 如果已存在同名快照,会被覆盖。\n * \n * @param state - 要保存的游戏状态\n * @param name - 快照名称(唯一标识符)\n * @param description - 快照描述(可选)\n * \n * @example\n * ```typescript\n * // 保存Boss战前的状态\n * history.pushNamed(gameState, 'before_boss_fight', '挑战最终Boss前');\n * \n * // 保存章节开始的状态\n * history.pushNamed(gameState, 'chapter_2_start', '第二章开始');\n * ```\n */\n pushNamed(state: GameState<S, I, F, X>, name: string, description?: string) {\n // 深拷贝状态\n const stateCopy = JSON.parse(JSON.stringify(state)) as GameState<S, I, F, X>;\n \n const snapshot: SnapshotInfo<S, I, F, X> = {\n id: `named_${name}_${Date.now()}`,\n name,\n timestamp: Date.now(),\n description,\n state: stateCopy\n };\n \n this.namedSnapshots.set(name, snapshot);\n }\n\n /**\n * 回退到上一个状态(撤销操作)\n * \n * 移除并返回最近的一个匿名快照。\n * 如果没有可用的快照,返回 undefined。\n * \n * 注意:此操作不会影响命名快照。\n * \n * @returns 上一个状态快照,如果历史为空则返回 undefined\n * \n * @example\n * ```typescript\n * const previousState = history.pop();\n * if (previousState) {\n * // 恢复到上一个状态\n * restoreState(previousState);\n * }\n * ```\n */\n pop(): GameState<S, I, F, X> | undefined {\n const snapshot = this.snapshots.pop();\n return snapshot?.state;\n }\n\n /**\n * 恢复到命名快照\n * \n * ⚠️ 新功能:通过名称恢复到指定的快照\n * \n * 返回指定名称的快照状态,但不从历史记录中删除它。\n * 这允许多次恢复到同一个命名快照。\n * \n * @param name - 快照名称\n * @returns 指定名称的状态快照,如果不存在则返回 undefined\n * \n * @example\n * ```typescript\n * // 恢复到Boss战前\n * const savedState = history.restoreNamed('before_boss_fight');\n * if (savedState) {\n * restoreState(savedState);\n * } else {\n * console.log('快照不存在');\n * }\n * ```\n */\n restoreNamed(name: string): GameState<S, I, F, X> | undefined {\n const snapshot = this.namedSnapshots.get(name);\n return snapshot?.state;\n }\n\n /**\n * 删除命名快照\n * \n * 从历史记录中删除指定名称的快照。\n * \n * @param name - 要删除的快照名称\n * @returns 是否成功删除\n * \n * @example\n * ```typescript\n * history.deleteNamed('before_boss_fight');\n * ```\n */\n deleteNamed(name: string): boolean {\n return this.namedSnapshots.delete(name);\n }\n\n /**\n * 检查命名快照是否存在\n * \n * @param name - 快照名称\n * @returns 是否存在指定名称的快照\n * \n * @example\n * ```typescript\n * if (history.hasNamed('before_boss_fight')) {\n * console.log('可以恢复到Boss战前');\n * }\n * ```\n */\n hasNamed(name: string): boolean {\n return this.namedSnapshots.has(name);\n }\n\n /**\n * 列出所有快照\n * \n * ⚠️ 新功能:获取所有快照的信息列表\n * \n * 返回所有快照(包括匿名和命名快照)的元数据。\n * 不包含实际的状态数据,只包含快照信息。\n * \n * @returns 快照信息数组,按时间倒序排列(最新的在前)\n * \n * @example\n * ```typescript\n * const snapshots = history.listSnapshots();\n * snapshots.forEach(snap => {\n * console.log(`${snap.name || '匿名'}: ${snap.description || '无描述'}`);\n * console.log(` 时间: ${new Date(snap.timestamp).toLocaleString()}`);\n * });\n * ```\n */\n listSnapshots(): Array<Omit<SnapshotInfo<S, I, F, X>, 'state'>> {\n const allSnapshots: Array<Omit<SnapshotInfo<S, I, F, X>, 'state'>> = [];\n \n // 添加匿名快照\n this.snapshots.forEach(snap => {\n allSnapshots.push({\n id: snap.id,\n name: snap.name,\n timestamp: snap.timestamp,\n description: snap.description\n });\n });\n \n // 添加命名快照\n this.namedSnapshots.forEach(snap => {\n allSnapshots.push({\n id: snap.id,\n name: snap.name,\n timestamp: snap.timestamp,\n description: snap.description\n });\n });\n \n // 按时间倒序排列\n return allSnapshots.sort((a, b) => b.timestamp - a.timestamp);\n }\n\n /**\n * 列出所有命名快照\n * \n * 只返回命名快照的信息列表。\n * \n * @returns 命名快照信息数组\n * \n * @example\n * ```typescript\n * const namedSnaps = history.listNamedSnapshots();\n * console.log(`共有 ${namedSnaps.length} 个命名快照`);\n * ```\n */\n listNamedSnapshots(): Array<Omit<SnapshotInfo<S, I, F, X>, 'state'>> {\n const result: Array<Omit<SnapshotInfo<S, I, F, X>, 'state'>> = [];\n \n this.namedSnapshots.forEach(snap => {\n result.push({\n id: snap.id,\n name: snap.name,\n timestamp: snap.timestamp,\n description: snap.description\n });\n });\n \n return result.sort((a, b) => b.timestamp - a.timestamp);\n }\n\n /**\n * 查看最近的快照但不移除\n * \n * 返回最新的匿名快照但不从历史记录中删除它。\n * 用于预览上一个状态而不实际执行撤销操作。\n * \n * @returns 最近的状态快照,如果历史为空则返回 undefined\n * \n * @example\n * ```typescript\n * const lastState = history.peek();\n * if (lastState) {\n * console.log('上一个状态:', lastState);\n * }\n * ```\n */\n peek(): GameState<S, I, F, X> | undefined {\n const snapshot = this.snapshots[this.snapshots.length - 1];\n return snapshot?.state;\n }\n\n /**\n * 清空所有历史记录\n * \n * 移除所有保存的快照(包括匿名和命名快照),释放内存。\n * 通常在开始新游戏或重置时使用。\n * \n * @param includeNamed - 是否同时清空命名快照(默认为 false)\n * \n * @example\n * ```typescript\n * // 只清空匿名快照\n * history.clear();\n * \n * // 清空所有快照(包括命名快照)\n * history.clear(true);\n * ```\n */\n clear(includeNamed = false) {\n this.snapshots = [];\n \n if (includeNamed) {\n this.namedSnapshots.clear();\n }\n }\n\n /**\n * 获取当前匿名快照数量\n * \n * @returns 当前保存的匿名快照数量\n * \n * @example\n * ```typescript\n * console.log(`历史记录数量: ${history.size}`);\n * if (history.size > 0) {\n * // 可以执行撤销操作\n * }\n * ```\n */\n get size() {\n return this.snapshots.length;\n }\n\n /**\n * 获取命名快照数量\n * \n * @returns 当前保存的命名快照数量\n * \n * @example\n * ```typescript\n * console.log(`命名快照数量: ${history.namedSize}`);\n * ```\n */\n get namedSize() {\n return this.namedSnapshots.size;\n }\n\n /**\n * 获取总快照数量\n * \n * @returns 所有快照的总数量(匿名 + 命名)\n * \n * @example\n * ```typescript\n * console.log(`总快照数量: ${history.totalSize}`);\n * ```\n */\n get totalSize() {\n return this.snapshots.length + this.namedSnapshots.size;\n }\n}\n","// src/engine/state/store.ts\n// ============================================================================\n// 游戏状态管理 - 使用Zustand实现全局状态管理和持久化\n// ============================================================================\n//\n// 这个文件提供了游戏引擎的状态管理解决方案,基于Zustand库实现。\n// 主要功能:\n// - 全局状态管理:统一管理游戏的所有状态数据\n// - 状态持久化:自动保存到localStorage,支持游戏存档\n// - 类型安全:完全的TypeScript类型支持\n// - 原子操作:提供细粒度的状态更新方法\n//\n// ============================================================================\n\nimport { create } from 'zustand';\nimport { persist, createJSONStorage } from 'zustand/middleware';\nimport type { GameState, LogEntry, NotificationPayload } from '../core/types';\nimport { gameEvents, EngineEvents } from '../systems/events';\nimport { HistoryManager } from './history';\nimport { SystemMessages } from '../core/messages';\nimport { DEFAULT_CONFIG } from '../core/constants';\nimport { generateId } from '../core/utils';\n\n/**\n * 游戏Store操作方法接口 - 定义所有可用的状态操作\n * \n * 这个接口定义了修改游戏状态的所有方法。所有方法都是原子操作,\n * 确保状态更新的一致性和可预测性。\n * \n * @template S - 数值属性键的联合类型\n * @template I - 物品ID的联合类型\n * @template F - 标记键的联合类型\n * \n * @example\n * ```typescript\n * const useStore = createGameEngineStore(initialState);\n * \n * // 在组件中使用\n * function GameComponent() {\n * const updateStat = useStore(state => state.updateStat);\n * const addItem = useStore(state => state.addItem);\n * \n * const handleAction = () => {\n * updateStat('hp', -10); // 减少10点生命值\n * addItem('potion'); // 获得药水\n * };\n * }\n * ```\n */\nexport interface GameStoreActions<\n S extends string,\n I extends string,\n F extends string,\n X = Record<string, unknown>\n> {\n // ========== 数值属性操作 ==========\n \n /**\n * 更新单个数值属性\n * \n * 对指定属性进行增量更新(正数增加,负数减少)。\n * 这是最常用的属性修改方法。\n * \n * @param stat - 要更新的属性键\n * @param delta - 变化量(正数增加,负数减少)\n * \n * @example\n * ```typescript\n * updateStat('hp', 20); // 恢复20点生命值\n * updateStat('gold', -50); // 花费50金币\n * ```\n */\n updateStat: (stat: S, delta: number) => void;\n\n /**\n * 批量更新多个数值属性\n * \n * 一次性更新多个属性,所有更新在同一个状态变更中完成。\n * 适用于需要同时修改多个属性的场景。\n * \n * @param stats - 属性变化的部分记录\n * \n * @example\n * ```typescript\n * setStats({ hp: 10, mp: -5, gold: 100 });\n * // 同时增加10点生命值,减少5点魔法值,增加100金币\n * ```\n */\n setStats: (stats: Partial<Record<S, number>>) => void;\n\n setExtra: (updater: Partial<X> | ((prev: X) => Partial<X>)) => void;\n\n // ========== 物品操作 ==========\n\n /**\n * 添加物品到库存\n * \n * 将指定物品添加到玩家的库存中。\n * 同一物品可以多次添加(如多个药水)。\n * \n * @param item - 要添加的物品ID\n * \n * @example\n * ```typescript\n * addItem('health_potion');\n * addItem('health_potion'); // 可以添加多个相同物品\n * ```\n */\n addItem: (item: I) => void;\n\n /**\n * 从库存移除物品\n * \n * 从玩家库存中移除指定物品的一个实例。\n * 如果有多个相同物品,只移除第一个匹配的。\n * \n * @param item - 要移除的物品ID\n * \n * @example\n * ```typescript\n * removeItem('health_potion'); // 移除一个生命药水\n * ```\n */\n removeItem: (item: I) => void;\n\n // ========== 标记操作 ==========\n\n /**\n * 设置布尔标记\n * \n * 设置或清除游戏标记,用于追踪任务进度、解锁状态等。\n * 标记是游戏逻辑的重要组成部分。\n * \n * @param flag - 标记键\n * @param value - 标记值(true或false)\n * \n * @example\n * ```typescript\n * setFlag('quest_completed', true); // 标记任务完成\n * setFlag('door_locked', false); // 解锁门\n * ```\n */\n setFlag: (flag: F, value: boolean) => void;\n\n // ========== 系统操作 ==========\n\n /**\n * 添加日志条目\n * \n * ⚠️ 重要:日志是持久化的历史记录\n * \n * 向游戏日志中添加新的消息,用于记录游戏事件。\n * 日志会:\n * - 被保存到 localStorage\n * - 在页面刷新后重新加载\n * - 永久显示在日志面板中\n * - 自动限制在最近50条\n * \n * @param text - 日志文本内容\n * @param type - 日志类型(默认为'info')\n * \n * @example\n * ```typescript\n * addLog('你进入了森林', 'info');\n * addLog('击败了哥布林', 'result');\n * addLog('获得了传说武器', 'success');\n * ```\n */\n addLog: (text: string, type?: LogEntry['type']) => void;\n\n /**\n * 显示飘字通知\n * \n * ⚠️ 重要:飘字是瞬时通知,不会被持久化\n * \n * 显示一个轻量级的飘字提示,会自动消失。\n * 飘字通知:\n * - 不会被保存到 localStorage\n * - 不会在页面刷新后重新出现\n * - 仅在当前会话中显示\n * - 适用于轻量级反馈\n * \n * @param text - 通知文本\n * @param type - 通知类型(默认为'info')\n * \n * @example\n * ```typescript\n * showToast('获得 10 金币', 'success');\n * showToast('体力不足', 'warn');\n * ```\n */\n showToast: (text: string, type?: LogEntry['type']) => void;\n\n /**\n * 显示弹窗通知\n * \n * ⚠️ 重要:弹窗是瞬时通知,不会被持久化\n * \n * 显示一个模态弹窗,需要用户确认才能关闭。\n * 弹窗通知:\n * - 不会被保存到 localStorage\n * - 不会在页面刷新后重新出现\n * - 仅在当前会话中显示\n * - 适用于重要信息和阻塞式交互\n * \n * @param text - 通知文本\n * @param type - 通知类型(默认为'info')\n * \n * @example\n * ```typescript\n * showModal('任务完成!获得传说装备', 'success');\n * showModal('警告:此操作不可撤销', 'warn');\n * ```\n */\n showModal: (text: string, type?: LogEntry['type']) => void;\n\n /**\n * 推进游戏时间\n * \n * 增加游戏内的天数,用于时间相关的游戏机制。\n * \n * @param amount - 要增加的天数(默认为1)\n * \n * @example\n * ```typescript\n * advanceTime(); // 推进1天\n * advanceTime(7); // 推进7天\n * ```\n */\n advanceTime: (amount?: number) => void;\n\n /**\n * 传送到指定地点\n * \n * 将玩家传送到指定的地点ID。\n * 这是改变玩家位置的主要方法。\n * \n * @param locationId - 目标地点的ID\n * \n * @example\n * ```typescript\n * teleport('town_square'); // 传送到城镇广场\n * teleport('dungeon_1'); // 传送到地牢\n * ```\n */\n teleport: (locationId: string) => void;\n\n // ========== 存档操作 ==========\n\n /**\n * 重置游戏状态\n * \n * 将游戏状态重置为初始状态,清空所有日志。\n * 用于开始新游戏或重置当前进度。\n * \n * @example\n * ```typescript\n * reset(); // 开始新游戏\n * ```\n */\n reset: () => void;\n\n // ========== 历史记录操作 ==========\n\n /**\n * 保存当前状态快照(匿名快照)\n * \n * 将当前游戏状态保存到历史记录中,用于后续的撤销操作。\n * 快照会自动排除日志数据以节省内存。\n * \n * 匿名快照用于常规的撤销操作,会受到数量限制。\n * \n * @param description - 快照描述(可选)\n * \n * @example\n * ```typescript\n * saveSnapshot(); // 在重要操作前保存快照\n * saveSnapshot('攻击Boss前'); // 带描述的快照\n * ```\n */\n saveSnapshot: (description?: string) => void;\n\n /**\n * 保存命名快照\n * \n * ⚠️ 新功能:保存可以通过名称访问的快照\n * \n * 命名快照不受数量限制,不会被自动清理。\n * 适用于重要的游戏节点,如Boss战前、章节开始等。\n * \n * @param name - 快照名称(唯一标识符)\n * @param description - 快照描述(可选)\n * \n * @example\n * ```typescript\n * saveNamedSnapshot('before_boss_fight', '挑战最终Boss前');\n * saveNamedSnapshot('chapter_2_start', '第二章开始');\n * ```\n */\n saveNamedSnapshot: (name: string, description?: string) => void;\n\n /**\n * 撤销到上一个状态\n * \n * 恢复到上一个保存的匿名快照状态。\n * 如果没有可用的历史记录,操作失败并返回false。\n * \n * @returns 是否成功撤销\n * \n * @example\n * ```typescript\n * if (undo()) {\n * console.log('撤销成功');\n * } else {\n * console.log('没有可撤销的历史记录');\n * }\n * ```\n */\n undo: () => boolean;\n\n /**\n * 恢复到命名快照\n * \n * ⚠️ 新功能:通过名称恢复到指定的快照\n * \n * 返回指定名称的快照状态,但不从历史记录中删除它。\n * 这允许多次恢复到同一个命名快照。\n * \n * @param name - 快照名称\n * @returns 是否成功恢复\n * \n * @example\n * ```typescript\n * if (restoreSnapshot('before_boss_fight')) {\n * console.log('已恢复到Boss战前');\n * } else {\n * console.log('快照不存在');\n * }\n * ```\n */\n restoreSnapshot: (name: string) => boolean;\n\n /**\n * 删除命名快照\n * \n * 从历史记录中删除指定名称的快照。\n * \n * @param name - 要删除的快照名称\n * @returns 是否成功删除\n * \n * @example\n * ```typescript\n * deleteSnapshot('before_boss_fight');\n * ```\n */\n deleteSnapshot: (name: string) => boolean;\n\n /**\n * 列出所有快照\n * \n * ⚠️ 新功能:获取所有快照的信息列表\n * \n * 返回所有快照(包括匿名和命名快照)的元数据。\n * \n * @returns 快照信息数组\n * \n * @example\n * ```typescript\n * const snapshots = listSnapshots();\n * snapshots.forEach(snap => {\n * console.log(`${snap.name || '匿名'}: ${snap.description || '无描述'}`);\n * });\n * ```\n */\n listSnapshots: () => Array<{\n id: string;\n name?: string;\n timestamp: number;\n description?: string;\n }>;\n\n /**\n * 检查命名快照是否存在\n * \n * @param name - 快照名称\n * @returns 是否存在指定名称的快照\n * \n * @example\n * ```typescript\n * if (hasSnapshot('before_boss_fight')) {\n * console.log('可以恢复到Boss战前');\n * }\n * ```\n */\n hasSnapshot: (name: string) => boolean;\n}\n\n/**\n * 游戏Store类型 - 组合数据和操作方法\n * \n * 这是完整的Store类型,包含游戏状态数据和所有操作方法。\n * 使用交叉类型将GameState和GameStoreActions合并。\n * \n * @template S - 数值属性键的联合类型\n * @template I - 物品ID的联合类型\n * @template F - 标记键的联合类型\n * \n * @example\n * ```typescript\n * const useGameStore: GameStore<'hp' | 'mp', 'sword', 'quest_done'>;\n * ```\n */\nexport type GameStore<\n S extends string,\n I extends string,\n F extends string,\n X = Record<string, unknown>\n> = GameState<S, I, F, X> & GameStoreActions<S, I, F, X>;\n\n/**\n * 创建游戏引擎Store的工厂函数\n * \n * 这是创建游戏状态管理Store的核心函数。它使用Zustand创建一个\n * 带有持久化功能的状态管理器,自动将游戏状态保存到localStorage。\n * \n * 工厂模式的优势:\n * - 可以创建多个独立的游戏实例\n * - 每个实例有自己的初始状态和存档名称\n * - 完全的类型安全和泛型支持\n * \n * @template S - 数值属性键的联合类型\n * @template I - 物品ID的联合类型\n * @template F - 标记键的联合类型\n * \n * @param initialState - 游戏的初始状态\n * @param persistName - localStorage中的存档键名(默认:'generic-rpg-save')\n * \n * @returns Zustand store hook,可在React组件中使用\n * \n * @example\n * ```typescript\n * // 定义游戏类型\n * type Stats = 'hp' | 'mp' | 'gold';\n * type Items = 'sword' | 'potion';\n * type Flags = 'quest_completed';\n * \n * // 创建初始状态\n * const initialState: GameState<Stats, Items, Flags> = {\n * stats: { hp: 100, mp: 50, gold: 0 },\n * inventory: [],\n * flags: { quest_completed: false },\n * world: { currentLocationId: 'start', day: 1, time: 0 },\n * logs: []\n * };\n * \n * // 创建store\n * export const useGameStore = createGameEngineStore(\n * initialState,\n * 'my-rpg-save'\n * );\n * \n * // 在组件中使用\n * function GameUI() {\n * const hp = useGameStore(state => state.stats.hp);\n * const updateStat = useGameStore(state => state.updateStat);\n * \n * return <button onClick={() => updateStat('hp', -10)}>受伤</button>;\n * }\n * ```\n */\nexport const createGameEngineStore = <\n S extends string,\n I extends string,\n F extends string,\n X = Record<string, unknown>\n>(\n initialState: GameState<S, I, F, X>,\n persistName: string = 'generic-rpg-save'\n) => {\n // 创建历史管理器实例(闭包内,每个store独立)\n const history = new HistoryManager<S, I, F, X>(\n DEFAULT_CONFIG.MAX_HISTORY_SNAPSHOTS\n );\n\n return create<GameStore<S, I, F, X>>()(\n persist(\n (set, get) => ({\n // 展开初始状态,包含所有游戏数据\n ...initialState,\n\n // ========== 数值属性操作实现 ==========\n\n /**\n * 实现:更新单个数值属性\n * 使用增量更新,保持其他属性不变\n * 发射 STAT_CHANGE 事件通知监听器\n */\n updateStat: (stat, delta) =>\n set((state) => {\n const currentVal = state.stats[stat] || 0;\n const newVal = currentVal + delta;\n\n // 发射事件\n gameEvents.emit(EngineEvents.STAT_CHANGE, {\n stat,\n delta,\n current: newVal,\n });\n\n return {\n stats: {\n ...state.stats,\n [stat]: newVal,\n },\n };\n }),\n\n /**\n * 实现:批量更新多个数值属性\n * 遍历所有变化并应用到新的stats对象\n */\n setStats: (changes) =>\n set((state) => {\n const newStats = { ...state.stats };\n Object.entries(changes).forEach(([k, v]) => {\n newStats[k as S] = (newStats[k as S] || 0) + (v as number);\n });\n return { stats: newStats };\n }),\n\n // ========== 扩展数据操作实现 ==========\n\n /**\n * 实现:更新扩展数据\n * \n * 支持两种更新方式:\n * 1. 直接传入部分更新对象\n * 2. 传入更新函数,接收当前值返回部分更新\n * \n * @example\n * ```typescript\n * // 方式1:直接更新\n * setExtra({ reputation: 100 });\n * \n * // 方式2:基于当前值更新\n * setExtra((prev) => ({ reputation: prev.reputation + 10 }));\n * ```\n */\n setExtra: (updater) =>\n set((state) => {\n const update =\n typeof updater === 'function' ? updater(state.extra) : updater;\n return {\n extra: { ...state.extra, ...update } as X,\n };\n }),\n\n // ========== 物品操作实现 ==========\n\n /**\n * 实现:添加物品到库存\n * 创建新数组,保持不可变性\n * 发射 ITEM_ADD 事件通知监听器\n */\n addItem: (item) =>\n set((state) => {\n // 发射事件\n gameEvents.emit(EngineEvents.ITEM_ADD, { item });\n\n return {\n inventory: [...state.inventory, item],\n };\n }),\n\n /**\n * 实现:从库存移除物品\n * 使用filter移除第一个匹配的物品\n * 发射 ITEM_REMOVE 事件通知监听器\n */\n removeItem: (item) =>\n set((state) => {\n // 发射事件\n gameEvents.emit(EngineEvents.ITEM_REMOVE, { item });\n\n return {\n inventory: state.inventory.filter((i) => i !== item),\n };\n }),\n\n // ========== 标记操作实现 ==========\n\n /**\n * 实现:设置布尔标记\n * 创建新的flags对象,更新指定标记\n * 发射 FLAG_CHANGE 事件通知监听器\n */\n setFlag: (flag, value) =>\n set((state) => {\n // 发射事件\n gameEvents.emit(EngineEvents.FLAG_CHANGE, { flag, value });\n\n return {\n flags: { ...state.flags, [flag]: value },\n };\n }),\n\n // ========== 系统操作实现 ==========\n\n /**\n * 实现:添加日志条目\n * \n * 创建新日志并添加到日志数组开头。\n * 使用 MAX_LOG_ENTRIES 限制日志数量,防止内存泄漏。\n * 日志ID使用时间戳+随机数确保唯一性。\n * \n * ⚠️ 注意:日志会被持久化到 localStorage\n */\n addLog: (text, type = 'info') =>\n set((state) => {\n const newLog: LogEntry = {\n id: generateId(),\n text,\n type,\n timestamp: state.world.day,\n };\n\n return { \n logs: [newLog, ...state.logs].slice(0, DEFAULT_CONFIG.MAX_LOG_ENTRIES) \n };\n }),\n\n /**\n * 实现:显示飘字通知\n * \n * 发射 NOTIFICATION 事件,UI 层监听后显示飘字效果。\n * \n * ⚠️ 注意:通知不会被持久化,仅在当前会话中显示\n */\n showToast: (text, type = 'info') => {\n const notification: NotificationPayload = {\n text,\n type,\n notificationType: 'toast',\n timestamp: Date.now(),\n };\n gameEvents.emit(EngineEvents.NOTIFICATION, notification);\n },\n\n /**\n * 实现:显示弹窗通知\n * \n * 发射 NOTIFICATION 事件,UI 层监听后显示模态弹窗。\n * \n * ⚠️ 注意:通知不会被持久化,仅在当前会话中显示\n */\n showModal: (text, type = 'info') => {\n const notification: NotificationPayload = {\n text,\n type,\n notificationType: 'modal',\n timestamp: Date.now(),\n };\n gameEvents.emit(EngineEvents.NOTIFICATION, notification);\n },\n\n /**\n * 实现:推进游戏时间\n * 增加world.day的值\n */\n advanceTime: (amount = 1) =>\n set((state) => ({\n world: { ...state.world, day: state.world.day + amount },\n })),\n\n /**\n * 实现:传送到指定地点\n * 更新world.currentLocationId\n */\n teleport: (locationId) =>\n set((state) => ({\n world: { ...state.world, currentLocationId: locationId },\n })),\n\n // ========== 存档操作实现 ==========\n\n /**\n * 实现:重置游戏状态\n * 恢复到初始状态,清空日志\n */\n reset: () => set({ ...initialState, logs: [] }),\n\n // ========== 历史记录操作实现 ==========\n\n /**\n * 实现:保存当前状态快照(匿名快照)\n * \n * 保存除日志外的所有状态数据到历史管理器。\n * 日志通常不需要回退,因此被排除以节省内存。\n */\n saveSnapshot: (description?: string) => {\n const currentState = get();\n // 保存完整状态(HistoryManager 会通过 JSON 序列化自动过滤掉方法)\n history.push(currentState, description);\n },\n\n /**\n * 实现:保存命名快照\n * \n * 保存可以通过名称访问的快照。\n * 命名快照不受数量限制,适用于重要的游戏节点。\n */\n saveNamedSnapshot: (name: string, description?: string) => {\n const currentState = get();\n history.pushNamed(currentState, name, description);\n },\n\n /**\n * 实现:撤销到上一个状态\n * \n * 从历史管理器中恢复上一个匿名快照。\n * 恢复时保留当前的日志,并添加系统提示。\n * \n * @returns 是否成功撤销\n */\n undo: () => {\n const prev = history.pop();\n if (prev) {\n set({\n stats: prev.stats,\n inventory: prev.inventory,\n flags: prev.flags,\n world: prev.world,\n extra: prev.extra,\n // logs 保留当前的,不回退日志\n });\n get().addLog(SystemMessages.UNDO_SUCCESS, 'info');\n return true;\n }\n return false;\n },\n\n /**\n * 实现:恢复到命名快照\n * \n * 通过名称恢复到指定的快照。\n * 快照不会被删除,可以多次恢复。\n * \n * @returns 是否成功恢复\n */\n restoreSnapshot: (name: string) => {\n const saved = history.restoreNamed(name);\n if (saved) {\n set({\n stats: saved.stats,\n inventory: saved.inventory,\n flags: saved.flags,\n world: saved.world,\n extra: saved.extra,\n // logs 保留当前的,不回退日志\n });\n get().addLog(`已恢复到快照:${name}`, 'info');\n return true;\n }\n return false;\n },\n\n /**\n * 实现:删除命名快照\n * \n * 从历史记录中删除指定名称的快照。\n * \n * @returns 是否成功删除\n */\n deleteSnapshot: (name: string) => {\n return history.deleteNamed(name);\n },\n\n /**\n * 实现:列出所有快照\n * \n * 返回所有快照的元数据列表。\n */\n listSnapshots: () => {\n return history.listSnapshots();\n },\n\n /**\n * 实现:检查命名快照是否存在\n * \n * @returns 是否存在指定名称的快照\n */\n hasSnapshot: (name: string) => {\n return history.hasNamed(name);\n },\n }),\n {\n // 持久化配置\n name: persistName, // localStorage中的键名\n storage: createJSONStorage(() => localStorage), // 使用localStorage存储\n\n /**\n * 部分持久化 - 只保存数据字段,排除方法\n * \n * 这很重要,因为方法不能被序列化到JSON。\n * 我们只持久化游戏状态数据,方法会在store重新创建时自动添加。\n */\n partialize: (state) =>\n ({\n stats: state.stats,\n inventory: state.inventory,\n flags: state.flags,\n world: state.world,\n logs: state.logs,\n extra: state.extra,\n }) as GameState<S, I, F, X>,\n }\n )\n );\n};","// src/engine/systems/query.ts\n// ============================================================================\n// 查询系统 - 游戏状态查询和条件检查\n// ============================================================================\n//\n// 这个文件提供了游戏状态的查询和验证功能。\n// 主要用于:\n// - 检查动作执行的前置条件(需求检查)\n// - 验证玩家是否有足够资源支付成本\n// - 提供统一的条件判断逻辑\n//\n// 设计模式:\n// - 使用静态方法类,无需实例化\n// - 纯函数设计,不修改状态\n// - 支持复杂的条件组合(AND逻辑)\n//\n// ============================================================================\n\nimport type { GameState, RequirementDef, RequirementCheckResult } from \"../core/types\";\n\n/**\n * 查询系统类 - 提供游戏状态查询和条件检查功能\n * \n * 这是一个工具类,所有方法都是静态的,不需要实例化。\n * 主要用于在执行游戏动作前验证各种条件。\n * \n * 核心功能:\n * - checkRequirements: 检查复杂的需求条件\n * - canAfford: 检查是否有足够资源支付成本\n * \n * @example\n * ```typescript\n * // 检查是否满足开门的需求\n * const canOpenDoor = QuerySystem.checkRequirements(gameState, {\n * hasItems: ['key'],\n * stats: { strength: { min: 5 } }\n * });\n * \n * // 检查是否能支付购买成本\n * const canBuy = QuerySystem.canAfford(gameState, { gold: 100 });\n * ```\n */\nexport class QuerySystem {\n /**\n * 检查是否满足所有需求条件(带失败原因)\n * \n * ⚠️ 增强版本:返回详细的检查结果,包括失败原因\n * \n * 这是核心的条件检查方法,用于验证玩家是否满足执行某个动作的所有前置条件。\n * 内置字段使用 AND 逻辑组合,复杂逻辑使用 custom 函数实现。\n * \n * @template S - 数值属性键的联合类型\n * @template I - 物品ID的联合类型\n * @template F - 标记键的联合类型\n * \n * @param state - 当前游戏状态\n * @param reqs - 需求定义(可选,未定义时返回通过)\n * \n * @returns RequirementCheckResult 包含是否通过和失败原因\n * \n * @example\n * ```typescript\n * // 检查需求并获取失败原因\n * const result = QuerySystem.checkRequirementsWithReason(state, {\n * hasItems: ['key'],\n * stats: { strength: { min: 5 } }\n * });\n * \n * if (!result.passed) {\n * console.log(result.reason); // 显示失败原因\n * }\n * ```\n */\n static checkRequirementsWithReason<\n S extends string,\n I extends string,\n F extends string,\n X = Record<string, unknown>\n >(\n state: GameState<S, I, F, X>,\n reqs?: RequirementDef<S, I, F, X>\n ): RequirementCheckResult {\n // 如果没有定义需求,默认通过\n if (!reqs) return { passed: true };\n\n // ========== 1. 标记检查 ==========\n\n /**\n * 检查必须为true的标记\n * 使用every确保所有指定的标记都为true(AND逻辑)\n */\n if (reqs.hasFlags && reqs.hasFlags.length > 0) {\n const missingFlags = reqs.hasFlags.filter((f) => !state.flags[f]);\n if (missingFlags.length > 0) {\n return {\n passed: false,\n reason: `需要满足条件:${missingFlags.join('、')}`\n };\n }\n }\n\n /**\n * 检查必须为false的标记\n * 使用some检查是否有任何标记为true(OR逻辑)\n */\n if (reqs.noFlags && reqs.noFlags.length > 0) {\n const conflictFlags = reqs.noFlags.filter((f) => state.flags[f]);\n if (conflictFlags.length > 0) {\n return {\n passed: false,\n reason: `不能满足条件:${conflictFlags.join('、')}`\n };\n }\n }\n\n // ========== 2. 物品检查 ==========\n\n /**\n * 检查必须拥有的物品\n * 使用every确保库存中包含所有指定的物品(AND逻辑)\n */\n if (reqs.hasItems && reqs.hasItems.length > 0) {\n const missingItems = reqs.hasItems.filter((i) => !state.inventory.includes(i));\n if (missingItems.length > 0) {\n return {\n passed: false,\n reason: `缺少必需物品:${missingItems.join('、')}`\n };\n }\n }\n\n /**\n * 检查不能拥有的物品\n * 使用some检查库存中是否包含任何禁止的物品(OR逻辑)\n */\n if (reqs.noItems && reqs.noItems.length > 0) {\n const conflictItems = reqs.noItems.filter((i) => state.inventory.includes(i));\n if (conflictItems.length > 0) {\n return {\n passed: false,\n reason: `不能携带物品:${conflictItems.join('、')}`\n };\n }\n }\n\n // ========== 3. 数值属性检查 ==========\n\n /**\n * 检查数值属性是否满足条件\n * 支持两种模式:\n * - 数字模式:表示最小值要求\n * - 对象模式:支持min和max范围检查\n */\n if (reqs.stats) {\n for (const [key, condition] of Object.entries(reqs.stats)) {\n // 获取当前属性值,如果不存在则默认为0\n const currentVal = state.stats[key as S] || 0;\n const cond = condition as number | { min?: number; max?: number };\n\n if (typeof cond === \"number\") {\n /**\n * 简写模式:数字表示最小值\n * 例如:{ hp: 10 } 表示hp至少为10\n */\n if (currentVal < cond) {\n return {\n passed: false,\n reason: `${key} 不足(需要 ${cond},当前 ${currentVal})`\n };\n }\n } else {\n /**\n * 对象模式:支持区间检查\n * 例如:{ hp: { min: 10, max: 50 } } 表示hp在10-50之间\n */\n if (cond.min !== undefined && currentVal < cond.min) {\n return {\n passed: false,\n reason: `${key} 过低(需要至少 ${cond.min},当前 ${currentVal})`\n };\n }\n if (cond.max !== undefined && currentVal > cond.max) {\n return {\n passed: false,\n reason: `${key} 过高(需要最多 ${cond.max},当前 ${currentVal})`\n };\n }\n }\n }\n }\n\n // ========== 4. 自定义函数检查 ==========\n\n /**\n * 执行自定义验证函数\n * 支持返回 boolean 或 RequirementCheckResult\n */\n if (reqs.custom) {\n const customResult = reqs.custom(state);\n \n // 如果返回的是对象(RequirementCheckResult)\n if (typeof customResult === 'object') {\n if (!customResult.passed) {\n return customResult;\n }\n } \n // 如果返回的是 boolean\n else if (!customResult) {\n return {\n passed: false,\n reason: '不满足自定义条件'\n };\n }\n }\n\n // 所有检查都通过\n return { passed: true };\n }\n\n /**\n * 检查是否满足所有需求条件(简化版本)\n * \n * 这是向后兼容的简化版本,只返回 boolean。\n * 如果需要失败原因,请使用 checkRequirementsWithReason。\n * \n * @template S - 数值属性键的联合类型\n * @template I - 物品ID的联合类型\n * @template F - 标记键的联合类型\n * \n * @param state - 当前游戏状态\n * @param reqs - 需求定义(可选,未定义时返回true)\n * \n * @returns true表示满足所有条件,false表示至少有一个条件不满足\n * \n * @example\n * ```typescript\n * // 简单需求\n * const simple = QuerySystem.checkRequirements(state, {\n * hasItems: ['key'],\n * stats: { strength: { min: 5 } }\n * });\n * \n * // 复杂逻辑使用 custom\n * const complex = QuerySystem.checkRequirements(state, {\n * custom: (state) => {\n * // (有钥匙 AND 力量>=5) OR 有万能钥匙\n * const hasKeyAndStrength = \n * state.inventory.includes('key') && state.stats.strength >= 5;\n * const hasMasterKey = state.inventory.includes('master_key');\n * return hasKeyAndStrength || hasMasterKey;\n * }\n * });\n * ```\n */\n static checkRequirements<\n S extends string,\n I extends string,\n F extends string,\n X = Record<string, unknown>\n >(\n state: GameState<S, I, F, X>,\n reqs?: RequirementDef<S, I, F, X>\n ): boolean {\n return this.checkRequirementsWithReason(state, reqs).passed;\n }\n\n /**\n * 检查是否有足够资源支付成本\n * \n * 验证玩家的数值属性是否足够支付指定的成本。\n * 这是一个简化的检查,只验证数值是否足够,不实际扣除。\n * \n * 与checkRequirements的区别:\n * - canAfford只检查数值属性\n * - checkRequirements检查完整的需求(标记、物品、数值、自定义)\n * - canAfford用于成本检查,checkRequirements用于前置条件检查\n * \n * @template S - 数值属性键的联合类型\n * @template I - 物品ID的联合类型\n * @template F - 标记键的联合类型\n * \n * @param state - 当前游戏状态\n * @param costs - 成本定义(可选,未定义时返回true)\n * \n * @returns true表示有足够资源,false表示资源不足\n * \n * @example\n * ```typescript\n * // 检查是否有足够金币购买物品\n * const canBuy = QuerySystem.canAfford(state, { gold: 100 });\n * \n * // 检查是否有足够资源施放技能\n * const canCast = QuerySystem.canAfford(state, {\n * mp: 30,\n * stamina: 10\n * });\n * \n * // 在动作执行前使用\n * if (QuerySystem.canAfford(state, action.costs)) {\n * // 执行动作并扣除成本\n * executeAction(action);\n * } else {\n * addLog('资源不足!', 'error');\n * }\n * ```\n */\n static canAfford<\n S extends string,\n I extends string,\n F extends string,\n X = Record<string, unknown>\n >(\n state: GameState<S, I, F, X>,\n costs?: Partial<Record<S, number>>\n ): boolean {\n // 如果没有定义成本,默认通过\n if (!costs) return true;\n\n /**\n * 遍历所有成本项,检查每个属性是否足够\n * 只要有一个属性不足,就返回false\n */\n for (const [key, cost] of Object.entries(costs)) {\n const currentVal = state.stats[key as S] || 0;\n if (currentVal < (cost as number)) return false;\n }\n\n // 所有资源都足够\n return true;\n }\n}\n","// src/engine/systems/flow.ts\n// ============================================================================\n// 流程系统 - 游戏动作执行引擎\n// ============================================================================\n//\n// 这个文件负责执行游戏动作的完整流程,包括:\n// - 条件验证:检查是否满足执行条件\n// - 成本扣除:扣除执行动作所需的资源\n// - 效果应用:应用动作产生的所有效果\n// - 日志记录:记录动作执行结果\n//\n// 设计原则:\n// - 原子性:动作要么完全执行,要么完全不执行\n// - 安全性:执行前进行最终检查,防止非法操作\n// - 可追溯:所有操作都记录日志\n//\n// ============================================================================\n\nimport type { GameStore } from \"../state/store\";\nimport type { ActionDef, EffectDef } from \"../core/types\";\nimport { QuerySystem } from \"./query\";\nimport { SystemMessages } from '../core/messages';\nimport { gameEvents, EngineEvents } from './events';\n\n/**\n * 流程系统类 - 负责游戏动作的执行流程\n *\n * 这是一个工具类,所有方法都是静态的,不需要实例化。\n * 主要功能是协调动作执行的各个步骤,确保游戏逻辑的正确性。\n *\n * 执行流程:\n * 1. 验证条件:检查需求和成本\n * 2. 扣除成本:消耗资源\n * 3. 应用效果:修改游戏状态\n * 4. 记录日志:反馈给玩家\n *\n * @example\n * ```typescript\n * // 在游戏中执行动作\n * const success = FlowSystem.executeAction(\n * useGameStore.getState(),\n * attackAction\n * );\n *\n * if (success) {\n * console.log('动作执行成功');\n * }\n * ```\n */\nexport class FlowSystem {\n /**\n * 执行一个游戏动作\n *\n * 这是核心方法,负责完整的动作执行流程。\n * 执行过程是原子性的:要么全部成功,要么全部失败。\n *\n * 执行步骤:\n * 1. 最终验证:检查需求和成本(防止UI滞后)\n * 2. 扣除成本:消耗资源(如体力、金币)\n * 3. 应用效果:修改状态(属性、物品、标记等)\n * 4. 记录日志:生成反馈信息\n *\n * @template S - 数值属性键的联合类型\n * @template I - 物品ID的联合类型\n * @template F - 标记键的联合类型\n *\n * @param store - Zustand Store 实例(包含状态和方法)\n * @param action - 要执行的动作定义\n *\n * @returns true表示执行成功,false表示执行失败\n *\n * @example\n * ```typescript\n * // 定义一个攻击动作\n * const attackAction: ActionDef<Stats, Items, Flags> = {\n * id: 'attack_goblin',\n * label: '攻击哥布林',\n * costs: { stamina: 10 },\n * requirements: { hasItems: ['weapon'] },\n * effects: {\n * statsChange: { exp: 5 },\n * flagsSet: { goblin_defeated: true }\n * },\n * resultText: '你击败了哥布林!'\n * };\n *\n * // 执行动作\n * const store = useGameStore.getState();\n * const success = FlowSystem.executeAction(store, attackAction);\n * ```\n */\n static executeAction<\n S extends string,\n I extends string,\n F extends string,\n X = Record<string, unknown>\n >(\n store: GameStore<S, I, F, X>,\n action: ActionDef<S, I, F, X>\n ): boolean {\n // Store 本身包含 State 数据(Zustand 的设计)\n const state = store;\n\n // ========== 步骤0:保存快照(可选) ==========\n\n /**\n * 在动作执行前保存状态快照\n * \n * 这允许玩家在动作执行后撤销操作。\n * 可以根据游戏设计决定是否启用此功能。\n * \n * 建议:对于重要或不可逆的动作启用快照\n */\n // store.saveSnapshot(); // 取消注释以启用自动快照\n\n // ========== 步骤1:最终验证 ==========\n\n /**\n * 检查需求条件\n *\n * 即使UI已经检查过,这里也要再次检查,因为:\n * - UI状态可能滞后\n * - 多个动作可能同时触发\n * - 防止作弊或bug\n * \n * 使用增强版本的检查方法,可以获取失败原因并显示给玩家\n */\n const reqCheck = QuerySystem.checkRequirementsWithReason(state, action.requirements);\n if (!reqCheck.passed) {\n console.warn(`条件不满足: ${action.id}`, reqCheck.reason);\n \n // 如果有失败原因,显示给玩家\n if (reqCheck.reason) {\n store.addLog(reqCheck.reason, \"warn\");\n }\n \n return false;\n }\n\n /**\n * 检查成本\n *\n * 确保玩家有足够的资源支付成本\n */\n if (!QuerySystem.canAfford(state, action.costs)) {\n store.addLog(SystemMessages.NOT_ENOUGH_RESOURCES, \"warn\");\n return false;\n }\n\n // ========== 步骤2:扣除成本 ==========\n\n /**\n * 扣除执行动作所需的成本\n *\n * 将成本转换为负数,然后应用到状态上。\n * 例如:{ stamina: 10 } 转换为 { stamina: -10 }\n */\n if (action.costs) {\n const costsToDeduct: Partial<Record<S, number>> = {};\n for (const [key, val] of Object.entries(action.costs)) {\n costsToDeduct[key as S] = -(val as number);\n }\n store.setStats(costsToDeduct);\n }\n\n // ========== 步骤3:应用效果 ==========\n \n /**\n * 效果执行顺序说明:\n * \n * 【阶段 1:静态效果】\n * 1. statsChange - 数值属性变更\n * 2. itemsAdd - 添加物品\n * 3. itemsRemove - 移除物品\n * 4. flagsSet - 设置标记\n * 5. flagsBatch - 批量标记操作\n * 6. teleport - 传送\n * 7. timeAdvance + onTimeAdvance - 时间推进及其钩子\n * 8. triggerEvent - 触发自定义事件\n * \n * 【阶段 2:条件效果】\n * 9. conditionalEffects - 根据阶段1后的状态决定额外效果\n * \n * 【阶段 3:自定义效果】\n * 10. custom - 修改 extra 扩展数据\n * 11. customFull - 修改完整游戏状态\n * \n * 【阶段 4:后置钩子】(在 effects 之外)\n * 12. afterEffects - 基于最终状态执行副作用\n * \n * 【阶段 5:结果文本】(在 effects 之外)\n * 13. resultText - 生成反馈文本\n */\n\n const { effects } = action;\n if (effects) {\n /**\n * 辅助函数:应用单个效果定义\n * \n * 将效果应用逻辑提取为函数,以便复用于静态效果和条件效果。\n * 此函数按固定顺序执行各种效果类型。\n */\n const applyEffectDef = (effectDef: Omit<EffectDef<S, I, F, X>, 'conditionalEffects' | 'custom' | 'customFull'>) => {\n // ===== 效果类型 1:数值属性变更 =====\n if (effectDef.statsChange) {\n const statsToChange = typeof effectDef.statsChange === 'function'\n ? effectDef.statsChange(store)\n : effectDef.statsChange;\n \n store.setStats(statsToChange);\n }\n\n // ===== 效果类型 2:添加物品 =====\n effectDef.itemsAdd?.forEach((i: I) => store.addItem(i));\n \n // ===== 效果类型 3:移除物品 =====\n effectDef.itemsRemove?.forEach((i: I) => store.removeItem(i));\n\n // ===== 效果类型 4:设置标记 =====\n if (effectDef.flagsSet) {\n const flagsToSet = typeof effectDef.flagsSet === 'function'\n ? effectDef.flagsSet(store)\n : effectDef.flagsSet;\n \n Object.entries(flagsToSet).forEach(([f, v]) => {\n store.setFlag(f as F, v as boolean);\n });\n }\n\n // ===== 效果类型 5:批量标记操作 =====\n if (effectDef.flagsBatch) {\n const batchOp = typeof effectDef.flagsBatch === 'function'\n ? effectDef.flagsBatch(store)\n : effectDef.flagsBatch;\n \n if (batchOp) {\n // 步骤1:清除标记\n if (batchOp.clear) {\n const allFlags = Object.keys(store.flags) as F[];\n let flagsToClear: string[] = [];\n\n if (batchOp.clear instanceof RegExp) {\n // 正则表达式匹配\n flagsToClear = allFlags.filter(f => batchOp.clear instanceof RegExp && batchOp.clear.test(f));\n } else if (typeof batchOp.clear === 'string') {\n // 前缀字符串匹配\n flagsToClear = allFlags.filter(f => f.startsWith(batchOp.clear as string));\n } else if (Array.isArray(batchOp.clear)) {\n // 标记列表\n flagsToClear = batchOp.clear;\n }\n\n // 清除匹配的标记(设置为 false)\n flagsToClear.forEach(f => {\n store.setFlag(f as F, false);\n });\n }\n\n // 步骤2:设置标记\n if (batchOp.set) {\n Object.entries(batchOp.set).forEach(([f, v]) => {\n store.setFlag(f as F, v as boolean);\n });\n }\n }\n }\n\n // ===== 效果类型 6:传送 =====\n if (effectDef.teleport) {\n store.teleport(effectDef.teleport);\n }\n\n // ===== 效果类型 7:时间推进 + onTimeAdvance 钩子 =====\n if (effectDef.timeAdvance !== undefined) {\n const daysToAdvance = typeof effectDef.timeAdvance === 'function'\n ? effectDef.timeAdvance(store)\n : effectDef.timeAdvance;\n \n if (daysToAdvance > 0) {\n const previousDay = store.world.day;\n \n // 推进时间\n store.advanceTime(daysToAdvance);\n \n // 如果定义了 onTimeAdvance 钩子,为每一天调用一次\n if (effectDef.onTimeAdvance) {\n const actions = {\n updateStat: store.updateStat,\n setStats: store.setStats,\n setExtra: store.setExtra,\n addItem: store.addItem,\n removeItem: store.removeItem,\n setFlag: store.setFlag,\n addLog: store.addLog,\n showToast: store.showToast,\n showModal: store.showModal,\n advanceTime: store.advanceTime,\n teleport: store.teleport,\n reset: store.reset,\n saveSnapshot: store.saveSnapshot,\n undo: store.undo,\n };\n \n // 为每一天分别调用钩子\n for (let i = 1; i <= daysToAdvance; i++) {\n const currentDay = previousDay + i;\n const dayBefore = currentDay - 1;\n \n // 获取当前最新状态\n const currentState = store;\n \n effectDef.onTimeAdvance(currentDay, dayBefore, currentState, actions);\n }\n }\n }\n }\n\n // ===== 效果类型 8:触发自定义事件 =====\n if (effectDef.triggerEvent) {\n gameEvents.emit(EngineEvents.CUSTOM, { id: effectDef.triggerEvent });\n }\n };\n\n /**\n * 【阶段 1:静态效果】\n * \n * 首先应用所有静态定义的效果。\n * 这些效果按固定顺序执行(见 applyEffectDef 函数内部)。\n */\n applyEffectDef(effects);\n\n /**\n * 【阶段 2:条件效果】\n * \n * 根据当前游戏状态(包含阶段1的修改)动态决定要应用的效果。\n * conditionalEffects 返回的效果会按阶段1的顺序再次执行。\n * \n * 使用场景:\n * - 基于修改后的属性值决定额外效果\n * - 实现\"如果...则...\"的逻辑\n * - 根据不同条件产生不同效果\n */\n if (effects.conditionalEffects) {\n // 获取当前最新状态(包含静态效果的修改)\n const currentState = store;\n \n // 执行条件函数,获取要应用的效果\n const conditionalEffect = effects.conditionalEffects(currentState);\n \n // 如果返回了效果定义,应用它\n if (conditionalEffect) {\n applyEffectDef(conditionalEffect);\n }\n }\n\n /**\n * 【阶段 3.1:自定义效果 - 修改 extra 字段】\n * \n * 在所有静态效果和条件效果之后执行。\n * 用于修改扩展数据(extra 字段)。\n * \n * 使用场景:\n * - 更新游戏特定的自定义数据\n * - 记录时间戳、计数器等元数据\n * - 存储复杂的状态信息\n */\n if (effects.custom) {\n const draft = { ...state.extra };\n const result = effects.custom(draft, state);\n if (result) {\n // 如果返回了部分更新,合并到 draft\n store.setExtra({ ...draft, ...result });\n } else {\n // 如果没有返回值,使用修改后的 draft\n store.setExtra(draft);\n }\n }\n\n /**\n * 【阶段 3.2:完整自定义效果 - 修改完整游戏状态】\n * \n * ⚠️ 最强大的效果类型,在所有其他效果之后执行\n * \n * 允许修改完整的游戏状态(stats、inventory、flags、world、extra)。\n * 可以覆盖或调整之前所有效果的结果。\n * \n * 使用场景:\n * - 实现复杂的连锁反应\n * - 基于最终状态进行调整\n * - 需要同时修改多个状态字段的复杂逻辑\n * - 实现\"护盾吸收伤害\"等覆盖机制\n * \n * 注意:\n * - 这是最后的修改机会(除了 afterEffects)\n * - 可以访问原始状态和当前状态\n * - 批量应用所有修改以提高性能\n */\n if (effects.customFull) {\n // 保存原始状态(只读,供函数参考)\n const originalState = { ...state };\n \n // 获取当前最新状态(包含之前效果的修改)\n const currentState = store;\n \n // 创建可修改的状态副本(不包含 logs 和方法)\n const draft = {\n stats: { ...currentState.stats },\n inventory: [...currentState.inventory],\n flags: { ...currentState.flags },\n world: { ...currentState.world },\n extra: { ...currentState.extra },\n };\n \n // 执行自定义函数,允许修改 draft\n effects.customFull(draft, originalState);\n \n // 批量应用所有修改\n // 使用 setStats 而不是直接赋值,以保持增量更新的语义\n const statsChanges: Partial<Record<S, number>> = {};\n for (const key in draft.stats) {\n const oldVal = currentState.stats[key as S] || 0;\n const newVal = draft.stats[key as S];\n const delta = newVal - oldVal;\n if (delta !== 0) {\n statsChanges[key as S] = delta;\n }\n }\n if (Object.keys(statsChanges).length > 0) {\n store.setStats(statsChanges);\n }\n \n // 应用物品变更\n // 计算需要添加和移除的物品\n const currentItems = new Set(currentState.inventory);\n const newItems = new Set(draft.inventory);\n \n // 移除不在新清单中的物品\n currentState.inventory.forEach(item => {\n if (!newItems.has(item)) {\n store.removeItem(item);\n }\n });\n \n // 添加新清单中的新物品\n draft.inventory.forEach(item => {\n if (!currentItems.has(item)) {\n store.addItem(item);\n }\n });\n \n // 应用标记变更\n for (const key in draft.flags) {\n const oldVal = currentState.flags[key as F];\n const newVal = draft.flags[key as F];\n if (oldVal !== newVal) {\n store.setFlag(key as F, newVal);\n }\n }\n \n // 应用世界状态变更\n if (draft.world.currentLocationId !== currentState.world.currentLocationId) {\n store.teleport(draft.world.currentLocationId);\n }\n if (draft.world.day !== currentState.world.day) {\n const dayDelta = draft.world.day - currentState.world.day;\n store.advanceTime(dayDelta);\n }\n // 注意:time 字段目前没有专门的更新方法,如果需要可以扩展\n \n // 应用扩展数据变更\n store.setExtra(draft.extra);\n }\n }\n\n // ========== 步骤4:执行后置效果钩子 ==========\n\n /**\n * 【阶段 4:后置钩子】\n * \n * 在所有效果(阶段1-3)执行完成后调用。\n * 这是最后一个可以修改状态的机会。\n * \n * 与 customFull 的区别:\n * - customFull: 在 effects 内部,用于修改效果本身\n * - afterEffects: 在 effects 外部,用于基于最终状态执行副作用\n * \n * 使用场景:\n * - 检查成就解锁\n * - 触发连锁事件\n * - 清理过期数据\n * - 自动保存快照\n * - 发送通知\n * \n * 职责分离:\n * - afterEffects: 执行副作用(修改状态、触发事件等)\n * - resultText: 生成反馈文本(纯函数,不修改状态)\n */\n if (action.afterEffects) {\n // 保存原始状态用于对比\n const originalState = { ...state };\n \n // 获取当前最新状态(包含所有效果的修改)\n const currentState = store;\n \n // 提取操作方法(不包含状态数据)\n const actions = {\n updateStat: store.updateStat,\n setStats: store.setStats,\n setExtra: store.setExtra,\n addItem: store.addItem,\n removeItem: store.removeItem,\n setFlag: store.setFlag,\n addLog: store.addLog,\n showToast: store.showToast,\n showModal: store.showModal,\n advanceTime: store.advanceTime,\n teleport: store.teleport,\n reset: store.reset,\n saveSnapshot: store.saveSnapshot,\n undo: store.undo,\n };\n \n // 执行后置效果钩子\n action.afterEffects(currentState, originalState, actions);\n }\n\n // ========== 步骤5:生成结果文本并记录日志 ==========\n\n /**\n * 【阶段 5:结果文本】\n * \n * 在所有效果和钩子执行完成后生成反馈文本。\n * \n * resultText 可以是静态字符串或动态函数。\n * 动态函数可以访问最终状态(包含所有修改)和原始状态,\n * 因此可以比较前后变化,生成准确的反馈信息。\n * \n * ⚠️ 增强功能:函数现在接收两个参数\n * - 第一个参数:最终状态(所有效果执行后)\n * - 第二个参数:原始状态(动作执行前)\n * \n * 这允许你比较状态变化,而无需通过 afterEffects + extra 传递信息。\n * \n * 职责分离:\n * - resultText 只负责生成文本,不应修改状态\n * - 所有状态修改应在 effects 或 afterEffects 中完成\n * \n * 使用场景:\n * - 根据最终状态生成个性化反馈\n * - 显示属性变化的具体数值\n * - 比较前后状态,检测是否触发了特殊效果\n * - 提示玩家达成的成就或触发的事件\n */\n const finalState = store; // 获取最终状态\n const resultText =\n typeof action.resultText === \"function\"\n ? action.resultText(finalState, state) // 传递最终状态和原始状态\n : action.resultText;\n\n store.addLog(resultText, \"result\");\n\n // ========== 步骤6:发射动作完成事件 ==========\n\n /**\n * 发射 ACTION_EXECUTED 事件\n * \n * 通知系统动作已成功执行。\n * UI 层或其他系统可以监听此事件来:\n * - 播放音效\n * - 显示动画\n * - 更新成就系统\n * - 触发连锁反应\n * \n * @example\n * ```typescript\n * // 在 UI 组件中监听动作执行\n * gameEvents.on(EngineEvents.ACTION_EXECUTED, (data) => {\n * console.log(`动作 ${data.actionId} 已执行`);\n * playSound('action_success');\n * });\n * ```\n */\n gameEvents.emit(EngineEvents.ACTION_EXECUTED, { actionId: action.id });\n\n // 执行成功\n return true;\n }\n}\n","import React from \"react\";\n\ninterface LayoutProps {\n sidebar?: React.ReactNode; // 左侧:状态、背包\n main?: React.ReactNode; // 中间:地点图、动作列表\n logs?: React.ReactNode; // 右侧:日志流\n className?: string;\n}\n\nexport const Layout: React.FC<LayoutProps> = ({\n sidebar,\n main,\n logs,\n className = \"\",\n}) => {\n return (\n <div\n className={`min-h-screen bg-[#0c0c0e] text-[#a1a1aa] font-sans flex overflow-hidden ${className}`}\n >\n {/* 1. 左侧侧边栏 (固定宽度) */}\n {sidebar && (\n <aside className=\"w-72 bg-[#141417] border-r border-[#27272a] flex flex-col shrink-0 z-10\">\n {sidebar}\n </aside>\n )}\n\n {/* 2. 中间主舞台 (自适应宽度) */}\n <main className=\"flex-1 flex flex-col min-w-0 relative\">{main}</main>\n\n {/* 3. 右侧日志栏 (固定宽度) */}\n {logs && (\n <aside className=\"w-80 bg-[#0c0c0e] border-l border-[#27272a] flex flex-col shrink-0 z-10\">\n {logs}\n </aside>\n )}\n </div>\n );\n};\n\n// 同时也导出一个用于 Main 区域内部的容器组件,方便统一内边距\nexport const MainContent: React.FC<{\n header?: React.ReactNode;\n children: React.ReactNode;\n}> = ({ header, children }) => (\n <>\n {/* 顶部标题区域 */}\n {header && (\n <div className=\"p-10 border-b border-[#27272a] bg-[#0c0c0e] shrink-0\">\n <div className=\"max-w-3xl mx-auto\">{header}</div>\n </div>\n )}\n\n {/* 内容滚动区域 */}\n <div className=\"flex-1 overflow-y-auto p-10 bg-[#101012]\">\n <div className=\"max-w-3xl mx-auto\">{children}</div>\n </div>\n </>\n);\n","import React, { useEffect, useRef } from \"react\";\nimport type { LogEntry } from \"../core/types\";\n\ninterface LogStreamProps {\n logs: LogEntry[];\n className?: string;\n title?: string;\n}\n\nexport const LogStream: React.FC<LogStreamProps> = ({\n logs,\n className = \"\",\n title = \"Chronicle\",\n}) => {\n const bottomRef = useRef<HTMLDivElement>(null);\n\n // 自动滚动到底部\n useEffect(() => {\n bottomRef.current?.scrollIntoView({ behavior: \"smooth\" });\n }, [logs]);\n\n // 根据类型返回样式\n const getLogStyle = (type: LogEntry[\"type\"]) => {\n switch (type) {\n case \"warn\":\n return \"text-amber-500 border-l-2 border-amber-500/50 pl-2\";\n case \"error\":\n return \"text-red-500 border-l-2 border-red-500/50 pl-2 font-bold\";\n case \"success\":\n return \"text-green-500 border-l-2 border-green-500/50 pl-2\";\n case \"result\":\n return \"text-stone-300 border-l-2 border-stone-600/50 pl-2\"; // 行动结果\n case \"info\":\n default:\n return \"text-stone-500 border-l-2 border-transparent pl-2\"; // 普通叙事\n }\n };\n\n return (\n <div\n className={`flex flex-col bg-[#0c0c0e] border-l border-[#27272a] h-full ${className}`}\n >\n {/* 标题栏 */}\n <div className=\"p-4 border-b border-[#27272a] bg-[#141417] shrink-0\">\n <h3 className=\"text-xs font-bold text-stone-500 uppercase tracking-wider\">\n {title}\n </h3>\n </div>\n\n {/* 滚动区域 */}\n <div className=\"flex-1 overflow-y-auto p-6 space-y-4 font-serif scroll-smooth\">\n {logs.length === 0 && (\n <div className=\"text-stone-700 text-sm italic text-center mt-10\">\n 暂无记录...\n </div>\n )}\n\n {logs.map((log) => (\n <div\n key={log.id}\n className={`text-sm leading-relaxed transition-all duration-500 animate-in fade-in slide-in-from-bottom-2 ${getLogStyle(\n log.type\n )}`}\n >\n {/* 时间戳 (可选,根据需求显示) */}\n {/* <span className=\"text-[10px] opacity-50 mr-2 font-mono\">[{log.timestamp}]</span> */}\n {log.text}\n </div>\n ))}\n\n {/* 锚点 */}\n <div ref={bottomRef} />\n </div>\n </div>\n );\n};\n","// src/engine/ui/OverlaySystem.tsx\n/**\n * Overlay System - 覆盖层系统\n * \n * ⚠️ 重要架构说明:\n * \n * 这个系统处理所有瞬时的 UI 通知,与持久化的日志系统完全分离:\n * \n * 1. Logs (日志) - LogStream 组件\n * - 持久化到 localStorage\n * - 页面刷新后重新加载\n * - 永久显示在日志面板\n * - 用于回顾历史\n * \n * 2. Toasts (飘字) - 本组件处理\n * - 瞬时通知,不持久化\n * - 自动消失(3秒)\n * - 不阻塞用户操作\n * - 用于轻量级反馈\n * \n * 3. Modals (弹窗) - 本组件处理\n * - 瞬时通知,不持久化\n * - 需要用户确认\n * - 阻塞式交互\n * - 用于重要信息\n */\n\nimport { useEffect, useState } from 'react';\nimport { gameEvents, EngineEvents } from '../systems/events';\nimport type { NotificationPayload } from '../core/types';\nimport { DEFAULT_CONFIG } from '../core/constants';\n\n/**\n * Toast 通知项\n */\ninterface ToastItem extends NotificationPayload {\n id: string;\n}\n\n/**\n * Overlay System 组件\n * \n * 监听 NOTIFICATION 事件并显示对应的 UI\n */\nexport function OverlaySystem() {\n const [toasts, setToasts] = useState<ToastItem[]>([]);\n const [modal, setModal] = useState<NotificationPayload | null>(null);\n\n useEffect(() => {\n // 监听通知事件\n const unsubscribe = gameEvents.on<NotificationPayload>(\n EngineEvents.NOTIFICATION,\n (payload) => {\n switch (payload.notificationType) {\n case 'toast': {\n // 添加飘字\n const toastId = `toast-${payload.timestamp}-${Math.random()}`;\n const toast: ToastItem = { ...payload, id: toastId };\n \n setToasts((prev) => [...prev, toast]);\n \n // 自动移除(使用配置的时长)\n setTimeout(() => {\n setToasts((prev) => prev.filter((t) => t.id !== toastId));\n }, DEFAULT_CONFIG.TOAST_DURATION);\n break;\n }\n\n case 'modal': {\n // 显示弹窗\n setModal(payload);\n break;\n }\n }\n }\n );\n\n return unsubscribe;\n }, []);\n\n return (\n <>\n {/* 飘字容器 */}\n <div className=\"toast-container\">\n {toasts.map((toast) => (\n <div\n key={toast.id}\n className={`toast toast-${toast.type}`}\n role=\"alert\"\n >\n {toast.text}\n </div>\n ))}\n </div>\n\n {/* 模态弹窗 */}\n {modal && (\n <div\n className=\"modal-overlay\"\n onClick={() => setModal(null)}\n role=\"dialog\"\n aria-modal=\"true\"\n >\n <div\n className=\"modal-content\"\n onClick={(e) => e.stopPropagation()}\n >\n <div className={`modal-message modal-${modal.type}`}>\n {modal.text}\n </div>\n <button\n className=\"modal-button\"\n onClick={() => setModal(null)}\n autoFocus\n >\n 确定\n </button>\n </div>\n </div>\n )}\n\n {/* 样式 */}\n <style>{`\n /* 飘字容器 */\n .toast-container {\n position: fixed;\n top: 20px;\n right: 20px;\n z-index: 1000;\n display: flex;\n flex-direction: column;\n gap: 10px;\n pointer-events: none;\n }\n\n /* 飘字样式 */\n .toast {\n padding: 12px 20px;\n border-radius: 8px;\n background: white;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n animation: slideIn 0.3s ease-out, fadeOut 0.3s ease-in 2.7s;\n pointer-events: auto;\n max-width: 300px;\n word-wrap: break-word;\n }\n\n .toast-info {\n border-left: 4px solid #3b82f6;\n color: #1e40af;\n }\n\n .toast-success {\n border-left: 4px solid #10b981;\n color: #065f46;\n }\n\n .toast-warn {\n border-left: 4px solid #f59e0b;\n color: #92400e;\n }\n\n .toast-error {\n border-left: 4px solid #ef4444;\n color: #991b1b;\n }\n\n .toast-result {\n border-left: 4px solid #6366f1;\n color: #3730a3;\n }\n\n @keyframes slideIn {\n from {\n transform: translateX(100%);\n opacity: 0;\n }\n to {\n transform: translateX(0);\n opacity: 1;\n }\n }\n\n @keyframes fadeOut {\n from {\n opacity: 1;\n }\n to {\n opacity: 0;\n }\n }\n\n /* 模态弹窗 */\n .modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 2000;\n animation: fadeIn 0.2s ease-out;\n }\n\n .modal-content {\n background: white;\n padding: 24px;\n border-radius: 12px;\n max-width: 400px;\n min-width: 300px;\n box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1);\n animation: scaleIn 0.2s ease-out;\n }\n\n .modal-message {\n margin-bottom: 20px;\n font-size: 16px;\n line-height: 1.5;\n color: #1f2937;\n }\n\n .modal-success {\n color: #10b981;\n }\n\n .modal-warn {\n color: #f59e0b;\n }\n\n .modal-error {\n color: #ef4444;\n }\n\n .modal-button {\n width: 100%;\n padding: 10px 20px;\n background: #3b82f6;\n color: white;\n border: none;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: background 0.2s;\n }\n\n .modal-button:hover {\n background: #2563eb;\n }\n\n .modal-button:active {\n background: #1d4ed8;\n }\n\n @keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n }\n\n @keyframes scaleIn {\n from {\n transform: scale(0.9);\n opacity: 0;\n }\n to {\n transform: scale(1);\n opacity: 1;\n }\n }\n `}</style>\n </>\n );\n}\n"]}