占位符替换(StringReplacer)
基本信息
| 属性 | 值 |
|---|---|
| 源码类 | lumien.custommainmenu.lib.StringReplacer(全静态) |
| 静态占位符 | replacePlaceholders(7 个) |
| 动态占位符 | dynamicPlaceholders + replaceDynamicPlaceholders(2 个) |
| 生效范围 | 按钮文本、按钮提示框、文本元素 |
7 个静态占位符
replacePlaceholders(StringReplacer.java:23-30),用 String.replace 逐个链式替换:
| 占位符 | 替换为 | 来源 |
|---|---|---|
#mcversion# |
硬编码字面量 "1.7.10" |
⚠️ 见下方说明 |
#fmlversion# |
Loader.instance().getFMLVersionString() |
FML |
#mcpversion# |
反射读 Loader.mcpversion |
静态块反射 |
#modsloaded# |
Loader.getModList().size() |
已加载 mod 总数 |
#modsactive# |
Loader.getActiveModList().size() |
实际激活的 mod 数 |
#forgeversion# |
ForgeVersion.getVersion() |
Forge |
#username# |
Minecraft.getSession().getUsername() |
当前登录名 |
⚠️ #mcversion# 是写死的 "1.7.10"(StringReplacer.java:24),不读 Minecraft.getMinecraft().getMinecraftVersion()。在 1.7.10 整合包里结果恰好正确,但源码层面它并不"动态"。
⚠️ #mcpversion# 依赖反射 Forge 私有静态字段 Loader.mcpversion。GTNH 改版 Forge 若重命名该字段,反射失败 → printStackTrace → mcpversion 保持 null → String.replace(target, null) 抛 NullPointerException,会让所有用到该占位符的文本渲染失败。这是 GTNH 环境下最值得关注的一处脆弱点。
2 个动态占位符
dynamicPlaceholders = { "#date#", "#time#" }(StringReplacer.java:21):
| 占位符 | 格式 | 说明 |
|---|---|---|
#date# |
DateFormat.getDateInstance(2, Locale.getDefault()) |
跟随系统语言与地区的本地化日期 |
#time# |
SimpleDateFormat("HH:mm") |
24 小时制本地时间 |
两者都每帧重新计算(见下),所以可以用来做实时时钟。
何时替换
渲染层按"先静态、命中动态才继续"的顺序处理(GuiCustomButton.java:113-122、GuiCustomLabel.java:87-95):
String text = StringReplacer.replacePlaceholders(hovered ? hoverText.get() : text.get());
for (String p : StringReplacer.dynamicPlaceholders) {
if (text.contains(p)) return StringReplacer.replaceDynamicPlaceholders(text);
}
return text;
| 场景 | 行为 |
|---|---|
文本不含 #date# / #time# |
只做静态替换,无每帧开销 |
| 文本含其一 | 追加一次动态替换(DateFormat 格式化每帧执行) |
提示框走另一条路
按钮 tooltip 不经过上面的逻辑,而是由 LogicUtil.getTooltip 按行调 replacePlaceholders(LogicUtil.java:11-16):
- 只做静态替换,⚠️
#date#/#time#在提示框里不会被替换,会原样显示这两个串。 - 按
\n拆行成ArrayList<String>交给原版悬停框。
已知限制
- 纯
String.replace,无转义机制:想显示字面量#date#做不到。 - 静态占位符在 文本来源 解析之后才替换,所以
web:拉回来的内容同样能享受替换。 - 飘字(SplashText)不经过
StringReplacer——drawScreen直接drawCenteredString(GuiCustom.java:269),飘字里写占位符不会生效。
相关条目
- 文本来源(IText) - 替换发生在文本解析之后
- 按钮(Button) - 提示框的替换差异
- 文本(Text) - 同样支持全部占位符