diff --git a/src/main/kotlin/net/skymoe/enchaddons/feature/awesomemap/AwesomeMapConfig.kt b/src/main/kotlin/net/skymoe/enchaddons/feature/awesomemap/AwesomeMapConfig.kt index 4cb2121..a5a42a1 100644 --- a/src/main/kotlin/net/skymoe/enchaddons/feature/awesomemap/AwesomeMapConfig.kt +++ b/src/main/kotlin/net/skymoe/enchaddons/feature/awesomemap/AwesomeMapConfig.kt @@ -15,6 +15,7 @@ interface AwesomeMapConfig : FeatureConfig { val playerHeads: Int val mapVanillaMarker: Boolean val mapVanillaMarkerTeammates: Boolean + val mapPlayerHeadColorBorder: Boolean val mapClip: Boolean val textScale: Float diff --git a/src/main/kotlin/net/skymoe/enchaddons/impl/config/feature/AwesomeMapConfigImpl.kt b/src/main/kotlin/net/skymoe/enchaddons/impl/config/feature/AwesomeMapConfigImpl.kt index 7c60623..c467b51 100644 --- a/src/main/kotlin/net/skymoe/enchaddons/impl/config/feature/AwesomeMapConfigImpl.kt +++ b/src/main/kotlin/net/skymoe/enchaddons/impl/config/feature/AwesomeMapConfigImpl.kt @@ -128,6 +128,14 @@ class AwesomeMapConfigImpl : ) override var mapVanillaMarkerTeammates = false + @Switch( + name = "Head Color Border", + description = "Add color border to player heads", + category = "Map", + subcategory = "Tweaks", + ) + override var mapPlayerHeadColorBorder = false + @Switch( name = "Clip Map", description = "Clip map which out of the HUD region.", @@ -176,6 +184,16 @@ class AwesomeMapConfigImpl : ) var playerHeadRadius = 2.0f + @Slider( + name = "Class Color Border Width", + description = "Width of player heads border.", + category = "Map", + subcategory = "Size", + min = 0F, + max = 2F, + ) + var colorBorderWidth = 1f + @Slider( name = "Player Name Scale", description = "Scale of player names relative to head size.", @@ -446,6 +464,46 @@ class AwesomeMapConfigImpl : ) var colorCheckMarkFailed = OneColor(255, 255, 255) + @Color( + name = "Archer", + category = "Colors", + subcategory = "Class", + allowAlpha = true, + ) + var colorTextArcher = OneColor(255, 170, 0) + + @Color( + name = "Tank", + category = "Colors", + subcategory = "Class", + allowAlpha = true, + ) + var colorTextTank = OneColor(85, 255, 85) + + @Color( + name = "Berserk", + category = "Colors", + subcategory = "Class", + allowAlpha = true, + ) + var colorTextBerserk = OneColor(255, 85, 85) + + @Color( + name = "Mage", + category = "Colors", + subcategory = "Class", + allowAlpha = true, + ) + var colorTextMage = OneColor(85, 255, 255) + + @Color( + name = "Healer", + category = "Colors", + subcategory = "Class", + allowAlpha = true, + ) + var colorTextHealer = OneColor(255, 85, 255) + @Switch( name = "Show Score", description = "Shows separate score element.", diff --git a/src/main/kotlin/net/skymoe/enchaddons/impl/feature/awesomemap/AwesomeMapWidget.kt b/src/main/kotlin/net/skymoe/enchaddons/impl/feature/awesomemap/AwesomeMapWidget.kt index a7f574a..ebdb14e 100644 --- a/src/main/kotlin/net/skymoe/enchaddons/impl/feature/awesomemap/AwesomeMapWidget.kt +++ b/src/main/kotlin/net/skymoe/enchaddons/impl/feature/awesomemap/AwesomeMapWidget.kt @@ -1,8 +1,7 @@ package net.skymoe.enchaddons.impl.feature.awesomemap -import net.minecraft.util.ResourceLocation import net.skymoe.enchaddons.impl.config.feature.AwesomeMapConfigImpl -import net.skymoe.enchaddons.impl.feature.awesomemap.awesomeMapPlayerMarker +import net.skymoe.enchaddons.impl.feature.awesomemap.core.DungeonClass import net.skymoe.enchaddons.impl.feature.awesomemap.core.DungeonPlayer import net.skymoe.enchaddons.impl.feature.awesomemap.core.map.* import net.skymoe.enchaddons.impl.feature.awesomemap.features.dungeon.Dungeon @@ -46,6 +45,21 @@ data class AwesomeMapWidget( private val config: AwesomeMapConfigImpl, private val mapAlpha: Double = 1.0, ) : Widget { + /** + * Maps dungeon class to their corresponding color from config + */ + private fun getClassColor(dungeonClass: DungeonClass): cc.polyfrost.oneconfig.config.core.OneColor = + when (dungeonClass) { + DungeonClass.TANK -> config.colorTextTank + DungeonClass.ARCHER -> config.colorTextArcher + DungeonClass.BERSERK -> config.colorTextBerserk + DungeonClass.MAGE -> config.colorTextMage + DungeonClass.HEALER -> config.colorTextHealer + DungeonClass.UNKNOWN -> + cc.polyfrost.oneconfig.config.core + .OneColor(0, 0, 0) // Black for unknown + } + override fun draw(context: NanoVGUIContext) { val realScale = mapScale context.run { @@ -446,8 +460,25 @@ data class AwesomeMapWidget( ttr size 0.0, ) } else { -// // Render black border around the player head -// renderRectBorder(-6.0, -6.0, 12.0, 12.0, 1.0, Color(0, 0, 0, 255)) + // Draw colored border based on dungeon class when enabled + if (config.mapPlayerHeadColorBorder && !config.mapVanillaMarkerTeammates) { + // Draw border for teammates (not using vanilla marker) + if (!isLocalPlayer || !config.mapVanillaMarker) { + val borderColor = getClassColor(player.dungeonClass) + val borderSize = config.colorBorderWidth.double + nvg.drawRoundedRectBorder( + vg, + ttr posX (-6.0 - borderSize / 2), + ttr posY (-6.0 - borderSize / 2), + ttr size (12.0 + borderSize), + ttr size (12.0 + borderSize), + ttr size borderSize, + ttr size config.playerHeadRadius.double, + borderColor.rgb, + ) + } + } + if (!config.mapVanillaMarkerTeammates || (player.isPlayer && name == MC.thePlayer.name)) { nvg.drawRoundedPlayerAvatar( vg, diff --git a/src/main/kotlin/net/skymoe/enchaddons/impl/feature/awesomemap/core/DungeonClass.kt b/src/main/kotlin/net/skymoe/enchaddons/impl/feature/awesomemap/core/DungeonClass.kt new file mode 100644 index 0000000..99063d7 --- /dev/null +++ b/src/main/kotlin/net/skymoe/enchaddons/impl/feature/awesomemap/core/DungeonClass.kt @@ -0,0 +1,26 @@ +package net.skymoe.enchaddons.impl.feature.awesomemap.core + +enum class DungeonClass( + val code: Char, +) { + TANK('T'), + ARCHER('A'), + BERSERK('B'), + MAGE('M'), + HEALER('H'), + UNKNOWN('?'); + + companion object { + fun fromCode(code: Char): DungeonClass = entries.find { it.code == code } ?: UNKNOWN + fun fromDisplayName(name: String): DungeonClass = + when (name) { + "Tank" -> TANK + "Archer" -> ARCHER + "Berserk" -> BERSERK + "Mage" -> MAGE + "Healer" -> HEALER + else -> UNKNOWN + } + } +} + diff --git a/src/main/kotlin/net/skymoe/enchaddons/impl/feature/awesomemap/core/DungeonPlayer.kt b/src/main/kotlin/net/skymoe/enchaddons/impl/feature/awesomemap/core/DungeonPlayer.kt index 92e85d6..07c31b6 100644 --- a/src/main/kotlin/net/skymoe/enchaddons/impl/feature/awesomemap/core/DungeonPlayer.kt +++ b/src/main/kotlin/net/skymoe/enchaddons/impl/feature/awesomemap/core/DungeonPlayer.kt @@ -10,6 +10,7 @@ import net.skymoe.enchaddons.feature.awesomemap.AwesomeMap import net.skymoe.enchaddons.impl.feature.awesomemap.core.map.Room import net.skymoe.enchaddons.impl.feature.awesomemap.features.dungeon.Dungeon import net.skymoe.enchaddons.impl.feature.awesomemap.utils.APIUtils +import net.skymoe.enchaddons.impl.feature.awesomemap.core.DungeonClass import net.skymoe.enchaddons.impl.feature.awesomemap.utils.Location import net.skymoe.enchaddons.impl.feature.awesomemap.utils.MapUtils import net.skymoe.enchaddons.impl.feature.awesomemap.utils.Utils @@ -26,6 +27,9 @@ data class DungeonPlayer( /** Minecraft formatting code for the player's name */ var colorPrefix = 'f' +/** The player's dungeon class */ + var dungeonClass: DungeonClass = DungeonClass.UNKNOWN + /** The player's name with formatting code */ val formattedName: String get() = "ยง$colorPrefix$name" diff --git a/src/main/kotlin/net/skymoe/enchaddons/impl/feature/awesomemap/features/dungeon/MapUpdate.kt b/src/main/kotlin/net/skymoe/enchaddons/impl/feature/awesomemap/features/dungeon/MapUpdate.kt index 7a39346..ce2a641 100644 --- a/src/main/kotlin/net/skymoe/enchaddons/impl/feature/awesomemap/features/dungeon/MapUpdate.kt +++ b/src/main/kotlin/net/skymoe/enchaddons/impl/feature/awesomemap/features/dungeon/MapUpdate.kt @@ -4,6 +4,7 @@ import net.minecraft.client.network.NetworkPlayerInfo import net.minecraft.init.Blocks import net.minecraft.util.BlockPos import net.minecraft.util.StringUtils +import net.skymoe.enchaddons.impl.feature.awesomemap.core.DungeonClass import net.skymoe.enchaddons.impl.feature.awesomemap.core.DungeonPlayer import net.skymoe.enchaddons.impl.feature.awesomemap.core.map.* import net.skymoe.enchaddons.impl.feature.awesomemap.utils.MapUtils @@ -33,18 +34,45 @@ object MapUpdate { var iconNum = 0 for (i in listOf(5, 9, 13, 17, 1)) { with(tabEntries[i]) { + val strippedEntry = StringUtils.stripControlCodes(second) + val name = StringUtils .stripControlCodes(second) .trim() .substringAfterLast("] ") .split(" ")[0] + if (name != "") { + var dungeonClass = DungeonClass.UNKNOWN + + // Look for class info in parentheses + if (strippedEntry.contains("(") && strippedEntry.contains(")")) { + val parenContent = strippedEntry.substringAfterLast("(").substringBefore(")") + + // Check if it's not EMPTY or DEAD + if (parenContent != "EMPTY" && parenContent != "DEAD") { + // Parse class from format like "Mage XL" or "Tank L" + val classInfo = parenContent.split(" ")[0] + + dungeonClass = + when (classInfo) { + "Tank" -> DungeonClass.TANK + "Archer" -> DungeonClass.ARCHER + "Berserk" -> DungeonClass.BERSERK + "Mage" -> DungeonClass.MAGE + "Healer" -> DungeonClass.HEALER + else -> DungeonClass.UNKNOWN + } + } + } + Dungeon.dungeonTeammates[name] = DungeonPlayer(first.locationSkin, TabList.getPlayerUUIDByName(name)).apply { MC.theWorld.getPlayerEntityByName(name)?.let { setData(it) } colorPrefix = second.substringBefore(name, "f").last() this.name = name + this.dungeonClass = dungeonClass icon = "icon-$iconNum" } iconNum++ @@ -64,6 +92,24 @@ object MapUpdate { if (name == "") continue Dungeon.dungeonTeammates[name]?.run { dead = tabText.contains("(DEAD)") + + // Update class info if it was previously unknown + if (dungeonClass == DungeonClass.UNKNOWN && tabText.contains("(") && tabText.contains(")")) { + val parenContent = tabText.substringAfterLast("(").substringBefore(")") + if (parenContent != "EMPTY" && parenContent != "DEAD") { + val classInfo = parenContent.split(" ")[0] + dungeonClass = + when (classInfo) { + "Tank" -> DungeonClass.TANK + "Archer" -> DungeonClass.ARCHER + "Berserk" -> DungeonClass.BERSERK + "Mage" -> DungeonClass.MAGE + "Healer" -> DungeonClass.HEALER + else -> DungeonClass.UNKNOWN + } + } + } + if (dead) { icon = "" } else { @@ -208,7 +254,9 @@ object MapUpdate { if (unique == null || unique.name.startsWith("Unknown")) { unique = connected .firstOrNull { - (Dungeon.Info.dungeonList[it.second * 11 + it.first] as? Room)?.uniqueRoom?.name?.startsWith("Unknown") == false + (Dungeon.Info.dungeonList[it.second * 11 + it.first] as? Room)?.uniqueRoom?.name?.startsWith( + "Unknown", + ) == false }?.let { (Dungeon.Info.dungeonList[it.second * 11 + it.first] as? Room)?.uniqueRoom } ?: unique diff --git a/src/main/kotlin/net/skymoe/enchaddons/impl/oneconfig/NanoVGAccessor.kt b/src/main/kotlin/net/skymoe/enchaddons/impl/oneconfig/NanoVGAccessor.kt index 9a1c265..a84f478 100644 --- a/src/main/kotlin/net/skymoe/enchaddons/impl/oneconfig/NanoVGAccessor.kt +++ b/src/main/kotlin/net/skymoe/enchaddons/impl/oneconfig/NanoVGAccessor.kt @@ -258,4 +258,15 @@ interface NanoVGAccessor { vg: Long, angle: Double, ) + + fun drawRoundedRectBorder( + vg: Long, + x: Double, + y: Double, + width: Double, + height: Double, + borderWidth: Double, + radius: Double, + color: Int, + ) } diff --git a/src/main/kotlin/net/skymoe/enchaddons/impl/oneconfig/ciallo/NanoVGAccessorImpl.kt b/src/main/kotlin/net/skymoe/enchaddons/impl/oneconfig/ciallo/NanoVGAccessorImpl.kt index 29d07aa..ffa5ca5 100644 --- a/src/main/kotlin/net/skymoe/enchaddons/impl/oneconfig/ciallo/NanoVGAccessorImpl.kt +++ b/src/main/kotlin/net/skymoe/enchaddons/impl/oneconfig/ciallo/NanoVGAccessorImpl.kt @@ -678,4 +678,31 @@ object NanoVGAccessorImpl : NanoVGAccessor { ) { nvgRotate(vg, angle.float) } + + override fun drawRoundedRectBorder( + vg: Long, + x: Double, + y: Double, + width: Double, + height: Double, + borderWidth: Double, + radius: Double, + color: Int, + ) { + withscope { + val nvgColor = NVGColor.calloc().using().fill(color) + nvgBeginPath(vg) + nvgRoundedRect( + vg, + x.float, + y.float, + width.float, + height.float, + radius.float, + ) + nvgStrokeColor(vg, nvgColor) + nvgStrokeWidth(vg, borderWidth.float) + nvgStroke(vg) + } + } }