sapdon 3.2.2 → 3.3.3

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.
Files changed (68) hide show
  1. package/README.md +245 -121
  2. package/doc/dev/architecture.md +415 -0
  3. package/doc/dev/cli.md +467 -0
  4. package/doc/dev/core.md +717 -0
  5. package/doc/dev/oc.md +582 -0
  6. package/doc/user/api/biome.md +558 -0
  7. package/doc/user/api/block.md +945 -0
  8. package/doc/user/api/entity.md +685 -0
  9. package/doc/user/api/extra.md +231 -0
  10. package/doc/user/api/item.md +896 -0
  11. package/doc/user/api/recipe.md +427 -0
  12. package/doc/user/api/texture.md +181 -0
  13. package/doc/user/config/build-config.md +84 -0
  14. package/doc/user/config/mod-info.md +33 -0
  15. package/doc/user/faq.md +160 -0
  16. package/doc/user/quick-start.md +108 -0
  17. package/doc/user/tutorials/block.md +463 -0
  18. package/doc/user/tutorials/entity.md +356 -0
  19. package/doc/user/tutorials/item.md +449 -0
  20. package/doc/user/tutorials/recipe.md +278 -0
  21. package/package.json +4 -3
  22. package/prod/cli/index.js +1 -1
  23. package/prod/cli/start.js +1 -1458
  24. package/prod/core/index.d.ts +3290 -2150
  25. package/prod/core/index.js +1 -59015
  26. package/prod/core/package.json +7 -0
  27. package/prod/oc/index.d.ts +348 -108
  28. package/prod/oc/index.js +1 -1
  29. package/prod/oc/package.json +7 -0
  30. package/prod/utils/index.d.ts +20 -2
  31. package/prod/utils/index.js +1 -1
  32. package/prod/utils/package.json +7 -0
  33. package/doc/BlockAPI.md +0 -145
  34. package/doc/api.md +0 -128
  35. package/doc/oc/index.md +0 -0
  36. package/doc/sapdon-ts.md +0 -64
  37. package/src/templates/js_sapdon/build.config +0 -23
  38. package/src/templates/js_sapdon/main.mjs +0 -4
  39. package/src/templates/js_sapdon/mod.info +0 -7
  40. package/src/templates/js_sapdon/pack_icon.png +0 -0
  41. package/src/templates/js_sapdon/package.json +0 -20
  42. package/src/templates/js_sapdon/res/animations/animation_item.animation.json +0 -34
  43. package/src/templates/js_sapdon/res/animations/large_item.animation.json +0 -27
  44. package/src/templates/js_sapdon/res/models/blocks/crop.geo.json +0 -48
  45. package/src/templates/js_sapdon/res/models/entity/animation/animation_item.geo.json +0 -26
  46. package/src/templates/js_sapdon/res/models/entity/animation/large_item.geo.json +0 -28
  47. package/src/templates/js_sapdon/res/textures/blocks/none.png +0 -0
  48. package/src/templates/js_sapdon/res/textures/blocks/test_log_oak.png +0 -0
  49. package/src/templates/js_sapdon/res/textures/blocks/test_log_top.png +0 -0
  50. package/src/templates/js_sapdon/res/textures/items/masterball.png +0 -0
  51. package/src/templates/js_sapdon/scripts/custom_components/cropComponent.js +0 -50
  52. package/src/templates/js_sapdon/scripts/custom_components/items/gui_book.js +0 -37
  53. package/src/templates/js_sapdon/scripts/custom_components/registry.js +0 -25
  54. package/src/templates/js_sapdon/scripts/index.js +0 -0
  55. package/src/templates/ts_sapdon/build.config +0 -23
  56. package/src/templates/ts_sapdon/main.ts +0 -11
  57. package/src/templates/ts_sapdon/mod.info +0 -7
  58. package/src/templates/ts_sapdon/pack_icon.png +0 -0
  59. package/src/templates/ts_sapdon/package.json +0 -20
  60. package/src/templates/ts_sapdon/res/models/blocks/crop.geo.json +0 -48
  61. package/src/templates/ts_sapdon/res/textures/blocks/test_log_oak.png +0 -0
  62. package/src/templates/ts_sapdon/res/textures/blocks/test_log_top.png +0 -0
  63. package/src/templates/ts_sapdon/res/textures/items/masterball.png +0 -0
  64. package/src/templates/ts_sapdon/scripts/components/cropComponent.ts +0 -44
  65. package/src/templates/ts_sapdon/scripts/components/items/guiBook.ts +0 -36
  66. package/src/templates/ts_sapdon/scripts/components/registry.ts +0 -24
  67. package/src/templates/ts_sapdon/scripts/index.ts +0 -7
  68. package/src/templates/ts_sapdon/tsconfig.json +0 -117
package/doc/dev/oc.md ADDED
@@ -0,0 +1,582 @@
1
+ # OC 运行时模块文档
2
+
3
+ `src/oc/` 是 Sapdon 的 **OC (Object-Component) 运行时**,是一个轻量级 ECS 风格游戏框架,专门用于 Minecraft Bedrock 版 Script API 环境。作为 `@sapdon/runtime` 发布。
4
+
5
+ ---
6
+
7
+ ## 1. 架构总览
8
+
9
+ OC 模块实现了一个简化的 **Entity-Component 架构**:
10
+
11
+ ```
12
+ ┌──────────────────────────────────────────────────┐
13
+ │ Minecraft 世界 │
14
+ │ │
15
+ │ ┌──────────────┐ ┌──────────────┐ │
16
+ │ │ Entity A │ │ Entity B │ │
17
+ │ │ │ │ │ │
18
+ │ │ ComponentManager │ │ ComponentManager │ │
19
+ │ │ ├─ HealthComp │ │ ├─ MoveComp │ │
20
+ │ │ ├─ InputComp │ │ ├─ RenderComp │ │
21
+ │ │ └─ HudComp │ │ └─ HealthComp │ │
22
+ │ └──────────────┘ └──────────────┘ │
23
+ │ │
24
+ │ ┌────────────────────────────────────────────────┐ │
25
+ │ │ Level (实体集合) │ │
26
+ │ │ └─ Scheduler (驱动 tick 循环) │ │
27
+ │ └────────────────────────────────────────────────┘ │
28
+ └──────────────────────────────────────────────────┘
29
+ ```
30
+
31
+ **核心概念:**
32
+
33
+ | 概念 | 说明 |
34
+ |------|------|
35
+ | **Component** | 附着在实体上的数据+行为单元,每个 Component 有自己的 `onTick()` |
36
+ | **ComponentManager** | 每个实体一个,管理其所有 Component 的生命周期 |
37
+ | **Level** | 实体集合,以 string ID 索引,每个 ID 对应一个 ComponentManager |
38
+ | **Scheduler** | 驱动游戏循环,每 tick 遍历所有实体的所有 Component 调用 `onTick()` |
39
+ | **Optional\<T\>** | Monadic 空值包装器 |
40
+ | **EventEmitter** | 自定义发布/订阅事件系统 |
41
+
42
+ ### 目录结构
43
+
44
+ ```
45
+ src/oc/
46
+ ├── index.ts # 包入口,聚合导出
47
+ ├── core.ts # 核心 ECS:Component, ComponentManager, lazyGet, RequireComponents
48
+ ├── arch.ts # 引导启动:GameInstance, initialize/finalize
49
+ ├── optional.ts # Optional Monad
50
+ ├── level.ts # Level + Scheduler 接口
51
+ ├── events/
52
+ │ └── index.ts # EventEmitter (自定义事件系统)
53
+ ├── input/
54
+ │ └── base.ts # PlayerInputComponent (按键/轴输入)
55
+ ├── math/
56
+ │ ├── index.ts # 聚合导出
57
+ │ ├── array.ts # ArrayEx (数组基类)
58
+ │ ├── spline.ts # SplineInterpolator (样条插值)
59
+ │ ├── vec/vec3.ts # Vec3 (3D 向量)
60
+ │ ├── vec/vec4.ts # Vec4 (4D 向量)
61
+ │ └── mat/mat4.ts # Matrix (4x4 矩阵)
62
+ ├── action/
63
+ │ ├── interface.ts # ActionValueType, IAction, IActionTrigger, IActionModifier
64
+ │ ├── triggers.ts # ActionTriggers (pressed/released/hold 等)
65
+ │ └── modifiers.ts # ActionModifiers (negate/scale)
66
+ ├── ui/hud.ts # HudComponent (基类)
67
+ └── minecraft/ # Minecraft 集成层
68
+ ├── index.ts # 聚合导出
69
+ ├── core.ts # MinecraftTickingScheduler, MinecraftLevel, MinecraftGameInstance
70
+ ├── decorator.ts # @Minecraft, @MinecraftMain, @PlayerSpawned, @EntitySpawned, @SpawnFilter
71
+ ├── utils.ts # MinecraftMethod 装饰器, utils 单例
72
+ ├── scriptEvent.ts # @ScriptEvent 装饰器 + 事件桥接
73
+ ├── input/
74
+ │ └── inputComponent.ts # MinecraftPlayerInputComponent
75
+ ├── component/
76
+ │ ├── kinematics.ts # EasyKinematicsComponent (力驱动运动)
77
+ │ └── vehicleComponent.ts # EasyVehicleComponent (载具物理)
78
+ └── ui/
79
+ └── actionbar.ts # PlayerHudComponent (actionbar HUD)
80
+ ```
81
+
82
+ ---
83
+
84
+ ## 2. Component 系统 (`core.ts`)
85
+
86
+ ### 2.1 接口层级
87
+
88
+ ```
89
+ Component<Actor> (接口)
90
+ ├── onTick(dt: number): void
91
+ ├── detach(): void
92
+ ├── getManager(): ComponentManager<Actor>
93
+ └── getEntity(): Actor
94
+
95
+ BasicComponent<Actor> (接口,extends Component)
96
+ ├── onAttach(manager: ComponentManager<Actor>): void
97
+ └── onDetach(manager: ComponentManager<Actor>): void
98
+
99
+ RequiredComponent<Actor> (接口,extends BasicComponent)
100
+ └── getComponent<T>(ctor): T
101
+ ```
102
+
103
+ ### 2.2 实现层级
104
+
105
+ ```
106
+ CustomComponent<Actor> (抽象类,实现 Component)
107
+ └── BaseComponent<Actor> (类,实现 BasicComponent)
108
+ ```
109
+
110
+ **CustomComponent** 使用 `Symbol` 存储 manager 和 entity 引用:
111
+
112
+ ```typescript
113
+ const REFLECT_MANAGER = Symbol('manager')
114
+ const REFLECT_ENTITY = Symbol('entity')
115
+
116
+ class CustomComponent<Actor> {
117
+ onTick(dt: number) {} // 默认空实现
118
+ detach() { this.getManager()?.update() }
119
+ getManager() { return this[REFLECT_MANAGER] }
120
+ getEntity() { return this[REFLECT_ENTITY] }
121
+ }
122
+ ```
123
+
124
+ **BaseComponent** 添加空的 `onAttach` / `onDetach` 钩子。
125
+
126
+ ### 2.3 Component 生命周期
127
+
128
+ ```
129
+ 构造 (new Component())
130
+
131
+
132
+ onAttach(manager) ← 被 ComponentManager.attachComponent() 调用
133
+
134
+
135
+ onTick(dt) ← 每帧由 ComponentManager.handleTicks() 调用
136
+ │ (可被多次调用)
137
+
138
+ detach() / onDetach(manager) ← 被 ComponentManager.detachComponent() 调用
139
+ ```
140
+
141
+ ### 2.4 ComponentManager
142
+
143
+ 每个实体拥有一个 `ComponentManager`,管理 `Map<ComponentCtor, Component>`:
144
+
145
+ | 方法 | 说明 |
146
+ |------|------|
147
+ | `attachComponent(component)` | 附加组件,调用 `onAttach`,处理 `RequiredComponent` 依赖 |
148
+ | `detachComponent(ctor)` | 分离组件,调用 `onDetach` |
149
+ | `getComponent<T>(ctor)` | 获取组件,不存在则报错 |
150
+ | `getComponentUnsafe<T>(ctor)` | 安全获取,返回 `Optional<T>` |
151
+ | `getOrCreate<T>(ctor, ...args)` | 获取或创建 |
152
+ | `has(ctor)` | 检查组件是否存在 |
153
+ | `clear()` | 清除所有组件 |
154
+ | `handleTicks(en, dt)` | 遍历所有组件调用 `onTick`,支持 before/after 队列 |
155
+ | `update()` | 触发组件重附加(用于依赖变更后刷新) |
156
+
157
+ **全局单例**:`ComponentManager.global` 用于存放全局(非实体相关)组件。
158
+
159
+ **性能分析**:`ComponentManager.profilerEnable = true` 可启用 tick 耗时日志。
160
+
161
+ ### 2.5 RequiredComponent (依赖注入)
162
+
163
+ `RequireComponents(...params)` 是一个 mixin 工厂,创建一个带依赖的 Component 类:
164
+
165
+ ```typescript
166
+ // 用法示例
167
+ const MyComponent = RequireComponents(
168
+ HealthComponent,
169
+ [MovementComponent, 1.0], // 带构造参数的依赖
170
+ TransformComponent
171
+ )
172
+
173
+ class MyComponent extends BaseComponent<Entity> {
174
+ // 通过 this.getComponent(HealthComponent) 访问依赖
175
+ }
176
+ ```
177
+
178
+ 每次 `attachComponent` 时,如果组件有 `REQUIRED_COMPONENTS` 符号属性,这些依赖会被自动构造并附加。
179
+
180
+ ### 2.6 lazyGet
181
+
182
+ `lazyGet(component, ctor)` 返回一个 **Proxy**,在首次访问属性时才通过 manager 查找目标组件。用于组件间交叉引用,避免循环依赖问题。
183
+
184
+ ---
185
+
186
+ ## 3. Level 与 Scheduler (`level.ts`)
187
+
188
+ ### 3.1 Level
189
+
190
+ ```typescript
191
+ abstract class Level<T> {
192
+ protected table: Map<string, ComponentManager<T>>
193
+
194
+ addEntity(id: string): ComponentManager<T>
195
+ removeEntity(id: string): void
196
+ getManager(id: string): ComponentManager<T>
197
+
198
+ abstract getScheduler(): Scheduler<T>
199
+
200
+ start() // → scheduler.start(table)
201
+ stop() // → scheduler.stop()
202
+ }
203
+ ```
204
+
205
+ - 实体用 string ID 标识
206
+ - `getManager(id)` 在不存在时自动创建新 manager
207
+ - `start()` / `stop()` 委托给 scheduler
208
+
209
+ ### 3.2 Scheduler
210
+
211
+ ```typescript
212
+ interface Scheduler<Actor> {
213
+ currentTick: number
214
+ timeDilation: number
215
+
216
+ start(table: Map<string, ComponentManager<Actor>>): void
217
+ stop(): void
218
+ }
219
+ ```
220
+
221
+ `timeDilation` 属性可加速/减速游戏时间(默认 1.0)。
222
+
223
+ ---
224
+
225
+ ## 4. Minecraft 集成
226
+
227
+ ### 4.1 整体启动流程
228
+
229
+ ```
230
+ Minecraft 启动
231
+
232
+
233
+ @MinecraftMain 装饰器
234
+ → GameInstance(target) 注册游戏类
235
+ → utils.start() 挂载生命周期钩子
236
+
237
+
238
+ system.beforeEvents.startup 触发
239
+
240
+
241
+ initialize(GameInstanceClass)
242
+ → new GameInstanceClass()
243
+ → instance.onStart()
244
+
245
+
246
+ MinecraftGameInstance.onStart()
247
+ → 创建 MinecraftLevel
248
+ → 创建 MinecraftTickingScheduler
249
+ → level.start() → scheduler.start(table)
250
+ → 安排 afterStart() 下一 tick 执行
251
+
252
+
253
+ 每游戏 tick:
254
+ scheduler.executeTick(table)
255
+ → 遍历每个实体的 ComponentManager
256
+ → manager.handleTicks(entity, dt)
257
+ → 每个 Component.onTick(dt)
258
+ ```
259
+
260
+ ### 4.2 MinecraftTickingScheduler
261
+
262
+ ```typescript
263
+ @Minecraft
264
+ class MinecraftTickingScheduler implements Scheduler<string> {
265
+ currentTick = 0
266
+ timeDilation = 1
267
+
268
+ start(table: Map<string, ComponentManager<Entity>>) {
269
+ system.runInterval(() => {
270
+ this.executeTick(table)
271
+ })
272
+ }
273
+
274
+ executeTick(table) {
275
+ this.currentTick++
276
+ const dt = this._timeStamp * this.timeDilation
277
+ for (const [id, manager] of table) {
278
+ // 使用 world.getEntity(id) 获取 Minecraft Entity 对象
279
+ manager.handleTicks(entity, dt)
280
+ }
281
+ }
282
+ }
283
+ ```
284
+
285
+ ### 4.3 MinecraftGameInstance
286
+
287
+ ```typescript
288
+ abstract class MinecraftGameInstance implements GameInstance {
289
+ onStart() {
290
+ const level = new MinecraftLevel()
291
+ this.setLevel(level)
292
+ level.start()
293
+ system.run(() => this.afterStart?.()) // 下一 tick 执行 afterStart
294
+ }
295
+ }
296
+ ```
297
+
298
+ 用户自定义游戏类 extends `MinecraftGameInstance`,实现 `onStart()` 和可选的 `afterStart()`。
299
+
300
+ ### 4.4 装饰器
301
+
302
+ #### 类装饰器
303
+
304
+ | 装饰器 | 说明 |
305
+ |--------|------|
306
+ | `@Minecraft` | 代理构造,确保在 Minecraft 环境中运行 |
307
+ | `@MinecraftMain` | 标记为主游戏类,注册 GameInstance + 挂载生命周期 + 设置生成监听 |
308
+ | `@PlayerSpawned(...deps)` | 标记在玩家生成时自动附加的 Component |
309
+ | `@EntitySpawned(...deps)` | 标记在实体生成时自动附加的 Component |
310
+ | `@ActorSpawned(...deps)` | 同时监听玩家和实体生成 |
311
+ | `@SpawnFilter(filter)` | 条件过滤:`(entity) => boolean`,返回 false 则不附加 |
312
+
313
+ #### 方法装饰器
314
+
315
+ | 装饰器 | 说明 |
316
+ |--------|------|
317
+ | `@MinecraftMethod` | 包装方法,执行前断言 Minecraft 环境 |
318
+ | `@ScriptEvent(eventId)` | 绑定方法到 Minecraft script event |
319
+
320
+ ### 4.5 生成时自动附加
321
+
322
+ `@MinecraftMain` 内部逻辑:
323
+
324
+ ```
325
+ world.afterEvents.playerSpawn
326
+ → 查找所有 @PlayerSpawned 装饰的类
327
+ → 构造实例 + attachComponent(playerManager)
328
+ → @SpawnFilter 可过滤
329
+
330
+ world.afterEvents.entitySpawn (排除 player)
331
+ → 查找所有 @EntitySpawned 装饰的类
332
+ → 构造实例 + attachComponent(entityManager)
333
+ ```
334
+
335
+ ### 4.6 ScriptEvent 桥接
336
+
337
+ ```typescript
338
+ // 方法装饰器用法
339
+ class MySystem {
340
+ @ScriptEvent('myAddon:event')
341
+ handleEvent(ev: ScriptEventCommandMessageAfterEvent) {
342
+ console.log('event received', ev)
343
+ }
344
+ }
345
+
346
+ // 编程式用法
347
+ ScriptEvent.on('myAddon:event', handler)
348
+ ScriptEvent.off('myAddon:event', handler)
349
+ ```
350
+
351
+ 内部通过 `EventEmitter` + `system.afterEvents.scriptEventReceive` 实现。
352
+
353
+ ---
354
+
355
+ ## 5. 输入系统 (`input/`)
356
+
357
+ ### 5.1 PlayerInputComponent
358
+
359
+ ```typescript
360
+ class PlayerInputComponent<Actor> extends BaseComponent<Actor> {
361
+ // 按键状态管理
362
+ inputKey(key: string, pressing: boolean): void
363
+ getKeyState(key: string): IKeyState
364
+ getKeyPressing(key: string): boolean
365
+ getKeyPressTimes(key: string): number
366
+ exhaust(key: string): void // 重置按键次数
367
+
368
+ // 轴输入
369
+ inputAxis(key: string, value: AxisValue): void
370
+ getAxis(key: string): AxisValue
371
+
372
+ // 轴工具
373
+ combineAxis(axis1, axis2): AxisValue
374
+ splitAxis(axis, nDim1, nDim2?): [AxisValue, AxisValue]
375
+ }
376
+ ```
377
+
378
+ **IKeyState**:`{ pressing: boolean, times: number, consume(): void }`
379
+
380
+ **AxisValue**:`number | [number, number] | [number, number, number]`
381
+
382
+ ### 5.2 MinecraftPlayerInputComponent
383
+
384
+ extends `PlayerInputComponent<Entity>`。集成 Minecraft 玩家的按钮输入和摇杆轴:
385
+
386
+ - 通过 `world.afterEvents.playerButtonInput` 监听按钮事件
387
+ - 每 tick 通过 `player.inputInfo.getMovementVector()` 获取移动轴
388
+
389
+ ---
390
+
391
+ ## 6. 动作系统 (`action/`)
392
+
393
+ | 导出 | 说明 |
394
+ |------|------|
395
+ | `ActionValueType` | 枚举:`BOOL(0)`, `VEC(1)`, `VEC2(2)`, `VEC3(3)` |
396
+ | `IActionModifier<E, V>` | 变换函数:`(type: E, value: V) => V` |
397
+ | `IActionTrigger` | 触发判定:`(type, value, ticks) => boolean` |
398
+ | `IAction<E>` | 组合:`valueType + modifiers[] + triggers[]` |
399
+ | `ActionTriggers` | 工厂:`pressed()`, `released()`, `hold(act, hold)`, `holdThenRelease(act)` |
400
+ | `ActionModifiers` | 工厂:`negate(mask)`, `scale(scalar)` |
401
+
402
+ ---
403
+
404
+ ## 7. 事件系统 (`events/`)
405
+
406
+ ### EventEmitter
407
+
408
+ 自定义实现,使用**双向链表**实现 O(1) 的添加/移除:
409
+
410
+ | 方法 | 说明 |
411
+ |------|------|
412
+ | `on(type, handler)` | 订阅事件 |
413
+ | `once(type, handler)` | 一次性订阅 |
414
+ | `prependListener(type, handler)` | 插到监听器列表头部 |
415
+ | `prependOnceListener(type, handler)` | 一次性插到头部 |
416
+ | `off(type, handler)` / `removeListener(type, handler)` | 取消订阅 |
417
+ | `removeAllListeners(type)` | 移除所有 |
418
+ | `emit(type, ...args)` | 触发事件(使用 bind thisArg) |
419
+ | `emitNone(type, ...args)` | 触发事件(不使用 thisArg) |
420
+ | `listenerCount(type)` | 监听器数量 |
421
+ | `listeners(type)` / `rawListeners(type)` | 获取监听器列表 |
422
+ | `eventNames()` | 获取所有事件名 |
423
+ | `setMaxListeners(n)` | 设置最大监听器数 |
424
+
425
+ 特点:
426
+ - 双向链表实现,O(1) add/remove
427
+ - 支持 `captureRejections`(捕获 Promise 返回的 handler 的 rejection)
428
+ - emit 过程中的错误会被捕获并重定向到 `'error'` 事件
429
+
430
+ ---
431
+
432
+ ## 8. 数学库 (`math/`)
433
+
434
+ ### Vec3 / Vec4 / Matrix
435
+
436
+ 向量和矩阵继承自 `ArrayEx`(extends `Array`):
437
+
438
+ **Vec3**:`fromXYZ()`、`normalize()`、`dot()`、`cross()`、`add()`、`sub()`、`mul()`、`div()`
439
+
440
+ **Vec4**:同上 + `multiply(Matrix)`(矩阵乘法)
441
+
442
+ **Matrix**(4x4):
443
+ - 静态:`identity()`、`translate()`、`perspective()`、`orthographic()`、`lookAt()`
444
+ - 实例:`setIdentity()`、`setTranslation()`、`setRotation()`、`setRotationX/Y/Z()`、`setScale()`、`transpose()`、`multiply()`
445
+
446
+ ### SplineInterpolator
447
+
448
+ 五点平滑样条插值(quincunx 算法):
449
+
450
+ ```typescript
451
+ const spline = SplineInterpolator.fromPoints(points, lambda)
452
+ spline.interpolate(x) // 插值
453
+ spline.max(step) // 找最大值
454
+ spline.min(step) // 找最小值
455
+ spline.curve(nInterval) // 获取曲线点集
456
+ ```
457
+
458
+ ---
459
+
460
+ ## 9. HUD 系统 (`ui/`)
461
+
462
+ ### HudComponent
463
+
464
+ ```typescript
465
+ abstract class HudComponent<Actor, Hud> extends CustomComponent<Actor> {
466
+ hud: Hud
467
+ actor: Optional<Actor>
468
+
469
+ abstract render(): Hud
470
+ abstract draw(): void
471
+
472
+ onTick(dt: number) {
473
+ this.hud = this.render()
474
+ this.draw()
475
+ }
476
+ }
477
+ ```
478
+
479
+ 每 tick 调用 `render()` 生成 HUD 数据,然后调用 `draw()` 渲染。
480
+
481
+ ### PlayerHudComponent
482
+
483
+ extends `HudComponent<Player, string>`。使用 `/title @s actionbar` 命令将字符串渲染到玩家动作栏。
484
+
485
+ ---
486
+
487
+ ## 10. 物理组件
488
+
489
+ ### EasyKinematicsComponent
490
+
491
+ ```typescript
492
+ class EasyKinematicsComponent extends CustomComponent<Entity> {
493
+ mass = 1
494
+ allowRotation = false
495
+ simulated = false // false=applyImpulse, true=tryTeleport
496
+ force: Vec3
497
+ angularVelocity: Vec3
498
+ }
499
+ ```
500
+
501
+ 每 tick 应用力和角速度。`simulated = false` 时使用 `applyImpulse`,`true` 时使用 `tryTeleport` + 牛顿运动学公式。
502
+
503
+ ### EasyVehicleComponent
504
+
505
+ 载具物理数据:
506
+
507
+ ```typescript
508
+ class EasyVehicleComponent extends CustomComponent<Entity> {
509
+ width = 2, height = 1.5, length = 4.5
510
+ mass = 1500
511
+ inertia: Vec3 // 由 _calcInertia() 自动计算(矩形棱柱公式)
512
+ }
513
+ ```
514
+
515
+ ---
516
+
517
+ ## 11. Optional Monad (`optional.ts`)
518
+
519
+ ```typescript
520
+ class Optional<T> {
521
+ static none<T>(): Optional<T> // 空值
522
+ static some<T>(value?: T): Optional<T> // 包装值
523
+
524
+ unwrap(): T // 取值,空则抛错
525
+ isEmpty(): boolean // 是否为 null/undefined
526
+ orElse(other: T): T // 空则返回默认值
527
+ use<R>(fn, self?): R | Optional<R> // monadic bind (flatMap)
528
+ }
529
+ ```
530
+
531
+ `use()` 是 flatMap 操作:非空时调用 `fn(value)`,如果返回值是 Optional 则直接返回,否则用 `Optional.some()` 包装;空时返回 `Optional.none()`。
532
+
533
+ ---
534
+
535
+ ## 12. 类继承关系总图
536
+
537
+ ```
538
+ Array (原生)
539
+ └── ArrayEx
540
+ ├── Vec3
541
+ ├── Vec4
542
+ └── Matrix
543
+
544
+ CustomComponent<Actor> (抽象)
545
+ ├── BaseComponent<Actor>
546
+ │ ├── PlayerInputComponent<Actor>
547
+ │ │ └── MinecraftPlayerInputComponent
548
+ │ ├── HudComponent<Actor, Hud> (抽象)
549
+ │ │ └── PlayerHudComponent (抽象)
550
+ │ └── RequireComponents() 生成的类
551
+ ├── EasyKinematicsComponent
552
+ └── EasyVehicleComponent
553
+
554
+ Level<T> (抽象)
555
+ └── MinecraftLevel
556
+
557
+ Scheduler<Actor> (接口)
558
+ └── MinecraftTickingScheduler
559
+
560
+ GameInstance<A> (接口)
561
+ └── MinecraftGameInstance (抽象)
562
+
563
+ EventEmitter (独立)
564
+ Optional<T> (独立)
565
+ SplineInterpolator (独立)
566
+ KeyState (独立)
567
+ ```
568
+
569
+ ---
570
+
571
+ ## 13. 包入口 (`index.ts`)
572
+
573
+ ```typescript
574
+ // src/oc/index.ts
575
+ export * from './core.js' // Component 体系 + ComponentManager
576
+ export * from './optional.js' // Optional<T>
577
+ export * from './input/base.js' // PlayerInputComponent
578
+ export * from './arch.js' // GameInstance, initialize
579
+ export * from './math/index.js' // Vec3, Vec4, Matrix, Spline, MathExt
580
+ export * from './minecraft/index.js' // Minecraft 集成全部
581
+ export * from './ui/hud.js' // HudComponent
582
+ ```