refactor: api change to add prompt text

This commit is contained in:
hypercross 2026-04-07 15:03:15 +08:00
parent b3cea805b0
commit beb8088009
4 changed files with 21 additions and 10 deletions

View File

@ -3,7 +3,6 @@ import {
CommandSchema,
CommandRegistry,
PromptEvent,
parseCommandSchema,
} from '@/utils/command';
import {createGameCommandRegistry, createGameContext, IGameContext, PromptDef} from './game';
@ -14,12 +13,14 @@ export class GameHost<TState extends Record<string, unknown>, TResult=unknown> {
readonly status: ReadonlySignal<GameHostStatus>;
readonly activePromptSchema: ReadonlySignal<CommandSchema | null>;
readonly activePromptPlayer: ReadonlySignal<string | null>;
readonly activePromptHint: ReadonlySignal<string | null>;
private _context: IGameContext<TState>;
private _start: (ctx: IGameContext<TState>) => Promise<TResult>;
private _status: Signal<GameHostStatus>;
private _activePromptSchema: Signal<CommandSchema | null>;
private _activePromptPlayer: Signal<string | null>;
private _activePromptHint: Signal<string | null>;
private _createInitialState: () => TState;
private _eventListeners: Map<'start' | 'dispose', Set<() => void>>;
private _isDisposed = false;
@ -46,6 +47,9 @@ export class GameHost<TState extends Record<string, unknown>, TResult=unknown> {
this._activePromptPlayer = new Signal<string | null>(null);
this.activePromptPlayer = this._activePromptPlayer;
this._activePromptHint = new Signal<string | null>(null);
this.activePromptHint = this._activePromptHint;
this._setupPromptTracking();
}
@ -56,17 +60,20 @@ export class GameHost<TState extends Record<string, unknown>, TResult=unknown> {
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', () => {
currentPromptEvent = null;
this._activePromptSchema.value = null;
this._activePromptPlayer.value = null;
this._activePromptHint.value = null;
});
// Initial state
this._activePromptSchema.value = null;
this._activePromptPlayer.value = null;
this._activePromptHint.value = null;
}
tryInput(input: string): string | null {
@ -77,7 +84,6 @@ export class GameHost<TState extends Record<string, unknown>, TResult=unknown> {
}
tryAnswerPrompt<TArgs extends any[]>(def: PromptDef<TArgs>, ...args: TArgs){
if(typeof def.schema === 'string') def.schema = parseCommandSchema(def.schema);
return this._context._commands._tryCommit({
name: def.schema.name,
params: args,

View File

@ -5,7 +5,7 @@ import {
CommandRunnerContextExport,
CommandSchema,
createCommandRegistry,
createCommandRunnerContext,
createCommandRunnerContext, parseCommandSchema,
} from "@/utils/command";
import {PromptValidator} from "@/utils/command/command-runner";
@ -47,7 +47,7 @@ export function createGameContext<TState extends Record<string, unknown> = {} >(
return commands.runParsed<T>(command);
},
prompt(def, validator, currentPlayer) {
return commands.prompt(def.schema, validator, currentPlayer);
return commands.prompt(def.schema, validator, def.hintText, currentPlayer);
},
_state: state,
@ -60,10 +60,12 @@ export function createGameContext<TState extends Record<string, unknown> = {} >(
}
export type PromptDef<TArgs extends any[]=any[]> = {
schema: CommandSchema | string,
schema: CommandSchema,
hintText?: string,
}
export function createPromptDef<TArgs extends any[]=any[]>(schema: CommandSchema | string): PromptDef<TArgs> {
return { schema };
export function createPromptDef<TArgs extends any[]=any[]>(schema: CommandSchema | string, hintText?: string): PromptDef<TArgs> {
schema = typeof schema === 'string' ? parseCommandSchema(schema) : schema;
return { schema, hintText };
}
export function createGameCommandRegistry<TState extends Record<string, unknown> = {} >() {

View File

@ -146,8 +146,9 @@ export function createCommandRunnerContext<TContext>(
};
const prompt = <TResult,TArgs extends any[]=any[]>(
schema: CommandSchema | string,
schema: CommandSchema,
validator: PromptValidator<TResult,TArgs>,
hintText?: string,
currentPlayer?: string | null
): Promise<TResult> => {
const resolvedSchema = typeof schema === 'string' ? parseCommandSchema(schema) : schema;
@ -174,7 +175,7 @@ export function createCommandRunnerContext<TContext>(
emitPromptEnd();
reject(new Error(reason ?? 'Cancelled'));
};
activePrompt = { schema: resolvedSchema, currentPlayer: currentPlayer ?? null, tryCommit, cancel };
activePrompt = { schema: resolvedSchema, hintText, currentPlayer: currentPlayer ?? null, tryCommit, cancel };
const event: PromptEvent = { schema: resolvedSchema, currentPlayer: currentPlayer ?? null, tryCommit, cancel };
for (const listener of promptListeners) {
listener(event);

View File

@ -2,6 +2,8 @@ import type { Command, CommandSchema } from './types';
export type PromptEvent = {
schema: CommandSchema;
/** 提示文本 */
hintText?: string;
/** 当前等待输入的玩家 */
currentPlayer: string | null;
/**
@ -35,7 +37,7 @@ export type CommandRunnerContext<TContext> = {
context: TContext;
run: <T=unknown>(input: string) => Promise<CommandResult<T>>;
runParsed: <T=unknown>(command: Command) => Promise<CommandResult<T>>;
prompt: <TResult,TArgs extends any[]=any[]>(schema: CommandSchema | string, validator: PromptValidator<TResult,TArgs>, currentPlayer?: string | null) => Promise<TResult>;
prompt: <TResult,TArgs extends any[]=any[]>(schema: CommandSchema, validator: PromptValidator<TResult,TArgs>, hintText?: string, currentPlayer?: string | null) => Promise<TResult>;
on: <T extends keyof CommandRunnerEvents>(event: T, listener: (e: CommandRunnerEvents[T]) => void) => void;
off: <T extends keyof CommandRunnerEvents>(event: T, listener: (e: CommandRunnerEvents[T]) => void) => void;
};