From 57c1220bc9084b766c554c00636cc8ca89832ee0 Mon Sep 17 00:00:00 2001 From: Empa <42304516+ItsEmpa@users.noreply.github.com> Date: Fri, 23 Aug 2024 09:45:54 +0200 Subject: Feature + Fix: Custom Scoreboard Souflow, Margin, and more (#1837) Co-authored-by: CalMWolfs <94038482+CalMWolfs@users.noreply.github.com> Co-authored-by: Cal Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com> Co-authored-by: ItsEmpa --- .../skyhanni/config/core/config/Position.java | 5 + .../gui/customscoreboard/AlignmentConfig.java | 6 + .../gui/customscoreboard/BackgroundConfig.java | 10 +- .../gui/customscoreboard/DisplayConfig.java | 10 ++ .../at/hannibal2/skyhanni/data/GuiEditManager.kt | 4 +- .../gui/customscoreboard/CustomScoreboard.kt | 32 ++-- .../gui/customscoreboard/CustomScoreboardUtils.kt | 2 +- .../gui/customscoreboard/RenderBackground.kt | 178 ++++++++------------- .../gui/customscoreboard/ScoreboardElements.kt | 86 ++++++---- .../gui/customscoreboard/ScoreboardPattern.kt | 4 + .../java/at/hannibal2/skyhanni/utils/TimeUtils.kt | 7 +- .../skyhanni/utils/renderables/Renderable.kt | 85 ++++++++++ 12 files changed, 264 insertions(+), 165 deletions(-) diff --git a/src/main/java/at/hannibal2/skyhanni/config/core/config/Position.java b/src/main/java/at/hannibal2/skyhanni/config/core/config/Position.java index 140fbf007..16e134574 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/core/config/Position.java +++ b/src/main/java/at/hannibal2/skyhanni/config/core/config/Position.java @@ -115,6 +115,11 @@ public class Position { return y; } + public void moveTo(int x, int y) { + this.x = x; + this.y = y; + } + public void setClicked(boolean state) { this.clicked = state; } diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/AlignmentConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/AlignmentConfig.java index 0b62bfcbc..fec0847f4 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/AlignmentConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/AlignmentConfig.java @@ -4,6 +4,7 @@ import at.hannibal2.skyhanni.utils.RenderUtils.HorizontalAlignment; import at.hannibal2.skyhanni.utils.RenderUtils.VerticalAlignment; import com.google.gson.annotations.Expose; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorDropdown; +import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorSlider; import io.github.notenoughupdates.moulconfig.annotations.ConfigOption; public class AlignmentConfig { @@ -17,4 +18,9 @@ public class AlignmentConfig { @ConfigOption(name = "Vertical Alignment", desc = "Alignment for the scoreboard on the vertical axis.") @ConfigEditorDropdown public VerticalAlignment verticalAlignment = VerticalAlignment.CENTER; + + @Expose + @ConfigOption(name = "Margin", desc = "Space between the border of your screen and the scoreboard.") + @ConfigEditorSlider(minValue = 0, maxValue = 50, minStep = 1) + public int margin = 0; } diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/BackgroundConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/BackgroundConfig.java index 18ffd3c58..be0f5f148 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/BackgroundConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/BackgroundConfig.java @@ -56,12 +56,20 @@ public class BackgroundConfig { @Expose @ConfigOption( - name = "Use Custom Background Image", + name = "Custom Background Image", desc = "Put that image into a resource pack, using the path \"skyhanni/scoreboard.png\"." ) @ConfigEditorBoolean public boolean useCustomBackgroundImage = false; + @Expose + @ConfigOption( + name = "Background Image Opacity", + desc = "The opacity of the custom background image." + ) + @ConfigEditorSlider(minValue = 0, maxValue = 100, minStep = 1) + public int customBackgroundImageOpacity = 100; + @Expose @ConfigOption( name = "Custom Background", diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/DisplayConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/DisplayConfig.java index c9e330b33..e2c6dd6fa 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/DisplayConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/DisplayConfig.java @@ -65,6 +65,11 @@ public class DisplayConfig { @ConfigEditorBoolean public boolean displayNumbersFirst = false; + @Expose + @ConfigOption(name = "Hide coins earned/lost", desc = "Hide the amount of coins earned or lost.") + @ConfigEditorBoolean + public boolean hideCoinsDifference = false; + @Expose @ConfigOption(name = "Show unclaimed bits", desc = "Show the amount of available Bits that can still be claimed.") @ConfigEditorBoolean @@ -119,6 +124,11 @@ public class DisplayConfig { } } + @Expose + @ConfigOption(name = "SkyBlock Time 24h Format", desc = "Display the current SkyBlock time in 24hr format rather than 12h Format.") + @ConfigEditorBoolean + public boolean skyblockTime24hFormat = false; + @Expose @ConfigOption(name = "Line Spacing", desc = "The amount of space between each line.") @ConfigEditorSlider(minValue = 0, maxValue = 20, minStep = 1) diff --git a/src/main/java/at/hannibal2/skyhanni/data/GuiEditManager.kt b/src/main/java/at/hannibal2/skyhanni/data/GuiEditManager.kt index 0f53a3e0c..e6dfa7671 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/GuiEditManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/GuiEditManager.kt @@ -78,14 +78,14 @@ object GuiEditManager { } @JvmStatic - fun add(position: Position, posLabel: String, x: Int, y: Int) { + fun add(position: Position, posLabel: String, width: Int, height: Int) { var name = position.internalName if (name == null) { name = if (posLabel == "none") "none " + UUID.randomUUID() else posLabel position.internalName = name } currentPositions[name] = position - currentBorderSize[posLabel] = Pair(x, y) + currentBorderSize[posLabel] = Pair(width, height) } private var lastHotkeyReminded = SimpleTimeMark.farPast() diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/CustomScoreboard.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/CustomScoreboard.kt index df8adab37..7c61eade8 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/CustomScoreboard.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/CustomScoreboard.kt @@ -1,20 +1,11 @@ // // TODO LIST // V2 RELEASE -// - Soulflow API // - Bank API (actually maybe not, I like the current design) -// - beacon power -// - skyblock level -// - more bg options (round, blurr, outline) // - countdown events like fishing festival + fiesta when its not on tablist -// - CookieAPI https://discord.com/channels/997079228510117908/1162844830360146080/1195695210433351821 -// - Rng meter display -// - option to hide coins earned +// - improve hide coin difference to also work with bits, motes, etc // - color options in the purse etc lines // - choose the amount of decimal places in shorten nums -// - more anchor points (alignment enums in renderutils) -// - 24h instead of 12h for skyblock time -// - only alert for lines that exist longer than 1s // package at.hannibal2.skyhanni.features.gui.customscoreboard @@ -34,9 +25,10 @@ import at.hannibal2.skyhanni.utils.DelayedRun.runDelayed import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.RenderUtils.HorizontalAlignment import at.hannibal2.skyhanni.utils.RenderUtils.VerticalAlignment -import at.hannibal2.skyhanni.utils.RenderUtils.renderStringsAlignedWidth +import at.hannibal2.skyhanni.utils.RenderUtils.renderRenderable import at.hannibal2.skyhanni.utils.StringUtils.firstLetterUppercase import at.hannibal2.skyhanni.utils.TabListData +import at.hannibal2.skyhanni.utils.renderables.Renderable import com.google.gson.JsonArray import com.google.gson.JsonPrimitive import net.minecraftforge.client.GuiIngameForge @@ -58,19 +50,25 @@ object CustomScoreboard { if (!isEnabled()) return if (display.isEmpty()) return - RenderBackground().renderBackground() - val render = if (!TabListData.fullyLoaded && displayConfig.cacheScoreboardOnIslandSwitch && cache.isNotEmpty()) { cache } else { display } - config.position.renderStringsAlignedWidth( - render, - posLabel = guiName, - extraSpace = displayConfig.lineSpacing - 10, + + val textRenderable = Renderable.verticalContainer( + render.map { Renderable.string(it.first, horizontalAlign = it.second) }, + 0, + horizontalAlign = HorizontalAlignment.CENTER, + verticalAlign = VerticalAlignment.CENTER, ) + + val finalRenderable = RenderBackground.addBackground(textRenderable) + + RenderBackground.updatePosition(finalRenderable) + + config.position.renderRenderable(finalRenderable, posLabel = guiName) } @SubscribeEvent diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/CustomScoreboardUtils.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/CustomScoreboardUtils.kt index d1eaf2abd..99fdc4f3f 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/CustomScoreboardUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/CustomScoreboardUtils.kt @@ -23,7 +23,7 @@ object CustomScoreboardUtils { pattern.matchMatcher(line) { group(group) } - } ?: "0" + } fun getProfileTypeSymbol() = when { HypixelData.ironman -> "§7♲ " diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/RenderBackground.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/RenderBackground.kt index ebbb7fa30..44e5c927c 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/RenderBackground.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/RenderBackground.kt @@ -1,139 +1,97 @@ package at.hannibal2.skyhanni.features.gui.customscoreboard -import at.hannibal2.skyhanni.config.core.config.Position import at.hannibal2.skyhanni.data.GuiEditManager import at.hannibal2.skyhanni.data.GuiEditManager.getAbsX import at.hannibal2.skyhanni.data.GuiEditManager.getAbsY -import at.hannibal2.skyhanni.data.GuiEditManager.getDummySize import at.hannibal2.skyhanni.utils.ColorUtils.toChromaColor import at.hannibal2.skyhanni.utils.RenderUtils +import at.hannibal2.skyhanni.utils.renderables.Renderable import net.minecraft.client.Minecraft import net.minecraft.client.gui.ScaledResolution -import net.minecraft.client.renderer.GlStateManager import net.minecraft.util.ResourceLocation -import org.lwjgl.opengl.GL11 -class RenderBackground { +object RenderBackground { - fun renderBackground() { - val alignmentConfig = CustomScoreboard.alignmentConfig + private val textureLocation by lazy { ResourceLocation("skyhanni", "scoreboard.png") } + + internal fun addBackground(renderable: Renderable): Renderable { val backgroundConfig = CustomScoreboard.backgroundConfig val outlineConfig = backgroundConfig.outline - val position = CustomScoreboard.config.position - val border = backgroundConfig.borderSize - - val x = position.getAbsX() - val y = position.getAbsY() - - val elementWidth = position.getDummySize().x - val elementHeight = position.getDummySize().y - - // Update the position to the alignment options - if ( - alignmentConfig.horizontalAlignment != RenderUtils.HorizontalAlignment.DONT_ALIGN - || alignmentConfig.verticalAlignment != RenderUtils.VerticalAlignment.DONT_ALIGN - ) { - position.set(updatePosition(position)) + val padding = backgroundConfig.borderSize + + if (!backgroundConfig.enabled) return renderable + + val backgroundRenderable = if (backgroundConfig.useCustomBackgroundImage) { + Renderable.drawInsideImage( + renderable, + textureLocation, + (backgroundConfig.customBackgroundImageOpacity * 255) / 100, + padding, + horizontalAlign = RenderUtils.HorizontalAlignment.CENTER, + verticalAlign = RenderUtils.VerticalAlignment.CENTER, + radius = backgroundConfig.roundedCornerSmoothness, + ) + } else { + Renderable.drawInsideRoundedRect( + renderable, + backgroundConfig.color.toChromaColor(), + padding, + backgroundConfig.roundedCornerSmoothness, + 1, + horizontalAlign = RenderUtils.HorizontalAlignment.CENTER, + verticalAlign = RenderUtils.VerticalAlignment.CENTER, + ) } - if (GuiEditManager.isInGui()) return - - GlStateManager.pushMatrix() - - GlStateManager.color(1f, 1f, 1f, 1f) - GL11.glDepthMask(false) - - if (backgroundConfig.enabled) { - if (backgroundConfig.useCustomBackgroundImage) { - val textureLocation = ResourceLocation("skyhanni", "scoreboard.png") - Minecraft.getMinecraft().textureManager.bindTexture(textureLocation) - - RenderUtils.drawRoundTexturedRect( - x - border, - y - border, - elementWidth + border * 3, - elementHeight + border * 2, - GL11.GL_NEAREST, - backgroundConfig.roundedCornerSmoothness, - ) - } else { - RenderUtils.drawRoundRect( - x - border, - y - border, - elementWidth + border * 3, - elementHeight + border * 2, - backgroundConfig.color.toChromaColor().rgb, - backgroundConfig.roundedCornerSmoothness, - ) - } - if (outlineConfig.enabled) { - RenderUtils.drawRoundRectOutline( - x - border, - y - border, - elementWidth + border * 3, - elementHeight + border * 2, - outlineConfig.colorTop.toChromaColor().rgb, - outlineConfig.colorBottom.toChromaColor().rgb, - outlineConfig.thickness, - backgroundConfig.roundedCornerSmoothness, - outlineConfig.blur, - ) - } - } - GL11.glDepthMask(true) - GlStateManager.popMatrix() + return if (outlineConfig.enabled) { + Renderable.drawInsideRoundedRectOutline( + backgroundRenderable, + 0, + backgroundConfig.roundedCornerSmoothness, + 1, + outlineConfig.colorTop.toChromaColor().rgb, + outlineConfig.colorBottom.toChromaColor().rgb, + outlineConfig.thickness, + outlineConfig.blur, + horizontalAlign = RenderUtils.HorizontalAlignment.CENTER, + verticalAlign = RenderUtils.VerticalAlignment.CENTER, + ) + } else backgroundRenderable } - private fun updatePosition(position: Position): Position { + internal fun updatePosition(renderable: Renderable) { + if (GuiEditManager.isInGui()) return val alignmentConfig = CustomScoreboard.alignmentConfig - val backgroundConfig = CustomScoreboard.backgroundConfig - val outlineConfig = backgroundConfig.outline - val border = backgroundConfig.borderSize - val x = position.getAbsX() - val y = position.getAbsY() + with(alignmentConfig) { + if (horizontalAlignment == RenderUtils.HorizontalAlignment.DONT_ALIGN && + verticalAlignment == RenderUtils.VerticalAlignment.DONT_ALIGN + ) return + } - val elementWidth = position.getDummySize().x - val elementHeight = position.getDummySize().y + val position = CustomScoreboard.config.position val scaledWidth = ScaledResolution(Minecraft.getMinecraft()).scaledWidth val scaledHeight = ScaledResolution(Minecraft.getMinecraft()).scaledHeight - - - var newX = when (alignmentConfig.horizontalAlignment) { - RenderUtils.HorizontalAlignment.LEFT -> border - RenderUtils.HorizontalAlignment.CENTER -> scaledWidth / 2 - (elementWidth + border * 3) / 2 - RenderUtils.HorizontalAlignment.RIGHT -> scaledWidth - (elementWidth + border * 2) - else -> x - } - - var newY = when (alignmentConfig.verticalAlignment) { - RenderUtils.VerticalAlignment.TOP -> border - RenderUtils.VerticalAlignment.CENTER -> scaledHeight / 2 - (elementHeight + border * 2) / 2 - RenderUtils.VerticalAlignment.BOTTOM -> scaledHeight - elementHeight - border - else -> y - } - - if (outlineConfig.enabled) { - val thickness = outlineConfig.thickness - if (alignmentConfig.horizontalAlignment == RenderUtils.HorizontalAlignment.RIGHT) { - newX -= thickness / 2 - } else if (alignmentConfig.horizontalAlignment == RenderUtils.HorizontalAlignment.LEFT) { - newX += thickness / 2 + val elementWidth = renderable.width + val elementHeight = renderable.height + + with(alignmentConfig) { + val x = when (horizontalAlignment) { + RenderUtils.HorizontalAlignment.DONT_ALIGN -> position.getAbsX() + RenderUtils.HorizontalAlignment.LEFT -> 0 + margin + RenderUtils.HorizontalAlignment.CENTER -> scaledWidth / 2 - elementWidth / 2 + RenderUtils.HorizontalAlignment.RIGHT -> scaledWidth - elementWidth - margin + else -> 0 } - - if (alignmentConfig.verticalAlignment == RenderUtils.VerticalAlignment.TOP) { - newY += thickness / 2 - } else if (alignmentConfig.verticalAlignment == RenderUtils.VerticalAlignment.BOTTOM) { - newY -= thickness / 2 + val y = when (verticalAlignment) { + RenderUtils.VerticalAlignment.DONT_ALIGN -> position.getAbsY() + RenderUtils.VerticalAlignment.TOP -> 0 + margin + RenderUtils.VerticalAlignment.CENTER -> scaledHeight / 2 - elementHeight / 2 + RenderUtils.VerticalAlignment.BOTTOM -> scaledHeight - elementHeight - margin + else -> 0 } + CustomScoreboard.config.position.moveTo(x, y) } - - return Position( - newX, - newY, - position.getScale(), - position.isCenter, - ) } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardElements.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardElements.kt index 7c9757da2..57376dbbb 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardElements.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardElements.kt @@ -11,6 +11,7 @@ import at.hannibal2.skyhanni.data.IslandType import at.hannibal2.skyhanni.data.MaxwellAPI import at.hannibal2.skyhanni.data.MayorAPI import at.hannibal2.skyhanni.data.MiningAPI +import at.hannibal2.skyhanni.data.MiningAPI.inGlaciteArea import at.hannibal2.skyhanni.data.PartyAPI import at.hannibal2.skyhanni.data.PurseAPI import at.hannibal2.skyhanni.data.QuiverAPI @@ -52,6 +53,7 @@ import at.hannibal2.skyhanni.utils.RenderUtils.HorizontalAlignment import at.hannibal2.skyhanni.utils.SkyBlockTime import at.hannibal2.skyhanni.utils.StringUtils.firstLetterUppercase import at.hannibal2.skyhanni.utils.StringUtils.pluralize +import at.hannibal2.skyhanni.utils.TabListData import at.hannibal2.skyhanni.utils.TimeLimitedSet import at.hannibal2.skyhanni.utils.TimeUtils.format import at.hannibal2.skyhanni.utils.TimeUtils.formatted @@ -147,9 +149,15 @@ enum class ScoreboardElement( ::shouldShowChunkedStats, "§652,763,737 §7| §d64,647 §7| §6249M\n§b59,264 §7| §c23,495 §7| §a57,873\n§c♨ 0 §7| §b0❄ §7| §d756", ), + SOULFLOW( + ::getSoulflowDisplayPair, + ::getSoulflowDisplayWhen, + "Soulflow: §3761", + ), EMPTY_LINE( ::getEmptyLineDisplayPair, - { true }, "", + { true }, + "", ), ISLAND( ::getIslandDisplayPair, @@ -203,7 +211,8 @@ enum class ScoreboardElement( ), EMPTY_LINE2( ::getEmptyLineDisplayPair, - { true }, "", + { true }, + "", ), OBJECTIVE( ::getObjectiveDisplayPair, @@ -363,16 +372,17 @@ private fun getTitleDisplayPair(): List = ).flatten() } -private fun getProfileDisplayPair() = - listOf(CustomScoreboardUtils.getProfileTypeSymbol() + HypixelData.profileName.firstLetterUppercase() to HorizontalAlignment.LEFT) +private fun getProfileDisplayPair() = listOf( + CustomScoreboardUtils.getProfileTypeSymbol() + HypixelData.profileName.firstLetterUppercase() + to HorizontalAlignment.LEFT, +) private fun getPurseDisplayPair(): List { var purse = PurseAPI.currentPurse.formatNum() - val earned = getGroupFromPattern(ScoreboardData.sidebarLinesFormatted, PurseAPI.coinsPattern, "earned") - - if (earned != "0") { - purse += " §7(§e+$earned§7)§6" + if (!displayConfig.hideCoinsDifference) { + val earned = getGroupFromPattern(ScoreboardData.sidebarLinesFormatted, PurseAPI.coinsPattern, "earned") + if (earned != null) purse += " §7(§e+$earned§7)§6" } return listOf( @@ -387,7 +397,7 @@ private fun getPurseDisplayPair(): List { private fun getPurseShowWhen() = !inAnyIsland(IslandType.THE_RIFT) private fun getMotesDisplayPair(): List { - val motes = getMotes().formatNum() + val motes = getMotes()?.formatNum() ?: "0" return listOf( when { @@ -434,7 +444,7 @@ private fun getBitsDisplayPair(): List { private fun getBitsShowWhen() = !HypixelData.bingo && !inAnyIsland(IslandType.CATACOMBS, IslandType.KUUDRA_ARENA) private fun getCopperDisplayPair(): List { - val copper = getCopper().formatNum() + val copper = getCopper()?.formatNum() ?: "0" return listOf( when { @@ -467,8 +477,8 @@ private fun getHeatDisplayPair(): List { return listOf( when { informationFilteringConfig.hideEmptyLines && heat == "§c♨ 0" -> "" - displayConfig.displayNumbersFirst/* && heat != "§6IMMUNE" */ -> if (heat == "0") "§c♨ 0 Heat" else "$heat Heat" - else -> if (heat == "0") "Heat: §c♨ 0" else "Heat: $heat" + displayConfig.displayNumbersFirst -> heat?.let { "$heat Heat" } ?: "§c♨ 0 Heat" + else -> heat?.let { "Heat: $heat" } ?: "§c♨ 0 Heat" } to HorizontalAlignment.LEFT, ) } @@ -488,11 +498,11 @@ private fun getColdDisplayPair(): List { ) } -private fun getColdShowWhen() = inAnyIsland(IslandType.DWARVEN_MINES, IslandType.MINESHAFT) - && ScoreboardData.sidebarLinesFormatted.any { ScoreboardPattern.coldPattern.matches(it) } +private fun getColdShowWhen() = inAnyIsland(IslandType.DWARVEN_MINES, IslandType.MINESHAFT) && + ScoreboardData.sidebarLinesFormatted.any { ScoreboardPattern.coldPattern.matches(it) } private fun getNorthStarsDisplayPair(): List { - val northStars = getNorthStars().formatNum() + val northStars = getNorthStars()?.formatNum() ?: "0" return listOf( when { @@ -510,6 +520,20 @@ private fun getChunkedStatsDisplayPair(): List = .chunked(chunkedConfig.maxStatsPerLine) .map { it.joinToString(" §f| ") to HorizontalAlignment.LEFT } +private fun getSoulflowDisplayPair(): List { + val soulflow = getGroupFromPattern(TabListData.getTabList(), ScoreboardPattern.soulflowPattern, "soulflow") + ?.formatNum() ?: "0" + return listOf( + when { + informationFilteringConfig.hideEmptyLines && soulflow == "0" -> "" + displayConfig.displayNumbersFirst -> "§3$soulflow Soulflow" + else -> "Soulflow: §3$soulflow" + } to HorizontalAlignment.LEFT, + ) +} + +private fun getSoulflowDisplayWhen() = !inAnyIsland(IslandType.THE_RIFT) + private fun getEmptyLineDisplayPair() = listOf("" to HorizontalAlignment.LEFT) private fun getIslandDisplayPair() = @@ -536,7 +560,8 @@ fun getPlayerAmountDisplayPair() = buildList { private fun getVisitDisplayPair() = listOf( - ScoreboardData.sidebarLinesFormatted.first { ScoreboardPattern.visitingPattern.matches(it) } to HorizontalAlignment.LEFT, + ScoreboardData.sidebarLinesFormatted.first { ScoreboardPattern.visitingPattern.matches(it) } to + HorizontalAlignment.LEFT, ) private fun getVisitShowWhen() = @@ -548,11 +573,12 @@ private fun getDateDisplayPair() = ) private fun getTimeDisplayPair(): List { - var symbol = getGroupFromPattern(ScoreboardData.sidebarLinesFormatted, ScoreboardPattern.timePattern, "symbol") - if (symbol == "0") symbol = "" + val symbol = + getGroupFromPattern(ScoreboardData.sidebarLinesFormatted, ScoreboardPattern.timePattern, "symbol") ?: "" return listOf( "§7" + SkyBlockTime.now() - .formatted(dayAndMonthElement = false, yearElement = false) + " $symbol" to HorizontalAlignment.LEFT, + .formatted(dayAndMonthElement = false, yearElement = false, timeFormat24h = config.display.skyblockTime24hFormat) + + " $symbol" to HorizontalAlignment.LEFT, ) } @@ -668,14 +694,14 @@ private fun getQuiverDisplayPair(): List { if (QuiverAPI.currentArrow == NONE_ARROW_TYPE) return listOf("No Arrows selected" to HorizontalAlignment.LEFT) - val amountString = (if (arrowConfig.colorArrowAmount) { - percentageColor( - QuiverAPI.currentAmount.toLong(), - QuiverAPI.MAX_ARROW_AMOUNT.toLong(), - ).getChatColor() - } else { - "" - }) + if (QuiverAPI.wearingSkeletonMasterChestplate) { + val amountString = ( + if (arrowConfig.colorArrowAmount) { + percentageColor( + QuiverAPI.currentAmount.toLong(), + QuiverAPI.MAX_ARROW_AMOUNT.toLong(), + ).getChatColor() + } else "" + ) + if (QuiverAPI.wearingSkeletonMasterChestplate) { "∞" } else { when (arrowConfig.arrowAmountDisplay) { @@ -809,11 +835,7 @@ private fun getPartyShowWhen() = if (DungeonAPI.inDungeon()) { if (partyConfig.showPartyEverywhere) { true } else { - inAnyIsland( - IslandType.DUNGEON_HUB, - IslandType.KUUDRA_ARENA, - IslandType.CRIMSON_ISLE, - ) + inAnyIsland(IslandType.DUNGEON_HUB, IslandType.KUUDRA_ARENA, IslandType.CRIMSON_ISLE) || inGlaciteArea() } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardPattern.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardPattern.kt index 2101409d1..126331ff2 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardPattern.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardPattern.kt @@ -570,6 +570,10 @@ object ScoreboardPattern { "bank", "^\\s*Bank: §6(?[\\w.,]+(?:§7 \\/ §6(?[\\w.,]+))?)$", ) + val soulflowPattern by tablistGroup.pattern( + "soulflow", + "^\\s*Soulflow: (?:§.)+(?[\\d,.]+)$", + ) val eventNamePattern by tablistGroup.pattern( "event", "^\\s*§e§lEvent: §r(?§.*)$", diff --git a/src/main/java/at/hannibal2/skyhanni/utils/TimeUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/TimeUtils.kt index dcb6dcc93..4d7b7ad4d 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/TimeUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/TimeUtils.kt @@ -104,9 +104,12 @@ object TimeUtils { dayAndMonthElement: Boolean = true, yearElement: Boolean = true, hoursAndMinutesElement: Boolean = true, + timeFormat24h: Boolean = false, ): String { - val hour = (this.hour + 11) % 12 + 1 - val timeOfDay = if (this.hour > 11) "pm" else "am" + val hour = if (timeFormat24h) this.hour else (this.hour + 11) % 12 + 1 + val timeOfDay = if (!timeFormat24h) { + if (this.hour > 11) "pm" else "am" + } else "" val minute = this.minute.toString().padStart(2, '0') val month = SkyBlockTime.monthName(this.month) val day = this.day diff --git a/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt b/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt index 7a6fbce4b..29105459c 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt @@ -28,6 +28,7 @@ import at.hannibal2.skyhanni.utils.renderables.RenderableUtils.renderXAligned import at.hannibal2.skyhanni.utils.renderables.RenderableUtils.renderXYAligned import at.hannibal2.skyhanni.utils.renderables.RenderableUtils.renderYAligned import at.hannibal2.skyhanni.utils.shader.ShaderManager +import io.github.moulberry.notenoughupdates.util.Utils import io.github.notenoughupdates.moulconfig.gui.GuiScreenElementWrapper import net.minecraft.client.Minecraft import net.minecraft.client.gui.Gui @@ -38,6 +39,7 @@ import net.minecraft.client.renderer.GlStateManager import net.minecraft.entity.player.EntityPlayer import net.minecraft.item.ItemStack import net.minecraft.util.ResourceLocation +import org.lwjgl.opengl.GL11 import java.awt.Color import java.util.Collections import kotlin.math.max @@ -907,6 +909,89 @@ interface Renderable { } } + fun drawInsideRoundedRectOutline( + input: Renderable, + padding: Int = 2, + radius: Int = 10, + smoothness: Int = 2, + topOutlineColor: Int, + bottomOutlineColor: Int, + borderOutlineThickness: Int, + blur: Float = 0.7f, + horizontalAlign: HorizontalAlignment = HorizontalAlignment.LEFT, + verticalAlign: VerticalAlignment = VerticalAlignment.TOP, + ) = object : Renderable { + override val width = input.width + padding * 2 + override val height = input.height + padding * 2 + override val horizontalAlign = horizontalAlign + override val verticalAlign = verticalAlign + + override fun render(posX: Int, posY: Int) { + GlStateManager.translate(padding.toFloat(), padding.toFloat(), 0f) + input.render(posX + padding, posY + padding) + GlStateManager.translate(-padding.toFloat(), -padding.toFloat(), 0f) + + RenderUtils.drawRoundRectOutline( + 0, + 0, + width, + height, + topOutlineColor, + bottomOutlineColor, + borderOutlineThickness, + radius, + blur, + ) + } + } + + fun drawInsideImage( + input: Renderable, + texture: ResourceLocation, + alpha: Int = 255, + padding: Int = 2, + horizontalAlign: HorizontalAlignment = HorizontalAlignment.LEFT, + verticalAlign: VerticalAlignment = VerticalAlignment.TOP, + radius: Int = 0, + ) = object : Renderable { + override val width = input.width + padding * 2 + override val height = input.height + padding * 2 + override val horizontalAlign = horizontalAlign + override val verticalAlign = verticalAlign + + override fun render(posX: Int, posY: Int) { + Minecraft.getMinecraft().textureManager.bindTexture(texture) + GlStateManager.color(1f, 1f, 1f, alpha / 255f) + RenderUtils.drawRoundTexturedRect(0, 0, width, height, GL11.GL_NEAREST, radius) + GlStateManager.color(1f, 1f, 1f, 1f) + + GlStateManager.translate(padding.toFloat(), padding.toFloat(), 0f) + input.render(posX + padding, posY + padding) + GlStateManager.translate(-padding.toFloat(), -padding.toFloat(), 0f) + } + } + + fun image( + texture: ResourceLocation, + width: Int, + height: Int, + alpha: Int = 255, + horizontalAlign: HorizontalAlignment = HorizontalAlignment.LEFT, + verticalAlign: VerticalAlignment = VerticalAlignment.TOP, + ) = object : Renderable { + override val width = width + override val height = height + override val horizontalAlign = horizontalAlign + override val verticalAlign = verticalAlign + + override fun render(posX: Int, posY: Int) { + Minecraft.getMinecraft().textureManager.bindTexture(texture) + GlStateManager.color(1f, 1f, 1f, alpha / 255f) + Utils.drawTexturedRect(0f, 0f, width.toFloat(), height.toFloat(), GL11.GL_NEAREST) + GlStateManager.color(1f, 1f, 1f, 1f) + } + } + fun drawInsideRoundedRectWithOutline( input: Renderable, color: Color, -- cgit