steamsheep-ts-game-engine 2.0.0 → 3.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.
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { L as LogEntry } from '../types-BLjkeE3R.mjs';
2
+ import { L as LogEntry } from '../types-C3Q7UPWy.mjs';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
4
 
5
5
  interface LayoutProps {
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { L as LogEntry } from '../types-BLjkeE3R.js';
2
+ import { L as LogEntry } from '../types-C3Q7UPWy.js';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
4
 
5
5
  interface LayoutProps {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "steamsheep-ts-game-engine",
3
- "version": "2.0.0",
3
+ "version": "3.0.0",
4
4
  "description": "通用游戏引擎框架 - 基于 TypeScript 和 Zustand 构建的文字冒险/RPG 游戏引擎",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -1,536 +0,0 @@
1
- /**
2
- * 游戏状态接口 - 存储游戏的完整状态
3
- *
4
- * 这是整个游戏引擎的核心数据结构,包含了游戏运行所需的所有状态信息。
5
- * 使用泛型使其适用于任何类型的游戏,无需修改引擎代码。
6
- *
7
- * @template S - 数值属性键的联合类型
8
- * @template I - 物品ID的联合类型
9
- * @template F - 标记键的联合类型
10
- *
11
- * @example
12
- * ```typescript
13
- * type RPGState = GameState<
14
- * 'hp' | 'mp' | 'gold',
15
- * 'sword' | 'potion',
16
- * 'dragon_defeated' | 'has_key'
17
- * >;
18
- * ```
19
- */
20
- interface GameState<S extends string, I extends string, F extends string, X = Record<string, unknown>> {
21
- /**
22
- * 数值属性记录 (如生命值、金币、经验等)
23
- * 使用Record类型确保所有定义的属性都有对应的数值
24
- */
25
- stats: Record<S, number>;
26
- /**
27
- * 物品清单 - 存储玩家拥有的物品ID
28
- * 使用数组允许同一物品多次出现(如多个药水)
29
- */
30
- inventory: I[];
31
- /**
32
- * 布尔标记 - 用于追踪游戏状态、任务进度等
33
- * 常用于记录剧情进度、解锁状态、触发条件等
34
- */
35
- flags: Record<F, boolean>;
36
- /**
37
- * 世界状态 - 包含位置、时间等世界级信息
38
- */
39
- world: WorldState;
40
- /**
41
- * 日志条目数组 - 记录游戏事件
42
- * 用于显示游戏历史和玩家操作反馈
43
- */
44
- logs: LogEntry[];
45
- /**
46
- * 扩展数据 - 存储游戏特定的额外状态
47
- *
48
- * 这是一个灵活的字段,允许不同游戏存储自定义数据。
49
- * 使用泛型 X 来定义具体的扩展数据类型。
50
- *
51
- * @example
52
- * ```typescript
53
- * // 定义扩展数据类型
54
- * interface MyGameExtra {
55
- * reputation: number;
56
- * guild: string;
57
- * achievements: string[];
58
- * }
59
- *
60
- * // 使用扩展数据
61
- * type MyGameState = GameState<Stats, Items, Flags, MyGameExtra>;
62
- * ```
63
- */
64
- extra: X;
65
- }
66
- /**
67
- * 世界状态接口 - 追踪游戏世界的时间和位置信息
68
- */
69
- interface WorldState {
70
- /** 当前所在位置的唯一标识符 */
71
- currentLocationId: string;
72
- /** 游戏内的天数 - 用于追踪游戏进度 */
73
- day: number;
74
- /** 当前时间 - 可以是0-24的小时制或自定义时间单位 */
75
- time: number;
76
- }
77
- /**
78
- * 日志条目接口 - 记录游戏中发生的事件
79
- *
80
- * ⚠️ 重要:LogEntry 是持久化的历史记录,会被保存到 localStorage
81
- *
82
- * 用于构建游戏日志系统,记录玩家操作、系统事件等信息。
83
- * 每条日志都有类型标记,便于UI层进行样式区分和过滤。
84
- *
85
- * 日志会:
86
- * - 被保存到 localStorage
87
- * - 在页面刷新后重新加载
88
- * - 永久显示在日志面板中
89
- * - 可以被玩家回顾
90
- */
91
- interface LogEntry {
92
- /**
93
- * 唯一标识符 - 用于React列表渲染的key
94
- * 建议使用UUID或时间戳+随机数生成
95
- */
96
- id: string;
97
- /**
98
- * 日志文本内容 - 显示给玩家的消息
99
- * 可以包含动态内容,如玩家名称、物品名称等
100
- */
101
- text: string;
102
- /**
103
- * 日志类型 - 用于UI显示不同样式和图标
104
- * - info: 普通信息(灰色)
105
- * - warn: 警告信息(黄色)
106
- * - error: 错误信息(红色)
107
- * - success: 成功信息(绿色)
108
- * - result: 动作执行结果(黑色)
109
- */
110
- type: "info" | "warn" | "error" | "success" | "result";
111
- /**
112
- * 日志产生的时间戳 - 游戏内时间或真实时间戳
113
- * 用于排序和显示时间信息
114
- */
115
- timestamp: number;
116
- }
117
- /**
118
- * 通知类型枚举
119
- *
120
- * ⚠️ 重要:通知是瞬时的 UI 状态,不会被持久化
121
- *
122
- * 定义不同强度的通知方式:
123
- * - toast: 飘字提示(轻量级,自动消失,不阻塞)
124
- * - modal: 弹窗消息(强提示,需要用户确认,阻塞式)
125
- */
126
- type NotificationType = 'toast' | 'modal';
127
- /**
128
- * 通知载荷 - 用于事件系统传递瞬时通知
129
- *
130
- * ⚠️ 与 LogEntry 的区别:
131
- * - NotificationPayload: 瞬时通知,不持久化,用于 UI 反馈
132
- * - LogEntry: 历史记录,持久化,用于回顾
133
- *
134
- * 通知会:
135
- * - 通过事件系统发送
136
- * - 仅在当前会话中显示
137
- * - 不会被保存到 localStorage
138
- * - 不会在页面刷新后重新出现
139
- */
140
- interface NotificationPayload {
141
- /** 通知文本 */
142
- text: string;
143
- /** 通知类型(影响样式) */
144
- type: LogEntry['type'];
145
- /** 通知方式(toast 或 modal) */
146
- notificationType: NotificationType;
147
- /** 时间戳(仅用于生成唯一 ID 和去重,不在 UI 中显示) */
148
- timestamp: number;
149
- }
150
- /**
151
- * 数值需求类型 - 定义属性检查的方式
152
- *
153
- * 可以是简单的数值(精确匹配)或范围对象(最小/最大值)
154
- *
155
- * @example
156
- * ```typescript
157
- * // 精确需求: 必须有10点体力
158
- * const exact: StatRequirement = 10;
159
- *
160
- * // 范围需求: 体力必须在5-20之间
161
- * const range: StatRequirement = { min: 5, max: 20 };
162
- *
163
- * // 最小需求: 至少需要5点体力
164
- * const minimum: StatRequirement = { min: 5 };
165
- * ```
166
- */
167
- type StatRequirement = number | {
168
- min?: number;
169
- max?: number;
170
- };
171
- /**
172
- * 需求定义接口 - 定义执行动作前必须满足的条件
173
- *
174
- * 用于检查玩家是否有资格执行某个动作。
175
- * 需求检查不会消耗资源,只是判断是否满足条件。
176
- *
177
- * @template S - 数值属性键的联合类型
178
- * @template I - 物品ID的联合类型
179
- * @template F - 标记键的联合类型
180
- *
181
- * @example
182
- * ```typescript
183
- * // 简单需求
184
- * const simpleReqs: RequirementDef<Stats, Items, Flags> = {
185
- * hasItems: ['key'],
186
- * stats: { strength: { min: 5 } }
187
- * };
188
- *
189
- * // 复杂逻辑使用 custom 函数
190
- * const complexReqs: RequirementDef<Stats, Items, Flags> = {
191
- * custom: (state) => {
192
- * // (有钥匙 AND 力量>=5) OR 有万能钥匙
193
- * const hasKeyAndStrength =
194
- * state.inventory.includes('key') && state.stats.strength >= 5;
195
- * const hasMasterKey = state.inventory.includes('master_key');
196
- * return hasKeyAndStrength || hasMasterKey;
197
- * }
198
- * };
199
- * ```
200
- */
201
- interface RequirementDef<S extends string, I extends string, F extends string, X = Record<string, unknown>> {
202
- /**
203
- * 数值属性需求 - 检查玩家属性是否满足条件
204
- * 使用Partial允许只检查部分属性
205
- * 所有指定的属性必须同时满足(AND逻辑)
206
- */
207
- stats?: Partial<Record<S, StatRequirement>>;
208
- /**
209
- * 必须拥有的物品列表
210
- * 玩家库存中必须包含所有列出的物品(AND逻辑)
211
- */
212
- hasItems?: I[];
213
- /**
214
- * 不能拥有的物品列表
215
- * 玩家库存中不能包含任何列出的物品(OR逻辑)
216
- */
217
- noItems?: I[];
218
- /**
219
- * 必须为true的标记列表
220
- * 所有列出的标记必须已设置为true(AND逻辑)
221
- */
222
- hasFlags?: F[];
223
- /**
224
- * 必须为false的标记列表
225
- * 所有列出的标记必须为false或未设置(OR逻辑)
226
- */
227
- noFlags?: F[];
228
- /**
229
- * 自定义需求函数 - 用于复杂逻辑
230
- *
231
- * 当需要表达复杂的逻辑关系时使用此函数。
232
- * 函数接收完整的游戏状态,返回true表示满足需求。
233
- *
234
- * 可以在函数中实现任意复杂的逻辑,包括:
235
- * - OR 逻辑:A || B
236
- * - 复杂组合:(A && B) || C
237
- * - 嵌套逻辑:((A || B) && C) || D
238
- * - 动态计算:基于多个状态的复杂判断
239
- *
240
- * @param state - 当前游戏状态
241
- * @returns true表示满足需求,false表示不满足
242
- *
243
- * @example
244
- * ```typescript
245
- * // 示例1:OR 逻辑 - 有钥匙或撬锁工具
246
- * custom: (state) =>
247
- * state.inventory.includes('key') ||
248
- * state.inventory.includes('lockpick')
249
- *
250
- * // 示例2:复杂组合 - (有钥匙 AND 力量>=5) OR 有万能钥匙
251
- * custom: (state) => {
252
- * const hasKeyAndStrength =
253
- * state.inventory.includes('key') && state.stats.strength >= 5;
254
- * const hasMasterKey = state.inventory.includes('master_key');
255
- * return hasKeyAndStrength || hasMasterKey;
256
- * }
257
- *
258
- * // 示例3:时间相关 - 夜晚时间
259
- * custom: (state) =>
260
- * state.world.time >= 18 || state.world.time <= 6
261
- *
262
- * // 示例4:使用扩展数据
263
- * custom: (state) =>
264
- * state.extra.reputation >= 100
265
- * ```
266
- */
267
- custom?: (state: GameState<S, I, F, X>) => boolean;
268
- }
269
- /**
270
- * 效果定义接口 - 定义动作执行后对游戏状态的改变
271
- *
272
- * 描述执行动作后会产生的所有效果,包括属性变化、物品变化、
273
- * 标记设置、位置传送等。所有效果会同时应用。
274
- *
275
- * @template S - 数值属性键的联合类型
276
- * @template I - 物品ID的联合类型
277
- * @template F - 标记键的联合类型
278
- *
279
- * @example
280
- * ```typescript
281
- * const drinkPotionEffect: EffectDef<Stats, Items, Flags> = {
282
- * statsChange: { hp: 20 }, // 恢复20点生命值
283
- * itemsRemove: ['potion'], // 消耗药水
284
- * flagsSet: { used_potion: true } // 标记已使用过药水
285
- * };
286
- * ```
287
- */
288
- interface EffectDef<S extends string, I extends string, F extends string, X = Record<string, unknown>> {
289
- /**
290
- * 数值属性变更
291
- * 正数表示增加,负数表示减少
292
- * 例如: { hp: 10, gold: -5 } 表示增加10点生命值,减少5金币
293
- */
294
- statsChange?: Partial<Record<S, number>>;
295
- /**
296
- * 添加到库存的物品列表
297
- * 物品会被添加到玩家的inventory数组中
298
- */
299
- itemsAdd?: I[];
300
- /**
301
- * 从库存移除的物品列表
302
- * 每个物品只会移除一次(如果有多个相同物品)
303
- */
304
- itemsRemove?: I[];
305
- /**
306
- * 标记设置
307
- * 设置指定标记的布尔值
308
- * 例如: { quest_completed: true, door_locked: false }
309
- */
310
- flagsSet?: Partial<Record<F, boolean>>;
311
- /**
312
- * 传送目标位置ID
313
- * 如果设置,玩家会被传送到指定位置
314
- */
315
- teleport?: string;
316
- /**
317
- * 触发特殊事件的标识符
318
- * 用于触发游戏中的特殊事件或剧情
319
- */
320
- triggerEvent?: string;
321
- /**
322
- * 自定义效果函数 - 用于修改扩展数据
323
- *
324
- * 当需要修改 extra 字段中的自定义数据时使用。
325
- * 函数接收当前的 extra 数据和完整游戏状态。
326
- * 可以直接修改 draft(Immer 风格),或返回部分更新。
327
- *
328
- * @param draft - 当前的扩展数据(可直接修改)
329
- * @param state - 完整的游戏状态(只读)
330
- * @returns void 或部分更新对象
331
- *
332
- * @example
333
- * ```typescript
334
- * // 示例1:直接修改 draft
335
- * custom: (draft) => {
336
- * draft.reputation += 10;
337
- * draft.achievements.push('first_quest');
338
- * }
339
- *
340
- * // 示例2:返回部分更新
341
- * custom: (draft, state) => {
342
- * return {
343
- * reputation: draft.reputation + 10,
344
- * lastAction: Date.now()
345
- * };
346
- * }
347
- * ```
348
- */
349
- custom?: (draft: X, state: GameState<S, I, F, X>) => void | Partial<X>;
350
- }
351
- /**
352
- * 动作定义接口 - 定义玩家可以执行的动作
353
- *
354
- * 动作是游戏交互的核心,包含了动作的显示信息、执行条件、
355
- * 消耗成本和产生的效果。
356
- *
357
- * @template S - 数值属性键的联合类型
358
- * @template I - 物品ID的联合类型
359
- * @template F - 标记键的联合类型
360
- *
361
- * @example
362
- * ```typescript
363
- * const attackAction: ActionDef<Stats, Items, Flags> = {
364
- * id: 'attack_goblin',
365
- * label: '攻击哥布林',
366
- * description: '用你的武器攻击哥布林',
367
- * costs: { stamina: 10 }, // 消耗10点体力
368
- * requirements: {
369
- * hasItems: ['weapon'] // 需要武器
370
- * },
371
- * effects: {
372
- * statsChange: { exp: 5 }, // 获得5点经验
373
- * flagsSet: { goblin_defeated: true }
374
- * },
375
- * resultText: '你击败了哥布林!'
376
- * };
377
- * ```
378
- */
379
- interface ActionDef<S extends string, I extends string, F extends string, X = Record<string, unknown>> {
380
- /** 动作的唯一标识符 */
381
- id: string;
382
- /**
383
- * 动作标签 - 显示在UI上的动作名称
384
- * 可以是静态字符串或根据游戏状态动态生成的函数
385
- */
386
- label: string | ((state: GameState<S, I, F>) => string);
387
- /**
388
- * 动作描述 - 详细说明动作的效果
389
- * 可选,可以是静态字符串或动态函数
390
- */
391
- description?: string | ((state: GameState<S, I, F>) => string);
392
- /**
393
- * 执行成本 - 执行动作时刚性扣除的资源
394
- *
395
- * 与requirements不同,costs会实际消耗资源。
396
- * 例如: { stamina: 10, gold: 5 } 会扣除10点体力和5金币
397
- */
398
- costs?: Partial<Record<S, number>>;
399
- /**
400
- * 执行需求 - 执行动作前必须满足的条件
401
- *
402
- * 需求检查不会消耗资源,只是判断是否有资格执行。
403
- * 如果不满足需求,动作将无法执行。
404
- */
405
- requirements?: RequirementDef<S, I, F, X>;
406
- /**
407
- * 执行效果 - 动作成功执行后产生的效果
408
- *
409
- * 包括属性变化、物品获得/失去、标记设置等。
410
- * 所有效果会在扣除costs后立即应用。
411
- */
412
- effects?: EffectDef<S, I, F, X>;
413
- /**
414
- * 结果文本 - 动作执行后显示给玩家的反馈信息
415
- * 可以是静态字符串或根据游戏状态动态生成的函数
416
- */
417
- resultText: string | ((state: GameState<S, I, F, X>) => string);
418
- }
419
- /**
420
- * 地点定义接口 - 定义游戏中的一个地点/场景
421
- *
422
- * 地点是游戏世界的基本单位,包含地点信息和可执行的动作列表。
423
- * 玩家在不同地点之间移动,每个地点提供不同的动作选项。
424
- *
425
- * @template S - 数值属性键的联合类型
426
- * @template I - 物品ID的联合类型
427
- * @template F - 标记键的联合类型
428
- * @template X - 扩展数据类型(默认为 Record<string, unknown>)
429
- *
430
- * @example
431
- * ```typescript
432
- * // 基础用法
433
- * const tavern: LocationDef<Stats, Items, Flags> = {
434
- * id: 'tavern',
435
- * name: '酒馆',
436
- * description: '一个热闹的酒馆,充满了冒险者',
437
- * actionIds: ['buy_drink', 'talk_bartender', 'rest'],
438
- * extra: {}
439
- * };
440
- *
441
- * // 使用自定义扩展数据
442
- * interface LocationEnvironment {
443
- * temperature: number;
444
- * humidity: number;
445
- * lightLevel: number;
446
- * }
447
- *
448
- * const cave: LocationDef<Stats, Items, Flags, LocationEnvironment> = {
449
- * id: 'cave',
450
- * name: '洞穴',
451
- * description: (state) => {
452
- * // 可以访问 state.extra
453
- * const temp = state.extra.temperature;
454
- * return temp < 0 ? '寒冷的洞穴' : '阴暗的洞穴';
455
- * },
456
- * actionIds: ['explore'],
457
- * extra: {
458
- * temperature: -5,
459
- * humidity: 80,
460
- * lightLevel: 2
461
- * }
462
- * };
463
- * ```
464
- */
465
- interface LocationDef<S extends string, I extends string, F extends string, X = Record<string, unknown>> {
466
- /** 地点的唯一标识符 */
467
- id: string;
468
- /** 地点名称 - 显示在UI上的地点名称 */
469
- name: string;
470
- /**
471
- * 地点描述 - 描述地点的外观、氛围等
472
- * 可以是静态字符串或根据游戏状态动态生成的函数
473
- * 例如:根据时间显示不同的描述
474
- */
475
- description: string | ((state: GameState<S, I, F, X>) => string);
476
- /**
477
- * 该地点可执行的动作ID列表
478
- *
479
- * 存储动作ID而非完整的ActionDef对象,通过动作注册表查找实际定义。
480
- * 这种设计提供了更好的解耦和灵活性:
481
- * - 同一个动作可以在多个地点复用
482
- * - 动作定义可以独立修改而不影响地点定义
483
- * - 减少数据冗余和内存占用
484
- *
485
- * 使用时需要配合ActionRegistry来查找完整的动作定义。
486
- */
487
- actionIds: string[];
488
- /**
489
- * 扩展数据 - 存储地点特定的额外信息
490
- *
491
- * 这是一个灵活的字段,允许不同游戏为地点存储自定义元数据。
492
- * 使用泛型 X 来定义具体的扩展数据类型。
493
- *
494
- * 常见用途:
495
- * - 环境参数(温度、湿度、光照等)
496
- * - 地点元数据(类别、发现时间、访问次数等)
497
- * - 特殊属性(危险度、资源丰富度等)
498
- * - 动态状态(天气、时间相关的变化等)
499
- *
500
- * @example
501
- * ```typescript
502
- * // 定义环境参数类型
503
- * interface LocationEnvironment {
504
- * temperature: number;
505
- * humidity: number;
506
- * lightLevel: number;
507
- * danger: number;
508
- * }
509
- *
510
- * // 使用扩展数据
511
- * type MyLocation = LocationDef<Stats, Items, Flags, LocationEnvironment>;
512
- *
513
- * const location: MyLocation = {
514
- * id: 'forest',
515
- * name: '森林',
516
- * description: (state) => {
517
- * // 在 description 函数中访问扩展数据
518
- * if (state.extra.danger > 5) {
519
- * return '这片森林看起来很危险...';
520
- * }
521
- * return '一片宁静的森林';
522
- * },
523
- * actionIds: ['explore'],
524
- * extra: {
525
- * temperature: 20,
526
- * humidity: 60,
527
- * lightLevel: 8,
528
- * danger: 3
529
- * }
530
- * };
531
- * ```
532
- */
533
- extra: X;
534
- }
535
-
536
- export type { ActionDef as A, EffectDef as E, GameState as G, LogEntry as L, NotificationType as N, RequirementDef as R, StatRequirement as S, WorldState as W, NotificationPayload as a, LocationDef as b };