steamsheep-ts-game-engine 1.0.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/README.md +1087 -0
- package/dist/core/index.d.mts +328 -0
- package/dist/core/index.d.ts +328 -0
- package/dist/core/index.js +220 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/index.mjs +195 -0
- package/dist/core/index.mjs.map +1 -0
- package/dist/index.d.mts +10 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +1196 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1160 -0
- package/dist/index.mjs.map +1 -0
- package/dist/state/index.d.mts +110 -0
- package/dist/state/index.d.ts +110 -0
- package/dist/state/index.js +479 -0
- package/dist/state/index.js.map +1 -0
- package/dist/state/index.mjs +476 -0
- package/dist/state/index.mjs.map +1 -0
- package/dist/store-BP5bpjRr.d.ts +327 -0
- package/dist/store-BeEHel1o.d.mts +327 -0
- package/dist/systems/index.d.mts +318 -0
- package/dist/systems/index.d.ts +318 -0
- package/dist/systems/index.js +347 -0
- package/dist/systems/index.js.map +1 -0
- package/dist/systems/index.mjs +341 -0
- package/dist/systems/index.mjs.map +1 -0
- package/dist/types-CZueoTHl.d.mts +464 -0
- package/dist/types-CZueoTHl.d.ts +464 -0
- package/dist/ui/index.d.mts +56 -0
- package/dist/ui/index.d.ts +56 -0
- package/dist/ui/index.js +412 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/index.mjs +407 -0
- package/dist/ui/index.mjs.map +1 -0
- package/package.json +76 -0
|
@@ -0,0 +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":["get","jsxs","jsx","useEffect","Fragment"],"mappings":"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","file":"index.mjs","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 * \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 * history.push(currentState);\n * const previousState = history.pop(); // 撤销到上一个状态\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: GameState<S, I, F, X>[] = [];\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 * @param state - 要保存的游戏状态\n * \n * @example\n * ```typescript\n * history.push(gameState);\n * ```\n */\n push(state: GameState<S, I, F, X>) {\n // 深拷贝状态,防止引用污染\n const snapshot = JSON.parse(JSON.stringify(state));\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 * 如果没有可用的快照,返回 undefined\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 return this.snapshots.pop();\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 return this.snapshots[this.snapshots.length - 1];\n }\n\n /**\n * 清空所有历史记录\n * \n * 移除所有保存的快照,释放内存\n * 通常在开始新游戏或重置时使用\n * \n * @example\n * ```typescript\n * history.clear(); // 清空所有历史\n * ```\n */\n clear() {\n this.snapshots = [];\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","// 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 * @example\n * ```typescript\n * saveSnapshot(); // 在重要操作前保存快照\n * ```\n */\n saveSnapshot: () => 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 * 游戏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: () => {\n const currentState = get();\n // 保存完整状态(HistoryManager 会通过 JSON 序列化自动过滤掉方法)\n history.push(currentState);\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 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 } 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 * 内置字段使用 AND 逻辑组合,复杂逻辑使用 custom 函数实现。\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 // 如果没有定义需求,默认通过\n if (!reqs) return true;\n\n // ========== 1. 标记检查 ==========\n\n /**\n * 检查必须为true的标记\n * 使用every确保所有指定的标记都为true(AND逻辑)\n */\n if (reqs.hasFlags && reqs.hasFlags.length > 0) {\n if (!reqs.hasFlags.every((f) => state.flags[f])) return false;\n }\n\n /**\n * 检查必须为false的标记\n * 使用some检查是否有任何标记为true(OR逻辑)\n */\n if (reqs.noFlags && reqs.noFlags.length > 0) {\n if (reqs.noFlags.some((f) => state.flags[f])) return false;\n }\n\n // ========== 2. 物品检查 ==========\n\n /**\n * 检查必须拥有的物品\n * 使用every确保库存中包含所有指定的物品(AND逻辑)\n */\n if (reqs.hasItems && reqs.hasItems.length > 0) {\n if (!reqs.hasItems.every((i) => state.inventory.includes(i)))\n return false;\n }\n\n /**\n * 检查不能拥有的物品\n * 使用some检查库存中是否包含任何禁止的物品(OR逻辑)\n */\n if (reqs.noItems && reqs.noItems.length > 0) {\n if (reqs.noItems.some((i) => state.inventory.includes(i))) return false;\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) return false;\n } else {\n /**\n * 对象模式:支持区间检查\n * 例如:{ hp: { min: 10, max: 50 } } 表示hp在10-50之间\n */\n if (cond.min !== undefined && currentVal < cond.min) return false;\n if (cond.max !== undefined && currentVal > cond.max) return false;\n }\n }\n }\n\n // ========== 4. 自定义函数检查 ==========\n\n /**\n * 执行自定义验证函数\n * 用于处理内置检查无法覆盖的复杂逻辑\n */\n if (reqs.custom && !reqs.custom(state)) return false;\n\n // 所有检查都通过\n return true;\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 } 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 if (!QuerySystem.checkRequirements(state, action.requirements)) {\n console.warn(`条件不满足: ${action.id}`);\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 const { effects } = action;\n if (effects) {\n /**\n * 3.1 应用数值属性变更\n *\n * 修改玩家的属性值(如生命值、经验值等)\n */\n if (effects.statsChange) {\n store.setStats(effects.statsChange);\n }\n\n /**\n * 3.2 应用物品变更\n *\n * 添加或移除物品\n */\n effects.itemsAdd?.forEach((i) => store.addItem(i));\n effects.itemsRemove?.forEach((i) => store.removeItem(i));\n\n /**\n * 3.3 应用标记变更\n *\n * 设置游戏标记(如任务进度、解锁状态等)\n */\n if (effects.flagsSet) {\n Object.entries(effects.flagsSet).forEach(([f, v]) => {\n store.setFlag(f as F, v as boolean);\n });\n }\n\n /**\n * 3.4 应用传送效果\n *\n * 如果动作包含传送,将玩家传送到指定地点\n */\n if (effects.teleport) {\n store.teleport(effects.teleport);\n }\n\n /**\n * 3.4.5 触发自定义事件\n * \n * 如果动作定义了 triggerEvent,发射自定义事件。\n * 这允许游戏逻辑监听特定事件并做出响应。\n * \n * 例如:触发剧情事件、播放音效、显示特效等\n */\n if (effects.triggerEvent) {\n gameEvents.emit(EngineEvents.CUSTOM, { id: effects.triggerEvent });\n }\n\n /**\n * 3.5 应用自定义效果(修改 extra 字段)\n *\n * 如果动作包含自定义效果函数,执行它来修改扩展数据。\n * 函数可以直接修改 draft 或返回部分更新。\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 // ========== 步骤4:记录日志 ==========\n\n /**\n * 生成结果文本并记录到日志\n *\n * resultText 可以是静态字符串或动态函数。\n * 动态函数可以根据当前状态生成个性化的反馈。\n */\n const resultText =\n typeof action.resultText === \"function\"\n ? action.resultText(state)\n : action.resultText;\n\n store.addLog(resultText, \"result\");\n\n // ========== 步骤5:发射动作完成事件 ==========\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"]}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
export { a as GameStore, G as GameStoreActions, c as createGameEngineStore } from '../store-BeEHel1o.mjs';
|
|
2
|
+
import { G as GameState } from '../types-CZueoTHl.mjs';
|
|
3
|
+
import 'zustand/middleware';
|
|
4
|
+
import 'zustand';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 历史管理器 - 管理游戏状态的历史快照
|
|
8
|
+
*
|
|
9
|
+
* 提供撤销/重做功能,通过保存游戏状态的快照来实现时间旅行
|
|
10
|
+
*
|
|
11
|
+
* @template S - 属性名称的字符串字面量类型
|
|
12
|
+
* @template I - 物品名称的字符串字面量类型
|
|
13
|
+
* @template F - 标志名称的字符串字面量类型
|
|
14
|
+
* @template X - 扩展数据的类型
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* const history = new HistoryManager<'health' | 'mana', 'sword', 'hasKey'>(20);
|
|
19
|
+
* history.push(currentState);
|
|
20
|
+
* const previousState = history.pop(); // 撤销到上一个状态
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
declare class HistoryManager<S extends string, I extends string, F extends string, X = Record<string, unknown>> {
|
|
24
|
+
/** 存储的状态快照数组 */
|
|
25
|
+
private snapshots;
|
|
26
|
+
/** 最大快照数量限制 */
|
|
27
|
+
private maxSnapshots;
|
|
28
|
+
/**
|
|
29
|
+
* 创建历史管理器实例
|
|
30
|
+
* @param maxSnapshots - 最大保存的快照数量,默认使用配置中的值
|
|
31
|
+
*/
|
|
32
|
+
constructor(maxSnapshots?: 20);
|
|
33
|
+
/**
|
|
34
|
+
* 保存当前状态快照
|
|
35
|
+
*
|
|
36
|
+
* 通过深拷贝保存状态,防止后续修改影响历史记录
|
|
37
|
+
* 当快照数量超过最大限制时,自动移除最旧的快照
|
|
38
|
+
*
|
|
39
|
+
* @param state - 要保存的游戏状态
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```typescript
|
|
43
|
+
* history.push(gameState);
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
push(state: GameState<S, I, F, X>): void;
|
|
47
|
+
/**
|
|
48
|
+
* 回退到上一个状态(撤销操作)
|
|
49
|
+
*
|
|
50
|
+
* 移除并返回最近的一个快照
|
|
51
|
+
* 如果没有可用的快照,返回 undefined
|
|
52
|
+
*
|
|
53
|
+
* @returns 上一个状态快照,如果历史为空则返回 undefined
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* const previousState = history.pop();
|
|
58
|
+
* if (previousState) {
|
|
59
|
+
* // 恢复到上一个状态
|
|
60
|
+
* restoreState(previousState);
|
|
61
|
+
* }
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
pop(): GameState<S, I, F, X> | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* 查看最近的快照但不移除
|
|
67
|
+
*
|
|
68
|
+
* 返回最新的快照但不从历史记录中删除它
|
|
69
|
+
* 用于预览上一个状态而不实际执行撤销操作
|
|
70
|
+
*
|
|
71
|
+
* @returns 最近的状态快照,如果历史为空则返回 undefined
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```typescript
|
|
75
|
+
* const lastState = history.peek();
|
|
76
|
+
* if (lastState) {
|
|
77
|
+
* console.log('上一个状态:', lastState);
|
|
78
|
+
* }
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
peek(): GameState<S, I, F, X> | undefined;
|
|
82
|
+
/**
|
|
83
|
+
* 清空所有历史记录
|
|
84
|
+
*
|
|
85
|
+
* 移除所有保存的快照,释放内存
|
|
86
|
+
* 通常在开始新游戏或重置时使用
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```typescript
|
|
90
|
+
* history.clear(); // 清空所有历史
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
clear(): void;
|
|
94
|
+
/**
|
|
95
|
+
* 获取当前历史记录数量
|
|
96
|
+
*
|
|
97
|
+
* @returns 当前保存的快照数量
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```typescript
|
|
101
|
+
* console.log(`历史记录数量: ${history.size}`);
|
|
102
|
+
* if (history.size > 0) {
|
|
103
|
+
* // 可以执行撤销操作
|
|
104
|
+
* }
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
get size(): number;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export { HistoryManager };
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
export { a as GameStore, G as GameStoreActions, c as createGameEngineStore } from '../store-BP5bpjRr.js';
|
|
2
|
+
import { G as GameState } from '../types-CZueoTHl.js';
|
|
3
|
+
import 'zustand/middleware';
|
|
4
|
+
import 'zustand';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 历史管理器 - 管理游戏状态的历史快照
|
|
8
|
+
*
|
|
9
|
+
* 提供撤销/重做功能,通过保存游戏状态的快照来实现时间旅行
|
|
10
|
+
*
|
|
11
|
+
* @template S - 属性名称的字符串字面量类型
|
|
12
|
+
* @template I - 物品名称的字符串字面量类型
|
|
13
|
+
* @template F - 标志名称的字符串字面量类型
|
|
14
|
+
* @template X - 扩展数据的类型
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* const history = new HistoryManager<'health' | 'mana', 'sword', 'hasKey'>(20);
|
|
19
|
+
* history.push(currentState);
|
|
20
|
+
* const previousState = history.pop(); // 撤销到上一个状态
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
declare class HistoryManager<S extends string, I extends string, F extends string, X = Record<string, unknown>> {
|
|
24
|
+
/** 存储的状态快照数组 */
|
|
25
|
+
private snapshots;
|
|
26
|
+
/** 最大快照数量限制 */
|
|
27
|
+
private maxSnapshots;
|
|
28
|
+
/**
|
|
29
|
+
* 创建历史管理器实例
|
|
30
|
+
* @param maxSnapshots - 最大保存的快照数量,默认使用配置中的值
|
|
31
|
+
*/
|
|
32
|
+
constructor(maxSnapshots?: 20);
|
|
33
|
+
/**
|
|
34
|
+
* 保存当前状态快照
|
|
35
|
+
*
|
|
36
|
+
* 通过深拷贝保存状态,防止后续修改影响历史记录
|
|
37
|
+
* 当快照数量超过最大限制时,自动移除最旧的快照
|
|
38
|
+
*
|
|
39
|
+
* @param state - 要保存的游戏状态
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```typescript
|
|
43
|
+
* history.push(gameState);
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
push(state: GameState<S, I, F, X>): void;
|
|
47
|
+
/**
|
|
48
|
+
* 回退到上一个状态(撤销操作)
|
|
49
|
+
*
|
|
50
|
+
* 移除并返回最近的一个快照
|
|
51
|
+
* 如果没有可用的快照,返回 undefined
|
|
52
|
+
*
|
|
53
|
+
* @returns 上一个状态快照,如果历史为空则返回 undefined
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* const previousState = history.pop();
|
|
58
|
+
* if (previousState) {
|
|
59
|
+
* // 恢复到上一个状态
|
|
60
|
+
* restoreState(previousState);
|
|
61
|
+
* }
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
pop(): GameState<S, I, F, X> | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* 查看最近的快照但不移除
|
|
67
|
+
*
|
|
68
|
+
* 返回最新的快照但不从历史记录中删除它
|
|
69
|
+
* 用于预览上一个状态而不实际执行撤销操作
|
|
70
|
+
*
|
|
71
|
+
* @returns 最近的状态快照,如果历史为空则返回 undefined
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```typescript
|
|
75
|
+
* const lastState = history.peek();
|
|
76
|
+
* if (lastState) {
|
|
77
|
+
* console.log('上一个状态:', lastState);
|
|
78
|
+
* }
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
peek(): GameState<S, I, F, X> | undefined;
|
|
82
|
+
/**
|
|
83
|
+
* 清空所有历史记录
|
|
84
|
+
*
|
|
85
|
+
* 移除所有保存的快照,释放内存
|
|
86
|
+
* 通常在开始新游戏或重置时使用
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```typescript
|
|
90
|
+
* history.clear(); // 清空所有历史
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
clear(): void;
|
|
94
|
+
/**
|
|
95
|
+
* 获取当前历史记录数量
|
|
96
|
+
*
|
|
97
|
+
* @returns 当前保存的快照数量
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```typescript
|
|
101
|
+
* console.log(`历史记录数量: ${history.size}`);
|
|
102
|
+
* if (history.size > 0) {
|
|
103
|
+
* // 可以执行撤销操作
|
|
104
|
+
* }
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
get size(): number;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export { HistoryManager };
|