Waila 兼容层

基本信息

属性 值
目的 让未针对 WDMla 改写的旧版 Waila 附属继续工作
兼容代码包 com.gtnewhorizons.wdmla.wailacompat(10 个文件,含 parser/ 子包 4 个)
旧版 API 标注 35 个文件带 @BackwardCompatibility(grep -rl '@BackwardCompatibility' src/main/java)
第二个 @Mod mcp.mobius.waila.Waila,modid Waila(Waila.java:37)
旧版 API 标记注解 mcp.mobius.waila.api.BackwardCompatibility
网络通道 沿用 Waila 通道名以保持封包兼容(见 Waila 协议通道)

功能

WDMla 是 WAILA 的 GTNH 分支,并没有抛弃旧 API——它把整套 WAILA 代码连同公开 API 一并保留在 mcp/mobius/waila/ 下,并在 mcmod.info 中同时声明 Waila 与 wdmla 两个 mod 条目。

兼容分两条路径。

路径一:IMC 注册的旧版 data provider

旧版 Waila 附属通过 FML IMC 发送 register 消息,把自己挂在 ModuleRegistrar 上。WDMla 在生成提示框时会同时跑一遍旧版 provider,再把结果转成自己的 UI 组件:

  • DataProviderCompat.getLegacyBlockTooltips / 对应的实体方法:按「先 head 后 body」的顺序遍历 ModuleRegistrar 的 provider,逐个调 getWailaHead / getWailaBody(DataProviderCompat.java:20-40)。类注释写明这是「通过模仿旧版 API 调用来收集全部 Waila 提示」(DataProviderCompat.java:17)。由于某些 head handler 会改写物品名,代码先插入一个占位名以免崩溃(DataProviderCompat.java:26),收集完再 remove(0) 删掉(DataProviderCompat.java:37-39)。
  • TERequestCompat.handleRequest / EntRequestCompat.handleRequest:在服务端处理请求包时并行执行 WDMla 的 provider 与旧版 Waila 的 provider,把两边的 NBT 合并回包。Message0x01TERequest 的类注释明写了这一点(Message0x01TERequest.java:18),调用点在 Message0x01TERequest.java:94;实体侧对应 Message0x03EntRequest.java:73。
  • TooltipCompat.computeRenderables:旧版 Waila Tooltip 的 computeRenderables 替代实现,把 List<String> 的旧式富文本解析成 WDMla 的 ITooltip 组件树(TooltipCompat.java:30-31),由 4 个解析器协作:HealthArgsParser、ItemArgsParser、ProgressArgsParser、IconArgsParser(TooltipCompat.java:25-28)。
  • HUDHandlerCompat:把旧版 HUD handler 的输出并入提示(HUDHandlerCompat.java:19-36)。
  • RayTracingCompat:enum 单例 INSTANCE,提供 getWailaEntity / getWailaStack——从命中结果反查旧版 Waila 眼中的方块/实体/物品表示(RayTracingCompat.java:25-29)。除兼容 handler 外,核心插件 的 DefaultBlockInfoProvider 也用它取替换物品栈(DefaultBlockInfoProvider.java:48)。

路径二:直接屏蔽重复实现

当 WDMla 已经覆盖了某个 mod 的信息时,屏蔽其旧版注册以免出现两套提示。机制见 储物抽屉插件:插件用 @WDMlaPlugin(overridingRegistrationMethodName = …) 声明要屏蔽的方法,PluginScanner 收进黑名单(PluginScanner.java:41-44),Waila.processIMC 在 General.overrideWailaTooltips 为真时据此跳过(Waila.java:109-119)。

交互

兼容层由两个 AccessorClientHandler 在客户端装配——BlockAccessorClientHandler 与 EntityAccessorClientHandler 各持有一个 TooltipCompat 与一个 DataProviderCompat 实例(BlockAccessorClientHandler.java:30-31、EntityAccessorClientHandler.java:28-29),并在处理命中结果时调用(BlockAccessorClientHandler.java:73、EntityAccessorClientHandler.java:66)。

旧版模组自身的 IMC 消息由 Waila.processIMC 处理,支持两个键:addconfig(按 $$ 分割为 3 段,解析失败只 warn 并 continue,Waila.java:91-107)与 register(Waila.java:109-119)。

旧版模块的注册在 FMLLoadCompleteEvent 时执行:Waila.loadComplete 先 proxy.registerLegacyMods() 再 proxy.registerIMCs()(Waila.java:80-84、ProxyServer.java:45)。注释明确写了这个顺序的原因:「这一阶段不要调用 wdmla,因为它还不存在」(Waila.java:50)。

兼容代码中的静默失败点

wailacompat 包里有四处 catch (Throwable e)(DataProviderCompat.java:60、DataProviderCompat.java:99、EntRequestCompat.java:53、TERequestCompat.java:86)。这些位置包住的是旧版附属的 provider 调用——第三方代码抛异常时不能让整个提示框崩掉,属于有意为之的隔离,不是缺陷。

真正需要留意的是同一兼容链路上的一处空 catch:Waila.initialize 反射读取 FMLModContainer.eventBus 并把自身注册上去,整段被 catch (Throwable ignored) {} 吞掉(Waila.java:60-65)。若目标 Forge 版本的字段名变化,FMLbus.register(this) 不会执行,而 loadComplete 的 @Subscribe 方法(Waila.java:80-84)将永远不会触发——类存在 ≠ 方法被调用。该 catch 无日志、无重抛。

同类空 catch 在本仓共 7 处:Waila.java:65、DataAccessorCommon.java:70、DataAccessorCommon.java:144、DisplayUtil.java:97、NEIHandler.java:54、HUDHandlerCompat.java:26、RayTracing.java:121 与 RayTracing.java:129(后两者为 catch (Exception ignored) {})。其中 DisplayUtil.java:97 与 HUDHandlerCompat.java:26 同属「吞掉旧版附属异常」的兼容策略;RayTracing.java 的两处位于物品收集的补充分支。

相关条目