Appearance
游戏会话管理
文档版本:基于 2026-06-01 代码分析
概述
游戏会话管理是逃走中MOD的核心调度器,负责管理游戏的完整生命周期。通过 RfmGameSessionManager 实现 IDLE → RUNNING → IDLE 的状态转换,并在 RUNNING 状态下管理三个子阶段(NORMAL / PAUSED / COUNTDOWN_FROZEN)的切换。每次服务器 tick 驱动倒计时、逃走币产出和猎人生效检测。
核心概念
状态与阶段双维度
| 维度 | 枚举 | 值 | 含义 |
|---|---|---|---|
| State(状态) | RfmGameState | idle / running | 是否正在进行一局游戏 |
| Phase(阶段) | RfmGamePhase | normal / paused / countdown_frozen | 游戏进行中的子状态 |
游戏状态由 State 和 Phase 共同决定:
| State | Phase | 语义 | 倒计时 | 逃走币产出 | 玩家行动 |
|---|---|---|---|---|---|
idle | normal | 未进行 | 停止 | 无 | 限制 |
running | normal | 正常运行 | 递减 | 正常发放 | 允许 |
running | paused | 已暂停 | 冻结 | 停止 | 禁止 |
running | countdown_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() 执行步骤
- 前置检查:
state != IDLE则拒绝 data.resetToIdle()— 冗余安全重置PersistentRfmRoundSavedData.snapshotOnlineRunners(server)— 快照在线逃走者 UUIDRfmAlarmManager.clearForGameLifecycle(server)— 清空警报RfmDetectBlockManager.resetForNewGame(server)— 重置侦测方块data.startRunning(System.currentTimeMillis())— State=RUNNING, Phase=NORMALRfmHunterSystemManager.onGameStarted(server)— 恢复逃走者状态、重置猎人回合数据、重置逃走币计时器RfmHunterSpawnManager.applyOnGameStarted(server)— 随机分配猎人出生点RfmRedstoneTriggerManager.resetAllOutputs(server)— 触发器断电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() 中的调用顺序:
| 顺序 | 子管理器 | 方法 | 作用 |
|---|---|---|---|
| 1 | RfmGameSessionManager | tick(server) | 游戏主循环 |
| 2 | RfmCoinStorageService | tick(server) | 每10分钟自动同步云存储 |
| 3 | RfmDetectBlockManager | tick(server) | 每5tick检测侦测方块范围 |
| 4 | RfmRedstoneTriggerManager | tick(server) | 每5tick检测触发器阈值 |
| 5 | RfmAlarmManager | tick(server) | 每tick遍历警报响铃 |
| 6 | RfmLocatorManager | tick(server) | 每5秒采样坐标 |
| 7 | RfmHunterEntityManager | tick(server) | A型猎人AI |
| 8 | RfmAnnounceHunterEntityManager | tick(server) | B型通报猎人AI |
| 9 | RfmHunterSystemManager | tickHunterDeviceRevival(server) | 猎人装置复活阶段 |
gameEnd() 终止途径
| 途径 | 触发条件 |
|---|---|
| 自然超时 | tick 中 elapsed >= totalSeconds |
| 命令终止 | /nfa basic stop |
| 团灭 | 所有逃走者被淘汰 |
| 叛节者胜利 | 仅剩叛节者存活 |
结算流程(settleRoundAndBroadcast)
- 获取所有参与者 UUID
- 读取每人的回合币
- 若有
eliminatedReward则使用淘汰补偿,否则用全量回合币 RfmPairingManager.applySettlementAdjustments()— 结对调整(COIN取高/LIFE相加)RfmCoinStorageService.addCoinsByMap()— 回合币→总币RfmCoinFileSyncService.appendRoundSettlement()— 写入CSV结算文件- 全服广播结算排名
数据持久化
PersistentRfmGameSavedData
| NBT 键 | 类型 | 说明 |
|---|---|---|
State | String | "idle" / "running" |
Phase | String | "normal" / "paused" / "countdown_frozen" |
TotalSeconds | int | 总游戏时间秒数(默认3600,范围60-86400) |
ElapsedBeforeRunSeconds | int | 暂停/冻结时刻锁定的已消耗秒数 |
RunStartMillis | long | 当前运行段开始的系统时间戳 |
PersistentRfmRoundSavedData
| NBT 键 | 类型 | 说明 |
|---|---|---|
Participants | List<UUID> | 本轮参与者的 UUID 列表 |
注意事项 / 限制
- IDLE→RUNNING 是唯一合法启动:无法从 PAUSED/FROZEN 状态直接开始,必须经过 IDLE。
- PAUSED 完全静止:暂停期间不执行任何 tick 子逻辑(包括猎人效果和冷却恢复),只有红石触发器的 SUSTAINED 模式例外。
- FROZEN 仅停逃走币:
COUNTDOWN_FROZEN阶段玩家仍可自由行动,猎人冷却/效果/淘汰队列继续处理,仅逃走币产出和倒计时停止。 - 逃走币结算时机:暂停或倒计时冻结前会先调用
onGamePaused()结算该时段已产生的逃走币,避免玩家损失。 - 同步频率:游戏状态每分钟自动同步一次到全服,HUD 数据同步频率更高。
- 数据持久化保存时机:
setDirty()后依赖 Minecraft 的 DataStorage 在世界自动保存时写入,非立即落盘。