Skip to content

游戏会话管理

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

概述

游戏会话管理是逃走中MOD的核心调度器,负责管理游戏的完整生命周期。通过 RfmGameSessionManager 实现 IDLE → RUNNING → IDLE 的状态转换,并在 RUNNING 状态下管理三个子阶段(NORMAL / PAUSED / COUNTDOWN_FROZEN)的切换。每次服务器 tick 驱动倒计时、逃走币产出和猎人生效检测。


核心概念

状态与阶段双维度

维度枚举含义
State(状态)RfmGameStateidle / running是否正在进行一局游戏
Phase(阶段)RfmGamePhasenormal / paused / countdown_frozen游戏进行中的子状态

游戏状态由 State 和 Phase 共同决定

StatePhase语义倒计时逃走币产出玩家行动
idlenormal未进行停止限制
runningnormal正常运行递减正常发放允许
runningpaused已暂停冻结停止禁止
runningcountdown_frozen倒计时冻结冻结停止允许

存活时间计算

游戏通过两个字段追踪时间流逝:

  • TotalSeconds:总倒计时秒数(默认 3600,范围 60-86400)
  • ElapsedBeforeRunSeconds:暂停/冻结时锁定的已消耗秒数
  • RunStartMillis:当前运行段开始的系统时间戳
已消耗秒数 = ElapsedBeforeRunSeconds + (当前毫秒 - RunStartMillis) / 1000
剩余秒数   = TotalSeconds - 已消耗秒数

架构设计

状态机图

mermaid
stateDiagram-v2
    [*] --> IDLE_NORMAL : 初始状态
    IDLE_NORMAL --> RUNNING_NORMAL : startGame()

    state RUNNING_NORMAL {
        [*] --> Normal
        Normal --> Paused : pauseGame()
        Paused --> Normal : resumeGame()
        Normal --> Frozen : startCountdownFreeze()
        Frozen --> Normal : stopCountdownFreeze()
    }

    RUNNING_NORMAL --> IDLE_NORMAL : terminateGame() / 超时 / 团灭

    note right of IDLE_NORMAL : State=IDLE, Phase=NORMAL
    note right of RUNNING_NORMAL : State=RUNNING
    note right of Paused : 倒计时冻结<br/>玩家行动禁止<br/>逃走币停止发放
    note right of Frozen : 倒计时冻结<br/>玩家行动允许<br/>猎人效果持续

游戏生命周期时序

mermaid
sequenceDiagram
    participant Admin as 管理员
    participant Cmd as BasicCommand
    participant GSM as RfmGameSessionManager
    participant HS as RfmHunterSystemManager
    participant Data as PersistentRfmGameSavedData
    participant All as 全服玩家

    Admin->>Cmd: /nfa basic start
    Cmd->>GSM: startGame(server)
    GSM->>Data: resetToIdle() 安全重置
    GSM->>Data: snapshotOnlineRunners()
    GSM->>Data: startRunning(now)
    Data-->>GSM: State=RUNNING, Phase=NORMAL
    GSM->>HS: onGameStarted() 重置状态
    GSM->>All: syncToAll() + syncHud()

    Note over GSM: tick() 循环开始

    Admin->>Cmd: /nfa basic pause
    Cmd->>GSM: pauseGame(server)
    GSM->>HS: onGamePaused() 结算逃走币
    GSM->>Data: pauseAtElapsed(elapsed)
    Data-->>GSM: Phase=PAUSED

    Admin->>Cmd: /nfa basic resume
    Cmd->>GSM: resumeGame(server)
    GSM->>Data: resumeCountdown(now)
    Data-->>GSM: Phase=NORMAL
    GSM->>HS: onGameResumed(now)

    Note over GSM: 倒计时归零 → 自动终止

    GSM->>HS: handleTimeExpired()
    GSM->>GSM: executeGameEnd(server)
    GSM->>Data: resetToIdle()
    GSM->>All: syncToAll() + syncHud()

关键文件

文件说明
com/chenxi/chenxi_rfm/server/rfm/RfmGameSessionManager.java游戏会话管理核心类
com/chenxi/chenxi_rfm/common/rfm/RfmGameState.java游戏状态枚举(IDLE/RUNNING)
com/chenxi/chenxi_rfm/common/rfm/RfmGamePhase.java游戏阶段枚举(NORMAL/PAUSED/COUNTDOWN_FROZEN)
com/chenxi/chenxi_rfm/common/rfm/RfmGameStateHelper.java状态/阶段辅助判断工具类
com/chenxi/chenxi_rfm/server/config/rfm/PersistentRfmGameSavedData.java游戏状态持久化(NBT)
com/chenxi/chenxi_rfm/server/config/rfm/PersistentRfmRoundSavedData.java回合参与者 UUID 快照
com/chenxi/chenxi_rfm/server/event/ServerRfmGameEvents.java服务端 tick 事件驱动
com/chenxi/chenxi_rfm/server/command/basic/BasicStartCommand.java/nfa basic start
com/chenxi/chenxi_rfm/server/command/basic/BasicPauseCommand.java/nfa basic pause
com/chenxi/chenxi_rfm/server/command/basic/BasicResumeCommand.java/nfa basic resume
com/chenxi/chenxi_rfm/server/command/basic/BasicStopCommand.java/nfa basic stop
com/chenxi/chenxi_rfm/server/command/rfm/RfmRoundCountdownFreezeStartCommand.java手动冻结倒计时
com/chenxi/chenxi_rfm/server/command/rfm/RfmRoundCountdownFreezeStopCommand.java手动解冻倒计时

关键流程

startGame() 执行步骤

  1. 前置检查state != IDLE 则拒绝
  2. data.resetToIdle() — 冗余安全重置
  3. PersistentRfmRoundSavedData.snapshotOnlineRunners(server) — 快照在线逃走者 UUID
  4. RfmAlarmManager.clearForGameLifecycle(server) — 清空警报
  5. RfmDetectBlockManager.resetForNewGame(server) — 重置侦测方块
  6. data.startRunning(System.currentTimeMillis())State=RUNNING, Phase=NORMAL
  7. RfmHunterSystemManager.onGameStarted(server) — 恢复逃走者状态、重置猎人回合数据、重置逃走币计时器
  8. RfmHunterSpawnManager.applyOnGameStarted(server) — 随机分配猎人出生点
  9. RfmRedstoneTriggerManager.resetAllOutputs(server) — 触发器断电
  10. syncToAll(server) + RfmHudSyncManager.syncToAll(server) — 全服同步

tick() 调度逻辑

每 tick(ServerTickEvent.Post)调用 RfmGameSessionManager.tick(server)

if (state != RUNNING) return;

if (phase == COUNTDOWN_FROZEN):
    → tickRunningWithoutCoin()  // 仅猎人效果+待处理淘汰+冷却,无逃走币
    return;

if (phase == PAUSED):
    return;  // 完全静止

if (elapsed >= totalSeconds):
    → onGamePaused() 结算最后逃走币
    → handleTimeExpired() 触发结算
    → executeGameEnd() 清理
    return;

→ tickRunning()  // 正常逃走币发放+猎人效果+冷却
→ 每分钟 syncToAll()

tick 中调用的子管理器

ServerRfmGameEvents.onServerTick() 中的调用顺序:

顺序子管理器方法作用
1RfmGameSessionManagertick(server)游戏主循环
2RfmCoinStorageServicetick(server)每10分钟自动同步云存储
3RfmDetectBlockManagertick(server)每5tick检测侦测方块范围
4RfmRedstoneTriggerManagertick(server)每5tick检测触发器阈值
5RfmAlarmManagertick(server)每tick遍历警报响铃
6RfmLocatorManagertick(server)每5秒采样坐标
7RfmHunterEntityManagertick(server)A型猎人AI
8RfmAnnounceHunterEntityManagertick(server)B型通报猎人AI
9RfmHunterSystemManagertickHunterDeviceRevival(server)猎人装置复活阶段

gameEnd() 终止途径

途径触发条件
自然超时tick 中 elapsed >= totalSeconds
命令终止/nfa basic stop
团灭所有逃走者被淘汰
叛节者胜利仅剩叛节者存活

结算流程(settleRoundAndBroadcast)

  1. 获取所有参与者 UUID
  2. 读取每人的回合币
  3. 若有 eliminatedReward 则使用淘汰补偿,否则用全量回合币
  4. RfmPairingManager.applySettlementAdjustments() — 结对调整(COIN取高/LIFE相加)
  5. RfmCoinStorageService.addCoinsByMap() — 回合币→总币
  6. RfmCoinFileSyncService.appendRoundSettlement() — 写入CSV结算文件
  7. 全服广播结算排名

数据持久化

PersistentRfmGameSavedData

NBT 键类型说明
StateString"idle" / "running"
PhaseString"normal" / "paused" / "countdown_frozen"
TotalSecondsint总游戏时间秒数(默认3600,范围60-86400)
ElapsedBeforeRunSecondsint暂停/冻结时刻锁定的已消耗秒数
RunStartMillislong当前运行段开始的系统时间戳

PersistentRfmRoundSavedData

NBT 键类型说明
ParticipantsList<UUID>本轮参与者的 UUID 列表

注意事项 / 限制

  1. IDLE→RUNNING 是唯一合法启动:无法从 PAUSED/FROZEN 状态直接开始,必须经过 IDLE。
  2. PAUSED 完全静止:暂停期间不执行任何 tick 子逻辑(包括猎人效果和冷却恢复),只有红石触发器的 SUSTAINED 模式例外。
  3. FROZEN 仅停逃走币COUNTDOWN_FROZEN 阶段玩家仍可自由行动,猎人冷却/效果/淘汰队列继续处理,仅逃走币产出和倒计时停止。
  4. 逃走币结算时机:暂停或倒计时冻结前会先调用 onGamePaused() 结算该时段已产生的逃走币,避免玩家损失。
  5. 同步频率:游戏状态每分钟自动同步一次到全服,HUD 数据同步频率更高。
  6. 数据持久化保存时机setDirty() 后依赖 Minecraft 的 DataStorage 在世界自动保存时写入,非立即落盘。

相关文档