refactor: update GameHost to use generic state and result types
Decouple GameHost from GameState and GameResult types by introducing generic parameters for TState and TResult. This improves type safety and flexibility when defining GameModules.
This commit is contained in:
parent
5c1ef232fd
commit
fb3c98b1ef
|
|
@ -1,29 +1,28 @@
|
|||
import { ReadonlySignal, Signal } from "@preact/signals-core";
|
||||
import { createPromptContext } from "@/utils/command";
|
||||
import { createGameContext, IGameContext } from "./game";
|
||||
import { PromptContext } from "@/utils/command/command-prompt";
|
||||
import { ReadonlySignal, Signal } from "@preact/signals-core";
|
||||
import { createGameContext, IGameContext } from "./game";
|
||||
|
||||
export type GameHostStatus = "created" | "running" | "disposed";
|
||||
|
||||
export class GameHost<TModule extends GameModule> {
|
||||
readonly state: ReadonlySignal<GameState<TModule>>;
|
||||
export class GameHost<
|
||||
TState extends Record<string, unknown>,
|
||||
TResult = unknown,
|
||||
TModule extends GameModule<TState, TResult> = GameModule<TState, TResult>,
|
||||
> {
|
||||
readonly state: ReadonlySignal<TState>;
|
||||
readonly status: ReadonlySignal<GameHostStatus>;
|
||||
readonly prompts: PromptContext;
|
||||
|
||||
private _context: IGameContext<GameState<TModule>>;
|
||||
private _start: (
|
||||
ctx: IGameContext<GameState<TModule>>,
|
||||
) => Promise<GameResult<TModule>>;
|
||||
private _context: IGameContext<TState>;
|
||||
private _start: (ctx: IGameContext<TState>) => Promise<TResult>;
|
||||
private _status: Signal<GameHostStatus>;
|
||||
private _createInitialState: () => GameState<TModule>;
|
||||
private _createInitialState: () => TState;
|
||||
private _eventListeners: Map<"start" | "dispose", Set<() => void>>;
|
||||
private _isDisposed = false;
|
||||
|
||||
constructor(public readonly gameModule: TModule) {
|
||||
const { createInitialState, start } = gameModule as unknown as GameModule<
|
||||
GameState<TModule>,
|
||||
GameResult<TModule>
|
||||
>;
|
||||
const { createInitialState, start } = gameModule;
|
||||
this._createInitialState = createInitialState;
|
||||
this._eventListeners = new Map();
|
||||
|
||||
|
|
@ -53,7 +52,7 @@ export class GameHost<TModule extends GameModule> {
|
|||
this._context._state.clearInterruptions();
|
||||
}
|
||||
|
||||
start(seed?: number): Promise<GameResult<TModule>> {
|
||||
start(seed?: number): Promise<TResult> {
|
||||
if (this._isDisposed) {
|
||||
throw new Error("GameHost is disposed");
|
||||
}
|
||||
|
|
@ -115,15 +114,11 @@ export type GameModule<
|
|||
createInitialState: () => TState;
|
||||
start: (ctx: IGameContext<TState>) => Promise<TResult>;
|
||||
};
|
||||
export type GameState<TModule extends GameModule> = ReturnType<
|
||||
TModule["createInitialState"]
|
||||
>;
|
||||
export type GameResult<TModule extends GameModule> = Awaited<
|
||||
ReturnType<TModule["start"]>
|
||||
>;
|
||||
|
||||
export function createGameHost<TModule extends GameModule>(
|
||||
gameModule: TModule,
|
||||
): GameHost<TModule> {
|
||||
export function createGameHost<
|
||||
TState extends Record<string, unknown> = Record<string, unknown>,
|
||||
TResult = unknown,
|
||||
TModule extends GameModule<TState, TResult> = GameModule<TState, TResult>,
|
||||
>(gameModule: TModule): GameHost<TState, TResult, TModule> {
|
||||
return new GameHost(gameModule);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,13 +7,7 @@
|
|||
export type { IGameContext } from "./core/game";
|
||||
export { createPromptDef } from "./core/game";
|
||||
|
||||
export type {
|
||||
GameHost,
|
||||
GameHostStatus,
|
||||
GameModule,
|
||||
GameState,
|
||||
GameResult,
|
||||
} from "./core/game-host";
|
||||
export type { GameHost, GameHostStatus, GameModule } from "./core/game-host";
|
||||
export { createGameHost } from "./core/game-host";
|
||||
|
||||
export type { Part } from "./core/part";
|
||||
|
|
|
|||
Loading…
Reference in New Issue