package at.hannibal2.skyhanni.utils import at.hannibal2.skyhanni.config.core.config.Position import at.hannibal2.skyhanni.data.GuiEditManager import at.hannibal2.skyhanni.data.GuiEditManager.Companion.getAbsX import at.hannibal2.skyhanni.data.GuiEditManager.Companion.getAbsY import at.hannibal2.skyhanni.events.GuiRenderItemEvent import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent import at.hannibal2.skyhanni.features.misc.RoundedRectangleShader import at.hannibal2.skyhanni.test.command.ErrorManager import at.hannibal2.skyhanni.utils.renderables.Renderable import at.hannibal2.skyhanni.utils.renderables.RenderableUtils.renderXAligned import at.hannibal2.skyhanni.utils.shader.ShaderManager import io.github.moulberry.moulconfig.internal.TextRenderUtils import io.github.moulberry.notenoughupdates.util.Utils import java.awt.Color import net.minecraft.client.Minecraft import net.minecraft.client.gui.FontRenderer import net.minecraft.client.gui.Gui import net.minecraft.client.gui.ScaledResolution import net.minecraft.client.renderer.GlStateManager import net.minecraft.client.renderer.Tessellator import net.minecraft.client.renderer.vertex.DefaultVertexFormats import net.minecraft.enchantment.Enchantment import net.minecraft.entity.Entity import net.minecraft.inventory.Slot import net.minecraft.item.ItemStack import net.minecraft.util.AxisAlignedBB import net.minecraft.util.MathHelper import net.minecraft.util.ResourceLocation import org.lwjgl.opengl.GL11 import kotlin.math.cos import kotlin.math.sin import kotlin.math.sqrt import kotlin.time.Duration import kotlin.time.DurationUnit object RenderUtils { enum class HorizontalAlignment { LEFT, CENTER, RIGHT } enum class VerticalAlignment { TOP, CENTER, BOTTOM } private val beaconBeam = ResourceLocation("textures/entity/beacon_beam.png") infix fun Slot.highlight(color: LorenzColor) { highlight(color.toColor()) } infix fun Slot.highlight(color: Color) { GlStateManager.color(1f, 1f, 1f, 1f) GlStateManager.pushAttrib() GL11.glDisable(GL11.GL_LIGHTING) GL11.glEnable(GL11.GL_DEPTH_TEST) GlStateManager.pushMatrix() // TODO don't use z GlStateManager.translate(0f, 0f, 110 + Minecraft.getMinecraft().renderItem.zLevel) Gui.drawRect( this.xDisplayPosition, this.yDisplayPosition, this.xDisplayPosition + 16, this.yDisplayPosition + 16, color.rgb ) GlStateManager.popMatrix() GlStateManager.popAttrib() } fun LorenzRenderWorldEvent.drawColor( location: LorenzVec, color: LorenzColor, beacon: Boolean = false, alpha: Float = -1f, ) { drawColor(location, color.toColor(), beacon, alpha) } fun LorenzRenderWorldEvent.drawColor( location: LorenzVec, color: Color, beacon: Boolean = false, alpha: Float = -1f, ) { val (viewerX, viewerY, viewerZ) = getViewerPos(partialTicks) val x = location.x - viewerX val y = location.y - viewerY val z = location.z - viewerZ val distSq = x * x + y * y + z * z val realAlpha = if (alpha == -1f) { (0.1f + 0.005f * distSq.toFloat()).coerceAtLeast(0.2f) } else { alpha } GlStateManager.disableDepth() GlStateManager.disableCull() drawFilledBoundingBox( AxisAlignedBB(x, y, z, x + 1, y + 1, z + 1).expandBlock(), color, realAlpha ) GlStateManager.disableTexture2D() if (distSq > 5 * 5 && beacon) renderBeaconBeam(x, y + 1, z, color.rgb, 1.0f, partialTicks) GlStateManager.disableLighting() GlStateManager.enableTexture2D() GlStateManager.enableDepth() GlStateManager.enableCull() } fun getViewerPos(partialTicks: Float) = exactLocation(Minecraft.getMinecraft().renderViewEntity, partialTicks) fun AxisAlignedBB.expandBlock() = expand(0.0020000000949949026, 0.0020000000949949026, 0.0020000000949949026) /** * Taken from NotEnoughUpdates under Creative Commons Attribution-NonCommercial 3.0 * https://github.com/Moulberry/NotEnoughUpdates/blob/master/LICENSE * @author Moulberry * @author Mojang */ fun renderBeaconBeam(x: Double, y: Double, z: Double, rgb: Int, alphaMultiplier: Float, partialTicks: Float) { val height = 300 val bottomOffset = 0 val topOffset = bottomOffset + height val tessellator = Tessellator.getInstance() val worldrenderer = tessellator.worldRenderer Minecraft.getMinecraft().textureManager.bindTexture(beaconBeam) GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, 10497.0f) GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, 10497.0f) GlStateManager.disableLighting() GlStateManager.enableCull() GlStateManager.enableTexture2D() GlStateManager.tryBlendFuncSeparate(770, 1, 1, 0) GlStateManager.enableBlend() GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0) val time = Minecraft.getMinecraft().theWorld.totalWorldTime + partialTicks.toDouble() val d1 = MathHelper.func_181162_h( -time * 0.2 - MathHelper.floor_double(-time * 0.1) .toDouble() ) val r = (rgb shr 16 and 0xFF) / 255f val g = (rgb shr 8 and 0xFF) / 255f val b = (rgb and 0xFF) / 255f val d2 = time * 0.025 * -1.5 val d4 = 0.5 + cos(d2 + 2.356194490192345) * 0.2 val d5 = 0.5 + sin(d2 + 2.356194490192345) * 0.2 val d6 = 0.5 + cos(d2 + Math.PI / 4.0) * 0.2 val d7 = 0.5 + sin(d2 + Math.PI / 4.0) * 0.2 val d8 = 0.5 + cos(d2 + 3.9269908169872414) * 0.2 val d9 = 0.5 + sin(d2 + 3.9269908169872414) * 0.2 val d10 = 0.5 + cos(d2 + 5.497787143782138) * 0.2 val d11 = 0.5 + sin(d2 + 5.497787143782138) * 0.2 val d14 = -1.0 + d1 val d15 = height.toDouble() * 2.5 + d14 worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR) worldrenderer.pos(x + d4, y + topOffset, z + d5).tex(1.0, d15).color(r, g, b, 1.0f * alphaMultiplier) .endVertex() worldrenderer.pos(x + d4, y + bottomOffset, z + d5).tex(1.0, d14).color(r, g, b, 1.0f).endVertex() worldrenderer.pos(x + d6, y + bottomOffset, z + d7).tex(0.0, d14).color(r, g, b, 1.0f).endVertex() worldrenderer.pos(x + d6, y + topOffset, z + d7).tex(0.0, d15).color(r, g, b, 1.0f * alphaMultiplier) .endVertex() worldrenderer.pos(x + d10, y + topOffset, z + d11).tex(1.0, d15).color(r, g, b, 1.0f * alphaMultiplier) .endVertex() worldrenderer.pos(x + d10, y + bottomOffset, z + d11).tex(1.0, d14).color(r, g, b, 1.0f).endVertex() worldrenderer.pos(x + d8, y + bottomOffset, z + d9).tex(0.0, d14).color(r, g, b, 1.0f).endVertex() worldrenderer.pos(x + d8, y + topOffset, z + d9).tex(0.0, d15).color(r, g, b, 1.0f * alphaMultiplier) .endVertex() worldrenderer.pos(x + d6, y + topOffset, z + d7).tex(1.0, d15).color(r, g, b, 1.0f * alphaMultiplier) .endVertex() worldrenderer.pos(x + d6, y + bottomOffset, z + d7).tex(1.0, d14).color(r, g, b, 1.0f).endVertex() worldrenderer.pos(x + d10, y + bottomOffset, z + d11).tex(0.0, d14).color(r, g, b, 1.0f).endVertex() worldrenderer.pos(x + d10, y + topOffset, z + d11).tex(0.0, d15).color(r, g, b, 1.0f * alphaMultiplier) .endVertex() worldrenderer.pos(x + d8, y + topOffset, z + d9).tex(1.0, d15).color(r, g, b, 1.0f * alphaMultiplier) .endVertex() worldrenderer.pos(x + d8, y + bottomOffset, z + d9).tex(1.0, d14).color(r, g, b, 1.0f).endVertex() worldrenderer.pos(x + d4, y + bottomOffset, z + d5).tex(0.0, d14).color(r, g, b, 1.0f).endVertex() worldrenderer.pos(x + d4, y + topOffset, z + d5).tex(0.0, d15).color(r, g, b, 1.0f * alphaMultiplier) .endVertex() tessellator.draw() GlStateManager.disableCull() val d12 = -1.0 + d1 val d13 = height + d12 worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR) worldrenderer.pos(x + 0.2, y + topOffset, z + 0.2).tex(1.0, d13).color(r, g, b, 0.25f * alphaMultiplier) .endVertex() worldrenderer.pos(x + 0.2, y + bottomOffset, z + 0.2).tex(1.0, d12).color(r, g, b, 0.25f).endVertex() worldrenderer.pos(x + 0.8, y + bottomOffset, z + 0.2).tex(0.0, d12).color(r, g, b, 0.25f).endVertex() worldrenderer.pos(x + 0.8, y + topOffset, z + 0.2).tex(0.0, d13).color(r, g, b, 0.25f * alphaMultiplier) .endVertex() worldrenderer.pos(x + 0.8, y + topOffset, z + 0.8).tex(1.0, d13).color(r, g, b, 0.25f * alphaMultiplier) .endVertex() worldrenderer.pos(x + 0.8, y + bottomOffset, z + 0.8).tex(1.0, d12).color(r, g, b, 0.25f).endVertex() worldrenderer.pos(x + 0.2, y + bottomOffset, z + 0.8).tex(0.0, d12).color(r, g, b, 0.25f).endVertex() worldrenderer.pos(x + 0.2, y + topOffset, z + 0.8).tex(0.0, d13).color(r, g, b, 0.25f * alphaMultiplier) .endVertex() worldrenderer.pos(x + 0.8, y + topOffset, z + 0.2).tex(1.0, d13).color(r, g, b, 0.25f * alphaMultiplier) .endVertex() worldrenderer.pos(x + 0.8, y + bottomOffset, z + 0.2).tex(1.0, d12).color(r, g, b, 0.25f).endVertex() worldrenderer.pos(x + 0.8, y + bottomOffset, z + 0.8).tex(0.0, d12).color(r, g, b, 0.25f).endVertex() worldrenderer.pos(x + 0.8, y + topOffset, z + 0.8).tex(0.0, d13).color(r, g, b, 0.25f * alphaMultiplier) .endVertex() worldrenderer.pos(x + 0.2, y + topOffset, z + 0.8).tex(1.0, d13).color(r, g, b, 0.25f * alphaMultiplier) .endVertex() worldrenderer.pos(x + 0.2, y + bottomOffset, z + 0.8).tex(1.0, d12).color(r, g, b, 0.25f).endVertex() worldrenderer.pos(x + 0.2, y + bottomOffset, z + 0.2).tex(0.0, d12).color(r, g, b, 0.25f).endVertex() worldrenderer.pos(x + 0.2, y + topOffset, z + 0.2).tex(0.0, d13).color(r, g, b, 0.25f * alphaMultiplier) .endVertex() tessellator.draw() } fun LorenzRenderWorldEvent.drawString( location: LorenzVec, text: String, seeThroughBlocks: Boolean = false, color: Color? = null, ) { GlStateManager.alphaFunc(516, 0.1f) GlStateManager.pushMatrix() val viewer = Minecraft.getMinecraft().renderViewEntity val renderManager = Minecraft.getMinecraft().renderManager var x = location.x - renderManager.viewerPosX var y = location.y - renderManager.viewerPosY - viewer.eyeHeight var z = location.z - renderManager.viewerPosZ val distSq = x * x + y * y + z * z val dist = sqrt(distSq) if (distSq > 144) { x *= 12 / dist y *= 12 / dist z *= 12 / dist } if (seeThroughBlocks) { GlStateManager.disableDepth() GlStateManager.disableCull() } GlStateManager.translate(x, y, z) GlStateManager.translate(0f, viewer.eyeHeight, 0f) drawNametag(text, color) GlStateManager.rotate(-renderManager.playerViewY, 0.0f, 1.0f, 0.0f) GlStateManager.rotate(renderManager.playerViewX, 1.0f, 0.0f, 0.0f) GlStateManager.translate(0f, -0.25f, 0f) GlStateManager.rotate(-renderManager.playerViewX, 1.0f, 0.0f, 0.0f) GlStateManager.rotate(renderManager.playerViewY, 0.0f, 1.0f, 0.0f) GlStateManager.popMatrix() GlStateManager.disableLighting() if (seeThroughBlocks) { GlStateManager.enableDepth() GlStateManager.enableCull() } } /** * @author Mojang */ fun drawNametag(str: String, color: Color?) { val fontRenderer = Minecraft.getMinecraft().fontRendererObj val f1 = 0.02666667f GlStateManager.pushMatrix() GL11.glNormal3f(0.0f, 1.0f, 0.0f) GlStateManager.rotate(-Minecraft.getMinecraft().renderManager.playerViewY, 0.0f, 1.0f, 0.0f) GlStateManager.rotate( Minecraft.getMinecraft().renderManager.playerViewX, 1.0f, 0.0f, 0.0f ) GlStateManager.scale(-f1, -f1, f1) GlStateManager.disableLighting() GlStateManager.depthMask(false) GlStateManager.enableBlend() GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0) val tessellator = Tessellator.getInstance() val worldrenderer = tessellator.worldRenderer val i = 0 val j = fontRenderer.getStringWidth(str) / 2 GlStateManager.disableTexture2D() worldrenderer.begin(7, DefaultVertexFormats.POSITION_COLOR) worldrenderer.pos((-j - 1).toDouble(), (-1 + i).toDouble(), 0.0).color(0.0f, 0.0f, 0.0f, 0.25f).endVertex() worldrenderer.pos((-j - 1).toDouble(), (8 + i).toDouble(), 0.0).color(0.0f, 0.0f, 0.0f, 0.25f).endVertex() worldrenderer.pos((j + 1).toDouble(), (8 + i).toDouble(), 0.0).color(0.0f, 0.0f, 0.0f, 0.25f).endVertex() worldrenderer.pos((j + 1).toDouble(), (-1 + i).toDouble(), 0.0).color(0.0f, 0.0f, 0.0f, 0.25f).endVertex() tessellator.draw() GlStateManager.enableTexture2D() val colorCode = color?.rgb ?: 553648127 fontRenderer.drawString(str, -j, i, colorCode) GlStateManager.depthMask(true) fontRenderer.drawString(str, -j, i, -1) GlStateManager.enableBlend() GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f) GlStateManager.popMatrix() } /** * @author Mojang */ fun drawLabel( pos: LorenzVec, text: String, partialTicks: Float, shadow: Boolean = false, scale: Float = 1f, yOff: Float = 0f, debug: Boolean = false, ) { val minecraft = Minecraft.getMinecraft() val player = minecraft.thePlayer val x = pos.x - player.lastTickPosX + (pos.x - player.posX - (pos.x - player.lastTickPosX)) * partialTicks val y = pos.y - player.lastTickPosY + (pos.y - player.posY - (pos.y - player.lastTickPosY)) * partialTicks val z = pos.z - player.lastTickPosZ + (pos.z - player.posZ - (pos.z - player.lastTickPosZ)) * partialTicks // 7 – 25 val translate = LorenzVec(x, y, z) val length = translate.length().toFloat() var finalText = text var factor = 1f var finalScale = scale if (debug) { finalText = "$text ${length.toInt()}" if (length < 8) { factor = 8 / length } if (length > 15) { factor = 15 / length } finalScale = scale * sqrt(factor.toDouble()).toFloat() } val f1 = 0.0266666688 val width = minecraft.fontRendererObj.getStringWidth(finalText) / 2 GlStateManager.pushMatrix() GlStateManager.translate(x, y, z) GL11.glNormal3f(0f, 1f, 0f) val renderManager = minecraft.renderManager GlStateManager.rotate(-renderManager.playerViewY, 0f, 1f, 0f) GlStateManager.rotate(renderManager.playerViewX, 1f, 0f, 0f) GlStateManager.scale(-f1, -f1, -f1) GlStateManager.scale(finalScale, finalScale, finalScale) GlStateManager.enableBlend() GlStateManager.disableLighting() GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0) GlStateManager.enableTexture2D() minecraft.fontRendererObj.drawString( finalText, (-width).toFloat(), yOff, LorenzColor.WHITE.toColor().rgb, shadow ) GlStateManager.disableBlend() GlStateManager.popMatrix() } fun interpolate(currentValue: Double, lastValue: Double, multiplier: Float): Double { return lastValue + (currentValue - lastValue) * multiplier } fun Position.transform(): Pair { GlStateManager.translate(getAbsX().toFloat(), getAbsY().toFloat(), 0F) GlStateManager.scale(effectiveScale, effectiveScale, 1F) val x = ((Utils.getMouseX() - getAbsX()) / effectiveScale).toInt() val y = ((Utils.getMouseY() - getAbsY()) / effectiveScale).toInt() return x to y } fun Position.renderString(string: String?, offsetX: Int = 0, offsetY: Int = 0, posLabel: String) { if (string == null) return if (string == "") return val x = renderString0(string, offsetX, offsetY, isCenter) GuiEditManager.add(this, posLabel, x, 10) } private fun Position.renderString0(string: String?, offsetX: Int = 0, offsetY: Int = 0, centered: Boolean): Int { val display = "§f$string" GlStateManager.pushMatrix() transform() val minecraft = Minecraft.getMinecraft() val renderer = minecraft.renderManager.fontRenderer GlStateManager.translate(offsetX + 1.0, offsetY + 1.0, 0.0) if (centered) { val strLen: Int = renderer.getStringWidth(string) val x2 = offsetX - strLen / 2f GL11.glTranslatef(x2, 0f, 0f) renderer.drawStringWithShadow(display, 0f, 0f, 0) GL11.glTranslatef(-x2, 0f, 0f) } else { renderer.drawStringWithShadow(display, 0f, 0f, 0) } GlStateManager.popMatrix() return renderer.getStringWidth(display) } fun Position.renderStrings(list: List, extraSpace: Int = 0, posLabel: String) { if (list.isEmpty()) return var offsetY = 0 var longestX = 0 for (s in list) { val x = renderString0(s, offsetY = offsetY, centered = false) if (x > longestX) { longestX = x } offsetY += 10 + extraSpace } GuiEditManager.add(this, posLabel, longestX, offsetY) } fun Position.renderRenderables( renderables: List, extraSpace: Int = 0, posLabel: String, ) { if (renderables.isEmpty()) return var longestY = 0 val longestX = renderables.maxOf { it.width } for (line in renderables) { GlStateManager.pushMatrix() val (x, y) = transform() GlStateManager.translate(0f, longestY.toFloat(), 0F) Renderable.withMousePosition(x, y) { line.renderXAligned(0, longestY, longestX) } longestY += line.height + extraSpace + 2 GlStateManager.popMatrix() } GuiEditManager.add(this, posLabel, longestX, longestY) } /** * Accepts a list of lines to print. * Each line is a list of things to print. Can print String or ItemStack objects. */ fun Position.renderStringsAndItems( list: List>, extraSpace: Int = 0, itemScale: Double = 1.0, posLabel: String, ) { if (list.isEmpty()) return var offsetY = 0 var longestX = 0 try { for (line in list) { val x = renderLine(line, offsetY, itemScale) if (x > longestX) { longestX = x } offsetY += 10 + extraSpace + 2 } } catch (e: NullPointerException) { println(" ") for (innerList in list) { println("new inner list:") for (any in innerList) { println("any: '$any'") } } e.printStackTrace() ChatUtils.debug("NPE in renderStringsAndItems!") } GuiEditManager.add(this, posLabel, longestX, offsetY) } /** * Accepts a single line to print. * This line is a list of things to print. Can print String or ItemStack objects. */ fun Position.renderSingleLineWithItems(list: List, itemScale: Double = 1.0, posLabel: String) { if (list.isEmpty()) return val longestX = renderLine(list, 0, itemScale) GuiEditManager.add(this, posLabel, longestX, 10) } private fun Position.renderLine(line: List, offsetY: Int, itemScale: Double = 1.0): Int { GlStateManager.pushMatrix() val (x, y) = transform() GlStateManager.translate(0f, offsetY.toFloat(), 0F) var offsetX = 0 Renderable.withMousePosition(x, y) { for (any in line) { val renderable = Renderable.fromAny(any, itemScale = itemScale) ?: throw RuntimeException("Unknown render object: $any") renderable.render(offsetX, offsetY) offsetX += renderable.width GlStateManager.translate(renderable.width.toFloat(), 0F, 0F) } } GlStateManager.popMatrix() return offsetX } fun MutableList.addItemIcon(item: ItemStack, highlight: Boolean = false) { try { if (highlight) { // Hack to add enchant glint, like Hypixel does it item.addEnchantment(Enchantment.protection, 0) } add(item) } catch (e: NullPointerException) { ErrorManager.logErrorWithData( e, "Add item icon to renderable list", "item" to item ) } } // totally not modified Autumn Client's TargetStrafe fun drawCircle(entity: Entity, partialTicks: Float, rad: Double, color: Color) { GlStateManager.pushMatrix() GL11.glNormal3f(0.0f, 1.0f, 0.0f) GlStateManager.enableDepth() GlStateManager.enableBlend() GlStateManager.depthFunc(GL11.GL_LEQUAL) GlStateManager.disableCull() GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0) GlStateManager.enableAlpha() GlStateManager.disableTexture2D() GlStateManager.disableDepth() var il = 0.0 val tessellator = Tessellator.getInstance() val worldRenderer = tessellator.worldRenderer while (il < 0.05) { GlStateManager.pushMatrix() GlStateManager.disableTexture2D() GL11.glLineWidth(2F) worldRenderer.begin(1, DefaultVertexFormats.POSITION) val renderManager = Minecraft.getMinecraft().renderManager val x: Double = entity.lastTickPosX + (entity.posX - entity.lastTickPosX) * partialTicks - renderManager.viewerPosX val y: Double = entity.lastTickPosY + (entity.posY - entity.lastTickPosY) * partialTicks - renderManager.viewerPosY val z: Double = entity.lastTickPosZ + (entity.posZ - entity.lastTickPosZ) * partialTicks - renderManager.viewerPosZ val pix2 = Math.PI * 2.0 for (i in 0 .. 90) { color.bindColor() worldRenderer.pos(x + rad * cos(i * pix2 / 45.0), y + il, z + rad * sin(i * pix2 / 45.0)).endVertex() } tessellator.draw() GlStateManager.enableTexture2D() GlStateManager.popMatrix() il += 0.0006 } GlStateManager.enableDepth() GlStateManager.enableCull() GlStateManager.enableTexture2D() GlStateManager.enableDepth() GlStateManager.disableBlend() GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f) GlStateManager.popMatrix() } fun drawCylinderInWorld( color: Color, x: Double, y: Double, z: Double, radius: Float, height: Float, partialTicks: Float, ) { GlStateManager.pushMatrix() GL11.glNormal3f(0.0f, 1.0f, 0.0f) GlStateManager.enableDepth() GlStateManager.enableBlend() GlStateManager.depthFunc(GL11.GL_LEQUAL) GlStateManager.disableCull() GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0) GlStateManager.enableAlpha() GlStateManager.disableTexture2D() color.bindColor() var x1 = x var y1 = y var z1 = z val renderViewEntity = Minecraft.getMinecraft().renderViewEntity val viewX = renderViewEntity.prevPosX + (renderViewEntity.posX - renderViewEntity.prevPosX) * partialTicks.toDouble() val viewY = renderViewEntity.prevPosY + (renderViewEntity.posY - renderViewEntity.prevPosY) * partialTicks.toDouble() val viewZ = renderViewEntity.prevPosZ + (renderViewEntity.posZ - renderViewEntity.prevPosZ) * partialTicks.toDouble() x1 -= viewX y1 -= viewY z1 -= viewZ val tessellator = Tessellator.getInstance() val worldrenderer = tessellator.worldRenderer worldrenderer.begin(GL11.GL_QUAD_STRIP, DefaultVertexFormats.POSITION) var currentAngle = 0f val angleStep = 0.1f while (currentAngle < 2 * Math.PI) { val xOffset = radius * cos(currentAngle.toDouble()).toFloat() val zOffset = radius * sin(currentAngle.toDouble()).toFloat() worldrenderer.pos(x1 + xOffset, y1 + height, z1 + zOffset).endVertex() worldrenderer.pos(x1 + xOffset, y1 + 0, z1 + zOffset).endVertex() currentAngle += angleStep } worldrenderer.pos(x1 + radius, y1 + height, z1).endVertex() worldrenderer.pos(x1 + radius, y1 + 0.0, z1).endVertex() tessellator.draw() GlStateManager.enableCull() GlStateManager.enableTexture2D() GlStateManager.enableDepth() GlStateManager.disableBlend() GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f) GlStateManager.popMatrix() } private fun Color.bindColor() = GlStateManager.color(this.red / 255f, this.green / 255f, this.blue / 255f, this.alpha / 255f) fun drawStringScaledMaxWidth( str: String?, fr: FontRenderer, x: Float, y: Float, shadow: Boolean, len: Int, colour: Int, ) { val strLen = fr.getStringWidth(str) var factor = len / strLen.toFloat() factor = 1f.coerceAtMost(factor) TextRenderUtils.drawStringScaled(str, fr, x, y, shadow, colour, factor) } fun LorenzRenderWorldEvent.drawDynamicText( location: LorenzVec, text: String, scaleMultiplier: Double, yOff: Float = 0f, hideTooCloseAt: Double = 4.5, smallestDistanceVew: Double = 5.0, ignoreBlocks: Boolean = true, ) { val thePlayer = Minecraft.getMinecraft().thePlayer val x = location.x val y = location.y val z = location.z val render = Minecraft.getMinecraft().renderViewEntity val renderOffsetX = render.lastTickPosX + (render.posX - render.lastTickPosX) * partialTicks val renderOffsetY = render.lastTickPosY + (render.posY - render.lastTickPosY) * partialTicks val renderOffsetZ = render.lastTickPosZ + (render.posZ - render.lastTickPosZ) * partialTicks val eyeHeight = thePlayer.eyeHeight val distToPlayerSq = (x - renderOffsetX) * (x - renderOffsetX) + (y - (renderOffsetY + eyeHeight)) * (y - (renderOffsetY + eyeHeight)) + (z - renderOffsetZ) * (z - renderOffsetZ) var distToPlayer = sqrt(distToPlayerSq) // TODO this is optional maybe? distToPlayer = distToPlayer.coerceAtLeast(smallestDistanceVew) if (distToPlayer < hideTooCloseAt) return val distRender = distToPlayer.coerceAtMost(50.0) val resultX = renderOffsetX + (x + 0.5 - renderOffsetX) / (distToPlayer / distRender) val resultY = (renderOffsetY + eyeHeight) + (y + 20 * distToPlayer / 300 - (renderOffsetY + eyeHeight)) / (distToPlayer / distRender) val resultZ = renderOffsetZ + (z + 0.5 - renderOffsetZ) / (distToPlayer / distRender) val renderLocation = LorenzVec(resultX, resultY, resultZ) var scale = distRender / 12 scale *= scaleMultiplier render(renderLocation, "§f$text", scale, !ignoreBlocks, true, yOff) } private fun render( location: LorenzVec, text: String, scale: Double, depthTest: Boolean, shadow: Boolean, yOff: Float, ) { if (!depthTest) { GL11.glDisable(GL11.GL_DEPTH_TEST) GL11.glDepthMask(false) } GlStateManager.pushMatrix() GlStateManager.enableBlend() GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0) val minecraft = Minecraft.getMinecraft() val fontRenderer = minecraft.fontRendererObj val renderManager = minecraft.renderManager GlStateManager.translate( location.x - renderManager.viewerPosX, location.y - renderManager.viewerPosY, location.z - renderManager.viewerPosZ ) GlStateManager.color(1f, 1f, 1f, 0.5f) GlStateManager.rotate(-renderManager.playerViewY, 0.0f, 1.0f, 0.0f) GlStateManager.rotate(renderManager.playerViewX, 1.0f, 0.0f, 0.0f) GlStateManager.scale(-scale / 25, -scale / 25, scale / 25) val stringWidth = fontRenderer.getStringWidth(text) if (shadow) { fontRenderer.drawStringWithShadow( text, (-stringWidth / 2).toFloat(), yOff, 0 ) } else { fontRenderer.drawString( text, -stringWidth / 2, 0, 0 ) } GlStateManager.color(1f, 1f, 1f) GlStateManager.disableBlend() GlStateManager.popMatrix() if (!depthTest) { GL11.glEnable(GL11.GL_DEPTH_TEST) GL11.glDepthMask(true) } } fun LorenzRenderWorldEvent.draw3DLine(p1: LorenzVec, p2: LorenzVec, color: Color, lineWidth: Int, depth: Boolean) { GlStateManager.disableCull() val render = Minecraft.getMinecraft().renderViewEntity val worldRenderer = Tessellator.getInstance().worldRenderer val realX = render.lastTickPosX + (render.posX - render.lastTickPosX) * partialTicks val realY = render.lastTickPosY + (render.posY - render.lastTickPosY) * partialTicks val realZ = render.lastTickPosZ + (render.posZ - render.lastTickPosZ) * partialTicks GlStateManager.pushMatrix() GlStateManager.translate(-realX, -realY, -realZ) GlStateManager.disableTexture2D() GlStateManager.enableBlend() GlStateManager.disableAlpha() GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0) GL11.glLineWidth(lineWidth.toFloat()) if (!depth) { GL11.glDisable(GL11.GL_DEPTH_TEST) GlStateManager.depthMask(false) } GlStateManager.color(color.red / 255f, color.green / 255f, color.blue / 255f, color.alpha / 255f) worldRenderer.begin(GL11.GL_LINE_STRIP, DefaultVertexFormats.POSITION) worldRenderer.pos(p1.x, p1.y, p1.z).endVertex() worldRenderer.pos(p2.x, p2.y, p2.z).endVertex() Tessellator.getInstance().draw() GlStateManager.translate(realX, realY, realZ) if (!depth) { GL11.glEnable(GL11.GL_DEPTH_TEST) GlStateManager.depthMask(true) } GlStateManager.disableBlend() GlStateManager.enableAlpha() GlStateManager.enableTexture2D() GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f) GlStateManager.popMatrix() GlStateManager.disableLighting() GlStateManager.enableDepth() } fun LorenzRenderWorldEvent.exactLocation(entity: Entity) = exactLocation(entity, partialTicks) fun LorenzRenderWorldEvent.exactPlayerEyeLocation(): LorenzVec { val player = Minecraft.getMinecraft().thePlayer val add = if (player.isSneaking) LorenzVec(0.0, 1.54, 0.0) else LorenzVec(0.0, 1.62, 0.0) return exactLocation(player).add(add) } fun exactLocation(entity: Entity, partialTicks: Float): LorenzVec { val x = entity.lastTickPosX + (entity.posX - entity.lastTickPosX) * partialTicks val y = entity.lastTickPosY + (entity.posY - entity.lastTickPosY) * partialTicks val z = entity.lastTickPosZ + (entity.posZ - entity.lastTickPosZ) * partialTicks return LorenzVec(x, y, z) } fun drawFilledBoundingBox(aabb: AxisAlignedBB, c: Color, alphaMultiplier: Float = 1f) { GlStateManager.enableBlend() GlStateManager.disableLighting() GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0) GlStateManager.disableTexture2D() val tessellator = Tessellator.getInstance() val worldRenderer = tessellator.worldRenderer GlStateManager.color(c.red / 255f, c.green / 255f, c.blue / 255f, c.alpha / 255f * alphaMultiplier) // vertical worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION) worldRenderer.pos(aabb.minX, aabb.minY, aabb.minZ).endVertex() worldRenderer.pos(aabb.maxX, aabb.minY, aabb.minZ).endVertex() worldRenderer.pos(aabb.maxX, aabb.minY, aabb.maxZ).endVertex() worldRenderer.pos(aabb.minX, aabb.minY, aabb.maxZ).endVertex() tessellator.draw() worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION) worldRenderer.pos(aabb.minX, aabb.maxY, aabb.maxZ).endVertex() worldRenderer.pos(aabb.maxX, aabb.maxY, aabb.maxZ).endVertex() worldRenderer.pos(aabb.maxX, aabb.maxY, aabb.minZ).endVertex() worldRenderer.pos(aabb.minX, aabb.maxY, aabb.minZ).endVertex() tessellator.draw() GlStateManager.color( c.red / 255f * 0.8f, c.green / 255f * 0.8f, c.blue / 255f * 0.8f, c.alpha / 255f * alphaMultiplier ) // x worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION) worldRenderer.pos(aabb.minX, aabb.minY, aabb.maxZ).endVertex() worldRenderer.pos(aabb.minX, aabb.maxY, aabb.maxZ).endVertex() worldRenderer.pos(aabb.minX, aabb.maxY, aabb.minZ).endVertex() worldRenderer.pos(aabb.minX, aabb.minY, aabb.minZ).endVertex() tessellator.draw() worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION) worldRenderer.pos(aabb.maxX, aabb.minY, aabb.minZ).endVertex() worldRenderer.pos(aabb.maxX, aabb.maxY, aabb.minZ).endVertex() worldRenderer.pos(aabb.maxX, aabb.maxY, aabb.maxZ).endVertex() worldRenderer.pos(aabb.maxX, aabb.minY, aabb.maxZ).endVertex() tessellator.draw() GlStateManager.color( c.red / 255f * 0.9f, c.green / 255f * 0.9f, c.blue / 255f * 0.9f, c.alpha / 255f * alphaMultiplier ) // z worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION) worldRenderer.pos(aabb.minX, aabb.maxY, aabb.minZ).endVertex() worldRenderer.pos(aabb.maxX, aabb.maxY, aabb.minZ).endVertex() worldRenderer.pos(aabb.maxX, aabb.minY, aabb.minZ).endVertex() worldRenderer.pos(aabb.minX, aabb.minY, aabb.minZ).endVertex() tessellator.draw() worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION) worldRenderer.pos(aabb.minX, aabb.minY, aabb.maxZ).endVertex() worldRenderer.pos(aabb.maxX, aabb.minY, aabb.maxZ).endVertex() worldRenderer.pos(aabb.maxX, aabb.maxY, aabb.maxZ).endVertex() worldRenderer.pos(aabb.minX, aabb.maxY, aabb.maxZ).endVertex() tessellator.draw() GlStateManager.enableTexture2D() GlStateManager.disableBlend() } // TODO nea please merge with 'drawFilledBoundingBox' fun LorenzRenderWorldEvent.drawFilledBoundingBox_nea( aabb: AxisAlignedBB, c: Color, alphaMultiplier: Float = 1f, /** * If set to `true`, renders the box relative to the camera instead of relative to the world. * If set to `false`, will be relativized to [RenderUtils.getViewerPos]. */ renderRelativeToCamera: Boolean = false, drawVerticalBarriers: Boolean = true, ) { drawFilledBoundingBox_nea(aabb, c, alphaMultiplier, renderRelativeToCamera, drawVerticalBarriers, partialTicks) } fun drawWireframeBoundingBox_nea( aabb: AxisAlignedBB, color: Color, partialTicks: Float, ) { GlStateManager.enableBlend() GlStateManager.disableLighting() GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0) GlStateManager.disableTexture2D() GlStateManager.disableCull() val vp = getViewerPos(partialTicks) val effectiveAABB = AxisAlignedBB( aabb.minX - vp.x, aabb.minY - vp.y, aabb.minZ - vp.z, aabb.maxX - vp.x, aabb.maxY - vp.y, aabb.maxZ - vp.z, ) val tessellator = Tessellator.getInstance() val worldRenderer = tessellator.worldRenderer with(color) { GlStateManager.color(red / 255f, green / 255f, blue / 255f, alpha / 255f) } // Bottom face worldRenderer.begin(GL11.GL_LINE_LOOP, DefaultVertexFormats.POSITION) with(effectiveAABB) { worldRenderer.pos(minX, minY, minZ).endVertex() worldRenderer.pos(maxX, minY, minZ).endVertex() worldRenderer.pos(maxX, minY, maxZ).endVertex() worldRenderer.pos(minX, minY, maxZ).endVertex() } tessellator.draw() // Top face worldRenderer.begin(GL11.GL_LINE_LOOP, DefaultVertexFormats.POSITION) with(effectiveAABB) { worldRenderer.pos(minX, maxY, maxZ).endVertex() worldRenderer.pos(maxX, maxY, maxZ).endVertex() worldRenderer.pos(maxX, maxY, minZ).endVertex() worldRenderer.pos(minX, maxY, minZ).endVertex() } tessellator.draw() worldRenderer.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION) with(effectiveAABB) { worldRenderer.pos(minX, minY, minZ).endVertex() worldRenderer.pos(minX, maxY, minZ).endVertex() worldRenderer.pos(minX, minY, maxZ).endVertex() worldRenderer.pos(minX, maxY, maxZ).endVertex() worldRenderer.pos(maxX, minY, minZ).endVertex() worldRenderer.pos(maxX, maxY, minZ).endVertex() worldRenderer.pos(maxX, minY, maxZ).endVertex() worldRenderer.pos(maxX, maxY, maxZ).endVertex() } tessellator.draw() GlStateManager.enableTexture2D() GlStateManager.enableCull() GlStateManager.disableBlend() } fun drawFilledBoundingBox_nea( aabb: AxisAlignedBB, c: Color, alphaMultiplier: Float = 1f, /** * If set to `true`, renders the box relative to the camera instead of relative to the world. * If set to `false`, will be relativized to [RenderUtils.getViewerPos]. Setting this to `false` requires * specifying [partialTicks]] */ renderRelativeToCamera: Boolean = true, drawVerticalBarriers: Boolean = true, partialTicks: Float = 0F, ) { GlStateManager.enableBlend() GlStateManager.disableLighting() GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0) GlStateManager.disableTexture2D() GlStateManager.disableCull() val effectiveAABB = if (!renderRelativeToCamera) { val vp = getViewerPos(partialTicks) AxisAlignedBB( aabb.minX - vp.x, aabb.minY - vp.y, aabb.minZ - vp.z, aabb.maxX - vp.x, aabb.maxY - vp.y, aabb.maxZ - vp.z, ) } else { aabb } val tessellator = Tessellator.getInstance() val worldRenderer = tessellator.worldRenderer // vertical if (drawVerticalBarriers) { GlStateManager.color(c.red / 255f, c.green / 255f, c.blue / 255f, c.alpha / 255f * alphaMultiplier) worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION) with(effectiveAABB) { worldRenderer.pos(minX, minY, minZ).endVertex() worldRenderer.pos(maxX, minY, minZ).endVertex() worldRenderer.pos(maxX, minY, maxZ).endVertex() worldRenderer.pos(minX, minY, maxZ).endVertex() tessellator.draw() worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION) worldRenderer.pos(minX, maxY, maxZ).endVertex() worldRenderer.pos(maxX, maxY, maxZ).endVertex() worldRenderer.pos(maxX, maxY, minZ).endVertex() worldRenderer.pos(minX, maxY, minZ).endVertex() tessellator.draw() } } GlStateManager.color( c.red / 255f * 0.8f, c.green / 255f * 0.8f, c.blue / 255f * 0.8f, c.alpha / 255f * alphaMultiplier ) // x worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION) with(effectiveAABB) { worldRenderer.pos(minX, minY, maxZ).endVertex() worldRenderer.pos(minX, maxY, maxZ).endVertex() worldRenderer.pos(minX, maxY, minZ).endVertex() worldRenderer.pos(minX, minY, minZ).endVertex() tessellator.draw() worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION) worldRenderer.pos(maxX, minY, minZ).endVertex() worldRenderer.pos(maxX, maxY, minZ).endVertex() worldRenderer.pos(maxX, maxY, maxZ).endVertex() worldRenderer.pos(maxX, minY, maxZ).endVertex() } tessellator.draw() GlStateManager.color( c.red / 255f * 0.9f, c.green / 255f * 0.9f, c.blue / 255f * 0.9f, c.alpha / 255f * alphaMultiplier ) // z worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION) with(effectiveAABB) { worldRenderer.pos(minX, maxY, minZ).endVertex() worldRenderer.pos(maxX, maxY, minZ).endVertex() worldRenderer.pos(maxX, minY, minZ).endVertex() worldRenderer.pos(minX, minY, minZ).endVertex() tessellator.draw() worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION) worldRenderer.pos(minX, minY, maxZ).endVertex() worldRenderer.pos(maxX, minY, maxZ).endVertex() worldRenderer.pos(maxX, maxY, maxZ).endVertex() worldRenderer.pos(minX, maxY, maxZ).endVertex() } tessellator.draw() GlStateManager.enableTexture2D() GlStateManager.enableCull() GlStateManager.disableBlend() } fun LorenzRenderWorldEvent.outlineTopFace( boundingBox: AxisAlignedBB, lineWidth: Int, colour: Color, depth: Boolean, ) { val cornerOne = LorenzVec(boundingBox.minX, boundingBox.maxY, boundingBox.minZ) val cornerTwo = LorenzVec(boundingBox.minX, boundingBox.maxY, boundingBox.maxZ) val cornerThree = LorenzVec(boundingBox.maxX, boundingBox.maxY, boundingBox.maxZ) val cornerFour = LorenzVec(boundingBox.maxX, boundingBox.maxY, boundingBox.minZ) this.draw3DLine(cornerOne, cornerTwo, colour, lineWidth, depth) this.draw3DLine(cornerTwo, cornerThree, colour, lineWidth, depth) this.draw3DLine(cornerThree, cornerFour, colour, lineWidth, depth) this.draw3DLine(cornerFour, cornerOne, colour, lineWidth, depth) } // TODO nea please merge with 'draw3DLine' fun LorenzRenderWorldEvent.draw3DLine_nea( p1: LorenzVec, p2: LorenzVec, color: Color, lineWidth: Int, depth: Boolean, ) { GlStateManager.disableDepth() GlStateManager.disableCull() val render = Minecraft.getMinecraft().renderViewEntity val worldRenderer = Tessellator.getInstance().worldRenderer val realX = render.lastTickPosX + (render.posX - render.lastTickPosX) * partialTicks val realY = render.lastTickPosY + (render.posY - render.lastTickPosY) * partialTicks val realZ = render.lastTickPosZ + (render.posZ - render.lastTickPosZ) * partialTicks GlStateManager.pushMatrix() GlStateManager.translate(-realX, -realY, -realZ) GlStateManager.disableTexture2D() GlStateManager.enableBlend() GlStateManager.disableAlpha() GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0) GL11.glLineWidth(lineWidth.toFloat()) if (!depth) { GL11.glDisable(GL11.GL_DEPTH_TEST) GlStateManager.depthMask(false) } GlStateManager.color(color.red / 255f, color.green / 255f, color.blue / 255f, color.alpha / 255f) worldRenderer.begin(GL11.GL_LINE_STRIP, DefaultVertexFormats.POSITION) worldRenderer.pos(p1.x, p1.y, p1.z).endVertex() worldRenderer.pos(p2.x, p2.y, p2.z).endVertex() Tessellator.getInstance().draw() GlStateManager.translate(realX, realY, realZ) if (!depth) { GL11.glEnable(GL11.GL_DEPTH_TEST) GlStateManager.depthMask(true) } GlStateManager.disableBlend() GlStateManager.enableAlpha() GlStateManager.enableTexture2D() GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f) GlStateManager.popMatrix() GlStateManager.disableLighting() GlStateManager.enableDepth() } fun chromaColor( timeTillRepeat: Duration, offset: Float = 0f, saturation: Float = 1F, brightness: Float = 0.8F, timeOverride: Long = System.currentTimeMillis(), ): Color { return Color( Color.HSBtoRGB( ((offset + timeOverride / timeTillRepeat.toDouble(DurationUnit.MILLISECONDS)) % 1).toFloat(), saturation, brightness ) ) } fun GuiRenderItemEvent.RenderOverlayEvent.GuiRenderItemPost.drawSlotText( xPos: Int, yPos: Int, text: String, scale: Float, ) { val fontRenderer = Minecraft.getMinecraft().fontRendererObj GlStateManager.disableLighting() GlStateManager.disableDepth() GlStateManager.disableBlend() GlStateManager.pushMatrix() GlStateManager.translate((xPos - fontRenderer.getStringWidth(text)).toFloat(), yPos.toFloat(), 0f) GlStateManager.scale(scale, scale, 1f) fontRenderer.drawStringWithShadow(text, 0f, 0f, 16777215) val reverseScale = 1 / scale GlStateManager.scale(reverseScale, reverseScale, 1f) GlStateManager.popMatrix() GlStateManager.enableLighting() GlStateManager.enableDepth() } /** * Method to draw a rounded rectangle. * * **NOTE:** If you are using [GlStateManager.translate] or [GlStateManager.scale] * with this method, ensure they are invoked in the correct order if you use both. That is, [GlStateManager.translate] * is called **BEFORE** [GlStateManager.scale], otherwise the rectangle will not be rendered correctly * * @param color color of rect * @param radius the radius of the corners (default 10) * @param smoothness how smooth the corners will appear (default 2). NOTE: This does very * little to the smoothness of the corners in reality due to how the final pixel color is calculated. * It is best kept at its default. */ fun drawRoundRect(x: Int, y: Int, width: Int, height: Int, color: Int, radius: Int = 10, smoothness: Int = 1) { val scaledRes = ScaledResolution(Minecraft.getMinecraft()) val widthIn = width * scaledRes.scaleFactor val heightIn = height * scaledRes.scaleFactor val xIn = x * scaledRes.scaleFactor val yIn = y * scaledRes.scaleFactor RoundedRectangleShader.scaleFactor = scaledRes.scaleFactor.toFloat() RoundedRectangleShader.radius = radius.toFloat() RoundedRectangleShader.smoothness = smoothness.toFloat() RoundedRectangleShader.halfSize = floatArrayOf(widthIn / 2f, heightIn / 2f) RoundedRectangleShader.centerPos = floatArrayOf(xIn + (widthIn / 2f), yIn + (heightIn / 2f)) GlStateManager.pushMatrix() ShaderManager.enableShader("rounded_rect") Gui.drawRect(x, y, x + width, y + height, color) ShaderManager.disableShader() GlStateManager.popMatrix() } }