refactor: even tighter api

This commit is contained in:
2026-04-02 14:46:34 +08:00
parent b2b35c3a99
commit e945d28fc3
3 changed files with 134 additions and 97 deletions
+31 -33
View File
@@ -1,45 +1,33 @@
import {createEntityCollection, entity, Entity, EntityCollection} from "../utils/entity";
import {Part} from "./part";
import {Region} from "./region";
import {entity, Entity} from "../utils/entity";
import {
Command,
CommandRegistry,
CommandRunnerContext,
CommandRunnerContextExport, CommandSchema, createCommandRegistry,
createCommandRunnerContext, parseCommandSchema,
PromptEvent, registerCommand
CommandRunnerContextExport,
CommandSchema,
createCommandRegistry,
createCommandRunnerContext,
parseCommandSchema,
registerCommand
} from "../utils/command";
import {AsyncQueue} from "../utils/async-queue";
export interface IGameContext<TState extends Record<string, unknown> = {} > {
parts: EntityCollection<Part>;
regions: EntityCollection<Region>;
state: Entity<TState>;
commands: CommandRunnerContextExport<IGameContext<TState>>;
prompts: AsyncQueue<PromptEvent>;
commands: CommandRunnerContextExport<Entity<TState>>;
}
export function createGameContext<TState extends Record<string, unknown> = {} >(
commandRegistry: CommandRegistry<IGameContext<TState>>,
commandRegistry: CommandRegistry<Entity<TState>>,
initialState?: TState | (() => TState)
): IGameContext<TState> {
const parts = createEntityCollection<Part>();
const regions = createEntityCollection<Region>();
const prompts = new AsyncQueue<PromptEvent>();
const state = typeof initialState === 'function' ? initialState() : initialState ?? {} as TState;
const stateValue = typeof initialState === 'function' ? initialState() : initialState ?? {} as TState;
const state = entity('state', stateValue);
const commands = createCommandRunnerContext(commandRegistry, state);
const ctx = {
parts,
regions,
prompts,
commands: null!,
state: entity('gameState', state),
} as IGameContext<TState>
ctx.commands = createCommandRunnerContext(commandRegistry, ctx);
ctx.commands.on('prompt', (prompt: PromptEvent) => ctx.prompts.push(prompt));
return ctx;
return {
state,
commands
};
}
/**
@@ -48,21 +36,31 @@ export function createGameContext<TState extends Record<string, unknown> = {} >(
*/
export function createGameContextFromModule<TState extends Record<string, unknown> = {} >(
module: {
registry: CommandRegistry<IGameContext<TState>>,
registry: CommandRegistry<Entity<TState>>,
createInitialState: () => TState
},
): IGameContext<TState> {
return createGameContext(module.registry, module.createInitialState);
}
export function createGameCommandRegistry<TState extends Record<string, unknown> = {} >(): CommandRegistry<IGameContext<TState>> {
return createCommandRegistry<IGameContext<TState>>();
export function createGameCommandRegistry<TState extends Record<string, unknown> = {} >() {
const registry = createCommandRegistry<Entity<TState>>();
return {
registry,
add<TResult = unknown>(
schema: CommandSchema | string,
run: (this: CommandRunnerContext<Entity<TState>>, command: Command) => Promise<TResult>
){
createGameCommand(registry, schema, run);
return this;
}
}
}
export function createGameCommand<TState extends Record<string, unknown> = {} , TResult = unknown>(
registry: CommandRegistry<IGameContext<TState>>,
registry: CommandRegistry<Entity<TState>>,
schema: CommandSchema | string,
run: (this: CommandRunnerContext<IGameContext<TState>>, command: Command) => Promise<TResult>
run: (this: CommandRunnerContext<Entity<TState>>, command: Command) => Promise<TResult>
) {
registerCommand(registry, {
schema: typeof schema === 'string' ? parseCommandSchema(schema) : schema,