refactor: hide api

This commit is contained in:
hypercross 2026-04-06 11:59:39 +08:00
parent 1e7dbea129
commit 49109963bc
2 changed files with 22 additions and 20 deletions

View File

@ -1,23 +1,20 @@
import { ReadonlySignal, Signal } from '@preact/signals-core';
import type {
import {
CommandSchema,
CommandRegistry,
PromptEvent,
CommandRunnerContextExport,
} from '@/utils/command';
import type { MutableSignal } from '@/utils/mutable-signal';
import {createGameCommandRegistry, createGameContext, IGameContext} from './game';
export type GameHostStatus = 'created' | 'running' | 'disposed';
export class GameHost<TState extends Record<string, unknown>, TResult=unknown> {
readonly context: IGameContext<TState>;
readonly state: ReadonlySignal<TState>;
readonly status: ReadonlySignal<GameHostStatus>;
readonly activePromptSchema: ReadonlySignal<CommandSchema | null>;
readonly activePromptPlayer: ReadonlySignal<string | null>;
private _state: MutableSignal<TState>;
private _commands: CommandRunnerContextExport<IGameContext<TState>>;
private _context: IGameContext<TState>;
private _start: (ctx: IGameContext<TState>) => Promise<TResult>;
private _status: Signal<GameHostStatus>;
private _activePromptSchema: Signal<CommandSchema | null>;
@ -35,8 +32,9 @@ export class GameHost<TState extends Record<string, unknown>, TResult=unknown> {
this._eventListeners = new Map();
const initialState = createInitialState();
this.context = createGameContext(registry, initialState);
this._context = createGameContext(registry, initialState);
this._start = start;
this.state = this._context._state;
this._status = new Signal<GameHostStatus>('created');
this.status = this._status;
@ -47,22 +45,19 @@ export class GameHost<TState extends Record<string, unknown>, TResult=unknown> {
this._activePromptPlayer = new Signal<string | null>(null);
this.activePromptPlayer = this._activePromptPlayer;
this._state = this.context._state;
this._commands = this.context._commands;
this._setupPromptTracking();
}
private _setupPromptTracking() {
let currentPromptEvent: PromptEvent | null = null;
this._commands.on('prompt', (e) => {
this._context._commands.on('prompt', (e) => {
currentPromptEvent = e as PromptEvent;
this._activePromptSchema.value = currentPromptEvent.schema;
this._activePromptPlayer.value = currentPromptEvent.currentPlayer;
});
this._commands.on('promptEnd', () => {
this._context._commands.on('promptEnd', () => {
currentPromptEvent = null;
this._activePromptSchema.value = null;
this._activePromptPlayer.value = null;
@ -77,7 +72,7 @@ export class GameHost<TState extends Record<string, unknown>, TResult=unknown> {
if (this._isDisposed) {
return 'GameHost is disposed';
}
return this._commands._tryCommit(input);
return this._context._commands._tryCommit(input);
}
/**
@ -85,7 +80,7 @@ export class GameHost<TState extends Record<string, unknown>, TResult=unknown> {
* @see MutableSignal.addInterruption
*/
addInterruption(promise: Promise<void>): void {
this._state.addInterruption(promise);
this._context._state.addInterruption(promise);
}
/**
@ -93,7 +88,7 @@ export class GameHost<TState extends Record<string, unknown>, TResult=unknown> {
* @see MutableSignal.clearInterruptions
*/
clearInterruptions(): void {
this._state.clearInterruptions();
this._context._state.clearInterruptions();
}
start(): Promise<TResult> {
@ -101,12 +96,12 @@ export class GameHost<TState extends Record<string, unknown>, TResult=unknown> {
throw new Error('GameHost is disposed');
}
this._commands._cancel();
this._context._commands._cancel();
const initialState = this._createInitialState();
this._state.value = initialState as any;
this._context._state.value = initialState as any;
const promise = this._start(this.context);
const promise = this._start(this._context);
this._status.value = 'running';
this._emitEvent('start');
@ -120,7 +115,7 @@ export class GameHost<TState extends Record<string, unknown>, TResult=unknown> {
}
this._isDisposed = true;
this._commands._cancel();
this._context._commands._cancel();
this._status.value = 'disposed';
// Emit dispose event BEFORE clearing listeners

View File

@ -10,11 +10,18 @@ import {
import { createGameHost, GameHost } from '@/core/game-host';
import type { PromptEvent } from '@/utils/command';
import { MutableSignal } from '@/utils/mutable-signal';
import {IGameContext} from "../../src";
type TestGameHost = GameHost<TicTacToeState> & {
_context: IGameContext<TicTacToeState>;
context: IGameContext<TicTacToeState>;
}
function createTestHost() {
const host = createGameHost(
const host: TestGameHost = createGameHost(
{ registry, createInitialState, start }
);
host.context = host._context;
return { host };
}