BattleSessionAutoReplacementExecutor.kt
package io.github.lishangbu.avalon.game.battle.engine.core.session
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.BattleRuntimeSnapshot
/**
* 自动替补执行器。
*
* 设计意图:
* - 接收已经解析好的 `BattleSessionReplacementPlan`,负责真正执行
* switch out / active 替换 / force switch 清理 / switch in;
* - 把自动替补的状态写回与日志事件记录从 resolver 主类中拆开;
* - 让“是否需要替补”与“如何执行替补”形成清晰分层。
*/
internal class BattleSessionAutoReplacementExecutor(
private val session: BattleSession,
) {
/**
* 根据计划执行自动替补。
*/
fun execute(
snapshot: BattleRuntimeSnapshot,
plan: BattleSessionReplacementPlan,
): BattleRuntimeSnapshot {
if (!plan.hasAutomaticReplacement) {
return snapshot
}
var transitionSnapshot = snapshot
plan.slotTransitions
.mapNotNull(BattleSessionSlotTransition::outgoingUnitId)
.forEach { outgoingUnitId ->
val outgoingUnit = transitionSnapshot.units[outgoingUnitId]
if ((outgoingUnit?.currentHp ?: 0) > 0) {
transitionSnapshot = session.processSwitchOut(outgoingUnitId, transitionSnapshot)
}
transitionSnapshot = BattleSessionSwitchBoostStateSupport.clearOutgoingBoosts(transitionSnapshot, outgoingUnitId)
}
val side = transitionSnapshot.sides.getValue(plan.sideId)
val replacedSnapshot =
transitionSnapshot.copy(
sides = transitionSnapshot.sides + (plan.sideId to side.copy(activeUnitIds = plan.nextActiveUnitIds)),
)
transitionSnapshot =
session.clearForceSwitchRequests(
snapshot = replacedSnapshot,
unitIds =
plan.slotTransitions.flatMap { transition ->
listOfNotNull(transition.outgoingUnitId, transition.incomingUnitId)
},
)
plan.slotTransitions
.mapNotNull(BattleSessionSlotTransition::incomingUnitId)
.forEach { incomingUnitId ->
val outgoingUnitId =
plan.slotTransitions
.firstOrNull { transition -> transition.incomingUnitId == incomingUnitId }
?.outgoingUnitId
transitionSnapshot =
BattleSessionSwitchBoostStateSupport.applyIncomingBoostCarry(
snapshot = transitionSnapshot,
outgoingUnitId = outgoingUnitId,
incomingUnitId = incomingUnitId,
)
transitionSnapshot = session.processSwitchIn(incomingUnitId, transitionSnapshot)
}
session.recordLog("Side ${plan.sideId} auto replaced active units: ${plan.beforeActiveUnitIds} -> ${plan.nextActiveUnitIds}.")
session.recordEvent(
BattleSessionAutoReplacedPayload(
sideId = plan.sideId,
before = plan.beforeActiveUnitIds,
after = plan.nextActiveUnitIds,
),
)
return transitionSnapshot
}
}