boardgame-core/src/core/context.ts

65 lines
1.8 KiB
TypeScript
Raw Normal View History

2026-04-01 13:36:16 +08:00
import {createModel, Signal, signal} from '@preact/signals-core';
import {createEntityCollection} from "../utils/entity";
import {Part} from "./part";
import {Region} from "./region";
2026-04-01 22:20:38 +08:00
import {RuleRegistry, RuleContext, dispatchCommand as dispatchRuleCommand} from "./rule";
2026-04-01 13:36:16 +08:00
export type Context = {
type: string;
}
export const GameContext = createModel((root: Context) => {
const parts = createEntityCollection<Part>();
const regions = createEntityCollection<Region>();
2026-04-01 22:20:38 +08:00
const rules = signal<RuleRegistry>(new Map());
const ruleContexts = signal<RuleContext<unknown>[]>([]);
2026-04-01 21:44:20 +08:00
const contexts = signal<Signal<Context>[]>([]);
contexts.value = [signal(root)];
2026-04-01 22:20:38 +08:00
2026-04-01 13:36:16 +08:00
function pushContext(context: Context) {
const ctxSignal = signal(context);
contexts.value = [...contexts.value, ctxSignal];
return context;
}
2026-04-01 22:20:38 +08:00
2026-04-01 13:36:16 +08:00
function popContext() {
2026-04-01 21:44:20 +08:00
if (contexts.value.length > 1) {
contexts.value = contexts.value.slice(0, -1);
}
2026-04-01 13:36:16 +08:00
}
2026-04-01 22:20:38 +08:00
2026-04-01 21:44:20 +08:00
function latestContext<T extends Context>(type: T['type']): Signal<T> | undefined {
2026-04-01 13:36:16 +08:00
for(let i = contexts.value.length - 1; i >= 0; i--){
if(contexts.value[i].value.type === type){
return contexts.value[i] as Signal<T>;
}
}
2026-04-01 21:44:20 +08:00
return undefined;
2026-04-01 13:36:16 +08:00
}
2026-04-01 17:34:21 +08:00
2026-04-01 22:20:38 +08:00
function dispatchCommand(input: string) {
return dispatchRuleCommand({
rules: rules.value,
ruleContexts: ruleContexts.value,
contexts,
}, input);
}
2026-04-01 13:36:16 +08:00
return {
parts,
regions,
2026-04-01 22:20:38 +08:00
rules,
ruleContexts,
2026-04-01 13:36:16 +08:00
contexts,
pushContext,
popContext,
latestContext,
2026-04-01 22:20:38 +08:00
dispatchCommand,
2026-04-01 13:36:16 +08:00
}
2026-04-01 17:34:21 +08:00
})
/** 创建游戏上下文实例 */
export function createGameContext(root: Context = { type: 'game' }) {
return new GameContext(root);
2026-04-01 22:20:38 +08:00
}