InGameInfoCore

单例核心:配置定位、三格式解析器选择、tick 与渲染

基本信息

属性 值
路径 com.github.lunatrius.ingameinfo.InGameInfoCore
行数 266(本 mod 第三大文件)
单例 public static final InGameInfoCore INSTANCE = new InGameInfoCore()(:39)
构造器 private InGameInfoCore() {}(:59)—— 强制单例

⚠️ 字段初始化顺序陷阱:private final Minecraft minecraft = Minecraft.getMinecraft()(:43) 与 public ScaledResolution scaledResolution = new ScaledResolution(minecraft, ...)(:51-54) 在静态 INSTANCE 初始化时就执行,即类加载即触碰 Minecraft 单例。 在服务端加载该类会出问题 —— 好在服务端路径不引用本类。

格式数据

private final Map<Alignment, List<List<Value>>> format = new HashMap<>();

三重嵌套:alignment → 行 → 该行的 value 列表。 这是 parser 与 printer 之间传递的唯一数据结构。

解析器选择(:109-132)

setConfigFile 按扩展名决定 parser:

扩展名 解析器
.xml XmlParser
.json JsonParser
.txt TextParser
其它 / 文件不存在 回落 XmlParser(:129)

⚠️ 文件不存在时(:128-131)会 configFile = null 并把 baseConfigFileName = null,此时 reloadConfig() 走 getInputStream() 的 else 分支,读 jar 内默认配置。

本地化文件名(:101-107)

String userLang = minecraft.getLanguageManager().getCurrentLanguage().getLanguageCode();
String[] parts = filename.split("\\.", 2);
return parts[0] + "_" + userLang + extension;

InGameInfo.xml + 语言 zh_CN → InGameInfo_zh_CN.xml。 split("\.", 2) 限制 2 段,所以 a.b.xml 会得到 base a / ext .b.xml(不严谨)。

setConfigFileWithLocale(:92-99)先试本地化名,存在则用它并把 baseName 记为无语言后缀的原名 —— 这个 base 名被 KeyInputHandler 用来推导「2 号配置」。

onTickClient(:134-156)

float scale = ClientConfigurationHandler.Scale / 10;
scaledWidth  = (int) (scaledResolution.getScaledWidth()  / scale);
scaledHeight = (int) (scaledResolution.getScaledHeight() / scale);
Tag.update();
if (needsRefresh) { refreshInfoTexts(); needsRefresh = false; }
for (Alignment alignment : Alignment.VALUES) { ... infoText.update(lastActiveIndex) ... }
ValueComplex.ValueFile.tick();
  • Scale 默认 10 → scale = 1.0f(Scale/10 是 float 运算,/10 不会整除)
  • ValueFile.tick() 是 file value 的定时重读,间隔由 fileInterval(默认 5 秒)控制

onTickRender(:158-169)

GL11.glPushMatrix();
GL11.glScalef(scale, scale, scale);
for (Alignment alignment : Alignment.VALUES)
    for (InfoText info : alignment.getLines()) info.draw();
GL11.glPopMatrix();

缩放靠 glScalef 包裹,每帧一次 push/pop。

reloadConfig(:175-194)

needsRefresh = true;
format.clear();
if (parser == null) return false;
InputStream is = getInputStream();
if (is == null) return false;
if (parser.load(is) && parser.parse(format)) return true;
format.clear();     // 失败时清空,避免残留半成品
return false;

⚠️ load() 与 parse() 是短路与:load 失败不会调 parse。 失败路径会 format.clear(),所以 HUD 变空而不是显示上次的旧内容。

getInputStream(:196-214)

优先用户配置文件(FileInputStream),否则读 jar 内 new ResourceLocation("ingameinfo", "InGameInfo.xml")(:205)—— 注意这里硬编码了资源域 ingameinfo,与 modid InGameInfoXML 不同。

异常统一 logger.error("", e) —— 消息为空字符串,只留堆栈。

moveConfig(:245-265)

把 config/InGameInfo.xml 移到 config/InGameInfoXML/InGameInfo.xml, 用于整理用户配置目录。带 destination.startsWith(directory) 路径逃逸检查(:251-254, 注释自称 “Maybe we don’t need but just in case”), 检查失败直接 throw new RuntimeException。

相关