diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/utils/entity/EntityExtensions.kt b/src/main/kotlin/net/ccbluex/liquidbounce/utils/entity/EntityExtensions.kt index 0160ff9c58e..f2df9d3da47 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/utils/entity/EntityExtensions.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/utils/entity/EntityExtensions.kt @@ -134,6 +134,8 @@ val ClientPlayerEntity.directionYaw: Float val ClientPlayerEntity.isBlockAction: Boolean get() = isUsingItem && activeItem.useAction == UseAction.BLOCK +fun Entity.lastRenderPos() = Vec3d(this.lastRenderX, this.lastRenderY, this.lastRenderZ) + /** * Check if the player can step up by [height] blocks. * diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/utils/render/TargetRenderer.kt b/src/main/kotlin/net/ccbluex/liquidbounce/utils/render/TargetRenderer.kt index 442241cbeb9..3bb84fcdc78 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/utils/render/TargetRenderer.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/utils/render/TargetRenderer.kt @@ -18,6 +18,8 @@ */ package net.ccbluex.liquidbounce.utils.render +import com.mojang.blaze3d.platform.GlStateManager +import com.mojang.blaze3d.systems.RenderSystem import net.ccbluex.liquidbounce.config.types.Choice import net.ccbluex.liquidbounce.config.types.ChoiceConfigurable import net.ccbluex.liquidbounce.config.types.ToggleableConfigurable @@ -27,18 +29,26 @@ import net.ccbluex.liquidbounce.render.engine.Color4b import net.ccbluex.liquidbounce.render.engine.Vec3 import net.ccbluex.liquidbounce.utils.entity.box import net.ccbluex.liquidbounce.utils.entity.interpolateCurrentPosition +import net.ccbluex.liquidbounce.utils.entity.lastRenderPos import net.ccbluex.liquidbounce.utils.math.plus import net.ccbluex.liquidbounce.utils.render.WorldToScreen.calculateScreenPos import net.minecraft.client.render.GameRenderer import net.minecraft.client.render.VertexFormat import net.minecraft.client.render.VertexFormats +import net.minecraft.client.util.math.MatrixStack import net.minecraft.entity.Entity import net.minecraft.entity.LivingEntity +import net.minecraft.util.Identifier import net.minecraft.util.math.Box +import net.minecraft.util.math.MathHelper +import net.minecraft.util.math.RotationAxis import net.minecraft.util.math.Vec3d +import java.awt.Color +import kotlin.math.cos import kotlin.math.min import kotlin.math.sin + /** * A target tracker to choose the best enemy to attack */ @@ -68,15 +78,147 @@ class WorldTargetRenderer(module: ClientModule) : TargetRenderer( module, "Mode", { glowingCircle }, - { arrayOf(legacy, circle, glowingCircle) } + { arrayOf(legacy, circle, glowingCircle, ghost) } ) + inner class Ghost : WorldTargetRenderAppearance("Ghost") { + + private val glow = Identifier.of("liquidbounce", "glow.png") + + private var lastTime = System.currentTimeMillis() + + override val parent: ChoiceConfigurable<*> + get() = appearance + + private val color by color("Color", Color4b(Color.BLUE.rgb, true)) + private var size by float("Size", 0.5f, 0.4f..0.7f) + private var length by int("Length", 25, 15..40) + + override fun render(env: WorldRenderEnvironment, entity: Entity, partialTicks: Float) { + RenderSystem.depthMask(false) + mc.gameRenderer.lightmapTextureManager.disable() + RenderSystem.blendFuncSeparate( + GlStateManager.SrcFactor.SRC_ALPHA, + GlStateManager.DstFactor.ONE, + GlStateManager.SrcFactor.ZERO, + GlStateManager.DstFactor.ONE + ) + env.matrixStack.push() + + + with(mc.gameRenderer.camera.pos) { + env.matrixStack.translate(-this.x, -this.y, -this.z) + } + + val interpolated = entity.pos.interpolate(entity.lastRenderPos(), partialTicks.toDouble()) + .add(0.0, 0.75, 0.0) + + with(interpolated) { + env.matrixStack.translate( + this.x + 0.2f, + this.y + 0.5f, + this.z + ) + } + + RenderSystem.setShaderTexture(0, glow) + + with(env) { + drawParticle( + { sin, cos -> translate(sin, cos, -cos) }, + { sin, cos -> translate(-sin, -cos, cos) } + ) + + drawParticle( + { sin, cos -> translate(-sin, sin, -cos) }, + { sin, cos -> translate(sin, -sin, cos) } + ) + + drawParticle( + { sin, cos -> translate(-sin, -sin, cos) }, + { sin, cos -> translate(sin, sin, -cos) } + ) + } + + RenderSystem.depthMask(false) + RenderSystem.defaultBlendFunc() + mc.gameRenderer.lightmapTextureManager.enable() + env.matrixStack.pop() + } + + private inline fun WorldRenderEnvironment.drawParticle( + translateBefore: MatrixStack.(Double, Double)->Unit, + translateAfter: MatrixStack.(Double, Double)->Unit + ) { + val radius = 0.67 + val distance = 10.0 + (length * 0.2) + val alphaFactor = 15 + + for (i in 0.. + vertex(matrix, 0.0f, -size, 0.0f) + .texture(0.0f, 0.0f) + .color(renderColor.toARGB()) + + vertex(matrix, -size, -size, 0.0f) + .texture(0.0f, 1.0f) + .color(renderColor.toARGB()) + + vertex(matrix, -size, 0.0f, 0.0f) + .texture(1.0f, 1.0f) + .color(renderColor.toARGB()) + + vertex(matrix, 0.0f, 0.0f, 0.0f) + .texture(1.0f, 0.0f) + .color(renderColor.toARGB()) + } + + with(matrixStack) { + translate(-size / 2.0, -size / 2.0, 0.0) + multiply(RotationAxis.POSITIVE_X.rotationDegrees(-mc.gameRenderer.camera.pitch)) + multiply(RotationAxis.POSITIVE_Y.rotationDegrees(mc.gameRenderer.camera.yaw)) + translate(size / 2.0, size / 2.0, 0.0) + translateAfter(sin, cos) + } + } + } + + private fun Vec3d.interpolate(start: Vec3d, multiple: Double) = + Vec3d( + this.x.interpolate(start.x, multiple), + this.y.interpolate(start.y, multiple), + this.z.interpolate(start.z, multiple), + ) + + private fun Double.interpolate(old: Double, scale: Double) = old + (this - old) * scale + } + inner class Legacy : WorldTargetRenderAppearance("Legacy") { override val parent: ChoiceConfigurable diff --git a/src/main/resources/assets/liquidbounce/glow.png b/src/main/resources/assets/liquidbounce/glow.png new file mode 100644 index 00000000000..0be84ecb7b1 Binary files /dev/null and b/src/main/resources/assets/liquidbounce/glow.png differ