DefaultHookRuleProcessor.kt
package io.github.lishangbu.avalon.game.battle.engine.core.runtime
import io.github.lishangbu.avalon.game.battle.engine.core.dsl.ConditionNode
import io.github.lishangbu.avalon.game.battle.engine.core.dsl.HookRule
import io.github.lishangbu.avalon.game.battle.engine.core.dsl.condition.AllConditionNode
import io.github.lishangbu.avalon.game.battle.engine.core.dsl.condition.AnyConditionNode
import io.github.lishangbu.avalon.game.battle.engine.core.dsl.condition.NotConditionNode
import io.github.lishangbu.avalon.game.battle.engine.core.event.EventContext
import io.github.lishangbu.avalon.game.battle.engine.core.mutation.BattleMutation
import io.github.lishangbu.avalon.game.battle.engine.core.registry.ActionExecutorRegistry
import io.github.lishangbu.avalon.game.battle.engine.core.registry.ConditionInterpreterRegistry
/**
* 默认 HookRule 处理器。
*
* 设计意图:
* - 串起条件求值与动作执行。
* - 以结构化 mutation 和 relay 变化作为处理输出。
*/
class DefaultHookRuleProcessor(
private val conditionInterpreterRegistry: ConditionInterpreterRegistry,
private val actionExecutorRegistry: ActionExecutorRegistry,
) : HookRuleProcessor {
override fun process(
rule: HookRule,
context: EventContext,
): HookRuleResult {
val matched: Boolean = rule.condition?.let { evaluateCondition(it, context) } ?: true
val selectedActions = if (matched) rule.thenActions else rule.elseActions
var currentRelay: Any? = context.relay
var cancelled = false
val mutations = mutableListOf<BattleMutation>()
for (action in selectedActions) {
val executor = actionExecutorRegistry.get(action.type)
val actionContext = context.copy(relay = currentRelay)
val actionResult = executor.execute(action, actionContext)
if (actionResult.relay != null) {
currentRelay = actionResult.relay
}
mutations += actionResult.mutations
if (actionResult.cancelled) {
cancelled = true
break
}
}
return HookRuleResult(
matched = matched,
cancelled = cancelled,
relay = currentRelay,
mutations = mutations,
)
}
private fun evaluateCondition(
condition: ConditionNode,
context: EventContext,
): Boolean =
when (condition) {
is AllConditionNode -> condition.conditions.all { evaluateCondition(it, context) }
is AnyConditionNode -> condition.conditions.any { evaluateCondition(it, context) }
is NotConditionNode -> !evaluateCondition(condition.condition, context)
else -> conditionInterpreterRegistry.get(condition.type).evaluate(condition, context)
}
}