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()是filevalue 的定时重读,间隔由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。
相关
- Alignment -
format的键 - Value -
format的叶子 - ConfigurationHandler -
Scale来源 - ClientProxy - 全部 setter 的调用方