From 8e2d5c04573a3f57c9200786a039ecc73ad78863 Mon Sep 17 00:00:00 2001 From: Empa <42304516+ItsEmpa@users.noreply.github.com> Date: Mon, 13 May 2024 18:05:40 +0200 Subject: Fix: Incomplete Scoreboard Lines (#1761) Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com> --- .../gui/customscoreboard/ScoreboardElements.kt | 51 +++++++++++++--------- .../gui/customscoreboard/ScoreboardPattern.kt | 4 -- .../gui/customscoreboard/UnknownLinesHandler.kt | 37 ++++++++++++---- .../hannibal2/skyhanni/utils/TimeLimitedCache.kt | 9 +++- .../at/hannibal2/skyhanni/utils/TimeLimitedSet.kt | 7 ++- 5 files changed, 70 insertions(+), 38 deletions(-) (limited to 'src/main/java') 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 18f8a9239..162124aa3 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 @@ -39,11 +39,35 @@ import at.hannibal2.skyhanni.utils.StringUtils.firstLetterUppercase import at.hannibal2.skyhanni.utils.StringUtils.matches 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 import java.util.function.Supplier +import kotlin.time.Duration.Companion.milliseconds + +internal var confirmedUnknownLines = mutableListOf() +internal var unconfirmedUnknownLines = listOf() +internal var unknownLinesSet = TimeLimitedSet(500.milliseconds) { onRemoval(it) } + +private fun onRemoval(line: String) { + if (!unconfirmedUnknownLines.contains(line)) return + unconfirmedUnknownLines = unconfirmedUnknownLines.filterNot { it == line } + confirmedUnknownLines.add(line) + if (!config.unknownLinesWarning) return + val pluralize = pluralize(confirmedUnknownLines.size, "unknown line", withNumber = true) + val message = "CustomScoreboard detected $pluralize" + ErrorManager.logErrorWithData( + CustomScoreboardUtils.UndetectedScoreboardLines(message), + message, + "Unknown Lines" to confirmedUnknownLines, + "Island" to HypixelData.skyBlockIsland, + "Area" to HypixelData.skyBlockArea, + "Full Scoreboard" to ScoreboardData.sidebarLinesFormatted, + noStackTrace = true, + betaOnly = true, + ) +} -internal var unknownLines = listOf() internal var amountOfUnknownLines = 0 enum class ScoreboardElement( @@ -773,30 +797,15 @@ private fun getFooterDisplayPair(): List = ).flatten() private fun getExtraDisplayPair(): List { - if (unknownLines.isEmpty()) return listOf("" to HorizontalAlignment.LEFT) - - val size = unknownLines.size - if (amountOfUnknownLines != size && config.unknownLinesWarning) { - val message = "CustomScoreboard detected ${pluralize(unknownLines.size, "unknown line", withNumber = true)}" - ErrorManager.logErrorWithData( - CustomScoreboardUtils.UndetectedScoreboardLines(message), - message, - "Unknown Lines" to unknownLines, - "Island" to HypixelData.skyBlockIsland, - "Area" to HypixelData.skyBlockArea, - "Full Scoreboard" to ScoreboardData.sidebarLinesFormatted, - noStackTrace = true, - betaOnly = true, - ) - amountOfUnknownLines = size - } + if (confirmedUnknownLines.isEmpty()) return listOf("" to HorizontalAlignment.LEFT) + amountOfUnknownLines = confirmedUnknownLines.size - return listOf("§cUndetected Lines:" to HorizontalAlignment.LEFT) + unknownLines.map { it to HorizontalAlignment.LEFT } + return listOf("§cUndetected Lines:" to HorizontalAlignment.LEFT) + confirmedUnknownLines.map { it to HorizontalAlignment.LEFT } } private fun getExtraShowWhen(): Boolean { - if (unknownLines.isEmpty()) { + if (confirmedUnknownLines.isEmpty()) { amountOfUnknownLines = 0 } - return unknownLines.isNotEmpty() + return confirmedUnknownLines.isNotEmpty() } 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 fdc2232be..84b6446fc 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 @@ -297,10 +297,6 @@ object ScoreboardPattern { "essence", "^\\s*.*Essence: §.(?-?\\d+(:?,\\d{3})*(?:\\.\\d+)?)$" ) - val brokenRedstonePattern by miscSb.pattern( - "brokenredstone", - "\\s*(?:(?:§.)*⚡ (§.)*Redston|e: (?:§.)*\\d+%)\\s*" - ) val redstonePattern by miscSb.pattern( "redstone", "\\s*(§.)*⚡ §cRedstone: (§.)*\\d{1,3}%$" diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/UnknownLinesHandler.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/UnknownLinesHandler.kt index da50f3a21..a5a991cfc 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/UnknownLinesHandler.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/UnknownLinesHandler.kt @@ -5,6 +5,7 @@ import at.hannibal2.skyhanni.data.PurseAPI import at.hannibal2.skyhanni.data.ScoreboardData import at.hannibal2.skyhanni.features.misc.ServerRestartTitle import at.hannibal2.skyhanni.features.rift.area.stillgorechateau.RiftBloodEffigies +import at.hannibal2.skyhanni.utils.ChatUtils import at.hannibal2.skyhanni.utils.CollectionUtils.nextAfter import at.hannibal2.skyhanni.utils.StringUtils.matches import at.hannibal2.skyhanni.utils.StringUtils.removeResets @@ -14,7 +15,7 @@ object UnknownLinesHandler { fun handleUnknownLines() { val sidebarLines = ScoreboardData.sidebarLinesFormatted - unknownLines = sidebarLines + unconfirmedUnknownLines = sidebarLines .map { it.removeResets() } .filter { it.isNotBlank() } .filter { it.trim().length > 3 } @@ -86,7 +87,6 @@ object UnknownLinesHandler { SbPattern.bossDamagePattern, SbPattern.slayerQuestPattern, SbPattern.essencePattern, - SbPattern.brokenRedstonePattern, SbPattern.redstonePattern, SbPattern.visitingPattern, SbPattern.flightDurationPattern, @@ -123,7 +123,7 @@ object UnknownLinesHandler { SbPattern.cluesPattern, ) - unknownLines = unknownLines.filterNot { line -> + unconfirmedUnknownLines = unconfirmedUnknownLines.filterNot { line -> patternsToExclude.any { pattern -> pattern.matches(line) } } @@ -134,16 +134,16 @@ object UnknownLinesHandler { val objectiveLine = sidebarLines.firstOrNull { SbPattern.objectivePattern.matches(it) } ?: "Objective" - unknownLines = unknownLines.filter { sidebarLines.nextAfter(objectiveLine) != it } + unconfirmedUnknownLines = unconfirmedUnknownLines.filter { sidebarLines.nextAfter(objectiveLine) != it } // TODO create function - unknownLines = unknownLines.filter { + unconfirmedUnknownLines = unconfirmedUnknownLines.filter { sidebarLines.nextAfter(objectiveLine, 2) != it && !SbPattern.thirdObjectiveLinePattern.matches(it) } // Remove jacobs contest for (i in 1..3) - unknownLines = unknownLines.filter { + unconfirmedUnknownLines = unconfirmedUnknownLines.filter { sidebarLines.nextAfter(sidebarLines.firstOrNull { line -> SbPattern.jacobsContestPattern.matches(line) } ?: "§eJacob's Contest", i) != it @@ -151,24 +151,43 @@ object UnknownLinesHandler { // Remove slayer for (i in 1..2) - unknownLines = unknownLines.filter { + unconfirmedUnknownLines = unconfirmedUnknownLines.filter { sidebarLines.nextAfter(sidebarLines.firstOrNull { line -> SbPattern.slayerQuestPattern.matches(line) } ?: "Slayer Quest", i) != it } // remove trapper mob location - unknownLines = unknownLines.filter { + unconfirmedUnknownLines = unconfirmedUnknownLines.filter { sidebarLines.nextAfter(sidebarLines.firstOrNull { line -> SbPattern.mobLocationPattern.matches(line) } ?: "Tracker Mob Location:") != it } // da - unknownLines = unknownLines.filter { + unconfirmedUnknownLines = unconfirmedUnknownLines.filter { sidebarLines.nextAfter(sidebarLines.firstOrNull { line -> SbPattern.darkAuctionCurrentItemPattern.matches(line) } ?: "Current Item:") != it } + + + /* + * handle broken scoreboard lines + */ + confirmedUnknownLines.forEach { line -> + if (!unconfirmedUnknownLines.contains(line)) { + confirmedUnknownLines = confirmedUnknownLines.filterNot { it == line }.toMutableList() + unconfirmedUnknownLines = unconfirmedUnknownLines.filterNot { it == line } + } + } + unconfirmedUnknownLines.forEach { line -> + if (confirmedUnknownLines.contains(line)) { + unconfirmedUnknownLines = unconfirmedUnknownLines.filterNot { it == line } + } else if (!unknownLinesSet.contains(line)) { + ChatUtils.debug("Unknown Scoreboard line: '$line'") + unknownLinesSet.add(line) + } + } } } diff --git a/src/main/java/at/hannibal2/skyhanni/utils/TimeLimitedCache.kt b/src/main/java/at/hannibal2/skyhanni/utils/TimeLimitedCache.kt index d903ada07..8b4b0c372 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/TimeLimitedCache.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/TimeLimitedCache.kt @@ -4,10 +4,15 @@ import com.google.common.cache.CacheBuilder import java.util.concurrent.TimeUnit import kotlin.time.Duration -class TimeLimitedCache(expireAfterWrite: Duration) { +class TimeLimitedCache( + expireAfterWrite: Duration, + private val removalListener: (K?, V?) -> Unit = { _, _ -> }, +) { private val cache = CacheBuilder.newBuilder() - .expireAfterWrite(expireAfterWrite.inWholeMilliseconds, TimeUnit.MILLISECONDS).build() + .expireAfterWrite(expireAfterWrite.inWholeMilliseconds, TimeUnit.MILLISECONDS) + .removalListener { removalListener(it.key, it.value) } + .build() fun put(key: K, value: V) = cache.put(key, value) diff --git a/src/main/java/at/hannibal2/skyhanni/utils/TimeLimitedSet.kt b/src/main/java/at/hannibal2/skyhanni/utils/TimeLimitedSet.kt index 39dac5247..5f0ccd404 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/TimeLimitedSet.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/TimeLimitedSet.kt @@ -2,9 +2,12 @@ package at.hannibal2.skyhanni.utils import kotlin.time.Duration -class TimeLimitedSet(expireAfterWrite: Duration) { +class TimeLimitedSet( + expireAfterWrite: Duration, + private val removalListener: (T) -> Unit = {}, +) { - private val cache = TimeLimitedCache(expireAfterWrite) + private val cache = TimeLimitedCache(expireAfterWrite) { key, _ -> key?.let { removalListener(it) } } fun add(element: T) = cache.put(element, Unit) -- cgit