refactor: renaming api

This commit is contained in:
hypercross 2026-04-06 09:46:59 +08:00
parent 8c2c6dc94c
commit 2d5200bdb7
7 changed files with 42 additions and 42 deletions

View File

@ -24,7 +24,7 @@ import { createGameHost } from 'boardgame-core';
import * as tictactoe from 'boardgame-core/samples/tic-tac-toe'; import * as tictactoe from 'boardgame-core/samples/tic-tac-toe';
const host = createGameHost(tictactoe); const host = createGameHost(tictactoe);
await host.setup('setup'); await host.start('start');
// 监听状态变化 // 监听状态变化
effect(() => { effect(() => {

View File

@ -23,7 +23,7 @@ export class GameHost<TState extends Record<string, unknown>> {
private _activePromptSchema: Signal<CommandSchema | null>; private _activePromptSchema: Signal<CommandSchema | null>;
private _activePromptPlayer: Signal<string | null>; private _activePromptPlayer: Signal<string | null>;
private _createInitialState: () => TState; private _createInitialState: () => TState;
private _eventListeners: Map<'setup' | 'dispose', Set<() => void>>; private _eventListeners: Map<'start' | 'dispose', Set<() => void>>;
private _isDisposed = false; private _isDisposed = false;
constructor( constructor(
@ -94,7 +94,7 @@ export class GameHost<TState extends Record<string, unknown>> {
this._state.clearInterruptions(); this._state.clearInterruptions();
} }
setup(setupCommand: string): Promise<CommandResult<unknown>> { start(startCommand: string): Promise<CommandResult<unknown>> {
if (this._isDisposed) { if (this._isDisposed) {
throw new Error('GameHost is disposed'); throw new Error('GameHost is disposed');
} }
@ -104,10 +104,10 @@ export class GameHost<TState extends Record<string, unknown>> {
const initialState = this._createInitialState(); const initialState = this._createInitialState();
this._state.value = initialState as any; this._state.value = initialState as any;
const promise = this._commands.run(setupCommand); const promise = this._commands.run(startCommand);
this._status.value = 'running'; this._status.value = 'running';
this._emitEvent('setup'); this._emitEvent('start');
return promise; return promise;
} }
@ -126,7 +126,7 @@ export class GameHost<TState extends Record<string, unknown>> {
this._eventListeners.clear(); this._eventListeners.clear();
} }
on(event: 'setup' | 'dispose', listener: () => void): () => void { on(event: 'start' | 'dispose', listener: () => void): () => void {
if (!this._eventListeners.has(event)) { if (!this._eventListeners.has(event)) {
this._eventListeners.set(event, new Set()); this._eventListeners.set(event, new Set());
} }
@ -137,7 +137,7 @@ export class GameHost<TState extends Record<string, unknown>> {
}; };
} }
private _emitEvent(event: 'setup' | 'dispose') { private _emitEvent(event: 'start' | 'dispose') {
const listeners = this._eventListeners.get(event); const listeners = this._eventListeners.get(event);
if (listeners) { if (listeners) {
for (const listener of listeners) { for (const listener of listeners) {

View File

@ -42,7 +42,7 @@ async function place(game: BoopGame, row: number, col: number, player: PlayerTyp
return { row, col, player, type, partId }; return { row, col, player, type, partId };
} }
const placeCommand = registry.register( 'place <row:number> <col:number> <player> <type>', place); const placeCommand = registry.asCommand( 'place <row:number> <col:number> <player> <type>', place);
/** /**
* boop - * boop -
@ -85,7 +85,7 @@ async function boop(game: BoopGame, row: number, col: number, type: PieceType) {
return { booped }; return { booped };
} }
const boopCommand = registry.register('boop <row:number> <col:number> <type>', boop); const boopCommand = registry.asCommand('boop <row:number> <col:number> <type>', boop);
/** /**
* (线) * (线)
@ -109,7 +109,7 @@ async function checkWin(game: BoopGame): Promise<WinnerType | null> {
} }
return null; return null;
} }
const checkWinCommand = registry.register('check-win', checkWin); const checkWinCommand = registry.asCommand('check-win', checkWin);
/** /**
* (线) * (线)
@ -145,7 +145,7 @@ async function checkGraduates(game: BoopGame){
} }
}); });
} }
const checkGraduatesCommand = registry.register('check-graduates', checkGraduates); const checkGraduatesCommand = registry.asCommand('check-graduates', checkGraduates);
async function setup(game: BoopGame) { async function setup(game: BoopGame) {
while (true) { while (true) {
@ -163,7 +163,7 @@ async function setup(game: BoopGame) {
return game.value; return game.value;
} }
registry.register('setup', setup); registry.asCommand('setup', setup);
async function checkFullBoard(game: BoopGame, turnPlayer: PlayerType){ async function checkFullBoard(game: BoopGame, turnPlayer: PlayerType){
// 检查8-piece规则: 如果玩家所有8个棋子都在棋盘上且没有获胜,强制升级一个小猫 // 检查8-piece规则: 如果玩家所有8个棋子都在棋盘上且没有获胜,强制升级一个小猫
@ -238,4 +238,4 @@ async function turn(game: BoopGame, turnPlayer: PlayerType) {
await checkFullBoard(game, turnPlayer); await checkFullBoard(game, turnPlayer);
return { winner: null }; return { winner: null };
} }
const turnCommand = registry.register('turn <player>', turn); const turnCommand = registry.asCommand('turn <player>', turn);

View File

@ -36,7 +36,7 @@ export type TicTacToeState = ReturnType<typeof createInitialState>;
export type TicTacToeGame = IGameContext<TicTacToeState>; export type TicTacToeGame = IGameContext<TicTacToeState>;
export const registry = createGameCommandRegistry<TicTacToeState>(); export const registry = createGameCommandRegistry<TicTacToeState>();
async function setup(game: TicTacToeGame) { async function start(game: TicTacToeGame) {
while (true) { while (true) {
const currentPlayer = game.value.currentPlayer; const currentPlayer = game.value.currentPlayer;
const turnNumber = game.value.turn + 1; const turnNumber = game.value.turn + 1;
@ -54,7 +54,7 @@ async function setup(game: TicTacToeGame) {
return game.value; return game.value;
} }
registry.register('setup', setup); registry.asCommand('start', start);
async function turn(game: TicTacToeGame, turnPlayer: PlayerType, turnNumber: number) { async function turn(game: TicTacToeGame, turnPlayer: PlayerType, turnNumber: number) {
const {player, row, col} = await game.prompt( const {player, row, col} = await game.prompt(
@ -83,7 +83,7 @@ async function turn(game: TicTacToeGame, turnPlayer: PlayerType, turnNumber: num
return { winner: null }; return { winner: null };
} }
const turnCommand = registry.register('turn <player:string> <turnNumber:int>', turn); const turnCommand = registry.asCommand('turn <player:string> <turnNumber:int>', turn);
function isValidMove(row: number, col: number): boolean { function isValidMove(row: number, col: number): boolean {
return !isNaN(row) && !isNaN(col) && row >= 0 && row < BOARD_SIZE && col >= 0 && col < BOARD_SIZE; return !isNaN(row) && !isNaN(col) && row >= 0 && row < BOARD_SIZE && col >= 0 && col < BOARD_SIZE;

View File

@ -18,7 +18,7 @@ type CanRunParsed = {
type CmdFunc<TContext> = (ctx: TContext, ...args: any[]) => Promise<unknown>; type CmdFunc<TContext> = (ctx: TContext, ...args: any[]) => Promise<unknown>;
export class CommandRegistry<TContext> extends Map<string, CommandRunner<TContext>>{ export class CommandRegistry<TContext> extends Map<string, CommandRunner<TContext>>{
register<TFunc extends CmdFunc<TContext> = CmdFunc<TContext>>(schema: CommandSchema | string, run: TFunc) { asCommand<TFunc extends CmdFunc<TContext> = CmdFunc<TContext>>(schema: CommandSchema | string, run: TFunc) {
const parsedSchema = typeof schema === 'string' ? parseCommandSchema(schema) : schema; const parsedSchema = typeof schema === 'string' ? parseCommandSchema(schema) : schema;
registerCommand(this, { registerCommand(this, {
schema: parsedSchema, schema: parsedSchema,

View File

@ -59,7 +59,7 @@ describe('GameHost', () => {
const { host } = createTestHost(); const { host } = createTestHost();
const promptPromise = waitForPromptEvent(host); const promptPromise = waitForPromptEvent(host);
const runPromise = host.context._commands.run('setup'); const runPromise = host.context._commands.run('start');
const promptEvent = await promptPromise; const promptEvent = await promptPromise;
expect(promptEvent.schema.name).toBe('play'); expect(promptEvent.schema.name).toBe('play');
@ -68,7 +68,7 @@ describe('GameHost', () => {
const error = host.onInput('play X 1 1'); const error = host.onInput('play X 1 1');
expect(error).toBeNull(); expect(error).toBeNull();
// Cancel to end the game since setup runs until game over // Cancel to end the game since start runs until game over
const nextPromptPromise = waitForPromptEvent(host); const nextPromptPromise = waitForPromptEvent(host);
const nextPrompt = await nextPromptPromise; const nextPrompt = await nextPromptPromise;
nextPrompt.cancel('test cleanup'); nextPrompt.cancel('test cleanup');
@ -81,7 +81,7 @@ describe('GameHost', () => {
const { host } = createTestHost(); const { host } = createTestHost();
const promptPromise = waitForPromptEvent(host); const promptPromise = waitForPromptEvent(host);
const runPromise = host.context._commands.run('setup'); const runPromise = host.context._commands.run('start');
const promptEvent = await promptPromise; const promptEvent = await promptPromise;
@ -106,7 +106,7 @@ describe('GameHost', () => {
const { host } = createTestHost(); const { host } = createTestHost();
const promptPromise = waitForPromptEvent(host); const promptPromise = waitForPromptEvent(host);
const runPromise = host.context._commands.run('setup'); const runPromise = host.context._commands.run('start');
const promptEvent = await promptPromise; const promptEvent = await promptPromise;
const schema = host.activePromptSchema.value; const schema = host.activePromptSchema.value;
@ -125,13 +125,13 @@ describe('GameHost', () => {
}); });
}); });
describe('setup', () => { describe('start', () => {
it('should reset state and run setup command', async () => { it('should reset state and run start command', async () => {
const { host } = createTestHost(); const { host } = createTestHost();
// First setup - make one move // First setup - make one move
let promptPromise = waitForPromptEvent(host); let promptPromise = waitForPromptEvent(host);
let runPromise = host.context._commands.run('setup'); let runPromise = host.context._commands.run('start');
let promptEvent = await promptPromise; let promptEvent = await promptPromise;
// Make a move // Make a move
@ -146,11 +146,11 @@ describe('GameHost', () => {
expect(result.success).toBe(false); // Cancelled expect(result.success).toBe(false); // Cancelled
expect(Object.keys(host.context._state.value.parts).length).toBe(1); expect(Object.keys(host.context._state.value.parts).length).toBe(1);
// Setup listener before calling setup // Setup listener before calling start
const newPromptPromise = waitForPromptEvent(host); const newPromptPromise = waitForPromptEvent(host);
// Reset - should reset state and start new game // Reset - should reset state and start new game
host.setup('setup'); host.start('start');
// State should be back to initial // State should be back to initial
expect(host.context._state.value.currentPlayer).toBe('X'); expect(host.context._state.value.currentPlayer).toBe('X');
@ -164,16 +164,16 @@ describe('GameHost', () => {
newPrompt.cancel('test end'); newPrompt.cancel('test end');
}); });
it('should cancel active prompt during setup', async () => { it('should cancel active prompt during start', async () => {
const { host } = createTestHost(); const { host } = createTestHost();
const promptPromise = waitForPromptEvent(host); const promptPromise = waitForPromptEvent(host);
const runPromise = host.context._commands.run('setup'); const runPromise = host.context._commands.run('start');
await promptPromise; await promptPromise;
// Setup should cancel the active prompt and reset state // Setup should cancel the active prompt and reset state
host.setup('setup'); host.start('start');
// The original runPromise should be rejected due to cancellation // The original runPromise should be rejected due to cancellation
try { try {
@ -192,7 +192,7 @@ describe('GameHost', () => {
const { host } = createTestHost(); const { host } = createTestHost();
host.dispose(); host.dispose();
expect(() => host.setup('setup')).toThrow('GameHost is disposed'); expect(() => host.start('start')).toThrow('GameHost is disposed');
}); });
}); });
@ -208,7 +208,7 @@ describe('GameHost', () => {
const { host } = createTestHost(); const { host } = createTestHost();
const promptPromise = waitForPromptEvent(host); const promptPromise = waitForPromptEvent(host);
const runPromise = host.context._commands.run('setup'); const runPromise = host.context._commands.run('start');
await promptPromise; await promptPromise;
@ -233,11 +233,11 @@ describe('GameHost', () => {
}); });
describe('events', () => { describe('events', () => {
it('should emit setup event', async () => { it('should emit start event', async () => {
const { host } = createTestHost(); const { host } = createTestHost();
let setupCount = 0; let setupCount = 0;
host.on('setup', () => { host.on('start', () => {
setupCount++; setupCount++;
}); });
@ -245,7 +245,7 @@ describe('GameHost', () => {
const promptPromise = waitForPromptEvent(host); const promptPromise = waitForPromptEvent(host);
// Initial setup via reset // Initial setup via reset
host.setup('setup'); host.start('start');
expect(setupCount).toBe(1); expect(setupCount).toBe(1);
// State should be running // State should be running
@ -272,7 +272,7 @@ describe('GameHost', () => {
const { host } = createTestHost(); const { host } = createTestHost();
let setupCount = 0; let setupCount = 0;
const unsubscribe = host.on('setup', () => { const unsubscribe = host.on('start', () => {
setupCount++; setupCount++;
}); });
@ -294,7 +294,7 @@ describe('GameHost', () => {
// Make a move // Make a move
const promptPromise = waitForPromptEvent(host); const promptPromise = waitForPromptEvent(host);
const runPromise = host.context._commands.run('setup'); const runPromise = host.context._commands.run('start');
const promptEvent = await promptPromise; const promptEvent = await promptPromise;
promptEvent.tryCommit({ name: 'play', params: ['X', 1, 1], options: {}, flags: {} }); promptEvent.tryCommit({ name: 'play', params: ['X', 1, 1], options: {}, flags: {} });
@ -320,7 +320,7 @@ describe('GameHost', () => {
// Start a command that triggers prompt // Start a command that triggers prompt
const promptPromise = waitForPromptEvent(host); const promptPromise = waitForPromptEvent(host);
const runPromise = host.context._commands.run('setup'); const runPromise = host.context._commands.run('start');
await promptPromise; await promptPromise;
@ -369,7 +369,7 @@ describe('GameHost', () => {
}); });
// Start setup command (runs game loop until completion) // Start setup command (runs game loop until completion)
const setupPromise = host.context._commands.run('setup'); const setupPromise = host.context._commands.run('start');
for (let i = 0; i < moves.length; i++) { for (let i = 0; i < moves.length; i++) {
// Wait until the next prompt event arrives // Wait until the next prompt event arrives
@ -415,7 +415,7 @@ describe('GameHost', () => {
const { host } = createTestHost(); const { host } = createTestHost();
const promptPromise = waitForPromptEvent(host); const promptPromise = waitForPromptEvent(host);
const runPromise = host.context._commands.run('setup'); const runPromise = host.context._commands.run('start');
const promptEvent = await promptPromise; const promptEvent = await promptPromise;
expect(promptEvent.currentPlayer).toBe('X'); expect(promptEvent.currentPlayer).toBe('X');
@ -433,7 +433,7 @@ describe('GameHost', () => {
// First prompt - X's turn // First prompt - X's turn
let promptPromise = waitForPromptEvent(host); let promptPromise = waitForPromptEvent(host);
let runPromise = host.context._commands.run('setup'); let runPromise = host.context._commands.run('start');
let promptEvent = await promptPromise; let promptEvent = await promptPromise;
expect(promptEvent.currentPlayer).toBe('X'); expect(promptEvent.currentPlayer).toBe('X');
expect(host.activePromptPlayer.value).toBe('X'); expect(host.activePromptPlayer.value).toBe('X');

View File

@ -176,7 +176,7 @@ describe('TicTacToe - game flow', () => {
it('should have setup and turn commands registered', () => { it('should have setup and turn commands registered', () => {
const { registry: reg } = createTestContext(); const { registry: reg } = createTestContext();
expect(reg.has('setup')).toBe(true); expect(reg.has('start')).toBe(true);
expect(reg.has('turn')).toBe(true); expect(reg.has('turn')).toBe(true);
}); });
@ -184,7 +184,7 @@ describe('TicTacToe - game flow', () => {
const { ctx } = createTestContext(); const { ctx } = createTestContext();
const promptPromise = waitForPrompt(ctx); const promptPromise = waitForPrompt(ctx);
const runPromise = ctx.run('setup'); const runPromise = ctx.run('start');
const promptEvent = await promptPromise; const promptEvent = await promptPromise;
expect(promptEvent).not.toBeNull(); expect(promptEvent).not.toBeNull();