import {MutableSignal, mutableSignal} from "@/utils/mutable-signal"; import { Command, CommandRegistry, CommandResult, CommandRunnerContextExport, CommandSchema, createCommandRegistry, createCommandRunnerContext, parseCommandSchema, } from "@/utils/command"; import {PromptValidator} from "@/utils/command/command-runner"; export interface IGameContext = {} > { get value(): TState; produce(fn: (draft: TState) => void): void; produceAsync(fn: (draft: TState) => void): Promise; run(input: string): Promise>; runParsed(command: Command): Promise>; prompt: (def: PromptDef, validator: PromptValidator, currentPlayer?: string | null) => Promise; // test only _state: MutableSignal; _commands: CommandRunnerContextExport>; } export function createGameContext = {} >( commandRegistry: CommandRegistry>, initialState?: TState | (() => TState) ): IGameContext { const stateValue = typeof initialState === 'function' ? initialState() : initialState ?? {} as TState; const state = mutableSignal(stateValue); let commands: CommandRunnerContextExport> = null as any; const context: IGameContext = { get value(): TState { return state.value; }, produce(fn) { return state.produce(fn); }, produceAsync(fn) { return state.produceAsync(fn); }, run(input: string) { return commands.run(input); }, runParsed(command: Command) { return commands.runParsed(command); }, prompt(def, validator, currentPlayer) { return commands.prompt(def.schema, validator, def.hintText, currentPlayer); }, _state: state, _commands: commands, }; context._commands = commands = createCommandRunnerContext(commandRegistry, context); return context; } export type PromptDef = { schema: CommandSchema, hintText?: string, } export function createPromptDef(schema: CommandSchema | string, hintText?: string): PromptDef { schema = typeof schema === 'string' ? parseCommandSchema(schema) : schema; return { schema, hintText }; } export function createGameCommandRegistry = {} >() { return createCommandRegistry>(); }