Skip to content

逃走币系统

文档版本:基于 2026-06-01 代码分析

概述

逃走币系统采用双轨制设计:回合币(Round Coin)在单局游戏中实时产出,总币(Total Coin)跨局永久累积。通过 RfmCoinStorageService 代理层管理本地 NBT 存储和可选的 PostgreSQL 云存储,每局结束时执行结算将回合币转换为总币。


核心概念

双轨制

属性回合币(Round Coin)总币(Total Coin)
存储PersistentRfmHunterRoundSavedDataPersistentRfmPlayerCoinsSavedData
存活周期每局重置跨局累积
产出机制tick 中按 rate_per_second 自动发放回合结算时通过 addCoinsByMap 累加
手动指令/nfa rfm coin clear(仅清零回合币)/nfa rfm coin add|sub|set|clear_total

产出率档位

rate_per_second 配置项经过规范化,只允许 4 个离散档位:

输入值实际生效
<= 5050
<= 100100(默认)
<= 200200
> 200500

架构设计

逃走币流向图

mermaid
flowchart LR
    subgraph InGame["局内产出"]
        Tick["每 tick"] -->|rate_per_second| Round["回合币<br/>PersistentRfmHunterRoundSavedData"]
    end

    subgraph Settlement["回合结算"]
        Round -->|"settleRoundAndBroadcast()"| Adjust["结对调整<br/>RfmPairingManager"]
        Adjust -->|"addCoinsByMap()"| Total["总币<br/>PersistentRfmPlayerCoinsSavedData"]
        Adjust -->|"appendRoundSettlement()"| CSV["CSV结算备份"]
    end

    subgraph Cloud["云存储(可选)"]
        Total -->|"writeOne()双写"| PG[("PostgreSQL<br/>mc_rfm_coin.rfm_player_coin")]
        PG -->|"每10分钟自动"| Total
        PG -->|"sync down指令"| Total
    end

    subgraph Display["显示"]
        Total -->|"syncToTabList"| SB["计分板<br/>nfa_rfm_coin"]
    end

云存储同步模式

mermaid
flowchart TD
    A[coin.storage.enabled] -->|true| B[Cloud Mode]
    A -->|false| C[Local Mode]

    B --> D["每次 writeOne() 双写<br/>本地NBT + PostgreSQL"]
    B --> E["每10分钟 tick 自动<br/>syncLocalToCloud()"]
    B --> F["指令手动<br/>sync up / down / now"]

    D --> G{SQL 异常?}
    G -->|是| H[自动回退 Local Mode<br/>通知在线管理员]
    G -->|否| I[继续 Cloud Mode]

关键文件

文件说明
com/chenxi/chenxi_rfm/server/rfm/RfmCoinStorageService.java逃走币存储代理(本地+云端)
com/chenxi/chenxi_rfm/server/rfm/RfmCoinPostgresService.javaPostgreSQL 数据库操作
com/chenxi/chenxi_rfm/server/rfm/RfmCoinCryptoService.javaAES-256/GCM 凭证加密
com/chenxi/chenxi_rfm/server/rfm/RfmCoinFileSyncService.javaCSV 结算文件追加
com/chenxi/chenxi_rfm/server/rfm/RfmCoinScoreboardService.java计分板同步
com/chenxi/chenxi_rfm/server/config/rfm/PersistentRfmPlayerCoinsSavedData.java总币 NBT 存储
com/chenxi/chenxi_rfm/server/config/rfm/PersistentRfmHunterRoundSavedData.java回合币 NBT 存储
com/chenxi/chenxi_rfm/server/config/rfm/RfmServerConfigStore.java服务端配置(rate、db参数)
com/chenxi/chenxi_rfm/server/rfm/RfmHunterSystemManager.javatick 产出调度 + 结算流程

关键流程

tick 产出机制

每 tick 调用链:

ServerTickEvent.Post
  → RfmGameSessionManager.tick()
    → RfmHunterSystemManager.tickRunning()
      → awardRoundCoinsByTime(server, elapsedSeconds, nowMillis)
        → 计算距上次发币的毫秒差
        → 如果 passed >= 1000ms:
            steps = passed / 1000L
            for i in 1..steps:
              awardRoundCoins(server)  // 每秒发放一次

awardRoundCoins 内部逻辑:

  1. 获取当前 ratePerSecond
  2. 遍历所有存活的参与者逃走者
  3. 跳过叛节者(traitor 不产生回合币)
  4. 跳过逃走币锁定状态(coinLocked 玩家)
  5. 对符合条件的逃走者:roundData.addRoundCoins(uuid, rate)

产出只在 NORMAL 阶段进行。PAUSED 和 COUNTDOWN_FROZEN 阶段不产币。

时光倒流阶段(TIME_REWIND):按相同速率扣除回合金币。已淘汰逃走者的淘汰奖励不受影响——淘汰锁定值在淘汰时已写入 EliminatedReward,不会被倒流减少。

时光混乱阶段(TIME_CHAOS):金币完全锁定。进入阶段时对存活逃走者的当前回合币做快照,混乱期间被捕的逃走者以该快照值计算淘汰奖励(roundCoins / 10)。正常结束混乱时快照被清除,游戏恢复正常金币产出。

结算流程

游戏结束时 settleRoundAndBroadcast()

  1. 获取所有参与者 UUID
  2. 读取每人的回合币 rawRoundCoins
  3. 若有 eliminatedReward(淘汰补偿=roundCoins/10,弃权补偿=roundCoins/2),使用补偿值替代
  4. 跳过单一胜利者:混乱阶段中设置的单一胜利者在此跳过(已直接获得全量总币 = 总秒数 × 金币速率)
  5. RfmPairingManager.applySettlementAdjustments() — COIN 模式取高,LIFE 模式相加
  6. RfmCoinStorageService.addCoinsByMap() — 写入总币
  7. RfmCoinFileSyncService.appendRoundSettlement() — 追加 CSV
  8. 全服广播结算排名

PostgreSQL 云存储

加密凭证

  • 密钥种子 = 服务器目录绝对路径
  • 加密算法 = AES-256/GCM,IV 随机 12 字节
  • 存储时加密,读取时解密

数据库表mc_rfm_coin.rfm_player_coin

  • online_uuidoffline_uuidplayer_namecoin_totalupdated_at
  • 唯一索引:online_uuid(非空时)、offline_uuid(非空时)

数据持久化

PersistentRfmPlayerCoinsSavedData

文件:<world>/data/nfa_rfm/rfm_player_coins.dat

Map<UUID, Integer> totalCoins

计分板

  • 目标名:nfa_rfm_coin,显示名"逃走币"
  • 显示槽位:DisplaySlot.LIST(TAB 列表)
  • 每次总币变更后自动同步

指令

指令权限说明
/nfa rfm coin add <targets> <amount>MASTER_OR_CB增加指定玩家的总币
/nfa rfm coin sub <targets> <amount>MASTER_OR_CB扣除指定玩家的总币
/nfa rfm coin set <targets> <amount>MASTER_OR_CB设置指定玩家的总币值
/nfa rfm coin clear <targets>MASTER_OR_CB清零指定玩家的回合币(仅回合币)
/nfa rfm coin clear_total <targets>MASTER_OR_CB清零指定玩家的总币
/nfa rfm coin sync upMASTER_OR_CB手动上传本地数据到云存储
/nfa rfm coin sync downMASTER_OR_CB手动从云存储下载数据覆盖本地
/nfa rfm coin sync nowMASTER_OR_CB立即同步云存储

注意事项 / 限制

  1. 产出仅对存活非叛节逃走者:叛节者不产币,被淘汰和弃权者不产币。
  2. 暂停时先结算pauseGame() 和阶段切换前会先调用 onGamePaused() 结算已产生的逃走币,再冻结产出。
  3. 时光倒流扣币仅对存活逃走者:已淘汰逃走者的淘汰奖励在淘汰时已锁定,不会因倒流而减少。扣币速率等于正常产出速率(coinRatePerSecond)。叛节者和锁定状态的玩家在倒流中也不受影响。
  4. 时光混乱锁定金币:进入混乱阶段时对存活逃走者当前回合币做快照,混乱期间被捕以快照值计算淘汰奖励。单一胜利者直接获得总秒数 × 速率 的全量金币。
  5. SQL 异常自动回退:云存储写入失败时自动切回本地模式,并向在线管理员发送红色警告。
  6. 离散档位:逃走币产出率只有 4 个档位,输入非标准值会被自动规范化为最近的档位。
  7. 淘汰补偿:正常淘汰时锁定 roundCoins / 10 作为补偿;弃权时锁定 roundCoins / 2

相关文档