refactor: api change to add prompt text
This commit is contained in:
parent
b3cea805b0
commit
beb8088009
|
|
@ -3,7 +3,6 @@ import {
|
||||||
CommandSchema,
|
CommandSchema,
|
||||||
CommandRegistry,
|
CommandRegistry,
|
||||||
PromptEvent,
|
PromptEvent,
|
||||||
parseCommandSchema,
|
|
||||||
} from '@/utils/command';
|
} from '@/utils/command';
|
||||||
import {createGameCommandRegistry, createGameContext, IGameContext, PromptDef} from './game';
|
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 status: ReadonlySignal<GameHostStatus>;
|
||||||
readonly activePromptSchema: ReadonlySignal<CommandSchema | null>;
|
readonly activePromptSchema: ReadonlySignal<CommandSchema | null>;
|
||||||
readonly activePromptPlayer: ReadonlySignal<string | null>;
|
readonly activePromptPlayer: ReadonlySignal<string | null>;
|
||||||
|
readonly activePromptHint: ReadonlySignal<string | null>;
|
||||||
|
|
||||||
private _context: IGameContext<TState>;
|
private _context: IGameContext<TState>;
|
||||||
private _start: (ctx: IGameContext<TState>) => Promise<TResult>;
|
private _start: (ctx: IGameContext<TState>) => Promise<TResult>;
|
||||||
private _status: Signal<GameHostStatus>;
|
private _status: Signal<GameHostStatus>;
|
||||||
private _activePromptSchema: Signal<CommandSchema | null>;
|
private _activePromptSchema: Signal<CommandSchema | null>;
|
||||||
private _activePromptPlayer: Signal<string | null>;
|
private _activePromptPlayer: Signal<string | null>;
|
||||||
|
private _activePromptHint: Signal<string | null>;
|
||||||
private _createInitialState: () => TState;
|
private _createInitialState: () => TState;
|
||||||
private _eventListeners: Map<'start' | 'dispose', Set<() => void>>;
|
private _eventListeners: Map<'start' | 'dispose', Set<() => void>>;
|
||||||
private _isDisposed = false;
|
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 = new Signal<string | null>(null);
|
||||||
this.activePromptPlayer = this._activePromptPlayer;
|
this.activePromptPlayer = this._activePromptPlayer;
|
||||||
|
|
||||||
|
this._activePromptHint = new Signal<string | null>(null);
|
||||||
|
this.activePromptHint = this._activePromptHint;
|
||||||
|
|
||||||
this._setupPromptTracking();
|
this._setupPromptTracking();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -56,17 +60,20 @@ export class GameHost<TState extends Record<string, unknown>, TResult=unknown> {
|
||||||
currentPromptEvent = e as PromptEvent;
|
currentPromptEvent = e as PromptEvent;
|
||||||
this._activePromptSchema.value = currentPromptEvent.schema;
|
this._activePromptSchema.value = currentPromptEvent.schema;
|
||||||
this._activePromptPlayer.value = currentPromptEvent.currentPlayer;
|
this._activePromptPlayer.value = currentPromptEvent.currentPlayer;
|
||||||
|
this._activePromptHint.value = currentPromptEvent.hintText || null;
|
||||||
});
|
});
|
||||||
|
|
||||||
this._context._commands.on('promptEnd', () => {
|
this._context._commands.on('promptEnd', () => {
|
||||||
currentPromptEvent = null;
|
currentPromptEvent = null;
|
||||||
this._activePromptSchema.value = null;
|
this._activePromptSchema.value = null;
|
||||||
this._activePromptPlayer.value = null;
|
this._activePromptPlayer.value = null;
|
||||||
|
this._activePromptHint.value = null;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Initial state
|
// Initial state
|
||||||
this._activePromptSchema.value = null;
|
this._activePromptSchema.value = null;
|
||||||
this._activePromptPlayer.value = null;
|
this._activePromptPlayer.value = null;
|
||||||
|
this._activePromptHint.value = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
tryInput(input: string): string | 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){
|
tryAnswerPrompt<TArgs extends any[]>(def: PromptDef<TArgs>, ...args: TArgs){
|
||||||
if(typeof def.schema === 'string') def.schema = parseCommandSchema(def.schema);
|
|
||||||
return this._context._commands._tryCommit({
|
return this._context._commands._tryCommit({
|
||||||
name: def.schema.name,
|
name: def.schema.name,
|
||||||
params: args,
|
params: args,
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import {
|
||||||
CommandRunnerContextExport,
|
CommandRunnerContextExport,
|
||||||
CommandSchema,
|
CommandSchema,
|
||||||
createCommandRegistry,
|
createCommandRegistry,
|
||||||
createCommandRunnerContext,
|
createCommandRunnerContext, parseCommandSchema,
|
||||||
} from "@/utils/command";
|
} from "@/utils/command";
|
||||||
import {PromptValidator} from "@/utils/command/command-runner";
|
import {PromptValidator} from "@/utils/command/command-runner";
|
||||||
|
|
||||||
|
|
@ -47,7 +47,7 @@ export function createGameContext<TState extends Record<string, unknown> = {} >(
|
||||||
return commands.runParsed<T>(command);
|
return commands.runParsed<T>(command);
|
||||||
},
|
},
|
||||||
prompt(def, validator, currentPlayer) {
|
prompt(def, validator, currentPlayer) {
|
||||||
return commands.prompt(def.schema, validator, currentPlayer);
|
return commands.prompt(def.schema, validator, def.hintText, currentPlayer);
|
||||||
},
|
},
|
||||||
|
|
||||||
_state: state,
|
_state: state,
|
||||||
|
|
@ -60,10 +60,12 @@ export function createGameContext<TState extends Record<string, unknown> = {} >(
|
||||||
}
|
}
|
||||||
|
|
||||||
export type PromptDef<TArgs extends any[]=any[]> = {
|
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> {
|
export function createPromptDef<TArgs extends any[]=any[]>(schema: CommandSchema | string, hintText?: string): PromptDef<TArgs> {
|
||||||
return { schema };
|
schema = typeof schema === 'string' ? parseCommandSchema(schema) : schema;
|
||||||
|
return { schema, hintText };
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createGameCommandRegistry<TState extends Record<string, unknown> = {} >() {
|
export function createGameCommandRegistry<TState extends Record<string, unknown> = {} >() {
|
||||||
|
|
|
||||||
|
|
@ -146,8 +146,9 @@ export function createCommandRunnerContext<TContext>(
|
||||||
};
|
};
|
||||||
|
|
||||||
const prompt = <TResult,TArgs extends any[]=any[]>(
|
const prompt = <TResult,TArgs extends any[]=any[]>(
|
||||||
schema: CommandSchema | string,
|
schema: CommandSchema,
|
||||||
validator: PromptValidator<TResult,TArgs>,
|
validator: PromptValidator<TResult,TArgs>,
|
||||||
|
hintText?: string,
|
||||||
currentPlayer?: string | null
|
currentPlayer?: string | null
|
||||||
): Promise<TResult> => {
|
): Promise<TResult> => {
|
||||||
const resolvedSchema = typeof schema === 'string' ? parseCommandSchema(schema) : schema;
|
const resolvedSchema = typeof schema === 'string' ? parseCommandSchema(schema) : schema;
|
||||||
|
|
@ -174,7 +175,7 @@ export function createCommandRunnerContext<TContext>(
|
||||||
emitPromptEnd();
|
emitPromptEnd();
|
||||||
reject(new Error(reason ?? 'Cancelled'));
|
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 };
|
const event: PromptEvent = { schema: resolvedSchema, currentPlayer: currentPlayer ?? null, tryCommit, cancel };
|
||||||
for (const listener of promptListeners) {
|
for (const listener of promptListeners) {
|
||||||
listener(event);
|
listener(event);
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ import type { Command, CommandSchema } from './types';
|
||||||
|
|
||||||
export type PromptEvent = {
|
export type PromptEvent = {
|
||||||
schema: CommandSchema;
|
schema: CommandSchema;
|
||||||
|
/** 提示文本 */
|
||||||
|
hintText?: string;
|
||||||
/** 当前等待输入的玩家 */
|
/** 当前等待输入的玩家 */
|
||||||
currentPlayer: string | null;
|
currentPlayer: string | null;
|
||||||
/**
|
/**
|
||||||
|
|
@ -35,7 +37,7 @@ export type CommandRunnerContext<TContext> = {
|
||||||
context: TContext;
|
context: TContext;
|
||||||
run: <T=unknown>(input: string) => Promise<CommandResult<T>>;
|
run: <T=unknown>(input: string) => Promise<CommandResult<T>>;
|
||||||
runParsed: <T=unknown>(command: Command) => 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;
|
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;
|
off: <T extends keyof CommandRunnerEvents>(event: T, listener: (e: CommandRunnerEvents[T]) => void) => void;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue