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:19 infohud.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 的两个总线类型不同,源码有意为之还是重复注册无法从代码判定。

关联