/** * This class was created by <Vazkii>. It's distributed as * part of the Botania Mod. Get the Source Code in github: * https://github.com/Vazkii/Botania * * Botania is Open Source and distributed under the * Botania License: http://botaniamod.net/license.php * * File Created @ [Oct 29, 2014, 6:46:10 PM (GMT)] */ package vazkii.botania.client.core.handler; import java.awt.Rectangle; import java.util.Collections; import java.util.Set; import java.util.UUID; import java.util.WeakHashMap; import org.lwjgl.opengl.ARBShaderObjects; import org.lwjgl.opengl.GL11; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.util.ResourceLocation; import net.minecraftforge.client.event.RenderGameOverlayEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import vazkii.botania.api.boss.IBotaniaBoss; import vazkii.botania.api.internal.ShaderCallback; import vazkii.botania.client.core.helper.RenderHelper; import vazkii.botania.client.core.helper.ShaderHelper; import vazkii.botania.client.lib.LibResources; public final class BossBarHandler { private BossBarHandler() {} // Only access on the client thread! public static final Set<IBotaniaBoss> bosses = Collections.newSetFromMap(new WeakHashMap<>()); public static final ResourceLocation defaultBossBar = new ResourceLocation(LibResources.GUI_BOSS_BAR); private static final BarCallback barUniformCallback = new BarCallback(); @SubscribeEvent public static void onBarRender(RenderGameOverlayEvent.BossInfo evt) { UUID infoUuid = evt.getBossInfo().getUniqueId(); for(IBotaniaBoss currentBoss : bosses) { if(currentBoss.getBossInfoUuid().equals(infoUuid)) { evt.setCanceled(true); Minecraft mc = Minecraft.getMinecraft(); Rectangle bgRect = currentBoss.getBossBarTextureRect(); Rectangle fgRect = currentBoss.getBossBarHPTextureRect(); String name = evt.getBossInfo().getName().getFormattedText(); int c = evt.getResolution().getScaledWidth() / 2; int x = evt.getX(); int y = evt.getY(); int xf = x + (bgRect.width - fgRect.width) / 2; int yf = y + (bgRect.height - fgRect.height) / 2; int fw = (int) ((double) fgRect.width * evt.getBossInfo().getPercent()); int tx = c - mc.fontRendererObj.getStringWidth(name) / 2; GlStateManager.color(1F, 1F, 1F, 1F); int auxHeight = currentBoss.bossBarRenderCallback(evt.getResolution(), x, y); GlStateManager.enableBlend(); GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); mc.renderEngine.bindTexture(currentBoss.getBossBarTexture()); drawBar(currentBoss, x, y, bgRect.x, bgRect.y, bgRect.width, bgRect.height, true); drawBar(currentBoss, xf, yf, fgRect.x, fgRect.y, fw, fgRect.height, false); mc.fontRendererObj.drawStringWithShadow(name, tx, y - 10, 0xA2018C); GlStateManager.enableBlend(); evt.setIncrement(Math.max(bgRect.height, fgRect.height) + auxHeight + mc.fontRendererObj.FONT_HEIGHT); } } } private static void drawBar(IBotaniaBoss currentBoss, int x, int y, int u, int v, int w, int h, boolean bg) { int program = currentBoss.getBossBarShaderProgram(bg); boolean useShader = program > 0; if(useShader) { ShaderCallback callback = currentBoss.getBossBarShaderCallback(bg, program); barUniformCallback.set(u, v, callback); ShaderHelper.useShader(program, barUniformCallback); } RenderHelper.drawTexturedModalRect(x, y, 0, u, v, w, h); if(useShader) ShaderHelper.releaseShader(); } private static class BarCallback implements ShaderCallback { int x, y; ShaderCallback callback; @Override public void call(int shader) { int startXUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "startX"); int startYUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "startY"); ARBShaderObjects.glUniform1iARB(startXUniform, x); ARBShaderObjects.glUniform1iARB(startYUniform, y); if(callback != null) callback.call(shader); } void set(int x, int y, ShaderCallback callback) { this.x = x; this.y = y; this.callback = callback; } } }