boardgame-core/src/core/rule.ts

81 lines
1.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import {Context} from "./context";
import {Command} from "../utils/command";
import {effect} from "@preact/signals-core";
export type RuleContext<T> = Context & {
actions: Command[];
handledActions: number;
invocations: RuleContext<unknown>[];
resolution?: T;
}
/**
* 调用规则生成器并管理其上下文
* @param pushContext - 用于推送上下文到上下文栈的函数
* @param type - 规则类型
* @param rule - 规则生成器函数
* @returns 规则执行结果
*/
export function invokeRuleContext<T>(
pushContext: (context: Context) => void,
type: string,
rule: Generator<string, T, Command>
): RuleContext<T> {
const ctx: RuleContext<T> = {
type,
actions: [],
handledActions: 0,
invocations: [],
resolution: undefined,
};
let disposed = false;
const executeRule = () => {
if (disposed || ctx.resolution !== undefined) return;
try {
const result = rule.next();
if (result.done) {
ctx.resolution = result.value;
return;
}
const actionType = result.value;
if (actionType) {
// 暂停于 yield 点,等待外部处理动作
// 当外部更新 actions 后effect 会重新触发
}
} catch (error) {
throw error;
}
};
const dispose = effect(() => {
if (ctx.resolution !== undefined) {
dispose();
disposed = true;
return;
}
executeRule();
});
pushContext(ctx);
return ctx;
}
/**
* 创建一个规则生成器辅助函数
* @param type - 规则类型
* @param fn - 规则逻辑函数
*/
export function createRule<T>(
type: string,
fn: (ctx: RuleContext<T>) => Generator<string, T, Command>
): (ctx: RuleContext<T>) => Generator<string, T, Command> {
return fn;
}