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-02 00:44:29 +08:00
|
|
|
|
import {RuleDef, RuleRegistry, RuleContext, RuleEngineHost, 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-02 00:44:29 +08:00
|
|
|
|
function registerRule(name: string, rule: RuleDef<unknown, RuleEngineHost>) {
|
2026-04-01 22:55:59 +08:00
|
|
|
|
const newRules = new Map(rules.value);
|
|
|
|
|
|
newRules.set(name, rule);
|
|
|
|
|
|
rules.value = newRules;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function unregisterRule(name: string) {
|
|
|
|
|
|
const newRules = new Map(rules.value);
|
|
|
|
|
|
newRules.delete(name);
|
|
|
|
|
|
rules.value = newRules;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function addRuleContext(ctx: RuleContext<unknown>) {
|
|
|
|
|
|
ruleContexts.value = [...ruleContexts.value, ctx];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function removeRuleContext(ctx: RuleContext<unknown>) {
|
|
|
|
|
|
ruleContexts.value = ruleContexts.value.filter(c => c !== ctx);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-02 00:44:29 +08:00
|
|
|
|
function dispatchCommand(this: GameContextInstance, input: string) {
|
2026-04-01 22:20:38 +08:00
|
|
|
|
return dispatchRuleCommand({
|
|
|
|
|
|
rules: rules.value,
|
|
|
|
|
|
ruleContexts: ruleContexts.value,
|
2026-04-01 22:55:59 +08:00
|
|
|
|
addRuleContext,
|
|
|
|
|
|
removeRuleContext,
|
2026-04-02 00:44:29 +08:00
|
|
|
|
pushContext,
|
|
|
|
|
|
popContext,
|
|
|
|
|
|
latestContext,
|
|
|
|
|
|
parts,
|
|
|
|
|
|
regions,
|
|
|
|
|
|
} as any, input);
|
2026-04-01 22:20:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
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:55:59 +08:00
|
|
|
|
registerRule,
|
|
|
|
|
|
unregisterRule,
|
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
|
|
|
|
})
|
|
|
|
|
|
|
2026-04-02 00:44:29 +08:00
|
|
|
|
/** 创建游戏上下文实<E69687>?*/
|
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
|
|
|
|
}
|
2026-04-01 23:58:07 +08:00
|
|
|
|
|
|
|
|
|
|
export type GameContextInstance = ReturnType<typeof createGameContext>;
|