package tconstruct.client; import static net.minecraftforge.client.event.RenderGameOverlayEvent.ElementType.HEALTH; import java.util.Random; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Gui; import net.minecraft.entity.SharedMonsterAttributes; import net.minecraft.entity.ai.attributes.IAttributeInstance; import net.minecraft.potion.Potion; import net.minecraft.util.MathHelper; import net.minecraft.util.ResourceLocation; import net.minecraftforge.client.GuiIngameForge; import net.minecraftforge.client.event.RenderGameOverlayEvent; import net.minecraftforge.common.MinecraftForge; import org.lwjgl.opengl.GL11; import cpw.mods.fml.common.Loader; import cpw.mods.fml.common.eventhandler.EventPriority; import cpw.mods.fml.common.eventhandler.SubscribeEvent; import cpw.mods.fml.common.gameevent.TickEvent; public class HealthBarRenderer extends Gui { private static final boolean isRpghudLoaded = Loader.isModLoaded("rpghud"); private static final boolean isTukmc_vzLoaded = Loader.isModLoaded("tukmc_Vz"); private static final boolean isBorderlandsModLoaded = Loader.isModLoaded("borderlands"); private static final ResourceLocation TINKER_HEARTS = new ResourceLocation("tinker", "textures/gui/newhearts.png"); private static final Minecraft mc = Minecraft.getMinecraft(); private final Random rand = new Random(); private int updateCounter = 0; @SubscribeEvent public void onTick(TickEvent.ClientTickEvent event) { if (event.phase == TickEvent.Phase.START && !mc.isGamePaused()) { this.updateCounter++; } } /* HUD */ @SubscribeEvent(priority = EventPriority.HIGH) // Not highest for DualHotbar compatibility public void renderHealthbar(RenderGameOverlayEvent.Pre event) { if (event.type != RenderGameOverlayEvent.ElementType.HEALTH) { return; } // uses different display, displays health correctly by itself. if (isRpghudLoaded) { return; } if (isTukmc_vzLoaded && !isBorderlandsModLoaded) { // Loader check to avoid conflicting // with a GUI mod (thanks Vazkii!) return; } mc.mcProfiler.startSection("health"); GL11.glEnable(GL11.GL_BLEND); final int width = event.resolution.getScaledWidth(); final int height = event.resolution.getScaledHeight(); final int xBasePos = width / 2 - 91; int yBasePos = height - 39; boolean highlight = mc.thePlayer.hurtResistantTime / 3 % 2 == 1; if (mc.thePlayer.hurtResistantTime < 10) { highlight = false; } final IAttributeInstance attrMaxHealth = mc.thePlayer.getEntityAttribute(SharedMonsterAttributes.maxHealth); final int health = MathHelper.ceiling_float_int(mc.thePlayer.getHealth()); final int healthLast = MathHelper.ceiling_float_int(mc.thePlayer.prevHealth); final float healthMax = Math.min(20F, (float) attrMaxHealth.getAttributeValue()); final float absorb = mc.thePlayer.getAbsorptionAmount(); final int healthRows = MathHelper.ceiling_float_int((healthMax + absorb) / 2.0F / 10.0F); final int rowHeight = Math.max(10 - (healthRows - 2), 3); this.rand.setSeed(updateCounter * 312871L); int left = width / 2 - 91; int top = height - GuiIngameForge.left_height; if (!GuiIngameForge.renderExperiance) { top += 7; yBasePos += 7; } int regen = -1; if (mc.thePlayer.isPotionActive(Potion.regeneration)) { regen = updateCounter % 25; } final int TOP; int tinkerTextureY = 0; if (mc.theWorld.getWorldInfo().isHardcoreModeEnabled()) { TOP = 9 * 5; tinkerTextureY += 27; } else { TOP = 0; } final int BACKGROUND = (highlight ? 25 : 16); int MARGIN = 16; if (mc.thePlayer.isPotionActive(Potion.poison)) { MARGIN += 36; tinkerTextureY = 9; } else if (mc.thePlayer.isPotionActive(Potion.wither)) { MARGIN += 72; tinkerTextureY = 18; } float absorbRemaining = absorb; // Render vanilla hearts for (int i = MathHelper.ceiling_float_int((healthMax + absorb) / 2.0F) - 1; i >= 0; --i) { final int row = MathHelper.ceiling_float_int((float) (i + 1) / 10.0F) - 1; int x = left + i % 10 * 8; int y = top - row * rowHeight; if (health <= 4) y += rand.nextInt(2); if (i == regen) y -= 2; this.drawTexturedModalRect(x, y, BACKGROUND, TOP, 9, 9); // heart background texture if (highlight) { if (i * 2 + 1 < healthLast) { this.drawTexturedModalRect(x, y, MARGIN + 54, TOP, 9, 9); // full heart damage texture } else if (i * 2 + 1 == healthLast) { this.drawTexturedModalRect(x, y, MARGIN + 63, TOP, 9, 9); // half heart damage texture } } if (absorbRemaining > 0.0F) { if (absorbRemaining == absorb && absorb % 2.0F == 1.0F) { this.drawTexturedModalRect(x, y, MARGIN + 153, TOP, 9, 9); // half heart absorption texture } else { this.drawTexturedModalRect(x, y, MARGIN + 144, TOP, 9, 9); // full heart absorption texture } absorbRemaining -= 2.0F; } else if (i * 2 + 1 + 20 >= health) { // only draw red vanilla hearts when it won't be covered by tinkers' hearts if (i * 2 + 1 < health) { this.drawTexturedModalRect(x, y, MARGIN + 36, TOP, 9, 9); // full heart texture } else if (i * 2 + 1 == health) { this.drawTexturedModalRect(x, y, MARGIN + 45, TOP, 9, 9); // half heart texture } } } if (health > 20) { // Render tinkers' hearts mc.getTextureManager().bindTexture(TINKER_HEARTS); for (int i = Math.max(0, health / 20 - 2); i < health / 20; i++) { // uncomment the line below to help with debugging // yBasePos -=20; final int heartIndexMax = Math.min(10, (health - 20 * (i + 1)) / 2); for (int j = 0; j < heartIndexMax; j++) { int y = 0; if (j == regen) y -= 2; if ((i + 1) * 20 + j * 2 + 21 >= health) { // full heart texture this.drawTexturedModalRect(xBasePos + 8 * j, yBasePos + y, 18 * i, tinkerTextureY, 9, 9); } } if (health % 2 == 1 && heartIndexMax < 10) { int y = 0; if (heartIndexMax == regen) y -= 2; // half heart texture this.drawTexturedModalRect( xBasePos + 8 * heartIndexMax, yBasePos + y, 9 + 18 * i, tinkerTextureY, 9, 9); } } mc.getTextureManager().bindTexture(icons); } GuiIngameForge.left_height += 10; if (absorb > 0) GuiIngameForge.left_height += 10; GL11.glDisable(GL11.GL_BLEND); mc.mcProfiler.endSection(); event.setCanceled(true); MinecraftForge.EVENT_BUS.post(new RenderGameOverlayEvent.Post(event, HEALTH)); } }