Skip to content

Custom highlight color #149

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
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
43 changes: 35 additions & 8 deletions src/main/kotlin/me/odinmain/commands/impl/HighlightCommand.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,46 @@ package me.odinmain.commands.impl
import com.github.stivais.commodore.Commodore
import com.github.stivais.commodore.utils.GreedyString
import me.odinmain.config.Config
import me.odinmain.features.impl.render.CustomHighlight.currentEntities
import me.odinmain.features.impl.render.CustomHighlight.highlightList
import me.odinmain.utils.render.Color
import me.odinmain.utils.skyblock.modMessage

@OptIn(ExperimentalStdlibApi::class)
val highlightCommand = Commodore("highlight") {
literal("add").runs { mob: GreedyString ->
val lowercase = mob.string.lowercase()
if (lowercase in highlightList) return@runs modMessage("$mob is already in the highlight list.")
val colorRegex = Regex("^(.*?)(?:\\s+#?([0-9a-fA-F]{6}|[0-9a-fA-F]{8}))?$")

literal("add").runs { input: GreedyString ->
val inputString = input.string.trim()
val matchResult = colorRegex.matchEntire(inputString) ?: return@runs modMessage("Invalid format. Use: /highlight add <mob name> [#hexcolor]")

val (mobName, colorCode) = matchResult.destructured
val mobNameTrimmed = mobName.trim()
val lowercase = mobNameTrimmed.lowercase()

if (mobNameTrimmed.isEmpty()) return@runs modMessage("Mob name cannot be empty.")

if (highlightList.any { it.key == lowercase }) return@runs modMessage("$mobNameTrimmed is already in the highlight list.")

if (colorCode.isNotEmpty() && !Regex("^[0-9a-fA-F]{6}|[0-9a-fA-F]{8}$").matches(colorCode)) return@runs modMessage("Invalid color format. Use #RRGGBB or #RRGGBBAA.")

val color = if (colorCode.isNotEmpty()) {
try {
Color(colorCode.padEnd(8, 'f'))
} catch (e: Exception) {
modMessage("Invalid color format. Use #RRGGBB or #RRGGBBAA.")
null
}
} else null

modMessage("Added $mob to the highlight list.")
highlightList.add(lowercase)
highlightList[lowercase] = color
modMessage("Added $mobNameTrimmed to the highlight list${if (colorCode.isNotEmpty()) " with color #$colorCode" else ""}.")
Config.save()
}

literal("remove").runs { mob: GreedyString ->
val lowercase = mob.string.lowercase()
if (lowercase !in highlightList) return@runs modMessage("$mob isn't in the highlight list.")
if (highlightList.none { it.key == lowercase }) return@runs modMessage("$mob isn't in the highlight list.")

modMessage("Removed $mob from the highlight list.")
highlightList.remove(lowercase)
Expand All @@ -28,11 +52,14 @@ val highlightCommand = Commodore("highlight") {
literal("clear").runs {
modMessage("Highlight list cleared.")
highlightList.clear()
currentEntities.clear()
Config.save()
}

literal("list").runs {
if (highlightList.isEmpty()) return@runs modMessage("Highlight list is empty")
modMessage("Highlight list:\n${highlightList.joinToString("\n")}")
modMessage("Highlight list:\n${highlightList.entries.joinToString("\n") {
"${it.key} - ${it.value?.rgba?.toHexString() ?: "default color"}"
}}")
}
}
}
31 changes: 19 additions & 12 deletions src/main/kotlin/me/odinmain/features/impl/render/CustomHighlight.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ import me.odinmain.features.settings.Setting.Companion.withDependency
import me.odinmain.features.settings.impl.*
import me.odinmain.ui.clickgui.util.ColorUtil.withAlpha
import me.odinmain.utils.isOtherPlayer
import me.odinmain.utils.render.Color
import me.odinmain.utils.render.HighlightRenderer
import me.odinmain.utils.render.Renderer
import me.odinmain.utils.render.*
import me.odinmain.utils.skyblock.dungeon.DungeonUtils
import net.minecraft.client.entity.EntityOtherPlayerMP
import net.minecraft.entity.Entity
Expand All @@ -34,9 +32,9 @@ object CustomHighlight : Module(
private val xray by BooleanSetting("Depth Check", false, description = "Highlights entities through walls.").withDependency { !isLegitVersion }
private val showInvisible by BooleanSetting("Show Invisible", false, description = "Highlights invisible entities.").withDependency { !isLegitVersion }

val highlightList: MutableList<String> by ListSetting("List", mutableListOf())
val highlightList: MutableMap<String, Color?> by MapSetting("Map", mutableMapOf(), "")
private inline val depthCheck get() = if (isLegitVersion) true else xray
private var currentEntities = mutableSetOf<Entity>()
val currentEntities = mutableSetOf<HighlightEntity>()

init {
execute({ scanDelay }) {
Expand All @@ -49,7 +47,9 @@ object CustomHighlight : Module(

HighlightRenderer.addEntityGetter({ HighlightRenderer.HighlightType.entries[mode]}) {
if (!enabled) emptyList()
else currentEntities.map { HighlightRenderer.HighlightEntity(it, color, thickness, depthCheck, style) }
else currentEntities.map {
HighlightRenderer.HighlightEntity(it.entity, it.color, thickness, depthCheck, style)
}
}
}

Expand All @@ -58,28 +58,35 @@ object CustomHighlight : Module(
checkEntity(entity)
if (starredMobESP) checkStarred(entity)
if (shadowAssassin && !isLegitVersion) checkAssassin(entity)
if (showInvisible && entity.isInvisible && !isLegitVersion && entity in currentEntities) entity.isInvisible = false
if (showInvisible && entity.isInvisible && !isLegitVersion && currentEntities.any { it.entity == entity }) entity.isInvisible = false
}
}

private fun checkEntity(entity: Entity) {
if (entity !is EntityArmorStand || highlightList.none { entity.name.contains(it, true) } || entity in currentEntities || !entity.alwaysRenderNameTag && !depthCheck) return
currentEntities.add(getMobEntity(entity) ?: return)
if (entity !is EntityArmorStand || highlightList.none { entity.name.contains(it.key, true) } || currentEntities.any { it.entity == entity} || !entity.alwaysRenderNameTag && !depthCheck) return
val highlightColor = getColorFromList(entity.name)
currentEntities.add(HighlightEntity(getMobEntity(entity) ?: return, highlightColor))
}

private fun checkStarred(entity: Entity) {
if (entity !is EntityArmorStand || !entity.name.startsWith("§6✯ ") || !entity.name.endsWith("§c❤") || entity in currentEntities || (!entity.alwaysRenderNameTag && depthCheck)) return
currentEntities.add(getMobEntity(entity) ?: return)
if (entity !is EntityArmorStand || !entity.name.startsWith("§6✯ ") || !entity.name.endsWith("§c❤") || currentEntities.any { it.entity == entity} || (!entity.alwaysRenderNameTag && depthCheck)) return
currentEntities.add(HighlightEntity(getMobEntity(entity) ?: return, color))
}

private fun checkAssassin(entity: Entity) {
if (entity !is EntityOtherPlayerMP || entity.name != "Shadow Assassin") return
currentEntities.add(entity)
currentEntities.add(HighlightEntity(entity, color))
}

private fun getMobEntity(entity: Entity): Entity? {
return mc.theWorld?.getEntitiesWithinAABBExcludingEntity(entity, entity.entityBoundingBox.offset(0.0, -1.0, 0.0))
?.filter { it !is EntityArmorStand && mc.thePlayer != it && !(it is EntityWither && it.isInvisible) && !(it is EntityOtherPlayerMP && it.isOtherPlayer()) }
?.minByOrNull { entity.getDistanceToEntity(it) }
}

private fun getColorFromList(name: String): Color {
return highlightList.entries.firstOrNull { name.contains(it.key, true) }?.value ?: color
}

data class HighlightEntity(val entity: Entity, val color: Color)
}
Loading