Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ import net.ccbluex.liquidbounce.features.module.modules.render.ModuleSkinChanger
import net.ccbluex.liquidbounce.features.module.modules.render.ModuleSmoothCamera
import net.ccbluex.liquidbounce.features.module.modules.render.ModuleStorageESP
import net.ccbluex.liquidbounce.features.module.modules.render.ModuleTNTTimer
import net.ccbluex.liquidbounce.features.module.modules.render.targeticon.ModuleTargetIcon
import net.ccbluex.liquidbounce.features.module.modules.render.ModuleTracers
import net.ccbluex.liquidbounce.features.module.modules.render.ModuleTrueSight
import net.ccbluex.liquidbounce.features.module.modules.render.ModuleVoidESP
Expand Down Expand Up @@ -676,6 +677,7 @@ object ModuleManager : EventListener, Collection<ClientModule> by modules {
ModuleSkinChanger,
ModuleProtectionZones,
ModuleCrosshair,
ModuleTargetIcon,

// World
ModuleAirPlace,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/*
* This file is part of LiquidBounce (https://github.com/CCBlueX/LiquidBounce)
*
* Copyright (c) 2015 - 2026 CCBlueX
*
* LiquidBounce is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LiquidBounce is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LiquidBounce. If not, see <https://www.gnu.org/licenses/>.
*/
package net.ccbluex.liquidbounce.features.module.modules.render.targeticon

import net.ccbluex.fastutil.toEnumSet
import net.ccbluex.liquidbounce.config.utils.TextureMode
import net.ccbluex.liquidbounce.event.events.AttackEntityEvent
import net.ccbluex.liquidbounce.event.events.OverlayRenderEvent
import net.ccbluex.liquidbounce.event.handler
import net.ccbluex.liquidbounce.features.module.ClientModule
import net.ccbluex.liquidbounce.features.module.ModuleCategories
import net.ccbluex.liquidbounce.features.module.modules.combat.killaura.ModuleKillAura
import net.ccbluex.liquidbounce.render.ClientRenderPipelines
import net.ccbluex.liquidbounce.render.drawTexQuad
import net.ccbluex.liquidbounce.render.engine.type.Color4b
import net.ccbluex.liquidbounce.utils.entity.interpolateCurrentPosition
import net.ccbluex.liquidbounce.utils.render.WorldToScreen
import net.ccbluex.liquidbounce.utils.render.textureSetup
import net.minecraft.client.renderer.texture.DynamicTexture
import net.minecraft.world.entity.LivingEntity

object ModuleTargetIcon : ClientModule("TargetIcon", ModuleCategories.RENDER) {

private val textureMode = choices("Source", 1) {
arrayOf(
TextureMode.Custom(it),
TextureMode.Builtin(
it,
TargetIconRegistry.WEARY,
TargetIconRegistry.entries.filter { e -> e.texture != null }.toEnumSet()
)
)
}

private val onlyKillAura by boolean("OnlyKillAura", false)
private val randomIcon by boolean("RandomIcon", false)
private val iconSize by int("Size", 80, 16..256)
private val heightFraction by float("Height", 0.85f, 0f..1.5f)
private val offsetX by float("OffsetX", 0f, -200f..200f)
private val offsetY by float("OffsetY", -10f, -200f..200f)

@Volatile private var trackedEntity: LivingEntity? = null
@Volatile private var randomTexture: DynamicTexture? = null
@Volatile private var showUntil: Long = 0L
@Volatile private var shownSince: Long = 0L

private val currentTexture: DynamicTexture?
get() = if (randomIcon) randomTexture ?: textureMode.activeMode.texture else textureMode.activeMode.texture

override fun onDisabled() {
showUntil = 0L
shownSince = 0L
trackedEntity = null
randomTexture = null
}

@Suppress("unused")
private val attackHandler = handler<AttackEntityEvent> { event ->
val target = event.entity

if (target !is LivingEntity || !target.isAlive) return@handler
if (onlyKillAura && !ModuleKillAura.running) return@handler

val now = System.currentTimeMillis()
val isNewTarget = now >= showUntil || trackedEntity !== target

if (isNewTarget && randomIcon) {
randomTexture = TargetIconRegistry.entries.filter { it.texture != null }.randomOrNull()?.texture
}

if (currentTexture == null) return@handler

if (now >= showUntil) {
shownSince = now
}

trackedEntity = target
showUntil = now + 1000L
}

@Suppress("unused")
private val overlayRenderHandler = handler<OverlayRenderEvent> { event ->
val texture = currentTexture ?: return@handler
val now = System.currentTimeMillis()

if (now >= showUntil) {
showUntil = 0L
shownSince = 0L
trackedEntity = null
randomTexture = null
return@handler
}

val target = trackedEntity
if (target == null || !target.isAlive || target.isRemoved) {
showUntil = 0L
shownSince = 0L
trackedEntity = null
randomTexture = null
return@handler
}

val worldPos = target.interpolateCurrentPosition(event.tickDelta)
.add(0.0, target.bbHeight.toDouble() * heightFraction, 0.0)
val screenPos = WorldToScreen.calculateScreenPos(worldPos) ?: return@handler

val size = iconSize.toFloat()
val x0 = screenPos.x + offsetX - size * 0.5f
val y0 = screenPos.y + offsetY - size * 0.5f

event.context.drawTexQuad(
textureSetup = texture.textureSetup,
x0 = x0, y0 = y0,
x1 = x0 + size, y1 = y0 + size,
u1 = 0f, v1 = 0f,
u2 = 1f, v2 = 1f,
argb = Color4b(255, 255, 255, 255).argb,
pipeline = ClientRenderPipelines.GUI.TexQuadNoCull,
)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* This file is part of LiquidBounce (https://github.com/CCBlueX/LiquidBounce)
*
* Copyright (c) 2015 - 2026 CCBlueX
*
* LiquidBounce is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LiquidBounce is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LiquidBounce. If not, see <https://www.gnu.org/licenses/>.
*/
package net.ccbluex.liquidbounce.features.module.modules.render.targeticon

import net.ccbluex.liquidbounce.LiquidBounce
import net.ccbluex.liquidbounce.config.utils.TextureMode
import net.ccbluex.liquidbounce.utils.render.asTexture
import net.ccbluex.liquidbounce.utils.render.readNativeImage
import net.minecraft.client.renderer.texture.DynamicTexture

@Suppress("unused")
enum class TargetIconRegistry(
override val tag: String,
hasTexture: Boolean = true,
) : TextureMode.Builtin.Preset {
NONE("None", false),
WEARY("Weary"),
ANGRY("Angry"),
SUNGLASSES("Sunglasses"),
VOMIT("Vomit"),
HEART("Heart"),
TUNG("Tung"),
BOYKISSER("Boykisser"),
EATSUKI("Eatsuki"),
CAT("Cat"),
SUNNA("Sunna");

override val texture: DynamicTexture? = if (hasTexture) {
LiquidBounce.resource("images/${name.lowercase()}.png")
.readNativeImage()
.asTexture { "TargetIcon: $tag" }
} else {
null
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/main/resources/resources/liquidbounce/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,7 @@
"liquidbounce.module.snapTap.description": "Prioritize the last pressed movement key.",
"liquidbounce.module.scaffold.description": "Automatically places blocks beneath your feet allowing you to walk across gaps.",
"liquidbounce.module.serverCrasher.description": "Attempts to crash the server by exploiting known bugs.",
"liquidbounce.module.targetIcon.description": "Render a Image when attacking someone.",
"liquidbounce.module.serverCrasher.messages.singleplayer": "Server Crasher is intended for multiplayer servers only.",
"liquidbounce.module.serverCrasher.messages.signExploit.missingProtocolTranslator": "ViaFabricPlus is required for this exploit to work.",
"liquidbounce.module.serverCrasher.messages.signExploit.wrongProtocolVersion": "Select 1.8 as protocol version for this exploit to work.",
Expand Down