package net.Chipperfluff.chipi.client.hud; import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.Chipperfluff.chipi.item.ModItems; import static net.Chipperfluff.chipi.util.ChipiTrackedData.CHIPI_ENERGY; public class ChipiStatusBar { private static final int ORANGE = 0xFFFF8000; private static final int OUTLINE_LIGHT = 0xFFB0B0B0; private static final int OUTLINE_DARK = 0xFF404040; private static final int TEXT_COLOR = 0xFFFFFFFF; private static final int BAR_HEIGHT = 6; public static void register() { HudRenderCallback.EVENT.register(ChipiStatusBar::render); } private static void render(DrawContext ctx, float tickDelta) { MinecraftClient client = MinecraftClient.getInstance(); if (client.player == null || client.options.hudHidden) return; if (!hasFullChipperArmor(client.player)) return; Float value = client.player.getDataTracker().get(CHIPI_ENERGY); if (value == null) return; value = Math.max(0f, Math.min(1f, value)); int screenWidth = client.getWindow().getScaledWidth(); int screenHeight = client.getWindow().getScaledHeight(); int centerX = screenWidth / 2; // ============================================================ // EXACT vanilla hunger bar bounds (pixel-perfect) // ============================================================ int hungerRight = centerX + 91; int hungerLeft = hungerRight - 81; // vanilla width (10 * 8 + 1) int barWidth = hungerRight - hungerLeft; // Base hunger Y int hungerY = screenHeight - 39; // While air bar is visible, hunger (and us) move up if (client.player.getAir() < client.player.getMaxAir()) { hungerY -= 10; } // Our bar sits directly above hunger int barY = hungerY - BAR_HEIGHT - 2; int fillWidth = (int)(barWidth * value); // ============================================================ // Alpha behavior // ============================================================ float alpha = value >= 1f ? 0.65f : value < 0.10f ? (float)(0.6f + 0.4f * Math.sin(System.currentTimeMillis() / 120.0)) : 1f; int outlineDark = applyAlpha(OUTLINE_DARK, alpha); int outlineLight = applyAlpha(OUTLINE_LIGHT, alpha); int fillColor = applyAlpha(ORANGE, alpha); int textColor = applyAlpha(TEXT_COLOR, alpha); // ============================================================ // Draw outline // ============================================================ ctx.fill(hungerLeft - 1, barY - 1, hungerRight + 1, barY, outlineDark); ctx.fill(hungerLeft - 1, barY + BAR_HEIGHT, hungerRight + 1, barY + BAR_HEIGHT + 1, outlineLight); ctx.fill(hungerLeft - 1, barY, hungerLeft, barY + BAR_HEIGHT, outlineDark); ctx.fill(hungerRight, barY, hungerRight + 1, barY + BAR_HEIGHT, outlineLight); // ============================================================ // Draw fill // ============================================================ ctx.fill(hungerLeft, barY, hungerLeft + fillWidth, barY + BAR_HEIGHT, fillColor); // ============================================================ // Percent text INSIDE bar, centered // ============================================================ String text = String.format("%03d%%", Math.round(value * 100f)); int textWidth = client.textRenderer.getWidth(text); int textX = hungerLeft + (barWidth - textWidth) / 2; int textY = barY - 1; ctx.drawText( client.textRenderer, text, textX, textY, textColor, true ); } private static int applyAlpha(int color, float alpha) { int a = (int)(((color >> 24) & 0xFF) * alpha); return (a << 24) | (color & 0x00FFFFFF); } private static boolean hasFullChipperArmor(PlayerEntity player) { PlayerInventory inv = player.getInventory(); return inv.getArmorStack(3).isOf(ModItems.CHIPPER_HELMET) && inv.getArmorStack(2).isOf(ModItems.CHIPPER_CHESTPLATE) && inv.getArmorStack(1).isOf(ModItems.CHIPPER_LEGGINGS) && inv.getArmorStack(0).isOf(ModItems.CHIPPER_BOOTS); } }