refactor: reformat code and fix type signatures in GameHost

Reformat `src/core/game-host.ts` to use double quotes and consistent
spacing. Update `createGameHost` to correctly propagate the `TResult`
generic from `GameModule`.
This commit is contained in:
hypercross 2026-04-19 15:44:59 +08:00
parent 8142fbfa60
commit 1e1d04777f
1 changed files with 165 additions and 157 deletions

View File

@ -1,14 +1,18 @@
import { ReadonlySignal, Signal } from '@preact/signals-core';
import { ReadonlySignal, Signal } from "@preact/signals-core";
import { CommandSchema, CommandRegistry, PromptEvent } from "@/utils/command";
import {
CommandSchema,
CommandRegistry,
PromptEvent,
} from '@/utils/command';
import {createGameCommandRegistry, createGameContext, IGameContext, PromptDef} from './game';
createGameCommandRegistry,
createGameContext,
IGameContext,
PromptDef,
} from "./game";
export type GameHostStatus = 'created' | 'running' | 'disposed';
export type GameHostStatus = "created" | "running" | "disposed";
export class GameHost<TState extends Record<string, unknown>, TResult=unknown> {
export class GameHost<
TState extends Record<string, unknown>,
TResult = unknown,
> {
readonly state: ReadonlySignal<TState>;
readonly status: ReadonlySignal<GameHostStatus>;
readonly activePromptSchema: ReadonlySignal<CommandSchema | null>;
@ -22,13 +26,13 @@ export class GameHost<TState extends Record<string, unknown>, TResult=unknown> {
private _activePromptPlayer: Signal<string | null>;
private _activePromptHint: Signal<string | null>;
private _createInitialState: () => TState;
private _eventListeners: Map<'start' | 'dispose', Set<() => void>>;
private _eventListeners: Map<"start" | "dispose", Set<() => void>>;
private _isDisposed = false;
constructor(
registry: CommandRegistry<IGameContext<TState>>,
createInitialState: () => TState,
start: (ctx: IGameContext<TState>) => Promise<TResult>
start: (ctx: IGameContext<TState>) => Promise<TResult>,
) {
this._createInitialState = createInitialState;
this._eventListeners = new Map();
@ -38,7 +42,7 @@ export class GameHost<TState extends Record<string, unknown>, TResult=unknown> {
this._start = start;
this.state = this._context._state;
this._status = new Signal<GameHostStatus>('created');
this._status = new Signal<GameHostStatus>("created");
this.status = this._status;
this._activePromptSchema = new Signal<CommandSchema | null>(null);
@ -56,14 +60,14 @@ export class GameHost<TState extends Record<string, unknown>, TResult=unknown> {
private _setupPromptTracking() {
let currentPromptEvent: PromptEvent | null = null;
this._context._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._activePromptHint.value = currentPromptEvent.hintText || null;
});
this._context._commands.on('promptEnd', () => {
this._context._commands.on("promptEnd", () => {
currentPromptEvent = null;
this._activePromptSchema.value = null;
this._activePromptPlayer.value = null;
@ -78,7 +82,7 @@ export class GameHost<TState extends Record<string, unknown>, TResult=unknown> {
tryInput(input: string): string | null {
if (this._isDisposed) {
return 'GameHost is disposed';
return "GameHost is disposed";
}
return this._context._commands._tryCommit(input);
}
@ -88,7 +92,7 @@ export class GameHost<TState extends Record<string, unknown>, TResult=unknown> {
name: def.schema.name,
params: args,
options: {},
flags: {}
flags: {},
});
}
@ -110,7 +114,7 @@ export class GameHost<TState extends Record<string, unknown>, TResult=unknown> {
start(seed?: number): Promise<TResult> {
if (this._isDisposed) {
throw new Error('GameHost is disposed');
throw new Error("GameHost is disposed");
}
this._context._commands._cancel();
@ -122,8 +126,8 @@ export class GameHost<TState extends Record<string, unknown>, TResult=unknown> {
this._context._rng.setSeed(seed);
const promise = this._start(this._context);
this._status.value = 'running';
this._emitEvent('start');
this._status.value = "running";
this._emitEvent("start");
return promise;
}
@ -135,14 +139,14 @@ export class GameHost<TState extends Record<string, unknown>, TResult=unknown> {
this._isDisposed = true;
this._context._commands._cancel();
this._status.value = 'disposed';
this._status.value = "disposed";
// Emit dispose event BEFORE clearing listeners
this._emitEvent('dispose');
this._emitEvent("dispose");
this._eventListeners.clear();
}
on(event: 'start' | 'dispose', listener: () => void): () => void {
on(event: "start" | "dispose", listener: () => void): () => void {
if (!this._eventListeners.has(event)) {
this._eventListeners.set(event, new Set());
}
@ -153,7 +157,7 @@ export class GameHost<TState extends Record<string, unknown>, TResult=unknown> {
};
}
private _emitEvent(event: 'start' | 'dispose') {
private _emitEvent(event: "start" | "dispose") {
const listeners = this._eventListeners.get(event);
if (listeners) {
for (const listener of listeners) {
@ -163,18 +167,22 @@ export class GameHost<TState extends Record<string, unknown>, TResult=unknown> {
}
}
export type GameModule<TState extends Record<string, unknown>, TResult=unknown> = {
export type GameModule<
TState extends Record<string, unknown>,
TResult = unknown,
> = {
registry?: CommandRegistry<IGameContext<TState>>;
createInitialState: () => TState;
start: (ctx: IGameContext<TState>) => Promise<TResult>;
}
};
export function createGameHost<TState extends Record<string, unknown>>(
gameModule: GameModule<TState>
): GameHost<TState> {
export function createGameHost<
TState extends Record<string, unknown>,
TResult = unknown,
>(gameModule: GameModule<TState, TResult>): GameHost<TState, TResult> {
return new GameHost(
gameModule.registry || createGameCommandRegistry(),
gameModule.createInitialState,
gameModule.start
gameModule.start,
);
}