Java tutorial
/** * 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 24, 2014, 7:02:37 PM (GMT)] */ package vazkii.botania.client.core.handler; import java.awt.Color; import java.util.List; import org.lwjgl.opengl.GL11; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; 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.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraftforge.client.event.RenderWorldLastEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandlerModifiable; import net.minecraftforge.items.wrapper.CombinedInvWrapper; import vazkii.botania.api.BotaniaAPI; import vazkii.botania.api.item.IWireframeCoordinateListProvider; import vazkii.botania.api.wand.ICoordBoundItem; import vazkii.botania.api.wand.IWireframeAABBProvider; public final class BoundTileRenderer { private BoundTileRenderer() { } @SubscribeEvent public static void onWorldRenderLast(RenderWorldLastEvent event) { GlStateManager.pushMatrix(); GL11.glPushAttrib(GL11.GL_LIGHTING_BIT); GlStateManager.disableDepth(); GlStateManager.disableTexture2D(); GlStateManager.enableBlend(); EntityPlayer player = Minecraft.getMinecraft().thePlayer; int color = Color.HSBtoRGB(ClientTickHandler.ticksInGame % 200 / 200F, 0.6F, 1F); if (player.getHeldItemMainhand() != null && player.getHeldItemMainhand().getItem() instanceof ICoordBoundItem) { BlockPos coords = ((ICoordBoundItem) player.getHeldItemMainhand().getItem()) .getBinding(player.getHeldItemMainhand()); if (coords != null) renderBlockOutlineAt(coords, color); } if (player.getHeldItemOffhand() != null && player.getHeldItemOffhand().getItem() instanceof ICoordBoundItem) { BlockPos coords = ((ICoordBoundItem) player.getHeldItemOffhand().getItem()) .getBinding(player.getHeldItemOffhand()); if (coords != null) renderBlockOutlineAt(coords, color); } IItemHandlerModifiable mainInv = (IItemHandlerModifiable) player .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, EnumFacing.UP); IItemHandlerModifiable baublesInv = BotaniaAPI.internalHandler.getBaublesInventoryWrapped(player); IItemHandler joined = baublesInv != null ? new CombinedInvWrapper(mainInv, baublesInv) : mainInv; for (int i = 0; i < joined.getSlots(); i++) { ItemStack stackInSlot = joined.getStackInSlot(i); if (stackInSlot != null && stackInSlot.getItem() instanceof IWireframeCoordinateListProvider) { IWireframeCoordinateListProvider provider = (IWireframeCoordinateListProvider) stackInSlot .getItem(); List<BlockPos> coordsList = provider.getWireframesToDraw(player, stackInSlot); if (coordsList != null) for (BlockPos coords : coordsList) renderBlockOutlineAt(coords, color); BlockPos coords = provider.getSourceWireframe(player, stackInSlot); if (coords != null && coords.getY() > -1) renderBlockOutlineAt(coords, color, 5F); } } GlStateManager.enableDepth(); GlStateManager.enableTexture2D(); GlStateManager.disableBlend(); GL11.glPopAttrib(); GlStateManager.popMatrix(); } private static void renderBlockOutlineAt(BlockPos pos, int color) { renderBlockOutlineAt(pos, color, 1F); } private static void renderBlockOutlineAt(BlockPos pos, int color, float thickness) { 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(pos.getX() - renderPosX, pos.getY() - renderPosY, pos.getZ() - renderPosZ + 1); Color colorRGB = new Color(color); GL11.glColor4ub((byte) colorRGB.getRed(), (byte) colorRGB.getGreen(), (byte) colorRGB.getBlue(), (byte) 255); World world = Minecraft.getMinecraft().theWorld; IBlockState state = world.getBlockState(pos); Block block = state.getBlock(); drawWireframe: { if (block != null) { AxisAlignedBB axis; if (block instanceof IWireframeAABBProvider) axis = ((IWireframeAABBProvider) block).getWireframeAABB(world, pos); else axis = state.getSelectedBoundingBox(world, pos); if (axis == null) break drawWireframe; axis = axis.offset(-pos.getX(), -pos.getY(), -(pos.getZ() + 1)); GlStateManager.scale(1F, 1F, 1F); GL11.glLineWidth(thickness); renderBlockOutline(axis); GL11.glLineWidth(thickness + 3F); GL11.glColor4ub((byte) colorRGB.getRed(), (byte) colorRGB.getGreen(), (byte) colorRGB.getBlue(), (byte) 64); renderBlockOutline(axis); } } GL11.glColor4ub((byte) 255, (byte) 255, (byte) 255, (byte) 255); GlStateManager.popMatrix(); } private static void renderBlockOutline(AxisAlignedBB aabb) { Tessellator tessellator = Tessellator.getInstance(); double ix = aabb.minX; double iy = aabb.minY; double iz = aabb.minZ; double ax = aabb.maxX; double ay = aabb.maxY; double az = aabb.maxZ; tessellator.getBuffer().begin(GL11.GL_LINES, DefaultVertexFormats.POSITION); tessellator.getBuffer().pos(ix, iy, iz).endVertex(); tessellator.getBuffer().pos(ix, ay, iz).endVertex(); tessellator.getBuffer().pos(ix, ay, iz).endVertex(); tessellator.getBuffer().pos(ax, ay, iz).endVertex(); tessellator.getBuffer().pos(ax, ay, iz).endVertex(); tessellator.getBuffer().pos(ax, iy, iz).endVertex(); tessellator.getBuffer().pos(ax, iy, iz).endVertex(); tessellator.getBuffer().pos(ix, iy, iz).endVertex(); tessellator.getBuffer().pos(ix, iy, az).endVertex(); tessellator.getBuffer().pos(ix, ay, az).endVertex(); tessellator.getBuffer().pos(ix, iy, az).endVertex(); tessellator.getBuffer().pos(ax, iy, az).endVertex(); tessellator.getBuffer().pos(ax, iy, az).endVertex(); tessellator.getBuffer().pos(ax, ay, az).endVertex(); tessellator.getBuffer().pos(ix, ay, az).endVertex(); tessellator.getBuffer().pos(ax, ay, az).endVertex(); tessellator.getBuffer().pos(ix, iy, iz).endVertex(); tessellator.getBuffer().pos(ix, iy, az).endVertex(); tessellator.getBuffer().pos(ix, ay, iz).endVertex(); tessellator.getBuffer().pos(ix, ay, az).endVertex(); tessellator.getBuffer().pos(ax, iy, iz).endVertex(); tessellator.getBuffer().pos(ax, iy, az).endVertex(); tessellator.getBuffer().pos(ax, ay, iz).endVertex(); tessellator.getBuffer().pos(ax, ay, az).endVertex(); tessellator.draw(); } }