Appearance
结对系统
文档版本:基于 2026-06-01 代码分析
概述
结对系统允许两名逃走者结成搭档,在逃走币结算时获得加成。系统支持两种模式:COIN 模式(双方取较高逃走币数)和 LIFE 模式(死亡联动淘汰 + 双方逃走币相加)。通过 A/B 槽位机制逐个填写,双方都填写后自动完成结对。
核心概念
结对模式
| 模式 | id | 结算效果 | 死亡联动 |
|---|---|---|---|
| OFF | "off" | 无(结对关闭) | 无 |
| COIN | "coin" | 双方取较高值 | 无 |
| LIFE | "life" | 双方逃走币相加 | 一方淘汰→伴侣联动淘汰 |
A/B 槽位机制
通过 /nfa rfm pairing a <player> 和 /nfa rfm pairing b <player> 分别设置两个槽位。每次设置后自动调用 tryCommitSlots() 尝试提交结对。
架构设计
结对状态机
mermaid
stateDiagram-v2
[*] --> 未结对 : 初始状态
未结对 --> A槽已填 : pairing a player
未结对 --> B槽已填 : pairing b player
A槽已填 --> 已结对 : pairing b player (tryCommitSlots成功)
B槽已填 --> 已结对 : pairing a player (tryCommitSlots成功)
A槽已填 --> 未结对 : 游戏重置/模式OFF
B槽已填 --> 未结对 : 游戏重置/模式OFF
已结对 --> 未结对 : 游戏重置/模式OFF
note right of 已结对
pairs: A↔B 双向映射
COIN: 取较高逃走币
LIFE: 逃走币相加+死亡联动
end notetryCommitSlots 检查逻辑
mermaid
flowchart TD
A[tryCommitSlots] --> B{A != null 且 B != null?}
B -->|否| C[返回 WAITING_FOR_OTHER_SLOT]
B -->|是| D{A != B?}
D -->|否| E[返回 INVALID_TARGET]
D -->|是| F{canPairNow A 且 canPairNow B?}
F -->|否| E
F -->|是| G{两者都未结对?}
G -->|否| H[返回 ALREADY_PAIRED]
G -->|是| I[addPair A↔B]
I --> J[clearSlots]
J --> K[返回 SUCCESS]canPairNow 前置条件
server != null && uuid != null- uuid 在当前回合参与者列表中
- 玩家身份必须是 RUNNER
- 未淘汰(
!eliminated)且未弃权(!abstained)
关键文件
| 文件 | 说明 |
|---|---|
com/chenxi/chenxi_rfm/server/rfm/RfmPairingManager.java | 结对管理核心 |
com/chenxi/chenxi_rfm/server/rfm/RfmPairingMode.java | 结对模式枚举(OFF/COIN/LIFE) |
com/chenxi/chenxi_rfm/server/config/rfm/PersistentRfmPairingSavedData.java | 结对数据持久化 |
com/chenxi/chenxi_rfm/server/rfm/RfmHunterSystemManager.java | 调用方:结算调整 + LIFE淘汰联动 |
com/chenxi/chenxi_rfm/server/command/rfm/RfmPairingCommand.java | /nfa rfm pairing 注册 |
com/chenxi/chenxi_rfm/server/command/rfm/RfmPairingModeCommand.java | pairing mode off/coin/life |
com/chenxi/chenxi_rfm/server/command/rfm/RfmPairingACommand.java | pairing a player |
com/chenxi/chenxi_rfm/server/command/rfm/RfmPairingBCommand.java | pairing b player |
com/chenxi/chenxi_rfm/server/config/rfm/RfmServerConfigStore.java | pairing.mode 配置项 |
关键流程
COIN 模式:结算调整
遍历所有已存在的 pair,对于双方都在最终奖励表中的情况:
pair_award = max(raw_a, raw_b)
out[a] = pair_award
out[b] = pair_award效果:两人获得相同的逃走币数,均为两人中较高值。鼓励强带弱。
LIFE 模式:死亡联动
当被淘汰者有结对伴侣时(handleLifeModeEliminateAndGetPartner):
- 计算两人回合币之和:
sum = roundCoins(eliminated) + roundCoins(partner) - 将此和记入两人的
lifeLockedAwards - 从
pairs中移除该结对 - 返回伴侣 UUID
然后在 finalizeElimination 中对伴侣再次调用淘汰逻辑(传入 fromLifeSync=true 防止无限递归)。
LIFE 模式:结算调整
- 两人都存活到结算:两人分别获得
roundCoins(a) + roundCoins(b) - 一人被淘汰:双方获得联动淘汰时锁定的
lifeLockedAwards(两人回合币之和) - 被淘汰者复活:
onRunnerResurrected清除其lifeLockedAwards
数据持久化
PersistentRfmPairingSavedData
文件:<world>/data/nfa_rfm/rfm_pairing.dat
| 字段 | 类型 | 说明 |
|---|---|---|
slotA | UUID | A 槽目标 |
slotB | UUID | B 槽目标 |
pairs | Map<UUID, UUID> | 双向结对映射 |
lifeLockedAwards | Map<UUID, Integer> | LIFE 模式锁定奖励 |
注意事项 / 限制
- 仅在参与者中结对:
canPairNow要求玩家在当前回合参与者列表中。 - 未结对不可结算调整:COIN/LIFE 的结算调整仅在 pair 存在时生效。
- LIFE 联动淘汰防止循环:通过
fromLifeSync=true标记阻止无限递归。 - 模式切换清空数据:将模式设为 OFF 会调用
clearRuntimeState()清空所有结对。 - 游戏重置清空数据:
onGameStarted和onGameStopped都会清空运行时结对状态。 - 槽位先后无关:A 和 B 的先后填写顺序不影响结对结果。