InGame Info XML

[!INFO] Git Commit: 5856788 | Updated: 2026-10-01

屏幕左下角(或任意九宫格位置)的可配置 HUD 叠加层,modid 为 InGameInfoXML。 显示内容完全由一份 XML/JSON/TXT 配置文件决定,内置 151 个 tag 与 31 个 value 函数。

身份

属性 实测值
modid InGameInfoXML(Reference.java:8)
modName InGame Info XML(gradle.properties)
资源域 ingameinfo(全小写,src/main/resources/assets/ingameinfo/)
lang key 前缀 ingameinfoxml(= MODID.toLowerCase(),见 Tag.java:68)
网络通道名 ingameinfoxml(PacketHandler.java:14)
Java 文件 73(7 706 行)
注册内容 0 方块 / 物品 / 实体(纯 HUD,无游戏内容)
作者 Lunatrius(mcmod.info authorList)
致谢 DaftPVF, bspkrs(mcmod.info credits)

[!WARNING] 四个名字互不相同 —— 本 mod 是「modid ≠ 资源域」的代表案例

用途 值 出处
FML modid InGameInfoXML Reference.java:8
资源域 ingameinfo assets/ingameinfo/
lang key 前缀 ingameinfoxml Tag.java:68、Names.Config.LANG_PREFIX
Wiki 分类名 ingame-info-xml 仓库名 InGame-Info-XML 小写化

mcmod.info 的 modid/name/version 三个字段全是 ${modId} 构建期占位符, 真实 modid 只能从 gradle.properties 的 modId = InGameInfoXML 与 Reference.MODID 实读。

[!IMPORTANT] 定位:HUD 叠加层,不是 F3 调试信息替换器 本 mod 的功能是「在游戏画面上叠加一层自定义文本」。 它默认不碰 F3:配置项 replaceDebug 默认 false (ConfigurationHandler.java:26),只有玩家主动改成 true 时 才会用 event.setCanceled(true) 顶掉原版 DEBUG 覆盖层 (Ticker 的 :22-25)。 分类名里的 “Info” 指屏幕信息,不是 F3/debug info。

依赖关系

依赖 作用域 说明
LunatriusCore api 唯一硬依赖,mcmod.info 写 LunatriusCore@[1.1.4,);提供 Vector2f/3f/3i、DelayedGuiDisplayTicker
Blood Magic compileOnly modid 实测 AWWayofTime(≠ 分类名 bloodmagic)
Thaumcraft compileOnly modid Thaumcraft,getDependencyVersion() 读 Thaumcraft.VERSION
GT5-Unofficial compileOnly modid gregtech_nh(≠ 分类名 gregtech)
cofh-lib compileOnly curse.maven
Simply Jetpacks compileOnly modid simplyjetpacks
TFC compileOnly curse.maven tfcraft
org.jetbrains:annotations compileOnly 仅 @NotNull / @Nullable 标注

已登记分类:lunatriuscore、thaumcraft、 gregtech(均已成文); bloodmagic 已登记未成文(前向引用)。 Simply Jetpacks / TFC / cofh-lib 不在收录范围,只以纯文本提及。

Access Transformer(META-INF/igi_at.cfg)

三条字段放开,全部服务于服务端取数:

目标 字段 用途
PlayerControllerMP field_78779_k(currentGameType) TagPlayerGeneral 的 gamemode
FoodStats field_75126_c(foodExhaustionLevel) 同上 exhaustion
NetHandlerPlayClient field_147310_i(playerInfoMap) TagMisc 的 servername

PlayerControllerMP 与 FoodStats 是服务端专属类, 所以这条 AT 等于让服务端持有这两个字段的访问权。

配置项(7 项 + 9 个对齐偏移)

全部定义在 ConfigurationHandler, 默认值读自 *_DEFAULT 常量:

配置键 类型 默认值 范围 说明
filename String InGameInfo.xml — 启动时加载的配置文件
ShowHUD boolean true — 是否渲染叠加层
replaceDebug boolean false — 顶掉原版 F3 DEBUG 层
showInChat boolean true — 聊天界面内也显示
showOnPlayerList boolean true — 多人列表打开时也显示
scale(new) int 10 1–20 缩放;实际除以 10 后传给 GL11.glScalef
fileInterval int 5 1–60 file tag 的文件重读间隔(秒)

⚠️ scale 的键名在 Names.Config 里是 "scale(new)"(Names.java:66), 注释明写 (use this one, the other is deprecated) —— 说明历史上存在过另一个 scale 项,当前只保留带 (new) 的。ClientProxy 把它和 fileInterval 都设为 GuiConfigEntries.NumberSliderEntry(ClientProxy.java:45-46), 所以在游戏内配置界面里是滑块。

filename 标了 setRequiresMcRestart(true)(:64),其余 6 项都是 false 或未设置。

九宫格对齐(9 项)

Alignment 枚举 9 个位置,每个在 alignment 分类下有一条 X Y 偏移配置,校验正则 -?\d+ -?\d+(:95)。 默认值见各枚举构造参数,详见 Alignment 条目。

配置文件格式

三种格式同权重:InGameInfoCore 按扩展名选解析器(:118-124)—— .xml / .json / .txt。

配置文件查找顺序(:92-107):

  1. <配置目录>/InGameInfo_<当前语言>.xml(locale 感知)
  2. <配置目录>/InGameInfo.xml
  3. 都没有 → 读 jar 内 assets/ingameinfo/InGameInfo.xml(:205-206)

preInit 会把配置文件移动到子目录 InGameInfoXML/ (ClientProxy.java:39-41 + InGameInfoCore.moveConfig)。

渲染时机

由 TickerManager 在连上服务器时才注册 Ticker,断开时反注册 —— 主菜单不渲染。

  • ClientTickEvent END 阶段 → Tag.update() + 逐行 InfoText.update()
  • RenderGameOverlayEvent.Post 的 TEXT 元素 → 绘制(:42-48)

源码缺陷

  1. Tag.update() 与 Tag.releaseResources() 每 tick 调用,但 Ticker 在主菜单 阶段从未注册 —— 这本身没问题;问题在于 WorldHandler(服务端)每秒 向全维度广播 MessageNextRain(见下)。
  2. 服务端每秒全维度广播雨时 —— WorldHandler :18 的节流条件是 world.getTotalWorldTime() % 20 != 0, 配合 :22 的 Side.SERVER && Phase.END,结果是每 20 tick(1 秒) 对每个有玩家的维度 sendToDimension。多人多维度时是持续的 N² 广播开销, 且该数据客户端本可自行推算。
  3. TagPlayerEquipment.Icon 注册两次同名构造 —— TagPlayerEquipment.java:202-203 用 new Icon(SLOTS[i], false) / new Icon(SLOTS[i], true) 生成 ...icon 与 ...largeicon, 但两者都指向同一个内部类 Icon,ValueRegistry 那种「类 → 名」反查(classStringMap)在这里会互相覆盖 (见 ValueRegistry 的 isAlias 分支逻辑)。
  4. Reference.logger 是 public static 可变字段 —— Reference.java:14 声明为 public static Logger(非 final), CommonProxy.preInit(:15)在运行时替换它。线程可见性无保护。
  5. Alignment.parse 无匹配返回 null 而不抛异常 —— Alignment.java:69-73 捕获所有异常后 return null; 调用方 TextParser 需自行判空。
  6. TagRegistry.register 的判空顺序错误 —— TagRegistry.java:29-37 先查 containsKey(name) 再判 name == null。 HashMap.containsKey(null) 不抛异常,所以逻辑上仍安全, 但两次判空的顺序与 ValueRegistry(:22-30,同样顺序)一致且都可正常拦截, 属冗余而非崩溃 —— 真正的问题是 register(Tag) 传入 tag.getName(),若 setName 从未调用则 name 为 null, 错误日志文案是「Tag name cannot be null!」,但此时该 tag 的别名也不会注册。

分类索引

核心

  • InGameInfoXML - 模组主类:5 个生命周期事件全部转发给 proxy
  • InGameInfoCore - 单例核心:配置定位、三格式解析器选择、tick 与渲染
  • Alignment - 九宫格对齐枚举:位掩码布局与偏移换算

常量

  • Reference - modid / 名称 / proxy 类名 / logger
  • Names - 第三方 modid、命令、配置键、文件名、键位常量

客户端 GUI

  • Info - 绘制基类:树形子节点、尺寸测量
  • InfoText - 一行文本:拼接 value、挂载图标/物品
  • InfoItem - 物品堆渲染节点(普通/大号)
  • InfoIcon - 纹理图集子矩形渲染节点
  • GuiFactory - IModGuiFactory 实现
  • GuiModConfig - Forge 配置界面
  • GuiTags - tag 浏览器界面
  • GuiTagList - tag 列表控件(按分类分组)

命令

  • InGameInfoCommand - /igi 客户端命令:reload/load/save/enable/disable/taglist/config

事件与配置

网络

解析器

输出器

Proxy

Tag

Value 函数

集成

源码:/Users/evlos/a/mirror/InGame-Info-XML/ 关系登记:见 data/relation.md(全局 Wiki 分类映射表)