/**
* 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 @ [Mar 31, 2015, 3:16:02 PM (GMT)]
*/
package vazkii.botania.client.core.handler;
import java.awt.Color;
import org.lwjgl.opengl.GL11;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.entity.Entity;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraftforge.client.event.RenderWorldLastEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import vazkii.botania.api.subtile.ISubTileContainer;
import vazkii.botania.api.subtile.RadiusDescriptor;
import vazkii.botania.api.subtile.SubTileEntity;
import vazkii.botania.common.Botania;
import vazkii.botania.common.core.helper.PlayerHelper;
import vazkii.botania.common.entity.EntityMagicLandmine;
import vazkii.botania.common.item.ItemTwigWand;
import vazkii.botania.common.item.ModItems;
public final class BlockHighlightRenderHandler {
private BlockHighlightRenderHandler() {}
@SubscribeEvent
public static void onWorldRenderLast(RenderWorldLastEvent event) {
Minecraft mc = Minecraft.getMinecraft();
RayTraceResult pos = mc.objectMouseOver;
GlStateManager.pushMatrix();
GlStateManager.disableTexture2D();
GL11.glPushAttrib(GL11.GL_LIGHTING_BIT);
GlStateManager.disableLighting();
GlStateManager.enableBlend();
GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
boundTile: {
if(Botania.proxy.isClientPlayerWearingMonocle() && pos != null && pos.entityHit == null) {
BlockPos bPos = pos.getBlockPos();
ItemStack stackHeld = PlayerHelper.getFirstHeldItem(mc.player, ModItems.twigWand);
if(!stackHeld.isEmpty() && ItemTwigWand.getBindMode(stackHeld)) {
BlockPos coords = ItemTwigWand.getBoundTile(stackHeld);
if(coords.getY() != -1)
bPos = coords;
}
TileEntity tile = mc.world.getTileEntity(bPos);
if(tile == null || !(tile instanceof ISubTileContainer))
break boundTile;
ISubTileContainer container = (ISubTileContainer) tile;
SubTileEntity subtile = container.getSubTile();
if(subtile == null)
break boundTile;
RadiusDescriptor descriptor = subtile.getRadius();
if(descriptor == null)
break boundTile;
if(descriptor.isCircle())
renderCircle(descriptor.getSubtileCoords(), descriptor.getCircleRadius());
else renderRectangle(descriptor.getAABB(), true, null, (byte) 32);
}
}
double offY = -1.0 / 16 + 0.005;
for(Entity e : mc.world.loadedEntityList)
if(e instanceof EntityMagicLandmine) {
BlockPos bpos = e.getPosition();
AxisAlignedBB aabb = new AxisAlignedBB(bpos).offset(0, offY, 0).expand(2.5, 0, 2.5);
float gs = (float) (Math.sin(ClientTickHandler.total / 20) + 1) * 0.2F + 0.6F;
int r = (int) (105 * gs);
int g = (int) (25 * gs);
int b = (int) (145 * gs);
Color color = new Color(r, g, b);
int alpha = 32;
if(e.ticksExisted < 8)
alpha *= Math.min((e.ticksExisted + event.getPartialTicks()) / 8F, 1F);
else if(e.ticksExisted > 47)
alpha *= Math.min(1F - (e.ticksExisted - 47 + event.getPartialTicks()) / 8F, 1F);
renderRectangle(aabb, false, color, (byte) alpha);
offY += 0.001;
}
GlStateManager.enableTexture2D();
GlStateManager.disableBlend();
GL11.glPopAttrib();
GlStateManager.popMatrix();
}
private static void renderRectangle(AxisAlignedBB aabb, boolean inner, Color color, byte alpha) {
double renderPosX, renderPosY, renderPosZ;
try {
renderPosX = (double) ClientMethodHandles.renderPosX_getter.invokeExact(Minecraft.getMinecraft().getRenderManager());
renderPosY = (double) ClientMethodHandles.renderPosY_getter.invokeExact(Minecraft.getMinecraft().getRenderManager());
renderPosZ = (double) ClientMethodHandles.renderPosZ_getter.invokeExact(Minecraft.getMinecraft().getRenderManager());
} catch (Throwable t) {
return;
}
GlStateManager.pushMatrix();
GlStateManager.translate(aabb.minX - renderPosX, aabb.minY - renderPosY, aabb.minZ - renderPosZ);
if(color == null)
color = Color.getHSBColor(ClientTickHandler.ticksInGame % 200 / 200F, 0.6F, 1F);
GL11.glColor4ub((byte) color.getRed(), (byte) color.getGreen(), (byte) color.getBlue(), alpha);
double f = 1F / 16F;
double x = aabb.maxX - aabb.minX - f;
double z = aabb.maxZ - aabb.minZ - f;
Tessellator tessellator = Tessellator.getInstance();
tessellator.getBuffer().begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION);
tessellator.getBuffer().pos(x, f, f).endVertex();
tessellator.getBuffer().pos(f, f, f).endVertex();
tessellator.getBuffer().pos(f, f, z).endVertex();
tessellator.getBuffer().pos(x, f, z).endVertex();
tessellator.draw();
if(inner) {
x += f;
z += f;
double f1 = f + f / 4F;
GL11.glColor4ub((byte) color.getRed(), (byte) color.getGreen(), (byte) color.getBlue(), (byte) (alpha * 2));
tessellator.getBuffer().begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION);
tessellator.getBuffer().pos(x, f1, 0).endVertex();
tessellator.getBuffer().pos(0, f1, 0).endVertex();
tessellator.getBuffer().pos(0, f1, z).endVertex();
tessellator.getBuffer().pos(x, f1, z).endVertex();
tessellator.draw();
}
GL11.glColor4ub((byte) 255, (byte) 255, (byte) 255, (byte) 255);
GlStateManager.popMatrix();
}
private static void renderCircle(BlockPos center, double radius) {
double renderPosX, renderPosY, renderPosZ;
try {
renderPosX = (double) ClientMethodHandles.renderPosX_getter.invokeExact(Minecraft.getMinecraft().getRenderManager());
renderPosY = (double) ClientMethodHandles.renderPosY_getter.invokeExact(Minecraft.getMinecraft().getRenderManager());
renderPosZ = (double) ClientMethodHandles.renderPosZ_getter.invokeExact(Minecraft.getMinecraft().getRenderManager());
} catch (Throwable t) {
return;
}
GlStateManager.pushMatrix();
double x = center.getX() + 0.5;
double y = center.getY();
double z = center.getZ() + 0.5;
GlStateManager.translate(x - renderPosX, y - renderPosY, z - renderPosZ);
int color = Color.HSBtoRGB(ClientTickHandler.ticksInGame % 200 / 200F, 0.6F, 1F);
Color colorRGB = new Color(color);
GL11.glColor4ub((byte) colorRGB.getRed(), (byte) colorRGB.getGreen(), (byte) colorRGB.getBlue(), (byte) 32);
double f = 1F / 16F;
int totalAngles = 360;
int drawAngles = 360;
int step = totalAngles / drawAngles;
radius -= f;
Tessellator tessellator = Tessellator.getInstance();
tessellator.getBuffer().begin(GL11.GL_TRIANGLE_FAN, DefaultVertexFormats.POSITION);
tessellator.getBuffer().pos(0, f, 0).endVertex();
for(int i = 0; i < totalAngles + 1; i += step) {
double rad = (totalAngles - i) * Math.PI / 180.0;
double xp = Math.cos(rad) * radius;
double zp = Math.sin(rad) * radius;
tessellator.getBuffer().pos(xp, f, zp).endVertex();
}
tessellator.getBuffer().pos(0, f, 0).endVertex();
tessellator.draw();
radius += f;
double f1 = f + f / 4F;
GL11.glColor4ub((byte) colorRGB.getRed(), (byte) colorRGB.getGreen(), (byte) colorRGB.getBlue(), (byte) 64);
tessellator.getBuffer().begin(GL11.GL_TRIANGLE_FAN, DefaultVertexFormats.POSITION);
tessellator.getBuffer().pos(0, f1, 0).endVertex();
for(int i = 0; i < totalAngles + 1; i += step) {
double rad = (totalAngles - i) * Math.PI / 180.0;
double xp = Math.cos(rad) * radius;
double zp = Math.sin(rad) * radius;
tessellator.getBuffer().pos(xp, f1, zp).endVertex();
}
tessellator.getBuffer().pos(0, f1, 0).endVertex();
tessellator.draw();
GL11.glColor4ub((byte) 255, (byte) 255, (byte) 255, (byte) 255);
GlStateManager.popMatrix();
}
}