TickerManager

按连接状态注册 / 反注册 Ticker

基本信息

属性 值
路径 com.github.lunatrius.ingameinfo.handler.TickerManager
行数 35(handler 包第二短)
实例数 1(由 ClientProxy.init(:52)创建)

持有单个 Ticker

private Ticker ticker = null;   // :13

⚠️ 非 final 的可变字段,在连接/断开事件里被反复赋值。 两个事件都在 FML 网络总线上,单线程(客户端主线程), 所以无并发问题。

onClientConnect(:15-22)

if (this.ticker == null) {
    this.ticker = new Ticker();
    MinecraftForge.EVENT_BUS.register(this.ticker);
    FMLCommonHandler.instance().bus().register(this.ticker);
}

双总线注册:

总线 承载的事件
MinecraftForge.EVENT_BUS RenderGameOverlayEvent.Pre / .Post、TickEvent.ClientTickEvent
FMLCommonHandler.instance().bus() TickEvent.ClientTickEvent

⚠️ ClientTickEvent 在两个总线上都发, 但 Ticker 的 onClientTick(:29) 只判 phase == END,所以 START/END 各触发一次时只处理 END —— 不会重复执行。属于靠 phase 判定规避重复,而非只注册一个总线。

⚠️ if (this.ticker == null) 幂等保护: 重复的连接事件不会重复注册。

onClientDisconnect(:24-33)

if (this.ticker != null) {
    MinecraftForge.EVENT_BUS.unregister(this.ticker);
    FMLCommonHandler.instance().bus().unregister(this.ticker);
    this.ticker = null;
    Tag.releaseResources();
    Tag.onClientDisconnect();
}
步骤 说明
双总线反注册 与注册严格配对
ticker = null 允许下次连接重建
Tag.releaseResources() 释放 tag 的每 tick 缓存
Tag.onClientDisconnect() 断开专用清理

⚠️ onClientDisconnect 调用的两个方法 Tag.releaseResources() 与 Tag.onClientDisconnect() 都是静态的, 所以即使 ticker 已经是 null(未连接过就收到断开事件)也会执行。

为什么主菜单不渲染

Ticker 的 isRunning 依赖 client.theWorld / client.thePlayer / client.currentScreen (见其条目⑤⑥),这些在主菜单阶段为 null 或不可靠。 把注册推迟到「连上服务器」既避免空引用, 也省掉主菜单阶段的每 tick 开销。

⚠️ 代价:切到主菜单时(仍连接)HUD 继续渲染, 因为断开事件只在真正断线时触发。

与 serverStarting 的分工

ClientProxy 的 serverStarting / serverStopping(:66-74)也操作 Tag.setServer(...),但那是单次服务器生命周期事件; 本类管的是客户端连接事件。

单机游戏时两者都会触发;多人时只有连接事件。 Tag.server 的赋值时机因此依赖 serverStarting 是否先于连接。

相关