HUD 信息行
基本信息
| 属性 | 值 |
|---|---|
| 注册真源 | hud/Hud.java:54-93 initLines() |
| InfoLine 类总数 | 18(hud/core/infolines/ 下 18 个文件) |
| 实例化总数 | 最多 20 个(15 个常驻 + 5 个条件) |
| 图标配置 | HudConfig.hudItems,19 个 String(物品 ID) |
| 顺序配置 | HudConfig.hudOrder,19 个 int(范围 1–100) |
| 开关配置 | HudConfig.hudEnabled,20 个 boolean(默认全 true) |
| 渲染位置 | HudConfig.hudGeneral(HudX=0、HudY=0、HudScale=1.0、范围 0.5–2.0) |
initLines() 每次调用先 lines.clear()(Hud.java:55)再重建,
因此改配置后可通过重新调用该方法即时重建,无需重启。
基类 InfoLine(hud/core/InfoLine.java)
| 成员 | 行 | 说明 |
|---|---|---|
mc |
18 |
Minecraft.getMinecraft()(protected final,非 static) |
ROUGHDIRECTION |
19 |
static final String[] = { "South", "West", "North", "East" } |
| 构造器 | 21 |
InfoLine(int order) |
canRender() |
29 |
抽象,子类实现 |
getLineString() |
33 |
抽象,子类实现 |
getX/Y/Z() |
37/41/45 |
玩家坐标 |
getPlayer() |
49 |
EntityClientPlayerMP |
getWorld() / getProvider() / getBiome() |
53/57/61 |
便捷访问 |
getItemName() / getChachedItemStack() |
65/69 |
图标(注意 Chached 拼写错误) |
tr(String, Object...) |
93 |
static,走 infohud.hud.info_line. 前缀 |
⚠️
ROUGHDIRECTION的顺序是{"South", "West", "North", "East"}(InfoLine.java:19), 索引由MathHelper.floor_double(rotationYaw * 4.0 / 360.0 + 0.5) & 3得出 (InfoDirection.java:16-17)。这是硬编码英文,不走tr()—— 即便有中文语言包,朝向文本也永远是英文。
20 个实例逐条
| # | 类 | lang 键 | 图标配置项 | 开关 | 条件 |
|---|---|---|---|---|---|
| 1 | InfoMemory(客户端) |
info_memory |
MemoryItem |
MemoryEnable |
常驻 |
| 2 | InfoMemory(服务端) |
info_server_memory |
ServerMemoryItem |
ServerMemoryEnable |
常驻 |
| 3 | InfoPing |
info_ping |
PingItem |
PingEnable |
常驻 |
| 4 | InfoTPS |
info_tps |
TpsItem |
TpsEnable |
常驻 |
| 5 | InfoPosition |
info_position |
PositionItem |
PositionEnable |
常驻 |
| 6 | InfoFPS |
info_fps |
FpsItem |
FpsEnable |
常驻 |
| 7 | InfoDimension |
info_dimension |
DimensionItem |
DimensionEnable |
常驻 |
| 8 | InfoBiome |
info_biome |
BiomeItem |
BiomeEnable |
常驻 |
| 9 | InfoDirection |
info_direction |
DirectionItem |
DirectionEnable |
常驻 |
| 10 | InfoSlimeChunk |
info_slimechunk |
SlimeChunkItem |
SlimeChunkEnable |
常驻 |
| 11 | InfoWorldTime(世界时间) |
info_worldtime.0/1/2 |
WorldTimeItem |
WorldTimeEnable |
常驻 |
| 12 | InfoWorldTime(游戏时长) |
info_playtime.0/1/2 |
PlayTimeItem |
PlayTimeEnable |
常驻 |
| 13 | InfoSessionTime |
info_sessiontime.0/1/2 |
SessionTimeItem |
SessionTimeEnable |
常驻 |
| 14 | InfoJump |
info_jump |
JumpItem |
JumpEnable |
常驻 |
| 15 | InfoCountItem |
无(裸数字) | 无 | CountItemEnable |
常驻 |
| 16 | InfoBloodMagic |
info_blood_magic |
LpItem |
LpEnable |
AWWayofTime |
| 17 | InfoThaumcraft |
info_warp |
WarpItem |
WarpEnable |
Thaumcraft |
| 18 | InfoOreChunk |
info_orechunk |
OreChunkItem |
OreChunkEnable |
gregtech_nh |
| 19 | InfoForestry |
无(借 Forestry 本地化) | ForestryItem |
ForestryEnable |
Forestry |
| 20 | InfoNutrient |
无(自建字符串) | NutrientItem |
NutrientEnable |
nutrition |
常驻 15 个实例来自 13 个类(InfoMemory 与 InfoWorldTime 各用两次),
条件 5 个(一行一个类)。合计 18 个类。
逐条细节
InfoMemory(InfoMemory.java)—— 双实例
return isServer ? tr("info_server_memory", DataStorage.serverMemUsed, DataStorage.serverMemMax)
: tr("info_memory", getUsedMemory(), getMaxMemory());
(InfoMemory.java:24-27)
isServer 由构造器第二参决定(Hud.java:57-58 分别传 false / true)。
| 模式 | 数据来源 | canRender() 条件 |
|---|---|---|
| 客户端 | JVM Runtime(InfoMemory.java:29-41:getUsedMemory = (total - free) / MB,getMaxMemory = maxMemory / MB) |
MemoryEnable |
| 服务端 | DataStorage.serverMemUsed / serverMemMax(由服务端通过网络下发) |
ServerMemoryEnable && !(DataStorage.serverMemUsed == -1)(InfoMemory.java:19) |
服务端内存行在未收到数据时(
-1)自动隐藏。
InfoFPS(InfoFPS.java:15)
return tr("info_fps", getPlayer().getDisplayName(), ((MinecraftAccessor) mc).getFps());
FPS 通过 MinecraftAccessor 这个 Mixin accessor 读取——
Minecraft 没有公开的 FPS 字段,必须用 accessor 注入。
lang 格式:§6%s §rFPS: §a%s(玩家名 + 帧率)。
InfoTPS(InfoTPS.java:20)
return tr("info_tps", DataStorage.getTPSColor(), DataStorage.tps,
DataStorage.getMSPTColor(), DataStorage.mspt);
同时显示 TPS 与 MSPT(每 tick 毫秒),两者都带颜色代码
(getTPSColor() / getMSPTColor() 按数值返回颜色)。
数据由服务端下发(hud/core/DataStorage.java)。
InfoPing(InfoPing.java:20)
return tr("info_ping", DataStorage.getPlayerPing(getPlayer().getUniqueID()));
按 玩家 UUID 取延迟——因此只能显示自己的, 数据同样来自服务端。
InfoPosition / InfoDimension / InfoBiome
| 类 | 取值 |
|---|---|
InfoPosition |
getX(), getY(), getZ()(基类 InfoLine.java:37-47) |
InfoDimension |
getProvider().getDimensionName() + getProvider().dimensionId(InfoDimension.java:14) |
InfoBiome |
getBiome().biomeName + String.format("%.0f", getBiome().rainfall * 100)(InfoBiome.java:14) |
InfoBiome显示的是rainfall(降雨量),lang 里却写成Humidity(湿度) ——en_US.lang:19infohud.hud.info_line.info_biome=Biome: §6%s §rHumidity: §a%s%%。 文案与实际取的值不符(BiomeGenBase 没有 humidity 字段,只有 rainfall/temperature)。
InfoDirection(InfoDirection.java:15-17)
return tr("info_direction",
ROUGHDIRECTION[MathHelper.floor_double(getPlayer().rotationYaw * 4.0 / 360.0 + 0.5) & 3]);
只有朝向(South/West/North/East 四向),无坐标。
InfoWorldTime(双实例,InfoWorldTime.java)
| 实例 | isWorldTime |
lang 键 | 内容 |
|---|---|---|---|
世界时间(Hud.java:67 传 false) |
游戏内世界时间 | info_worldtime.0/1/2 |
世界秒/分/时 + HH:mm + 昼夜后缀 |
游戏时长(Hud.java:68 传 true) |
累计游玩时长 | info_playtime.0/1/2 |
游玩秒/分/时 |
同一类用两个 lang 键:info_worldtime.* 与 info_playtime.*。
时长格式化用 String.format("%02d:%02d", hours, minutes)
与 String.format("%,d", totalHours)(千分位)。
lang 提供 3 档(.0 秒 / .1 分 / .2 时),由代码按量级切换。
InfoSessionTime(InfoSessionTime.java:16-31)
本次会话的在线时长,同样 3 档切换:
if (...) return tr("info_sessiontime.0", 0); // < 1 分钟
if (...) return tr("info_sessiontime.2", hours, minutes, seconds);
if (...) return tr("info_sessiontime.1", minutes, seconds);
return tr("info_sessiontime.0", seconds);
lang 格式差异(en_US.lang:29-31):
.0=Session: §6%ss、.1=Session: §6%sm %ss、.2=Session: §6%sh %sm %ss。
InfoJump(InfoJump.java:28)
跳跃次数累计,lang info_jump=Jumps: §6%s。
InfoCountItem(InfoCountItem.java)—— 唯一无 lang、无图标的行
public String getLineString() {
...
return ""; // 第 21 行:无效时返回空串
...
return String.valueOf(count); // 第 39 行
}
显示手持物品的数量。它:
- 没有 lang 键(直接
String.valueOf(count),只输出数字) - 没有 图标配置项(
HudConfig.hudItems里没有CountItem字段) canRender()为count > 1 && HudConfig.hudEnabled.CountItemEnable(InfoCountItem.java:63) ——只有手持数量 > 1 才显示getLineString()在无效时返回""(InfoCountItem.java:21)而非null- 实例化时 order 硬编码为
0:lines.add(new InfoCountItem(0));(Hud.java:72) ——不受HudConfig.hudOrder任何配置项控制
⚠️
HudConfig.hudOrder有 19 项、hudItems有 19 项、hudEnabled有 20 项。 三者数量不一致的原因就是InfoCountItem:有开关无顺序无图标。
InfoSlimeChunk(InfoSlimeChunk.java:16)/ InfoOreChunk(InfoOreChunk.java:17)
两者只在「是」的时候显示一行,不是则不显示:
// InfoSlimeChunk
return tr("info_slimechunk");
// InfoOreChunk
return tr("info_orechunk");
InfoOreChunk.canRender() 是 OreChunkEnable && isOreChunk()(InfoOreChunk.java:30)——
开关打开但当前不在矿脉区块时,这一行直接不出现。
lang 文本(en_US.lang:21-22):
This is an §a§nore chunk§r / This is a §a§nslime chunk§r。
InfoSlimeChunk走的canRender()在InfoLine基类里只要求开关; 区块判定应在getLineString之前完成(InfoSlimeChunk.java:16无条件 return 文本)。 两者的隐藏机制不完全对称:InfoSlimeChunk似乎不检查是否真的在史莱姆区块。 源码两处实现不同,不要把它们当同一套逻辑。
InfoBloodMagic(InfoBloodMagic.java:16-24)
return tr("info_blood_magic", getCurrentLP(), getMaxLP());
读取玩家 NBT 的 LP 标签:
return String.format("%,d", HudUtils.getPlayerLPTag(getPlayer()));
HudUtils 直接读 LP 的 NBT,不经 Blood Magic API——
这是本 mod 对 Blood Magic 的全部耦合点。
InfoThaumcraft(InfoThaumcraft.java:19-24)
return tr("info_warp", getWarpTotal(getPlayer()), getWarpPerm(getPlayer()),
getWarpSticky(getPlayer()), getWarpTemp(getPlayer()));
显示 4 个扭曲值:总扭曲 / 权限 / 粘性 / 临时。
lang:Warp: §6%s §r(P: §c%s §r| S: §c%s §r| T: §c%s§r)。
InfoForestry(InfoForestry.java:20-27)
return AlleleManager.climateHelper.toDisplay(temperature) + ": " + ...
直接调用 Forestry 的 AlleleManager.climateHelper.toDisplay()——
因此文本与语言包由 Forestry 提供,本 mod 不翻译。
InfoNutrient(InfoNutrient.java:23-43)
用 StringBuilder 自行拼装(InfoNutrient.java:43 return sb.toString() + ...),
并有 switch (nutrientName.toLowerCase())(InfoNutrient.java:58)做营养素名映射。
不用 lang 键。
事件注册(Hud.java:40-51)
| 行 | 注册对象 | 事件总线 |
|---|---|---|
40-42 |
TickListener |
FMLCommonHandler.bus() |
43-44 |
JoinWorldEvent |
MinecraftForge.EVENT_BUS |
45-47 |
JoinWorldEvent(同一个实例) |
FMLCommonHandler.bus() |
49-51 |
BloodMagicEvent |
MinecraftForge.EVENT_BUS,仅当 AWWayofTime 已加载 |
JoinWorldEvent被同时注册到两个事件总线(Hud.java:44、47)—— Forge 的两个总线类型不同,源码有意为之还是重复注册无法从代码判定。