Ticker
tick 与渲染事件;F3 顶替与可见性判定
基本信息
| 属性 | 值 |
|---|---|
| 路径 | com.github.lunatrius.ingameinfo.handler.Ticker |
| 行数 | 85 |
| 实例数 | 每个连接 1 个(由 TickerManager 创建) |
三个事件处理器
1. onRenderGameOverlayEventPre(:20-26)—— 顶掉 F3
if (ConfigurationHandler.showHUD && ConfigurationHandler.replaceDebug
&& event.type == RenderGameOverlayEvent.ElementType.DEBUG) {
event.setCanceled(true);
}
三个条件同时满足才取消原版 DEBUG 层:
| 条件 | 默认值 |
|---|---|
showHUD |
true |
replaceDebug |
false |
事件类型是 DEBUG |
— |
⚠️ replaceDebug 默认 false —— 所以默认不接管 F3。
本 mod 与 F3 的关系是「可选替换」,不是「F3 增强」。
⚠️ 事件类型是 Pre(RenderGameOverlayEvent.Pre),
所以在原版绘制之前取消,这是能阻止绘制的唯一时机。
2. onClientTick(:28-38)—— 每 tick 逻辑
if (event.phase == TickEvent.Phase.END) {
this.client.mcProfiler.startSection("ingameinfo");
if (isRunning()) { this.core.onTickClient(); }
Tag.releaseResources();
this.client.mcProfiler.endSection();
}
| 步骤 | 说明 |
|---|---|
startSection("ingameinfo") |
挂到 mcProfiler 的 F3 计时里 |
isRunning() 才调 onTickClient() |
见下 |
Tag.releaseResources() 在 isRunning() 之外 |
⚠️ 无条件执行 |
endSection() |
配对 |
⚠️ Tag.releaseResources() 无条件调用,
即使 HUD 关闭也每 tick 执行。
它会清 TagPlayerPotion 的 potionEffects 缓存等。
HUD 关闭时这是纯浪费(每 tick 20 次/秒)。
⚠️ 只在 Phase.END 处理,Phase.START 被忽略。
3. onRenderGUI(:40-49)—— 绘制
if (event.type == RenderGameOverlayEvent.ElementType.TEXT) {
this.client.mcProfiler.startSection("ingameinfo");
if (isRunning()) { this.core.onTickRender(event.resolution); }
this.client.mcProfiler.endSection();
}
⚠️ 事件类型是 Post,元素类型是 TEXT(聊天框)——
即本 mod 的 HUD 绘制在原版聊天文本之后,
所以 HUD 文字会盖在聊天消息上。
replaceDebug 开启时,F3 DEBUG 层已被步骤 1 取消,
但 TEXT 层仍在,所以 HUD 显示在原版该显示聊天框的位置。
isRunning 的可见性判定(:51-84)
if (!ConfigurationHandler.showHUD) return false; // ①
if (this.client.mcProfiler.profilingEnabled) return true; // ②
if (ConfigurationHandler.replaceDebug == this.client.gameSettings.showDebugInfo) { // ③
if (this.client.gameSettings.hideGUI) return false; // ④
if (!ConfigurationHandler.showOnPlayerList
&& this.client.gameSettings.keyBindPlayerList.getIsKeyPressed()) { // ⑤
if (this.client.theWorld != null && this.client.thePlayer != null) {
final ScoreObjective scoreobjective = this.client.theWorld.getScoreboard().func_96539_a(0);
final NetHandlerPlayClient handler = this.client.thePlayer.sendQueue;
if (!this.client.isIntegratedServerRunning() || handler.playerInfoList.size() > 1
|| scoreobjective != null) return false;
}
}
if (this.client.currentScreen == null) return true; // ⑥
return ConfigurationHandler.showInChat && this.client.currentScreen instanceof GuiChat; // ⑦
}
return false; // ⑧
| # | 判定 | 含义 |
|---|---|---|
| ① | showHUD == false |
配置总开关 |
| ② | profiler 在跑 | 无条件显示(F3+Shift 的调试计时) |
| ③ | replaceDebug == showDebugInfo |
状态对齐检查 |
| ④ | hideGUI(F1 隐藏 GUI) |
隐藏 |
| ⑤ | 按 Tab 且不满足「单人物语」条件 | 隐藏 |
| ⑥ | 无 GUI 打开 | 显示 |
| ⑦ | 在聊天界面 | 取决于 showInChat |
| ⑧ | ③ 不成立 | 隐藏 |
③ 的设计意图(关键)
replaceDebug(配置)与 showDebugInfo(原版 F3 开关)必须相等才显示 HUD。
replaceDebug |
showDebugInfo |
结果 |
|---|---|---|
false(默认) |
false |
显示 HUD |
false(默认) |
true(按 F3) |
隐藏 HUD |
true |
true |
显示 HUD(顶掉原版 F3) |
true |
false |
隐藏 HUD |
即:HUD 与 F3「互斥接管」 —— 关掉原版 F3 才用自己的,关掉自己的就还回原版 F3。
⚠️ 这个设计有代价:想同时看 F3 和 HUD 做不到,
除非把 showDebugInfo 关掉(此时 F3 已被 replaceDebug 顶掉)。
⚠️ ② 的 profiler 分支在 ③ 之前,
所以「F3 profiling 模式」下 HUD 无条件显示,
不管 replaceDebug 与 showDebugInfo 是否对齐。
⑤ 的「单人物语」判定
按 Tab 打开多人列表时,只有满足全部条件才隐藏 HUD:
| 条件 | 含义 |
|---|---|
isIntegratedServerRunning() |
单机 |
playerInfoList.size() > 1 |
玩家数 ≤ 1 |
scoreobjective != null → 不隐藏 |
记分板有任何目标就保持显示 |
即:单机 + 只有自己 + 没有记分板时隐藏 HUD,
避免单人游戏时按 Tab 看到自己的 HUD 挡着列表。
func_96539_a(0) 是 Scoreboard.getObjectiveInDisplaySlot(0) 的
SRG 名(未映射),取第 0 槽(sidebar)目标。
两个实例字段(:17-18)
private final Minecraft client = Minecraft.getMinecraft();
private final InGameInfoCore core = InGameInfoCore.INSTANCE;
⚠️ 在构造时取 Minecraft.getMinecraft() 单例。
TickerManager 在 ClientConnectedToServerEvent 时创建本类,
此时 Minecraft 必然已初始化。
相关
- TickerManager - 生命周期管理者
- ConfigurationHandler - 4 个判定用到的配置项
- InGameInfoCore -
onTickClient/onTickRender - Tag -
releaseResources