docs: sync updated boardgame-core
This commit is contained in:
parent
4d4889f825
commit
cbee709a27
|
|
@ -57,6 +57,9 @@ const hand = createRegion('hand', [
|
|||
**区域操作:**
|
||||
|
||||
```ts
|
||||
// 注意:parts 现在是 Record<string, Part> 格式
|
||||
const parts: Record<string, Part> = { ... };
|
||||
|
||||
// 对齐/紧凑排列(根据 axis.align 自动调整位置)
|
||||
applyAlign(hand, parts);
|
||||
|
||||
|
|
@ -78,7 +81,7 @@ removeFromRegion(part, region);
|
|||
`Part<TMeta>` 表示游戏中的一个部件(棋子、卡牌等)。
|
||||
|
||||
```ts
|
||||
import { createPart, createParts, createPartPool, flip, flipTo, roll } from 'boardgame-core';
|
||||
import { createPart, createParts, createPartPool, flip, flipTo, roll, mergePartPools } from 'boardgame-core';
|
||||
|
||||
// 创建单个部件
|
||||
const piece = createPart(
|
||||
|
|
@ -86,7 +89,7 @@ const piece = createPart(
|
|||
'piece-1'
|
||||
);
|
||||
|
||||
// 批量创建(生成 piece-pawn-0, piece-pawn-1, ...)
|
||||
// 批量创建(生成 piece-pawn-1, piece-pawn-2, ...)
|
||||
const pawns = createParts(
|
||||
{ regionId: 'supply', position: [0, 0] },
|
||||
8,
|
||||
|
|
@ -141,6 +144,12 @@ roll(dice, rng);
|
|||
```ts
|
||||
import { findPartById, isCellOccupied, getPartAtPosition } from 'boardgame-core';
|
||||
|
||||
// Parts 现在是 Record<string, Part> 格式
|
||||
const parts: Record<string, Part> = {
|
||||
'piece-1': piece1,
|
||||
'piece-2': piece2,
|
||||
};
|
||||
|
||||
// 按 ID 查找
|
||||
const piece = findPartById(parts, 'piece-1');
|
||||
|
||||
|
|
@ -358,7 +367,7 @@ export function createInitialState() {
|
|||
{ name: 'x', min: 0, max: BOARD_SIZE - 1 },
|
||||
{ name: 'y', min: 0, max: BOARD_SIZE - 1 },
|
||||
]),
|
||||
parts: [] as TicTacToePart[],
|
||||
parts: {} as Record<string, TicTacToePart>,
|
||||
currentPlayer: 'X' as PlayerType,
|
||||
winner: null as PlayerType | 'draw' | null,
|
||||
turn: 0,
|
||||
|
|
@ -411,7 +420,7 @@ registration.add('turn <player> <turn:number>', async function(cmd) {
|
|||
if (row < 0 || row >= BOARD_SIZE || col < 0 || col >= BOARD_SIZE) {
|
||||
return `Invalid position: (${row}, ${col})`;
|
||||
}
|
||||
if (isCellOccupied(this.context, row, col)) {
|
||||
if (isCellOccupied(this.context.value.parts, 'board', [row, col])) {
|
||||
return `Cell (${row}, ${col}) is occupied`;
|
||||
}
|
||||
return null;
|
||||
|
|
@ -426,7 +435,7 @@ registration.add('turn <player> <turn:number>', async function(cmd) {
|
|||
`piece-${player}-${turnNumber}`
|
||||
);
|
||||
this.context.produce(state => {
|
||||
state.parts.push(piece);
|
||||
state.parts[piece.id] = piece;
|
||||
state.board.childIds.push(piece.id);
|
||||
state.board.partMap[`${row},${col}`] = piece.id;
|
||||
});
|
||||
|
|
@ -486,12 +495,12 @@ const game = createGameContextFromModule(ticTacToe);
|
|||
| `PartTemplate<TMeta>` | 部件模板(创建时排除 id) |
|
||||
| `PartPool<TMeta>` | 部件池(draw/return/remaining) |
|
||||
| `createPart(template, id)` | 创建单个部件 |
|
||||
| `createParts(template, count, idPrefix)` | 批量创建部件 |
|
||||
| `createParts(template, count, idPrefix)` | 批量创建部件(ID 从 1 开始:`prefix-1`, `prefix-2`, ...) |
|
||||
| `createPartPool(template, count, idPrefix)` | 创建部件池 |
|
||||
| `mergePartPools(...pools)` | 合并部件池 |
|
||||
| `findPartById(parts, id)` | 按 ID 查找 |
|
||||
| `isCellOccupied(parts, regionId, position)` | 检查位置占用 |
|
||||
| `getPartAtPosition(parts, regionId, position)` | 获取位置上的部件 |
|
||||
| `findPartById(parts, id)` | 按 ID 查找(`parts` 为 `Record<string, Part>`) |
|
||||
| `isCellOccupied(parts, regionId, position)` | 检查位置占用(`parts` 为 `Record<string, Part>`) |
|
||||
| `getPartAtPosition(parts, regionId, position)` | 获取位置上的部件(`parts` 为 `Record<string, Part>`) |
|
||||
| `flip(part)` | 翻面 |
|
||||
| `flipTo(part, side)` | 翻到指定面 |
|
||||
| `roll(part, rng)` | 随机面 |
|
||||
|
|
@ -503,10 +512,10 @@ const game = createGameContextFromModule(ticTacToe);
|
|||
| `Region` | 区域类型 |
|
||||
| `RegionAxis` | 坐标轴定义 |
|
||||
| `createRegion(id, axes)` | 创建区域 |
|
||||
| `applyAlign(region, parts)` | 对齐/紧凑排列 |
|
||||
| `shuffle(region, parts, rng)` | 随机打乱位置 |
|
||||
| `moveToRegion(part, sourceRegion?, targetRegion, position?)` | 移动部件 |
|
||||
| `moveToRegionAll(parts, sourceRegion?, targetRegion, positions?)` | 批量移动 |
|
||||
| `applyAlign(region, parts)` | 对齐/紧凑排列(`parts` 为 `Record<string, Part>`) |
|
||||
| `shuffle(region, parts, rng)` | 随机打乱位置(`parts` 为 `Record<string, Part>`) |
|
||||
| `moveToRegion(part, sourceRegion?, targetRegion, position?)` | 移动部件(`sourceRegion` 可选) |
|
||||
| `moveToRegionAll(parts, sourceRegion?, targetRegion, positions?)` | 批量移动(`parts` 为 `Record<string, Part>`,`sourceRegion` 可选) |
|
||||
| `removeFromRegion(part, region)` | 移除部件 |
|
||||
|
||||
### Command
|
||||
|
|
@ -520,12 +529,18 @@ const game = createGameContextFromModule(ticTacToe);
|
|||
| `parseCommandSchema(schema)` | 解析模式字符串 |
|
||||
| `validateCommand(cmd, schema)` | 验证命令 |
|
||||
| `parseCommandWithSchema(cmd, schema)` | 解析并验证 |
|
||||
| `applyCommandSchema(cmd, schema)` | 应用模式验证并返回验证后的命令 |
|
||||
| `createCommandRegistry<TContext>()` | 创建命令注册表 |
|
||||
| `registerCommand(registry, runner)` | 注册命令 |
|
||||
| `unregisterCommand(registry, name)` | 取消注册命令 |
|
||||
| `hasCommand(registry, name)` | 检查命令是否存在 |
|
||||
| `getCommand(registry, name)` | 获取命令处理器 |
|
||||
| `runCommand(registry, context, input)` | 解析并运行命令 |
|
||||
| `runCommandParsed(registry, context, command)` | 运行已解析的命令 |
|
||||
| `createCommandRunnerContext(registry, context)` | 创建命令运行器上下文 |
|
||||
| `PromptEvent` | Prompt 事件(tryCommit/cancel) |
|
||||
| `CommandRunnerContext<TContext>` | 命令运行器上下文 |
|
||||
| `CommandRunnerContextExport<TContext>` | 导出的命令运行器上下文(含 `promptQueue`) |
|
||||
|
||||
### Utilities
|
||||
|
||||
|
|
@ -541,16 +556,20 @@ const game = createGameContextFromModule(ticTacToe);
|
|||
|
||||
- **总是使用 `produce()`** 更新状态,不要直接修改 `.value`
|
||||
- `produce()` 内部是 draft 模式,可以直接修改属性
|
||||
- **Parts 使用 Record 格式**,通过 ID 作为键访问
|
||||
|
||||
```ts
|
||||
// ✅ 正确
|
||||
state.produce(draft => {
|
||||
draft.score += 1;
|
||||
draft.parts.push(newPart);
|
||||
draft.parts[newPart.id] = newPart;
|
||||
});
|
||||
|
||||
// ❌ 错误 — 会破坏响应式
|
||||
state.value.score = 10;
|
||||
|
||||
// ❌ 错误 — parts 是 Record 不是数组
|
||||
state.parts.push(newPart);
|
||||
```
|
||||
|
||||
### 命令设计
|
||||
|
|
|
|||
|
|
@ -39,11 +39,10 @@ export function bindRegion<TState, TMeta>(
|
|||
container: Phaser.GameObjects.Container,
|
||||
): { cleanup: () => void; objects: Map<string, Phaser.GameObjects.GameObject> } {
|
||||
const objects = new Map<string, Phaser.GameObjects.GameObject>();
|
||||
const effects: DisposeFn[] = [];
|
||||
|
||||
const offset = options.offset ?? { x: 0, y: 0 };
|
||||
|
||||
function syncParts() {
|
||||
const dispose = effect(function(this: { dispose: () => void }) {
|
||||
const parts = partsGetter(state.value);
|
||||
const currentIds = new Set(region.childIds);
|
||||
for (const [id, obj] of objects) {
|
||||
|
|
@ -73,14 +72,11 @@ export function bindRegion<TState, TMeta>(
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const e = effect(syncParts);
|
||||
effects.push(e);
|
||||
});
|
||||
|
||||
return {
|
||||
cleanup: () => {
|
||||
for (const e of effects) e();
|
||||
dispose();
|
||||
for (const [, obj] of objects) obj.destroy();
|
||||
objects.clear();
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in New Issue