diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/ModuleManager.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/ModuleManager.kt index 85f1d551705..726b9f12ff4 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/ModuleManager.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/ModuleManager.kt @@ -125,6 +125,7 @@ object ModuleManager : Listenable, Collection by MODULE_REGISTRY { ItemESP, ItemPhysics, ItemTeleport, + JumpCircle, KeepAlive, KeepContainer, KeepTabList, diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/render/JumpCircle.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/render/JumpCircle.kt new file mode 100644 index 00000000000..af73f82f37b --- /dev/null +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/render/JumpCircle.kt @@ -0,0 +1,77 @@ +/* + * LiquidBounce Hacked Client + * A free open source mixin-based injection hacked client for Minecraft using Minecraft Forge. + * https://github.com/CCBlueX/LiquidBounce/ + */ +package net.ccbluex.liquidbounce.features.module.modules.render + +import net.ccbluex.liquidbounce.config.boolean +import net.ccbluex.liquidbounce.config.color +import net.ccbluex.liquidbounce.config.floatRange +import net.ccbluex.liquidbounce.config.int +import net.ccbluex.liquidbounce.event.JumpEvent +import net.ccbluex.liquidbounce.event.Render3DEvent +import net.ccbluex.liquidbounce.event.handler +import net.ccbluex.liquidbounce.features.module.Category +import net.ccbluex.liquidbounce.features.module.Module +import net.ccbluex.liquidbounce.utils.client.ClientUtils.runTimeTicks +import net.ccbluex.liquidbounce.utils.extensions.currPos +import net.ccbluex.liquidbounce.utils.extensions.lerpWith +import net.ccbluex.liquidbounce.utils.render.ColorUtils.shiftHue +import net.ccbluex.liquidbounce.utils.render.ColorUtils.withAlpha +import net.ccbluex.liquidbounce.utils.render.RenderUtils.drawHueCircle +import net.minecraft.util.Vec3 +import java.awt.Color + +/** + * @author Original by Ell1ott (Nextgen) + * @author Modified by EclipsesDev + */ +object JumpCircle : Module("JumpCircle", Category.RENDER, hideModule = false) { + private val circleRadius by floatRange("CircleRadius", 0.15F..0.8F, 0F..3F) + private val innerColor = color("InnerColor", Color(0, 0, 0, 50)) + private val outerColor = color("OuterColor", Color(0, 111, 255, 255)) + private val hueOffsetAnim by int("HueOffsetAnim", 63, -360..360) + private val lifeTime by int("LifeTime", 20, 1..50, "Ticks") + private val blackHole by boolean("BlackHole", false) + + private val circles = mutableListOf() + + val onJump = handler { + circles += JumpData(mc.thePlayer.currPos, runTimeTicks + if (blackHole) lifeTime else 0) + } + + val onRender3D = handler { + val partialTick = it.partialTicks + + circles.removeIf { + val progress = ((runTimeTicks + partialTick) - it.endTime) / lifeTime + val radius = circleRadius.lerpWith(progress) + + drawHueCircle( + it.pos, + radius, + animateColor(innerColor.selectedColor(), progress), + animateColor(outerColor.selectedColor(), progress) + ) + + progress >= 1F + } + } + + override fun onDisable() { + circles.clear() + } + + private fun animateColor(baseColor: Color, progress: Float): Color { + val color = baseColor.withAlpha((baseColor.alpha * (1 - progress)).toInt().coerceIn(0, 255)) + + if (hueOffsetAnim == 0) { + return color + } + + return shiftHue(color, (hueOffsetAnim * progress).toInt()) + } + + data class JumpData(val pos: Vec3, val endTime: Int) +} \ No newline at end of file diff --git a/src/main/java/net/ccbluex/liquidbounce/ui/client/hud/element/elements/Target.kt b/src/main/java/net/ccbluex/liquidbounce/ui/client/hud/element/elements/Target.kt index 7c0ba680c47..73747eb9944 100644 --- a/src/main/java/net/ccbluex/liquidbounce/ui/client/hud/element/elements/Target.kt +++ b/src/main/java/net/ccbluex/liquidbounce/ui/client/hud/element/elements/Target.kt @@ -21,7 +21,6 @@ import net.ccbluex.liquidbounce.utils.render.RenderUtils.drawRect import net.ccbluex.liquidbounce.utils.render.RenderUtils.drawRoundedBorderRect import net.ccbluex.liquidbounce.utils.render.RenderUtils.drawScaledCustomSizeModalRect import net.ccbluex.liquidbounce.utils.render.animation.AnimationUtil -import net.ccbluex.liquidbounce.utils.render.animation.AnimationUtil.debugFPS import net.ccbluex.liquidbounce.utils.render.shader.shaders.RainbowShader import net.ccbluex.liquidbounce.utils.render.shader.shaders.FrostShader import net.minecraft.client.gui.GuiChat @@ -32,11 +31,8 @@ import java.awt.Color import java.text.DecimalFormat import java.text.DecimalFormatSymbols import java.util.* -import kotlin.collections.component1 -import kotlin.collections.component2 import kotlin.math.abs import kotlin.math.pow -import kotlin.math.roundToInt /** * A Target HUD @@ -92,19 +88,13 @@ class Target : Element() { private var delayCounter = 0 override fun drawElement(): Border { + val smoothMode = animation == "Smooth" + val fadeMode = animation == "Fade" + + val shouldRender = KillAura.handleEvents() && KillAura.target != null || mc.currentScreen is GuiChat val target = KillAura.target ?: if (delayCounter >= vanishDelay) mc.thePlayer else lastTarget ?: mc.thePlayer assumeNonVolatile { - val shouldRender = KillAura.handleEvents() && KillAura.target != null || mc.currentScreen is GuiChat - val smoothMode = animation == "Smooth" - val fadeMode = animation == "Fade" - - var (textAlpha, borderAlpha) = if (fadeMode) { - intArrayOf(alphaText, alphaBorder) - } else { - intArrayOf(textColor.alpha, borderColor.alpha) - } - val stringWidth = (40f + (target.name?.let(titleFont::getStringWidth) ?: 0)).coerceAtLeast(118F) if (shouldRender) { @@ -113,24 +103,18 @@ class Target : Element() { delayCounter++ } - if (smoothMode && !shouldRender && delayCounter >= vanishDelay) { - val decrement = (animationSpeed / (debugFPS / 60)).coerceAtLeast(0f) - width -= decrement - height -= decrement - } - if (shouldRender || isRendered || isAlpha) { val targetHealth = getHealth(target!!, healthFromScoreboard, absorption) val maxHealth = target.maxHealth + if (absorption) target.absorptionAmount else 0F // Calculate health color based on entity's health val healthColor = when { - targetHealth <= 0 -> Color(255, 0, 0, if (fadeMode) alphaText else textAlpha) + targetHealth <= 0 -> Color(255, 0, 0, if (fadeMode) alphaText else textColor.alpha) else -> { ColorUtils.interpolateHealthColor( target, 255, 255, 0, - if (fadeMode) alphaText else textAlpha, + if (fadeMode) alphaText else textColor.alpha, healthFromScoreboard, absorption ) @@ -143,24 +127,21 @@ class Target : Element() { if (smoothMode) { val targetWidth = if (shouldRender) stringWidth else if (delayCounter >= vanishDelay) 0f else width - width = - AnimationUtil.base(width.toDouble(), targetWidth.toDouble(), animationSpeed.toDouble()) - .toFloat() - .coerceAtLeast(0f) + width = AnimationUtil.base(width.toDouble(), targetWidth.toDouble(), animationSpeed.toDouble()) + .toFloat() + .coerceAtLeast(0f) val targetHeight = if (shouldRender) 40f else if (delayCounter >= vanishDelay) 0f else height - height = - AnimationUtil.base(height.toDouble(), targetHeight.toDouble(), animationSpeed.toDouble()) - .toFloat() - .coerceAtLeast(0f) + height = AnimationUtil.base(height.toDouble(), targetHeight.toDouble(), animationSpeed.toDouble()) + .toFloat() + .coerceAtLeast(0f) } else { width = stringWidth height = 40f - val targetText = if (shouldRender) textAlpha else if (delayCounter >= vanishDelay) 0f else alphaText - alphaText = - AnimationUtil.base(alphaText.toDouble(), targetText.toDouble(), animationSpeed.toDouble()) - .roundToInt() + val targetText = if (shouldRender) textColor.alpha else if (delayCounter >= vanishDelay) 0f else alphaText + alphaText = AnimationUtil.base(alphaText.toDouble(), targetText.toDouble(), animationSpeed.toDouble()) + .toInt() val targetBackground = if (shouldRender) { backgroundColor.alpha @@ -172,7 +153,7 @@ class Target : Element() { alphaBackground.toDouble(), targetBackground.toDouble(), animationSpeed.toDouble() - ).roundToInt() + ).toInt() val targetBorder = if (shouldRender) { borderColor.alpha @@ -180,18 +161,19 @@ class Target : Element() { 0f } else alphaBorder - alphaBorder = - AnimationUtil.base(alphaBorder.toDouble(), targetBorder.toDouble(), animationSpeed.toDouble()) - .roundToInt() - - borderAlpha = alphaBorder - textAlpha = alphaText + alphaBorder = AnimationUtil.base(alphaBorder.toDouble(), targetBorder.toDouble(), animationSpeed.toDouble()) + .toInt() } - val backgroundAlpha = if (fadeMode) alphaBackground else backgroundColor.alpha - val backgroundCustomColor = backgroundColor.withAlpha(backgroundAlpha).rgb - val borderCustomColor = borderColor.withAlpha(borderAlpha).rgb - val textCustomColor = textColor.withAlpha(textAlpha).rgb + val backgroundCustomColor = backgroundColor.withAlpha( + if (fadeMode) alphaBackground else backgroundColor.alpha + ).rgb + val borderCustomColor = borderColor.withAlpha( + if (fadeMode) alphaBorder else borderColor.alpha + ).rgb + val textCustomColor = textColor.withAlpha( + if (fadeMode) alphaText else textColor.alpha + ).rgb val rainbowOffset = System.currentTimeMillis() % 10000 / 10000F val rainbowX = if (rainbowX == 0f) 0f else 1f / rainbowX @@ -202,7 +184,10 @@ class Target : Element() { glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) - if (fadeMode && shouldRender || smoothMode && shouldRender || delayCounter < vanishDelay) { + if (fadeMode && isAlpha || smoothMode && isRendered || delayCounter < vanishDelay) { + val width = width.coerceAtLeast(0F) + val height = height.coerceAtLeast(0F) + when (backgroundMode) { "Frost" -> { FrostShader.begin(true, frostIntensity).use { @@ -227,7 +212,7 @@ class Target : Element() { } // Health bar - val healthBarWidth = (targetHealth / maxHealth).coerceIn(0F, 1F) * (width - 6f) + val healthBarWidth = (targetHealth / maxHealth).coerceIn(0F, 1F) * (width - 6f).coerceAtLeast(0F) drawRect(3F, 34F, 3f + healthBarWidth, 36F, healthColor.rgb) // Easing health update @@ -244,31 +229,36 @@ class Target : Element() { drawRect(3f + healthBarWidth, 34F, 3f + easingHealthWidth, 36F, Color(252, 185, 65).rgb) } - // Draw title text - target.name?.let { titleFont.drawString(it, 36F, 5F, textCustomColor, textShadow) } + val shouldRenderBody = (fadeMode && alphaText + alphaBackground + alphaBorder > 100) || + (smoothMode && width + height > 100) - // Draw body text - bodyFont.drawString( - "Distance: ${decimalFormat.format(mc.thePlayer.getDistanceToEntityBox(target))}", - 36F, - 15F, - textCustomColor, - textShadow - ) + if (shouldRenderBody) { + // Draw title text + target.name?.let { titleFont.drawString(it, 36F, 5F, textCustomColor, textShadow) } - // Draw info - mc.netHandler?.getPlayerInfo(target.uniqueID)?.let { + // Draw body text bodyFont.drawString( - "Ping: ${it.responseTime.coerceAtLeast(0)}", + "Distance: ${decimalFormat.format(mc.thePlayer.getDistanceToEntityBox(target))}", 36F, - 24F, + 15F, textCustomColor, textShadow ) - // Draw head - val locationSkin = it.locationSkin - drawHead(locationSkin, 30, 30) + // Draw info + mc.netHandler?.getPlayerInfo(target.uniqueID)?.let { + bodyFont.drawString( + "Ping: ${it.responseTime.coerceAtLeast(0)}", + 36F, + 24F, + textCustomColor, + textShadow + ) + + // Draw head + val locationSkin = it.locationSkin + drawHead(locationSkin, 30, 30) + } } } diff --git a/src/main/java/net/ccbluex/liquidbounce/ui/font/GameFontRenderer.kt b/src/main/java/net/ccbluex/liquidbounce/ui/font/GameFontRenderer.kt index aaa5a28acfc..66f2597f726 100644 --- a/src/main/java/net/ccbluex/liquidbounce/ui/font/GameFontRenderer.kt +++ b/src/main/java/net/ccbluex/liquidbounce/ui/font/GameFontRenderer.kt @@ -23,7 +23,7 @@ import java.awt.Font /** * Extends Minecraft's [FontRenderer] for potential fallback usage. * - * * @author opZywl + * @author opZywl */ class GameFontRenderer( font: Font diff --git a/src/main/java/net/ccbluex/liquidbounce/utils/render/ColorUtils.kt b/src/main/java/net/ccbluex/liquidbounce/utils/render/ColorUtils.kt index 448f658f834..22ae5df229e 100644 --- a/src/main/java/net/ccbluex/liquidbounce/utils/render/ColorUtils.kt +++ b/src/main/java/net/ccbluex/liquidbounce/utils/render/ColorUtils.kt @@ -33,7 +33,9 @@ object ColorUtils { } fun Color.withAlpha(a: Int) = Color(red, green, blue, a) + fun Color.normalize() = Color(this.red / 255f, this.green / 255f, this.blue / 255f, this.alpha / 255f) + fun packARGBValue(r: Int, g: Int, b: Int, a: Int = 0xff): Int { return (a and 255 shl 24) or (r and 255 shl 16) or (g and 255 shl 8) or (b and 255) } @@ -128,6 +130,16 @@ object ColorUtils { return Color(red, green, b, a) } + /** + * @author Ell1ott + */ + fun shiftHue(color: Color, shift: Int): Color { + val hsb = Color.RGBtoHSB(color.red, color.green, color.blue, null) + val shiftedColor = Color(Color.HSBtoRGB((hsb[0] + shift.toFloat() / 360) % 1F, hsb[1], hsb[2])) + + return Color(shiftedColor.red, shiftedColor.green, shiftedColor.blue, color.alpha) + } + fun fade(colorSettings: ColorSettingsInteger, speed: Int, count: Int): Color { val color = colorSettings.color() diff --git a/src/main/java/net/ccbluex/liquidbounce/utils/render/RenderUtils.kt b/src/main/java/net/ccbluex/liquidbounce/utils/render/RenderUtils.kt index afc50c8e3f3..ee7aafea160 100644 --- a/src/main/java/net/ccbluex/liquidbounce/utils/render/RenderUtils.kt +++ b/src/main/java/net/ccbluex/liquidbounce/utils/render/RenderUtils.kt @@ -15,14 +15,12 @@ import net.ccbluex.liquidbounce.utils.extensions.* import net.ccbluex.liquidbounce.utils.render.animation.AnimationUtil import net.minecraft.client.gui.FontRenderer import net.minecraft.client.gui.ScaledResolution -import net.minecraft.client.renderer.GlStateManager 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.entity.EntityLivingBase import net.minecraft.util.* -import org.lwjgl.opengl.GL11 import org.lwjgl.opengl.GL11.* import org.lwjgl.opengl.GL12.GL_CLAMP_TO_EDGE import org.lwjgl.opengl.GL14 @@ -47,7 +45,6 @@ object RenderUtils : MinecraftInstance { fun deltaTimeNormalized(ticks: Int = 1) = (deltaTime / (ticks.toDouble() * 50)).coerceAtMost(1.0) - private const val CIRCLE_STEPS = 40 private val circlePoints = Array(CIRCLE_STEPS + 1) { @@ -280,6 +277,58 @@ object RenderUtils : MinecraftInstance { glPopAttrib() } + fun drawHueCircle(position: Vec3, radius: Float, innerColor: Color, outerColor: Color) { + val manager = mc.renderManager + + val renderX = manager.viewerPosX + val renderY = manager.viewerPosY + val renderZ = manager.viewerPosZ + + glPushAttrib(GL_ALL_ATTRIB_BITS) + glPushMatrix() + + glDisable(GL_TEXTURE_2D) + glEnable(GL_BLEND) + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) + glEnable(GL_LINE_SMOOTH) + glDisable(GL_DEPTH_TEST) + glDisable(GL_CULL_FACE) + glEnable(GL_ALPHA_TEST) + glAlphaFunc(GL_GREATER, 0.0f) + mc.entityRenderer.disableLightmap() + + glBegin(GL_TRIANGLE_FAN) + circlePoints.forEachIndexed { index, pos -> + val innerX = pos.xCoord * radius + val innerZ = pos.zCoord * radius + + val innerHue = ColorUtils.shiftHue(innerColor, (index / CIRCLE_STEPS).toInt()) + glColor4f(innerHue.red / 255f, innerHue.green / 255f, innerHue.blue / 255f, innerColor.alpha / 255f) + glVertex3d(position.xCoord - renderX + innerX, position.yCoord - renderY, position.zCoord - renderZ + innerZ) + } + glEnd() + + glBegin(GL_LINE_LOOP) + circlePoints.forEachIndexed { index, pos -> + val outerX = pos.xCoord * radius + val outerZ = pos.zCoord * radius + + val outerHue = ColorUtils.shiftHue(outerColor, (index / CIRCLE_STEPS).toInt()) + glColor4f(outerHue.red / 255f, outerHue.green / 255f, outerHue.alpha / 255f, outerColor.alpha / 255f) + glVertex3d(position.xCoord - renderX + outerX, position.yCoord - renderY, position.zCoord - renderZ + outerZ) + } + glEnd() + + glEnable(GL_CULL_FACE) + glEnable(GL_DEPTH_TEST) + glDisable(GL_ALPHA_TEST) + glDisable(GL_LINE_SMOOTH) + glDisable(GL_BLEND) + glEnable(GL_TEXTURE_2D) + glPopMatrix() + glPopAttrib() + } + /** * Draws a dome around the specified [pos] * @@ -385,61 +434,61 @@ object RenderUtils : MinecraftInstance { } fun drawConesForEntities(f: () -> Unit) { - GlStateManager.pushAttrib() - GlStateManager.pushMatrix() + pushAttrib() + pushMatrix() - GlStateManager.disableTexture2D() - GlStateManager.disableCull() + disableTexture2D() + disableCull() - GlStateManager.enableBlend() - GlStateManager.enableDepth() - GlStateManager.depthMask(false) - GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA) + enableBlend() + enableDepth() + depthMask(false) + blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) f() - GlStateManager.resetColor() + resetColor() - GlStateManager.enableTexture2D() - GlStateManager.depthMask(true) - GlStateManager.enableCull() + enableTexture2D() + depthMask(true) + enableCull() - GlStateManager.disableBlend() - GlStateManager.disableDepth() + disableBlend() + disableDepth() - GlStateManager.popMatrix() - GlStateManager.popAttrib() + popMatrix() + popAttrib() } fun drawCone(width: Float, height: Float, useTexture: Boolean = false) { if (useTexture) { // TODO: Maybe image option support to allow many different type of hats. mc.textureManager.bindTexture(ResourceLocation("liquidbounce/textures/hat.png")) - GlStateManager.enableTexture2D() - GlStateManager.depthMask(true) + enableTexture2D() + depthMask(true) } - GL11.glBegin(GL11.GL_TRIANGLE_FAN) + glBegin(GL_TRIANGLE_FAN) if (useTexture) { // Place texture in the middle, on the tip - GL11.glTexCoord2d(0.5, 0.5) + glTexCoord2d(0.5, 0.5) } // The tip of the cone - GL11.glVertex3d(0.0, height.toDouble(), 0.0) + glVertex3d(0.0, height.toDouble(), 0.0) for (point in circlePoints) { if (useTexture) { val u = 0.5 + 0.5 * point.xCoord val v = 0.5 + 0.5 * point.zCoord - GL11.glTexCoord2d(u, v) + glTexCoord2d(u, v) } - GL11.glVertex3d(point.xCoord * width, 0.0, point.zCoord * width) + glVertex3d(point.xCoord * width, 0.0, point.zCoord * width) } - GL11.glEnd() + glEnd() } fun drawEntityBox(entity: Entity, color: Color, outline: Boolean) { @@ -1108,7 +1157,7 @@ object RenderUtils : MinecraftInstance { fun glColor(color: Color) = glColor(color.red, color.green, color.blue, color.alpha) fun glStateManagerColor(color: Color) = - GlStateManager.color(color.red / 255f, color.green / 255f, color.blue / 255f, color.alpha / 255f) + color(color.red / 255f, color.green / 255f, color.blue / 255f, color.alpha / 255f) private fun glColor(hex: Int) = glColor(hex shr 16 and 0xFF, hex shr 8 and 0xFF, hex and 0xFF, hex shr 24 and 0xFF) diff --git a/src/main/resources/assets/minecraft/liquidbounce/lang/en_US.json b/src/main/resources/assets/minecraft/liquidbounce/lang/en_US.json index e50fcad8f74..e112f4d6c00 100644 --- a/src/main/resources/assets/minecraft/liquidbounce/lang/en_US.json +++ b/src/main/resources/assets/minecraft/liquidbounce/lang/en_US.json @@ -214,6 +214,8 @@ "module.itemPhysics.description": "Allows dropped items to have physics", + "module.jumpCircle.description": "Renders a circle below you when jumping.", + "module.keepAlive.description": "Tries to prevent you from dying.", "module.keepContainer.description": "Allows you to open a formerly closed inventory container everywhere. (Press INSERT Key to open)",