From a5b7f032cf57960dfe0e1e5f5fab74b69d7cf345 Mon Sep 17 00:00:00 2001 From: Bernhard Bonigl Date: Mon, 17 Oct 2016 18:48:37 +0200 Subject: [PATCH] Add the extra heart rendering from 1.7 TiC --- src/main/java/slimeknights/mantle/Mantle.java | 10 + .../client/ExtraHeartRenderHandler.java | 246 ++++++++++++++++++ .../assets/mantle/textures/gui/absorb.png | Bin 0 -> 5893 bytes .../assets/mantle/textures/gui/hearts.png | Bin 0 -> 5828 bytes 4 files changed, 256 insertions(+) create mode 100644 src/main/java/slimeknights/mantle/client/ExtraHeartRenderHandler.java create mode 100644 src/main/resources/assets/mantle/textures/gui/absorb.png create mode 100644 src/main/resources/assets/mantle/textures/gui/hearts.png diff --git a/src/main/java/slimeknights/mantle/Mantle.java b/src/main/java/slimeknights/mantle/Mantle.java index 8628f564..8e245d13 100644 --- a/src/main/java/slimeknights/mantle/Mantle.java +++ b/src/main/java/slimeknights/mantle/Mantle.java @@ -1,13 +1,16 @@ package slimeknights.mantle; +import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.Instance; import net.minecraftforge.fml.common.SidedProxy; +import net.minecraftforge.fml.common.event.FMLPostInitializationEvent; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import slimeknights.mantle.client.ExtraHeartRenderHandler; import slimeknights.mantle.common.CommonProxy; /** @@ -41,4 +44,11 @@ public class Mantle { public void preInit(FMLPreInitializationEvent event){ proxy.preInit(); } + + @Mod.EventHandler + public void postInit(FMLPostInitializationEvent event) { + if(event.getSide().isClient()) { + MinecraftForge.EVENT_BUS.register(new ExtraHeartRenderHandler()); + } + } } diff --git a/src/main/java/slimeknights/mantle/client/ExtraHeartRenderHandler.java b/src/main/java/slimeknights/mantle/client/ExtraHeartRenderHandler.java new file mode 100644 index 00000000..fd4b3f4c --- /dev/null +++ b/src/main/java/slimeknights/mantle/client/ExtraHeartRenderHandler.java @@ -0,0 +1,246 @@ +package slimeknights.mantle.client; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.attributes.IAttributeInstance; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.MobEffects; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.MathHelper; +import net.minecraftforge.client.GuiIngameForge; +import net.minecraftforge.client.event.RenderGameOverlayEvent; +import net.minecraftforge.fml.common.eventhandler.EventPriority; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import java.util.Random; + +import slimeknights.mantle.Mantle; + +@SideOnly(Side.CLIENT) +public class ExtraHeartRenderHandler { + private static final ResourceLocation ICON_HEARTS = new ResourceLocation(Mantle.modId, "textures/gui/hearts.png"); + private static final ResourceLocation ICON_ABSORB = new ResourceLocation(Mantle.modId, "textures/gui/absorb.png"); + private static final ResourceLocation ICON_VANILLA = Gui.ICONS; + + private final Minecraft mc = Minecraft.getMinecraft(); + + private int updateCounter = 0; + private int playerHealth = 0; + private int lastPlayerHealth = 0; + private long healthUpdateCounter = 0; + private long lastSystemTime = 0; + private Random rand = new Random(); + + private int height; + private int width; + private int regen; + + private static int left_height = 39; + + public void drawTexturedModalRect(int x, int y, int textureX, int textureY, int width, int height) { + Minecraft.getMinecraft().ingameGUI.drawTexturedModalRect(x, y, textureX, textureY, width, height); + } + + /* HUD */ + @SubscribeEvent(priority = EventPriority.LOW) + public void renderHealthbar(RenderGameOverlayEvent.Pre event) { + if(event.getType() != RenderGameOverlayEvent.ElementType.HEALTH || event.isCanceled()) { + return; + } + // extra setup stuff from us + left_height = 39; + ScaledResolution resolution = event.getResolution(); + width = resolution.getScaledWidth(); + height = resolution.getScaledHeight(); + event.setCanceled(true); + updateCounter = mc.ingameGUI.getUpdateCounter(); + + // start default forge/mc rendering + // changes are indicated by comment + mc.mcProfiler.startSection("health"); + GlStateManager.enableBlend(); + + EntityPlayer player = (EntityPlayer)this.mc.getRenderViewEntity(); + int health = MathHelper.ceiling_float_int(player.getHealth()); + boolean highlight = healthUpdateCounter > (long)updateCounter && (healthUpdateCounter - (long)updateCounter) / 3L %2L == 1L; + + if (health < this.playerHealth && player.hurtResistantTime > 0) + { + this.lastSystemTime = Minecraft.getSystemTime(); + this.healthUpdateCounter = (long)(this.updateCounter + 20); + } + else if (health > this.playerHealth && player.hurtResistantTime > 0) + { + this.lastSystemTime = Minecraft.getSystemTime(); + this.healthUpdateCounter = (long)(this.updateCounter + 10); + } + + if (Minecraft.getSystemTime() - this.lastSystemTime > 1000L) + { + this.playerHealth = health; + this.lastPlayerHealth = health; + this.lastSystemTime = Minecraft.getSystemTime(); + } + + this.playerHealth = health; + int healthLast = this.lastPlayerHealth; + + IAttributeInstance attrMaxHealth = player.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH); + float healthMax = (float)attrMaxHealth.getAttributeValue(); + float absorb = MathHelper.ceiling_float_int(player.getAbsorptionAmount()); + + // CHANGE: simulate 10 hearts max if there's more, so vanilla only renders one row max + healthMax = Math.min(healthMax, 20f); + health = Math.min(health, 20); + absorb = Math.min(absorb, 20); + + int healthRows = MathHelper.ceiling_float_int((healthMax + absorb) / 2.0F / 10.0F); + int rowHeight = Math.max(10 - (healthRows - 2), 3); + + this.rand.setSeed((long)(updateCounter * 312871)); + + int left = width / 2 - 91; + int top = height - left_height; + left_height += (healthRows * rowHeight); + if (rowHeight != 10) left_height += 10 - rowHeight; + + regen = -1; + if (player.isPotionActive(MobEffects.REGENERATION)) + { + regen = updateCounter % 25; + } + + final int TOP = 9 * (mc.theWorld.getWorldInfo().isHardcoreModeEnabled() ? 5 : 0); + final int BACKGROUND = (highlight ? 25 : 16); + int MARGIN = 16; + if (player.isPotionActive(MobEffects.POISON)) MARGIN += 36; + else if (player.isPotionActive(MobEffects.WITHER)) MARGIN += 72; + float absorbRemaining = absorb; + + for (int i = MathHelper.ceiling_float_int((healthMax + absorb) / 2.0F) - 1; i >= 0; --i) + { + //int b0 = (highlight ? 1 : 0); + 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; + + drawTexturedModalRect(x, y, BACKGROUND, TOP, 9, 9); + + if (highlight) + { + if (i * 2 + 1 < healthLast) + drawTexturedModalRect(x, y, MARGIN + 54, TOP, 9, 9); //6 + else if (i * 2 + 1 == healthLast) + drawTexturedModalRect(x, y, MARGIN + 63, TOP, 9, 9); //7 + } + + if (absorbRemaining > 0.0F) + { + if (absorbRemaining == absorb && absorb % 2.0F == 1.0F) + { + drawTexturedModalRect(x, y, MARGIN + 153, TOP, 9, 9); //17 + absorbRemaining -= 1.0F; + } + else + { + drawTexturedModalRect(x, y, MARGIN + 144, TOP, 9, 9); //16 + absorbRemaining -= 2.0F; + } + } + else + { + if (i * 2 + 1 < health) + drawTexturedModalRect(x, y, MARGIN + 36, TOP, 9, 9); //4 + else if (i * 2 + 1 == health) + drawTexturedModalRect(x, y, MARGIN + 45, TOP, 9, 9); //5 + } + } + + + renderExtraHearts(left, top, player); + renderExtraAbsorption(left, top - rowHeight, player); + + + this.mc.getTextureManager().bindTexture(ICON_VANILLA); + GuiIngameForge.left_height += 10; + if(absorb > 0) { + GuiIngameForge.left_height += 10; + } + + event.setCanceled(true); + + GlStateManager.disableBlend(); + mc.mcProfiler.endSection(); + } + + private void renderExtraHearts(int xBasePos, int yBasePos, EntityPlayer player) { + int potionOffset = getPotionOffset(player); + + // Extra hearts + this.mc.getTextureManager().bindTexture(ICON_HEARTS); + + int hp = MathHelper.ceiling_float_int(player.getHealth()); + renderCustomHearts(xBasePos, yBasePos, potionOffset, hp, false); + } + + private void renderCustomHearts(int xBasePos, int yBasePos, int potionOffset, int count, boolean absorb) { + int regenOffset = absorb ? 10 : 0; + for(int iter = 0; iter < count / 20; iter++) { + int renderHearts = (count - 20 * (iter + 1)) / 2; + if(renderHearts > 10) { + renderHearts = 10; + } + for(int i = 0; i < renderHearts; i++) { + int y = 0; + if(i + regenOffset == regen) { + y -= 2; + } + if(absorb) { + this.drawTexturedModalRect(xBasePos + 8 * i, yBasePos + y, 0, 54, 9, 9); + } + this.drawTexturedModalRect(xBasePos + 8 * i, yBasePos + y, 0 + 18 * iter, potionOffset, 9, 9); + } + if(count % 2 == 1 && renderHearts < 10) { + if(absorb) { + this.drawTexturedModalRect(xBasePos + 8 * renderHearts, yBasePos, 0, 54, 9, 9); + } + this.drawTexturedModalRect(xBasePos + 8 * renderHearts, yBasePos, 9 + 18 * iter, potionOffset, 9, 9); + } + } + } + + private int getPotionOffset(EntityPlayer player) { + int potionOffset = 0; + PotionEffect potion = player.getActivePotionEffect(MobEffects.WITHER); + if(potion != null) { + potionOffset = 18; + } + potion = player.getActivePotionEffect(MobEffects.POISON); + if(potion != null) { + potionOffset = 9; + } + if(mc.theWorld.getWorldInfo().isHardcoreModeEnabled()) { + potionOffset += 27; + } + return potionOffset; + } + + private void renderExtraAbsorption(int xBasePos, int yBasePos, EntityPlayer player) { + int potionOffset = getPotionOffset(player); + + // Extra hearts + this.mc.getTextureManager().bindTexture(ICON_ABSORB); + + int absorb = MathHelper.ceiling_float_int(player.getAbsorptionAmount()); + renderCustomHearts(xBasePos, yBasePos, potionOffset, absorb, true); + } +} diff --git a/src/main/resources/assets/mantle/textures/gui/absorb.png b/src/main/resources/assets/mantle/textures/gui/absorb.png new file mode 100644 index 0000000000000000000000000000000000000000..76ab6eec3f81fd0b359640b6d7caa2fe414adec7 GIT binary patch literal 5893 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/mantle/textures/gui/hearts.png b/src/main/resources/assets/mantle/textures/gui/hearts.png new file mode 100644 index 0000000000000000000000000000000000000000..ae9cedfd6d637b5317aa00a6da292e5da4366d7d GIT binary patch literal 5828 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 F{{eXT;OGDV literal 0 HcmV?d00001