add Armor HUD module showing worn armor durability

lists the four worn armor pieces helmet-to-boots, skipping empty slots.
with Icons on (default) each row draws the item icon with its durability
percentage beside it, vertically centered; with Icons off it draws the
item's hover name plus the percentage as plain text. the percentage is
colored by condition (green >= 60%, yellow >= 30%, red below) and shows
a dash for items without durability. width/height track the drawn rows
so the editor box matches, falling back to the constructor size when
nothing is equipped
This commit is contained in:
froslanz
2026-10-24 12:57:42 -04:00
parent accbc69521
commit 6593a3f089
2 changed files with 82 additions and 0 deletions
@@ -0,0 +1,80 @@
package cc.fros.features.modules.hud;
import cc.fros.event.impl.render.Render2DEvent;
import cc.fros.features.modules.client.HudModule;
import cc.fros.features.settings.Setting;
import cc.fros.util.render.FrosFont;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.item.ItemStack;
public class ArmorHudModule extends HudModule {
/** helmet first, boots last */
private static final EquipmentSlot[] SLOTS = {
EquipmentSlot.HEAD, EquipmentSlot.CHEST, EquipmentSlot.LEGS, EquipmentSlot.FEET
};
private static final int HEALTHY = 0x55FF55;
private static final int WORN = 0xFFFF55;
private static final int CRITICAL = 0xFF5555;
public final Setting<Boolean> icons = bool("Icons", true);
public ArmorHudModule() {
super("Armor", "Display armor durability", 70, 40);
}
@Override
protected void render(Render2DEvent e) {
super.render(e);
if (nullCheck()) return;
float x = getX();
float y = getY();
boolean showIcons = icons.getValue();
int rowHeight = showIcons ? 16 : FrosFont.lineHeight();
int rows = 0;
int textWidth = 0;
for (EquipmentSlot slot : SLOTS) {
ItemStack stack = mc.player.getItemBySlot(slot);
if (stack.isEmpty()) continue;
float rowY = y + rows * rowHeight;
float ratio = durability(stack);
String percent = ratio < 0f ? "\u2014" : Math.round(ratio * 100) + "%";
int color = ratio < 0f ? -1
: ratio >= 0.6f ? HEALTHY
: ratio >= 0.3f ? WORN
: CRITICAL;
int textX;
int textY;
if (showIcons) {
e.getContext().renderItem(stack, (int) x, (int) rowY);
textX = (int) x + 19;
textY = (int) (rowY + 8 - FrosFont.visualCenter());
} else {
Component name = stack.getHoverName();
FrosFont.draw(e.getContext(), name, (int) x, (int) rowY, -1);
textX = (int) (x + FrosFont.width(name) + 4);
textY = (int) rowY;
}
FrosFont.draw(e.getContext(), percent, textX, textY, color);
textWidth = Math.max(textWidth, textX - (int) x + FrosFont.width(percent));
rows++;
}
if (rows > 0) {
setWidth(textWidth);
setHeight(rows * rowHeight);
}
}
/** durability left as 0..1, or -1 for items without durability */
private static float durability(ItemStack stack) {
int max = stack.getMaxDamage();
if (max <= 0) return -1f;
return (max - stack.getDamageValue()) / (float) max;
}
}
@@ -18,6 +18,7 @@ import cc.fros.features.modules.combat.KillAuraModule;
import cc.fros.features.modules.combat.CriticalsModule;
import cc.fros.features.modules.combat.KeyPearlModule;
import cc.fros.features.modules.hud.ArrayListHudModule;
import cc.fros.features.modules.hud.ArmorHudModule;
import cc.fros.features.modules.hud.CoordinatesHudModule;
import cc.fros.features.modules.hud.FpsHudModule;
import cc.fros.features.modules.hud.PingHudModule;
@@ -57,6 +58,7 @@ public class ModuleManager implements Jsonable, Util {
register(new RadarHudModule());
register(new WelcomerHudModule());
register(new TimeHudModule());
register(new ArmorHudModule());
register(new HudEditorModule());
register(new ClickGuiModule());
register(new NotificationsModule());