From a33034e3bf528999c128aeefda4a77f0799eb9ff Mon Sep 17 00:00:00 2001 From: David Cole <40234707+DavidArthurCole@users.noreply.github.com> Date: Wed, 16 Oct 2024 06:42:40 -0400 Subject: [PATCH 01/26] Feature: Hoppity Purse Blocker (#2664) --- .../hoppity/HoppityCallWarningConfig.java | 11 +++++++ .../event/hoppity/HoppityCallWarning.kt | 30 +++++++++++++++++++ .../skyhanni/utils/HypixelCommands.kt | 4 +++ 3 files changed, 45 insertions(+) diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/event/hoppity/HoppityCallWarningConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/event/hoppity/HoppityCallWarningConfig.java index 6e4ccf027305..0406b268d8b8 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/event/hoppity/HoppityCallWarningConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/event/hoppity/HoppityCallWarningConfig.java @@ -7,6 +7,7 @@ import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorButton; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorColour; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorKeybind; +import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorSlider; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorText; import io.github.notenoughupdates.moulconfig.annotations.ConfigOption; import io.github.notenoughupdates.moulconfig.observer.Property; @@ -44,4 +45,14 @@ public class HoppityCallWarningConfig { @ConfigOption(name = "Sounds", desc = "Click to open the list of available sounds.") @ConfigEditorButton(buttonText = "OPEN") public Runnable sounds = () -> OSUtils.openBrowser("https://www.minecraftforum.net/forums/mapping-and-modding-java-edition/mapping-and-modding-tutorials/2213619-1-8-all-playsound-sound-arguments"); + + @Expose + @ConfigOption(name = "Ensure Coins Pre-Trade", desc = "Block opening Hoppity's abiphone trade menu if you do not have enough coins in your purse.") + @ConfigEditorBoolean + public boolean ensureCoins = true; + + @Expose + @ConfigOption(name = "Coin Threshold", desc = "The amount of coins you need to have in your purse to be able to open Hoppity's abiphone trade menu.") + @ConfigEditorSlider(minValue = 250000, maxValue = 5000000, minStep = 250000) + public int coinThreshold = 5000000; } diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCallWarning.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCallWarning.kt index 57bc0975fac8..92daf50d4280 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCallWarning.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCallWarning.kt @@ -1,18 +1,22 @@ package at.hannibal2.skyhanni.features.event.hoppity +import at.hannibal2.skyhanni.data.PurseAPI import at.hannibal2.skyhanni.events.ConfigLoadEvent import at.hannibal2.skyhanni.events.GuiRenderEvent import at.hannibal2.skyhanni.events.LorenzChatEvent import at.hannibal2.skyhanni.events.LorenzKeyPressEvent +import at.hannibal2.skyhanni.events.MessageSendToServerEvent import at.hannibal2.skyhanni.events.SecondPassedEvent import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryAPI import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.utils.ChatUtils import at.hannibal2.skyhanni.utils.ColorUtils.toChromaColorInt import at.hannibal2.skyhanni.utils.ConditionalUtils import at.hannibal2.skyhanni.utils.DelayedRun import at.hannibal2.skyhanni.utils.HypixelCommands import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.RegexUtils.matches +import at.hannibal2.skyhanni.utils.SimpleTimeMark import at.hannibal2.skyhanni.utils.SoundUtils import at.hannibal2.skyhanni.utils.StringUtils.isValidUuid import net.minecraft.client.Minecraft @@ -59,6 +63,14 @@ object HoppityCallWarning { "§e\\[NPC] §aHoppity§f: §b✆ §f§rWhat's up, .*§f\\?", ) + /** + * REGEX-TEST: /selectnpcoption hoppity r_2_1 + */ + private val pickupOutgoingCommandPattern by ChocolateFactoryAPI.patternGroup.pattern( + "hoppity.call.pickup.outgoing", + "/selectnpcoption hoppity r_2_1", + ) + private val config get() = HoppityEggsManager.config.hoppityCallWarning private var warningSound = SoundUtils.createSound("note.pling", 1f) private var activeWarning = false @@ -66,6 +78,7 @@ object HoppityCallWarning { private var finalWarningTime: Instant? = null private val callLength = 7.seconds private var acceptUUID: String? = null + private var commandSentTimer = SimpleTimeMark.farPast() @SubscribeEvent fun onKeyPress(event: LorenzKeyPressEvent) { @@ -128,6 +141,23 @@ object HoppityCallWarning { GlStateManager.color(1F, 1F, 1F, 1F) } + @SubscribeEvent + fun onCommandSend(event: MessageSendToServerEvent) { + if (!LorenzUtils.inSkyBlock || !config.ensureCoins) return + if (!pickupOutgoingCommandPattern.matches(event.message)) return + if (commandSentTimer.passedSince() < 5.seconds) return + if (PurseAPI.getPurse() >= config.coinThreshold) return + + commandSentTimer = SimpleTimeMark.now() + event.cancel() + ChatUtils.clickToActionOrDisable( + "§cBlocked picking up Hoppity without enough coins!", + config::ensureCoins, + actionName = "open bank menu", + action = { HypixelCommands.bank() }, + ) + } + private fun readPickupUuid(event: LorenzChatEvent) { val siblings = event.chatComponent.siblings.takeIf { it.size >= 3 } ?: return val clickEvent = siblings[2]?.chatStyle?.chatClickEvent ?: return diff --git a/src/main/java/at/hannibal2/skyhanni/utils/HypixelCommands.kt b/src/main/java/at/hannibal2/skyhanni/utils/HypixelCommands.kt index b163a8d393ec..608ba9d8e2ff 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/HypixelCommands.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/HypixelCommands.kt @@ -158,6 +158,10 @@ object HypixelCommands { send("cb $uuid") } + fun bank() { + send("bank") + } + fun pickupStash() { send("pickupstash") } From 359ba9dbb26fd1e31d6620a610093e55056c2739 Mon Sep 17 00:00:00 2001 From: hannibal2 <24389977+hannibal00212@users.noreply.github.com> Date: Wed, 16 Oct 2024 12:44:58 +0200 Subject: [PATCH 02/26] code cleanup --- .../skyhanni/features/event/hoppity/HoppityCallWarning.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCallWarning.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCallWarning.kt index 92daf50d4280..7881af19d3cb 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCallWarning.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCallWarning.kt @@ -68,7 +68,7 @@ object HoppityCallWarning { */ private val pickupOutgoingCommandPattern by ChocolateFactoryAPI.patternGroup.pattern( "hoppity.call.pickup.outgoing", - "/selectnpcoption hoppity r_2_1", + "\\/selectnpcoption hoppity r_2_1", ) private val config get() = HoppityEggsManager.config.hoppityCallWarning @@ -154,6 +154,7 @@ object HoppityCallWarning { "§cBlocked picking up Hoppity without enough coins!", config::ensureCoins, actionName = "open bank menu", + // TODO if no booster cookie active, suggest to warp to hub/path find to bank. ideally into an utils action = { HypixelCommands.bank() }, ) } From 707959f8e3ffacd1b51e615330346404a5033c80 Mon Sep 17 00:00:00 2001 From: David Cole <40234707+DavidArthurCole@users.noreply.github.com> Date: Wed, 16 Oct 2024 06:58:00 -0400 Subject: [PATCH 03/26] Fix: Crash with FlowstateHelperConfig (#2740) --- .idea/dictionaries/default_user.xml | 1 + .../skyhanni/config/features/mining/FlowstateHelperConfig.java | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.idea/dictionaries/default_user.xml b/.idea/dictionaries/default_user.xml index 86cfbc3f33b1..32875a5fbed8 100644 --- a/.idea/dictionaries/default_user.xml +++ b/.idea/dictionaries/default_user.xml @@ -86,6 +86,7 @@ firedust firesale firesales + flowstate framebuffer getfromsacks ghast diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/mining/FlowstateHelperConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/mining/FlowstateHelperConfig.java index 37a0f08aadd4..03f2c01fb0bc 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/mining/FlowstateHelperConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/mining/FlowstateHelperConfig.java @@ -11,6 +11,7 @@ import io.github.notenoughupdates.moulconfig.annotations.ConfigOption; import io.github.notenoughupdates.moulconfig.annotations.SearchTag; +import java.util.ArrayList; import java.util.List; public class FlowstateHelperConfig { @@ -23,7 +24,7 @@ public class FlowstateHelperConfig { @Expose @ConfigOption(name = "Appearance", desc = "Drag text to change the appearance.") @ConfigEditorDraggableList() - public List appearance = FlowstateElements.defaultOption; + public List appearance = new ArrayList<>(FlowstateElements.defaultOption); @Expose @ConfigOption(name = "Dynamic Color", desc = "Makes the timer's color dynamic.") From d8a4d6c37f01364e1cd05b6176acec57f69c2ca2 Mon Sep 17 00:00:00 2001 From: David Cole <40234707+DavidArthurCole@users.noreply.github.com> Date: Wed, 16 Oct 2024 06:59:13 -0400 Subject: [PATCH 04/26] Fix: El Dorado HoppityAPI (#2742) --- .../features/event/hoppity/HoppityAPI.kt | 18 +++++++++++------- .../ChocolateFactoryStrayTracker.kt | 4 ++-- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityAPI.kt index 5e1910d0d1c9..8d3ac22c3e76 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityAPI.kt @@ -16,6 +16,7 @@ import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactor import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryStrayTracker import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryStrayTracker.duplicateDoradoStrayPattern import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryStrayTracker.duplicatePseudoStrayPattern +import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryStrayTracker.formLoreToSingleLine import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.InventoryUtils import at.hannibal2.skyhanni.utils.ItemUtils.getLore @@ -117,16 +118,19 @@ object HoppityAPI { duplicate = it.stack.getLore().any { line -> duplicatePseudoStrayPattern.matches(line) } attemptFireRabbitFound() } - "El Dorado" -> { - EggFoundEvent(STRAY, it.slotNumber).post() - lastName = "§6El Dorado" - lastMeal = STRAY - duplicate = it.stack.getLore().any { line -> duplicateDoradoStrayPattern.matches(line) } - attemptFireRabbitFound() - } else -> return@matchMatcher } } + ChocolateFactoryStrayTracker.strayDoradoPattern.matchMatcher(formLoreToSingleLine(it.stack.getLore())) { + // We don't need to do a handleStrayClicked here - the lore from El Dorado is already: + // §6§lGolden Rabbit §d§lCAUGHT! + // Which will trigger the above matcher. We only need to check name here to fire the found event for Dorado. + EggFoundEvent(STRAY, it.slotNumber).post() + lastName = "§6El Dorado" + lastMeal = STRAY + duplicate = it.stack.getLore().any { line -> duplicateDoradoStrayPattern.matches(line) } + attemptFireRabbitFound() + } } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryStrayTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryStrayTracker.kt index 9c890aa56dc3..80ed140e7827 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryStrayTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryStrayTracker.kt @@ -77,7 +77,7 @@ object ChocolateFactoryStrayTracker { * REGEX-TEST: §7You caught a stray §6§lGolden Rabbit§7! §7You caught §6El Dorado §7- quite the elusive rabbit! * REGEX-TEST: §7You caught a stray §6§lGolden Rabbit§7! §7You caught §6El Dorado§7! Since you §7already have captured him before, §7you gained §6+324,364,585 Chocolate§7. */ - private val strayDoradoPattern by ChocolateFactoryAPI.patternGroup.pattern( + val strayDoradoPattern by ChocolateFactoryAPI.patternGroup.pattern( "stray.dorado", ".*§6El Dorado(?:.*?§6\\+?(?[\\d,]+) Chocolate)?.*", ) @@ -147,7 +147,7 @@ object ChocolateFactoryStrayTracker { var goldenTypesCaught: MutableMap = mutableMapOf() } - private fun formLoreToSingleLine(lore: List): String { + fun formLoreToSingleLine(lore: List): String { val notEmptyLines = lore.filter { it.isNotEmpty() } return notEmptyLines.joinToString(" ") } From 56707dc4f7c2025bd505911c7cfdbdbd0acaaba1 Mon Sep 17 00:00:00 2001 From: jani270 <69345714+jani270@users.noreply.github.com> Date: Wed, 16 Oct 2024 12:59:37 +0200 Subject: [PATCH 05/26] Fix: Millennia-Aged Blaze not getting highlighted by the Area Boss Highlight feature (#2707) --- .../skyhanni/features/combat/mobs/AreaMiniBossFeatures.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/at/hannibal2/skyhanni/features/combat/mobs/AreaMiniBossFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/combat/mobs/AreaMiniBossFeatures.kt index 5c480b8a1124..3d5dd3fd75da 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/combat/mobs/AreaMiniBossFeatures.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/combat/mobs/AreaMiniBossFeatures.kt @@ -100,7 +100,7 @@ object AreaMiniBossFeatures { LorenzVec(-573, 51, -353), ), MILLENNIA_AGED_BLAZE( - "Millenia-Aged Blaze", LorenzColor.DARK_RED, 60, + "Millennia-Aged Blaze", LorenzColor.DARK_RED, 60, LorenzVec(-292, 97, -999), LorenzVec(-232, 77, -951), LorenzVec(-304, 73, -952), From 17b3900dabc7ba6d73e9fc50c4936f408314f30d Mon Sep 17 00:00:00 2001 From: NeoNyaa <56982408+NeoNyaa@users.noreply.github.com> Date: Wed, 16 Oct 2024 12:02:03 +0100 Subject: [PATCH 06/26] Improvement: Added option to show the barn fishing timer anywhere. (#2735) Co-authored-by: martimavocado <39881008+martimavocado@users.noreply.github.com> Co-authored-by: Cal Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com> --- .../skyhanni/config/features/fishing/BarnTimerConfig.java | 8 ++++++++ .../hannibal2/skyhanni/features/fishing/FishingTimer.kt | 8 +++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/fishing/BarnTimerConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/fishing/BarnTimerConfig.java index d62d066e590f..d06cee6d329f 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/fishing/BarnTimerConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/fishing/BarnTimerConfig.java @@ -21,6 +21,14 @@ public class BarnTimerConfig { @FeatureToggle public Property enabled = Property.of(true); + @Expose + @ConfigOption( + name = "Show Anywhere", + desc = "Show the Barn Fishing Timer whenever you fish up a sea creature, regardless of location." + ) + @ConfigEditorBoolean + public boolean showAnywhere = false; + @Expose @ConfigOption( name = "Worm Fishing", diff --git a/src/main/java/at/hannibal2/skyhanni/features/fishing/FishingTimer.kt b/src/main/java/at/hannibal2/skyhanni/features/fishing/FishingTimer.kt index 5be021fbb8a1..c699191a5e26 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/fishing/FishingTimer.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/fishing/FishingTimer.kt @@ -65,7 +65,7 @@ object FishingTimer { @SubscribeEvent fun onSecondPassed(event: SecondPassedEvent) { if (!isEnabled()) return - updateLocation() + rightLocation = updateLocation() if (startTime.passedSince().inWholeSeconds - config.alertTime in 0..3) { playSound() } @@ -170,8 +170,10 @@ object FishingTimer { display = createDisplay() } - private fun updateLocation() { - rightLocation = when (LorenzUtils.skyBlockIsland) { + private fun updateLocation(): Boolean { + if (config.showAnywhere) return true + + return when (LorenzUtils.skyBlockIsland) { IslandType.CRYSTAL_HOLLOWS -> config.crystalHollows.get() IslandType.CRIMSON_ISLE -> config.crimsonIsle.get() IslandType.WINTER -> config.winterIsland.get() From 1d79bb1e97153db7f32df4bb46b7a97c2cfd0ff3 Mon Sep 17 00:00:00 2001 From: CalMWolfs <94038482+CalMWolfs@users.noreply.github.com> Date: Wed, 16 Oct 2024 22:03:12 +1100 Subject: [PATCH 07/26] Fix: Stop SkyHanni messages from being sent twice by accident (#2736) --- src/main/java/at/hannibal2/skyhanni/utils/ChatUtils.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/at/hannibal2/skyhanni/utils/ChatUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/ChatUtils.kt index c923d1deed77..2187ab9a9c59 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/ChatUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/ChatUtils.kt @@ -92,15 +92,15 @@ object ChatUtils { ): Boolean { val text = ChatComponentText(message) - if (replaceSameMessage) { + return if (replaceSameMessage) { text.send(getUniqueMessageIdForString(message)) + chat(text, false) } else { chat(text) } - return chat(text) } - fun chat(message: IChatComponent): Boolean { + fun chat(message: IChatComponent, send: Boolean = true): Boolean { val formattedMessage = message.getFormattedTextCompat() log.log(formattedMessage) @@ -116,7 +116,7 @@ object ChatUtils { return false } - thePlayer.addChatMessage(message) + if (send) thePlayer.addChatMessage(message) return true } From 9e97dff77ac15011d42c6db684e3f686b2efa926 Mon Sep 17 00:00:00 2001 From: MTOnline69 <97001154+MTOnline69@users.noreply.github.com> Date: Wed, 16 Oct 2024 12:42:44 +0100 Subject: [PATCH 08/26] Improvement: Stop Time Tower Usage Warning spam (#2730) --- .../ChocolateFactoryTimeTowerManager.kt | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryTimeTowerManager.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryTimeTowerManager.kt index 30af77ac8b8b..39e0df3da460 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryTimeTowerManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryTimeTowerManager.kt @@ -12,7 +12,6 @@ import at.hannibal2.skyhanni.utils.SoundUtils import at.hannibal2.skyhanni.utils.StringUtils import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import kotlin.time.Duration -import kotlin.time.Duration.Companion.hours import kotlin.time.Duration.Companion.minutes import kotlin.time.Duration.Companion.seconds @@ -23,6 +22,7 @@ object ChocolateFactoryTimeTowerManager { private val profileStorage get() = ChocolateFactoryAPI.profileStorage private var lastTimeTowerWarning = SimpleTimeMark.farPast() + private var warnedAboutLatestCharge = false private var wasTimeTowerRecentlyActive = false @SubscribeEvent @@ -45,24 +45,30 @@ object ChocolateFactoryTimeTowerManager { if (ChocolateFactoryAPI.inChocolateFactory) return - val nextCharge = profileStorage.nextTimeTower - - if (nextCharge.isInPast() && !nextCharge.isFarPast() && currentCharges() < maxCharges()) { - profileStorage.currentTimeTowerUses++ - - val nextTimeTower = profileStorage.nextTimeTower + profileStorage.timeTowerCooldown.hours - profileStorage.nextTimeTower = nextTimeTower + if (timeTowerFullTimeMark().isInPast()) { + profileStorage.currentTimeTowerUses = maxCharges() + } else { + var nextCharge = profileStorage.nextTimeTower + while (nextCharge.isInPast() && !nextCharge.isFarPast()) { + profileStorage.currentTimeTowerUses++ + nextCharge += ChocolateFactoryAPI.timeTowerChargeDuration() + profileStorage.nextTimeTower = nextCharge + warnedAboutLatestCharge = false + } + } + if (currentCharges() < maxCharges()) { if (!config.timeTowerWarning || timeTowerActive()) return + if (warnedAboutLatestCharge) return ChatUtils.clickableChat( - "Your Time Tower has another charge available §7(${timeTowerCharges()})§e, " + + "Your Time Tower has an available charge §7(${timeTowerCharges()})§e. " + "Click here to use one.", onClick = { HypixelCommands.chocolateFactory() }, HOVER_TEXT, ) SoundUtils.playBeepSound() lastTimeTowerWarning = SimpleTimeMark.now() - return + warnedAboutLatestCharge = true } checkTimeTowerWarning(false) } From f2bff363b409d06a88dd576dbc58e33309ddffd2 Mon Sep 17 00:00:00 2001 From: CalMWolfs <94038482+CalMWolfs@users.noreply.github.com> Date: Wed, 16 Oct 2024 23:08:09 +1100 Subject: [PATCH 09/26] Backend: No longer use neu gui elements in config (#2725) --- .../config/core/elements/GuiElement.kt | 19 ++++++++++++++++ .../config/core/elements/GuiElementButton.kt | 22 +++++++++++++++++++ .../config/core/elements/GuiElementText.kt | 21 ++++++++++++++++++ .../misc/update/GuiOptionEditorUpdateCheck.kt | 16 +++++++------- 4 files changed, 70 insertions(+), 8 deletions(-) create mode 100644 src/main/java/at/hannibal2/skyhanni/config/core/elements/GuiElement.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/config/core/elements/GuiElementButton.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/config/core/elements/GuiElementText.kt diff --git a/src/main/java/at/hannibal2/skyhanni/config/core/elements/GuiElement.kt b/src/main/java/at/hannibal2/skyhanni/config/core/elements/GuiElement.kt new file mode 100644 index 000000000000..6144dddf295b --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/config/core/elements/GuiElement.kt @@ -0,0 +1,19 @@ +package at.hannibal2.skyhanni.config.core.elements + +import net.minecraft.client.gui.Gui + +abstract class GuiElement : Gui() { + abstract fun render(x: Int, y: Int) + + abstract val width: Int + + abstract val height: Int + + open fun mouseClicked(mouseX: Int, mouseY: Int, mouseButton: Int) {} + + fun mouseClickMove(mouseX: Int, mouseY: Int, clickedMouseButton: Int, timeSinceLastClick: Long) {} + + fun otherComponentClick() {} + + fun keyTyped(typedChar: Char, keyCode: Int) {} +} diff --git a/src/main/java/at/hannibal2/skyhanni/config/core/elements/GuiElementButton.kt b/src/main/java/at/hannibal2/skyhanni/config/core/elements/GuiElementButton.kt new file mode 100644 index 000000000000..504171ac418f --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/config/core/elements/GuiElementButton.kt @@ -0,0 +1,22 @@ +package at.hannibal2.skyhanni.config.core.elements + +import java.awt.Color + +class GuiElementButton(text: String, colour: Int, private val callback: Runnable) : GuiElementText(text, colour) { + + override val height: Int + get() = super.height + 5 + + override val width: Int + get() = super.width + 10 + + override fun mouseClicked(mouseX: Int, mouseY: Int, mouseButton: Int) { + callback.run() + } + + override fun render(x: Int, y: Int) { + drawRect(x, y, x + width, y + super.height, Color.WHITE.rgb) + drawRect(x + 1, y + 1, x + width - 1, y + super.height - 1, Color.BLACK.rgb) + super.render(x + 5, y - 1) + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/config/core/elements/GuiElementText.kt b/src/main/java/at/hannibal2/skyhanni/config/core/elements/GuiElementText.kt new file mode 100644 index 000000000000..541edc49bf0d --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/config/core/elements/GuiElementText.kt @@ -0,0 +1,21 @@ +package at.hannibal2.skyhanni.config.core.elements + +import net.minecraft.client.Minecraft + +open class GuiElementText(var text: String, private val colour: Int) : GuiElement() { + + override val height: Int + get() = 18 + + override val width: Int + get() { + val fr = Minecraft.getMinecraft().fontRendererObj + return fr.getStringWidth(text) + } + + override fun render(x: Int, y: Int) { + val fr = Minecraft.getMinecraft().fontRendererObj + + fr.drawString(text, x, y + 6, colour) + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/update/GuiOptionEditorUpdateCheck.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/update/GuiOptionEditorUpdateCheck.kt index 9f2d2ac595d4..2fbbc395d0c8 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/update/GuiOptionEditorUpdateCheck.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/update/GuiOptionEditorUpdateCheck.kt @@ -1,7 +1,7 @@ package at.hannibal2.skyhanni.features.misc.update import at.hannibal2.skyhanni.SkyHanniMod -import io.github.moulberry.notenoughupdates.itemeditor.GuiElementButton +import at.hannibal2.skyhanni.config.core.elements.GuiElementButton import io.github.notenoughupdates.moulconfig.gui.GuiOptionEditor import io.github.notenoughupdates.moulconfig.internal.TextRenderUtils import io.github.notenoughupdates.moulconfig.processor.ProcessedOption @@ -20,7 +20,7 @@ class GuiOptionEditorUpdateCheck(option: ProcessedOption) : GuiOptionEditor(opti GlStateManager.pushMatrix() GlStateManager.translate(x.toFloat() + 10, y.toFloat(), 1F) - val width = width - 20 + val adjustedWidth = width - 20 val nextVersion = UpdateManager.getNextVersion() button.text = when (UpdateManager.updateState) { @@ -29,20 +29,20 @@ class GuiOptionEditorUpdateCheck(option: ProcessedOption) : GuiOptionEditor(opti UpdateManager.UpdateState.DOWNLOADED -> "Downloaded" UpdateManager.UpdateState.NONE -> if (nextVersion == null) "Check for Updates" else "Up to date" } - button.render(getButtonPosition(width), 10) + button.render(getButtonPosition(adjustedWidth), 10) if (UpdateManager.updateState == UpdateManager.UpdateState.DOWNLOADED) { TextRenderUtils.drawStringCentered( "${GREEN}The update will be installed after your next restart.", fr, - width / 2F, + adjustedWidth / 2F, 40F, true, - -1 + -1, ) } - val widthRemaining = width - button.width - 10 + val widthRemaining = adjustedWidth - button.width - 10 GlStateManager.scale(2F, 2F, 1F) val currentVersion = SkyHanniMod.version @@ -67,9 +67,9 @@ class GuiOptionEditorUpdateCheck(option: ProcessedOption) : GuiOptionEditor(opti } override fun mouseInput(x: Int, y: Int, width: Int, mouseX: Int, mouseY: Int): Boolean { - val width = width - 20 + val adjustedWidth = width - 20 if (Mouse.getEventButtonState() && - (mouseX - getButtonPosition(width) - x) in (0..button.width) && + (mouseX - getButtonPosition(adjustedWidth) - x) in (0..button.width) && (mouseY - 10 - y) in (0..button.height) ) { when (UpdateManager.updateState) { From 58ba6a5fbc527033359902a061a9b71e23ac8eaa Mon Sep 17 00:00:00 2001 From: CalMWolfs <94038482+CalMWolfs@users.noreply.github.com> Date: Thu, 17 Oct 2024 01:14:10 +1100 Subject: [PATCH 10/26] Backend: Add skyhanni notifications (#2630) --- .../skyhanni/data/NotificationManager.kt | 112 ++++++++++++++++++ .../at/hannibal2/skyhanni/utils/ItemUtils.kt | 30 ++--- 2 files changed, 128 insertions(+), 14 deletions(-) create mode 100644 src/main/java/at/hannibal2/skyhanni/data/NotificationManager.kt diff --git a/src/main/java/at/hannibal2/skyhanni/data/NotificationManager.kt b/src/main/java/at/hannibal2/skyhanni/data/NotificationManager.kt new file mode 100644 index 000000000000..748e46892865 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/data/NotificationManager.kt @@ -0,0 +1,112 @@ +package at.hannibal2.skyhanni.data + +import at.hannibal2.skyhanni.api.event.HandleEvent +import at.hannibal2.skyhanni.config.commands.CommandCategory +import at.hannibal2.skyhanni.config.commands.CommandRegistrationEvent +import at.hannibal2.skyhanni.events.GuiRenderEvent +import at.hannibal2.skyhanni.events.LorenzKeyPressEvent +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.utils.GuiRenderUtils +import at.hannibal2.skyhanni.utils.InventoryUtils +import at.hannibal2.skyhanni.utils.SimpleTimeMark +import at.hannibal2.skyhanni.utils.TimeUtils.format +import at.hannibal2.skyhanni.utils.compat.GuiScreenUtils +import io.github.notenoughupdates.moulconfig.internal.RenderUtils +import net.minecraft.client.Minecraft +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import org.lwjgl.input.Keyboard +import kotlin.time.Duration +import kotlin.time.Duration.Companion.milliseconds + +@SkyHanniModule +object NotificationManager { + + private val notificationQueue = mutableListOf() + + private var currentNotification: SkyHanniNotification? = null + private var lastNotificationClosed = SimpleTimeMark.farPast() + + private const val CLOSE_TEXT = "§c[X] Close" + + @SubscribeEvent + fun onKeyClick(event: LorenzKeyPressEvent) { + currentNotification ?: return + if (lastNotificationClosed.passedSince() < 200.milliseconds) return + if (event.keyCode != Keyboard.KEY_X) return + currentNotification = null + lastNotificationClosed = SimpleTimeMark.now() + } + + @SubscribeEvent + fun onRenderOverlay(event: GuiRenderEvent) { + val notification = getCurrentNotification() ?: return + + if (InventoryUtils.inInventory() && !notification.showOverInventory) return + + val midX = GuiScreenUtils.scaledWindowWidth / 2 + val topY = (GuiScreenUtils.scaledWindowHeight * 0.75 - notification.height / 2).toInt() + + RenderUtils.drawFloatingRectDark(midX - notification.width / 2, topY, notification.width, notification.height) + val closeTextWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(CLOSE_TEXT) + + GuiRenderUtils.drawString(CLOSE_TEXT, midX + notification.width / 2 - 3 - closeTextWidth, topY + 4) + + if (notification.length.isFinite()) { + val remainingTime = "§8" + notification.endTime.timeUntil().format() + GuiRenderUtils.drawString(remainingTime, midX - notification.width / 2 + 4, topY + 4) + } + + notification.message.forEachIndexed { index, line -> + GuiRenderUtils.drawStringCentered("§7$line", midX, topY + 19 + index * 10) + } + } + + private fun getCurrentNotification(): SkyHanniNotification? { + currentNotification?.let { + if (it.endTime.isInPast()) currentNotification = null + } + if (currentNotification == null) { + currentNotification = notificationQueue.removeFirstOrNull() + currentNotification?.setEndTime() + } + return currentNotification + } + + fun queueNotification(notification: SkyHanniNotification) { + notificationQueue.add(notification) + } + + @HandleEvent + fun onCommandRegistration(event: CommandRegistrationEvent) { + event.register("shtestnotification") { + description = "Shows a test notification" + category = CommandCategory.DEVELOPER_TEST + callback { + val testingText = it.joinToString(" ").replace("\\n", "\n") + queueNotification(SkyHanniNotification(testingText, Duration.INFINITE)) + } + } + } +} + +data class SkyHanniNotification( + val message: List, + val length: Duration, + val showOverInventory: Boolean = false, +) { + constructor(message: String, length: Duration, showOverInventory: Boolean = false) : this( + message.lines(), + length, + showOverInventory, + ) + + var endTime = SimpleTimeMark.farFuture() + + val width by lazy { (message.maxOfOrNull { Minecraft.getMinecraft().fontRendererObj.getStringWidth(it) } ?: 0) + 8 } + val height by lazy { message.size * 10 + 18 } + + fun setEndTime() { + if (length.isInfinite()) return + endTime = SimpleTimeMark.now() + length + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/utils/ItemUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/ItemUtils.kt index d39b37c8abb1..1198ed7ae6a2 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/ItemUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/ItemUtils.kt @@ -1,6 +1,8 @@ package at.hannibal2.skyhanni.utils +import at.hannibal2.skyhanni.data.NotificationManager import at.hannibal2.skyhanni.data.PetAPI +import at.hannibal2.skyhanni.data.SkyHanniNotification import at.hannibal2.skyhanni.events.DebugDataCollectEvent import at.hannibal2.skyhanni.features.misc.items.EstimatedItemValueCalculator.getAttributeName import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule @@ -19,8 +21,6 @@ import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.isRecombobulated import at.hannibal2.skyhanni.utils.StringUtils.removeColor import at.hannibal2.skyhanni.utils.StringUtils.removeResets import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern -import com.google.common.collect.Lists -import io.github.moulberry.notenoughupdates.util.NotificationHandler import net.minecraft.client.Minecraft import net.minecraft.init.Items import net.minecraft.item.Item @@ -32,6 +32,8 @@ import net.minecraftforge.common.util.Constants import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import java.util.LinkedList import java.util.regex.Matcher +import kotlin.time.Duration.Companion.INFINITE +import kotlin.time.Duration.Companion.minutes import kotlin.time.Duration.Companion.seconds @SkyHanniModule @@ -40,6 +42,7 @@ object ItemUtils { private val itemNameCache = mutableMapOf() // internal name -> item name private val missingRepoItems = mutableSetOf() + private var lastRepoWarning = SimpleTimeMark.farPast() fun ItemStack.cleanName() = this.displayName.removeColor() @@ -544,20 +547,19 @@ object ItemUtils { fun addMissingRepoItem(name: String, message: String) { if (!missingRepoItems.add(name)) return ChatUtils.debug(message) -// showRepoWarning() + + if (lastRepoWarning.passedSince() < 3.minutes) return + lastRepoWarning = SimpleTimeMark.now() + showRepoWarning(name) } - // Running NEU's function `Utils.showOutdatedRepoNotification()` caused a NoSuchMethodError in dev env. - // Therefore we run NotificationHandler.displayNotification directly - private fun showRepoWarning() { - NotificationHandler.displayNotification( - Lists.newArrayList( - "§c§lMissing repo data", - "§cData used for some SkyHanni features is not up to date, this should normally not be the case.", - "§cYou can try §l/neuresetrepo§r§c and restart your game to see if that fixes the issue.", - "§cIf the problem persists please join the SkyHanni Discord and message in §l#support§r§c to get support.", - ), - true, true, + private fun showRepoWarning(item: String) { + val text = listOf( + "§c§lMissing repo data for item: $item", + "§cData used for some SkyHanni features is not up to date, this should normally not be the case.", + "§cYou can try §l/neuresetrepo§r§c and restart your game to see if that fixes the issue.", + "§cIf the problem persists please join the SkyHanni Discord and message in §l#support§r§c to get support.", ) + NotificationManager.queueNotification(SkyHanniNotification(text, INFINITE, true)) } } From aaaa0206963f0eb00d571cd2d68c385b7e0d2b40 Mon Sep 17 00:00:00 2001 From: Empa <42304516+ItsEmpa@users.noreply.github.com> Date: Wed, 16 Oct 2024 19:43:35 +0200 Subject: [PATCH 11/26] Fix: Compact Item Stars (#2741) Co-authored-by: ItsEmpa Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com> --- .../skyhanni/features/inventory/ItemStars.kt | 124 +++++------------- .../items/EstimatedItemValueCalculator.kt | 66 +++------- .../features/nether/kuudra/KuudraAPI.kt | 32 +++++ .../at/hannibal2/skyhanni/utils/NEUItems.kt | 7 + 4 files changed, 88 insertions(+), 141 deletions(-) diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/ItemStars.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/ItemStars.kt index d89c2aca9e3b..7e0ab8d7d7b2 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/ItemStars.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/ItemStars.kt @@ -2,16 +2,20 @@ package at.hannibal2.skyhanni.features.inventory import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.config.features.inventory.InventoryConfig.ItemNumberEntry.CRIMSON_ARMOR -import at.hannibal2.skyhanni.data.jsonobjects.repo.ItemsJson import at.hannibal2.skyhanni.events.LorenzToolTipEvent import at.hannibal2.skyhanni.events.RenderItemTipEvent -import at.hannibal2.skyhanni.events.RepositoryReloadEvent import at.hannibal2.skyhanni.features.inventory.ItemDisplayOverlayFeatures.isSelected +import at.hannibal2.skyhanni.features.nether.kuudra.KuudraAPI.getKuudraTier +import at.hannibal2.skyhanni.features.nether.kuudra.KuudraAPI.isKuudraArmor import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.utils.ItemUtils.getInternalNameOrNull import at.hannibal2.skyhanni.utils.ItemUtils.name import at.hannibal2.skyhanni.utils.LorenzUtils -import at.hannibal2.skyhanni.utils.RegexUtils.matches +import at.hannibal2.skyhanni.utils.RegexUtils.findMatcher +import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getDungeonStarCount +import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getStarCount import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern +import net.minecraft.item.ItemStack import net.minecraftforge.fml.common.eventhandler.EventPriority import net.minecraftforge.fml.common.eventhandler.SubscribeEvent @@ -20,115 +24,47 @@ object ItemStars { private val config get() = SkyHanniMod.feature.inventory - private val starPattern by RepoPattern.pattern( - "inventory.itemstars.stars", - "(.*)§.✪(.*)" - ) + private val repoGroup = RepoPattern.group("inventory.itemstars") - private val armorNames = mutableListOf() - private val tiers = mutableMapOf() - private val armorParts = listOf("Helmet", "Chestplate", "Leggings", "Boots") + /** + * REGEX-TEST: §6Ancient Terror Leggings §d✪✪§6✪✪✪ + * REGEX-TEST: §dRenowned Burning Crimson Helmet §6✪✪✪✪✪ + */ + private val starPattern by repoGroup.pattern( + "stars", + "^(?.+) (?(?:(?:§.)?✪)+)" + ) @SubscribeEvent(priority = EventPriority.LOW) fun onTooltip(event: LorenzToolTipEvent) { if (!isEnabled()) return val stack = event.itemStack if (stack.stackSize != 1) return - - val itemName = stack.name - val stars = getStars(itemName) - - if (stars > 0) { - var name = itemName - while (starPattern.matches(name)) { - name = name.replaceFirst("§.✪".toRegex(), "") - } - name = name.trim() + val stars = stack.grabStarCount() ?: return + starPattern.findMatcher(stack.name) { + val name = group("name") event.toolTip[0] = "$name §c$stars✪" } } - @SubscribeEvent - fun onRepoReload(event: RepositoryReloadEvent) { - val data = event.getConstant("Items") - armorNames.clear() - tiers.clear() - armorNames.addAll(data.crimsonArmors) - for (tier in data.crimsonTiers) { - tiers[tier.key] = tier.value - } - } - @SubscribeEvent fun onRenderItemTip(event: RenderItemTipEvent) { + if (!LorenzUtils.inSkyBlock) return if (!CRIMSON_ARMOR.isSelected()) return val stack = event.stack - val number = getCrimsonStars(stack.name) - if (number != -1) { - event.stackTip = number.toString() - } - } - - private fun getStars(name: String): Int { - val stars = getCrimsonStars(name) - if (stars != -1) { - return stars - } - - return getOtherStars(name) + if (stack.getInternalNameOrNull()?.isKuudraArmor() != true) return + val stars = stack.grabStarCount() ?: return + event.stackTip = stars.toString() } - private fun getCrimsonStars(name: String): Int { - if (!armorNames.any { name.contains(it) } || !armorParts.any { name.contains(it) }) { - return -1 + private fun ItemStack.grabStarCount(): Int? { + val internalName = getInternalNameOrNull() ?: return null + val baseStars = getDungeonStarCount() ?: getStarCount() ?: return null + if (internalName.isKuudraArmor()) { + val tier = internalName.getKuudraTier() ?: return baseStars + return baseStars + tier * 10 } - var name1 = name - var gold = 0 - var pink = 0 - var aqua = 0 - while (name1.contains("§6✪")) { - name1 = name1.replaceFirst("§6✪", "") - gold++ - } - while (name1.contains("§d✪")) { - name1 = name1.replaceFirst("§d✪", "") - pink++ - } - while (name1.contains("§b✪")) { - name1 = name1.replaceFirst("§b✪", "") - aqua++ - } - return (tiers.entries.find { name1.contains(it.key) }?.value ?: 0) + if (aqua > 0) { - 10 + aqua - } else if (pink > 0) { - 5 + pink - } else { - gold - } - } - - private fun getOtherStars(originalName: String): Int { - var name = originalName - - var gold = 0 - var red = 0 - while (name.contains("§6✪")) { - name = name.replaceFirst("§6✪", "") - gold++ - } - while (name.contains("§c✪")) { - name = name.replaceFirst("§c✪", "") - red++ - } - while (name.contains("§d✪")) { - name = name.replaceFirst("§d✪", "") - red++ - } - - if (red > 0) return 5 + red - if (gold > 0) return gold - - return -1 + return baseStars } private fun isEnabled() = LorenzUtils.inSkyBlock && config.itemStars diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValueCalculator.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValueCalculator.kt index 15c55e02e7fc..30d3267502b4 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValueCalculator.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValueCalculator.kt @@ -2,6 +2,10 @@ package at.hannibal2.skyhanni.features.misc.items import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.api.ReforgeAPI +import at.hannibal2.skyhanni.features.nether.kuudra.KuudraAPI +import at.hannibal2.skyhanni.features.nether.kuudra.KuudraAPI.getKuudraTier +import at.hannibal2.skyhanni.features.nether.kuudra.KuudraAPI.isKuudraArmor +import at.hannibal2.skyhanni.features.nether.kuudra.KuudraAPI.removeKuudraTier import at.hannibal2.skyhanni.test.command.ErrorManager import at.hannibal2.skyhanni.utils.CollectionUtils.addOrPut import at.hannibal2.skyhanni.utils.CollectionUtils.sorted @@ -24,6 +28,7 @@ import at.hannibal2.skyhanni.utils.NEUItems.getItemStackOrNull import at.hannibal2.skyhanni.utils.NEUItems.getNpcPriceOrNull import at.hannibal2.skyhanni.utils.NEUItems.getPriceOrNull import at.hannibal2.skyhanni.utils.NEUItems.getRawCraftCostOrNull +import at.hannibal2.skyhanni.utils.NEUItems.removePrefix import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators import at.hannibal2.skyhanni.utils.NumberUtil.shortFormat import at.hannibal2.skyhanni.utils.PrimitiveIngredient @@ -69,8 +74,6 @@ object EstimatedItemValueCalculator { private val config get() = SkyHanniMod.feature.inventory.estimatedItemValues - private val kuudraSets = listOf("AURORA", "CRIMSON", "TERROR", "HOLLOW", "FERVOR") - var starChange = 0 get() = if (SkyHanniMod.feature.dev.debug.enabled) field else 0 @@ -134,31 +137,22 @@ object EstimatedItemValueCalculator { return Pair(totalPrice, basePrice) } - private fun isKuudraSet(internalName: String) = ( - kuudraSets.any { internalName.contains(it) } && - listOf( - "CHESTPLATE", - "LEGGINGS", - "HELMET", - "BOOTS", - ).any { internalName.endsWith(it) } - ) - private fun addAttributeCost(stack: ItemStack, list: MutableList): Double { val attributes = stack.getAttributes() ?: return 0.0 - var internalName = removeKuudraArmorPrefix(stack.getInternalName().asString().removePrefix("VANQUISHED_")) - var genericName = internalName - if (isKuudraSet(internalName)) { - genericName = kuudraSets.fold(internalName) { acc, part -> acc.replace(part, "GENERIC_KUUDRA") } + val internalName = stack.getInternalName() + val internalNameString = internalName.removeKuudraTier().removePrefix("VANQUISHED_").asString() + var genericName = internalNameString + if (internalName.isKuudraArmor()) { + genericName = KuudraAPI.kuudraSets.fold(internalNameString) { acc, part -> acc.replace(part, "GENERIC_KUUDRA") } } stack.getAttributeFromShard()?.let { return 0.0 } if (attributes.size != 2) return 0.0 - val basePrice = internalName.asInternalName().getPriceOrNull() ?: 0.0 + val basePrice = internalName.getPriceOrNull() ?: 0.0 var subTotal = 0.0 - val combo = ("$internalName+ATTRIBUTE_${attributes[0].first}+ATTRIBUTE_${attributes[1].first}") - var comboPrice = combo.asInternalName().getPriceOrNull() + val combo = ("$internalNameString+ATTRIBUTE_${attributes[0].first}+ATTRIBUTE_${attributes[1].first}") + val comboPrice = combo.asInternalName().getPriceOrNull() if (comboPrice != null) { val useless = isUselessAttribute(combo) @@ -194,16 +188,6 @@ object EstimatedItemValueCalculator { return subTotal + 0.1 } - private fun removeKuudraArmorPrefix(original: String): String { - if (!isKuudraSet(original)) return original - - var internalName = original - for (prefix in kuudraUpgradeTiers) { - internalName = internalName.removePrefix(prefix) - } - return internalName - } - private fun addAttributePrice(attributePrice: Double, basePrice: Double): Double = if (attributePrice > basePrice) { attributePrice - basePrice } else { @@ -493,14 +477,13 @@ object EstimatedItemValueCalculator { inputStars: Int, ): Pair>? { var totalStars = inputStars - val rawInternalName = internalName.asString() - val (price, maxStars) = if (isKuudraSet(rawInternalName)) { - val tier = getKuudraTier(internalName) - totalStars += (tier + 1) * 10 + val (price, maxStars) = if (internalName.isKuudraArmor()) { + val tier = internalName.getKuudraTier() ?: 0 + totalStars += tier * 10 var remainingStars = totalStars - val removed = removeKuudraArmorPrefix(rawInternalName) + val removed = internalName.removeKuudraTier().asString() var maxStars = 0 var finalPrice: EssenceItemUtils.EssenceUpgradePrice? = null @@ -508,7 +491,7 @@ object EstimatedItemValueCalculator { for ((id, _) in EssenceItemUtils.itemPrices) { if (!id.contains(removed)) continue - tiers[id] = getKuudraTier(id) + tiers[id] = (id.getKuudraTier() ?: 0) - 1 } for ((id, _) in tiers.sorted()) { @@ -535,17 +518,6 @@ object EstimatedItemValueCalculator { return price to (havingStars to maxStars) } - private fun getKuudraTier(internalName: NEUInternalName): Int { - for (tier in kuudraUpgradeTiers) { - if (internalName.asString().contains(tier)) { - return kuudraUpgradeTiers.indexOf(tier) - } - } - return -1 - } -// private fun getKuudraTier(internalName: NEUInternalName): Int? = -// kuudraUpgradeTiers.firstOrNull { it in internalName.toString() }?.let { kuudraUpgradeTiers.indexOf(it) } - private fun getPriceFor( prices: Map, totalStars: Int, @@ -697,7 +669,7 @@ object EstimatedItemValueCalculator { } private fun addBaseItem(stack: ItemStack, list: MutableList): Double { - val internalName = removeKuudraArmorPrefix(stack.getInternalName().asString()).asInternalName() + val internalName = stack.getInternalName().removeKuudraTier() stack.getAttributeFromShard()?.let { val price = it.getAttributePrice() diff --git a/src/main/java/at/hannibal2/skyhanni/features/nether/kuudra/KuudraAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/nether/kuudra/KuudraAPI.kt index dbae485dcde8..f2b1557da326 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/nether/kuudra/KuudraAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/nether/kuudra/KuudraAPI.kt @@ -8,7 +8,11 @@ import at.hannibal2.skyhanni.events.LorenzTickEvent import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.NEUInternalName +import at.hannibal2.skyhanni.utils.NEUItems.removePrefix +import at.hannibal2.skyhanni.utils.RegexUtils.matchGroup import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher +import at.hannibal2.skyhanni.utils.RegexUtils.matches import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern import net.minecraftforge.fml.common.eventhandler.SubscribeEvent @@ -26,7 +30,35 @@ object KuudraAPI { "§.\\s*(?:§.)*KUUDRA DOWN!" ) + /** + * REGEX-TEST: BURNING_AURORA_CHESTPLATE + * REGEX-TEST: CRIMSON_LEGGINGS + * REGEX-TEST: FIERY_CRIMSON_LEGGINGS + * REGEX-TEST: TERROR_CHESTPLATE + */ + private val kuudraArmorPattern by patternGroup.pattern( + "internalname.armor", + "(?HOT|BURNING|FIERY|INFERNAL|)_?(?AURORA|CRIMSON|TERROR|HOLLOW|FERVOR)_(?:HELMET|CHESTPLATE|LEGGINGS|BOOTS)" + ) + + private val kuudraTiers = listOf("", "HOT", "BURNING", "FIERY", "INFERNAL") + val kuudraSets = listOf("AURORA", "CRIMSON", "TERROR", "HOLLOW", "FERVOR") + + fun NEUInternalName.isKuudraArmor(): Boolean = kuudraArmorPattern.matches(asString()) + + fun NEUInternalName.getKuudraTier(): Int? { + val tier = kuudraArmorPattern.matchGroup(asString(), "tier") ?: return null + return (kuudraTiers.indexOf(tier) + 1).takeIf { it != 0 } + } + + fun NEUInternalName.removeKuudraTier(): NEUInternalName { + val prefix = kuudraArmorPattern.matchGroup(asString(), "tier") ?: return this + return removePrefix("${prefix}_") + } + var kuudraTier: Int? = null + private set + fun inKuudra() = kuudraTier != null @SubscribeEvent diff --git a/src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt b/src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt index 75c6173ba57e..f5db6b429c77 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt @@ -226,6 +226,13 @@ object NEUItems { fun NEUInternalName.isVanillaItem(): Boolean = manager.auctionManager.isVanillaItem(this.asString()) + fun NEUInternalName.removePrefix(prefix: String): NEUInternalName { + if (prefix.isEmpty()) return this + val string = asString() + if (!string.startsWith(prefix)) return this + return string.substring(prefix.length).asInternalName() + } + const val itemFontSize = 2.0 / 3.0 fun ItemStack.renderOnScreen( From 068e021a288d0b0a2e9e1947dbefec3bd619db1e Mon Sep 17 00:00:00 2001 From: hannibal2 <24389977+hannibal00212@users.noreply.github.com> Date: Wed, 16 Oct 2024 19:44:04 +0200 Subject: [PATCH 12/26] formatting --- .../hannibal2/skyhanni/features/inventory/ItemStars.kt | 2 +- .../features/misc/items/EstimatedItemValueCalculator.kt | 9 +++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/ItemStars.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/ItemStars.kt index 7e0ab8d7d7b2..05b0d46c75e7 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/ItemStars.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/ItemStars.kt @@ -32,7 +32,7 @@ object ItemStars { */ private val starPattern by repoGroup.pattern( "stars", - "^(?.+) (?(?:(?:§.)?✪)+)" + "^(?.+) (?(?:(?:§.)?✪)+)", ) @SubscribeEvent(priority = EventPriority.LOW) diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValueCalculator.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValueCalculator.kt index 30d3267502b4..80478744883b 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValueCalculator.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValueCalculator.kt @@ -730,12 +730,9 @@ object EstimatedItemValueCalculator { val map = mutableMapOf() // todo use repo - val tieredEnchants = - listOf("compact", "cultivating", "champion", "expertise", "hecatomb", "toxophilite") - val onlyTierOnePrices = - listOf("ultimate_chimera", "ultimate_fatal_tempo", "smoldering", "ultimate_flash", "divine_gift") - val onlyTierFivePrices = - listOf("ferocious_mana", "hardened_mana", "mana_vampire", "strong_mana") + val tieredEnchants = listOf("compact", "cultivating", "champion", "expertise", "hecatomb", "toxophilite") + val onlyTierOnePrices = listOf("ultimate_chimera", "ultimate_fatal_tempo", "smoldering", "ultimate_flash", "divine_gift") + val onlyTierFivePrices = listOf("ferocious_mana", "hardened_mana", "mana_vampire", "strong_mana") val internalName = stack.getInternalName() for ((rawName, rawLevel) in enchantments) { From e2f7293cae6c76b31ad77f59380a688fcdcacde2 Mon Sep 17 00:00:00 2001 From: David Cole <40234707+DavidArthurCole@users.noreply.github.com> Date: Wed, 16 Oct 2024 13:47:41 -0400 Subject: [PATCH 13/26] Feature: Rabbit the Fish GUI Close Blocker (#2712) Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com> --- .../skyhanni/config/ConfigUpdaterMigrator.kt | 2 +- .../event/hoppity/HoppityEggsConfig.java | 14 +-- .../event/hoppity/HoppityWarpMenuConfig.java | 20 ++++ .../event/hoppity/HoppityEggsManager.kt | 2 + .../hoppity/HoppityRabbitTheFishChecker.kt | 99 +++++++++++++++++++ .../features/event/hoppity/WarpMenuUniques.kt | 6 +- .../transformers/gui/MixinGuiContainer.java | 8 ++ 7 files changed, 140 insertions(+), 11 deletions(-) create mode 100644 src/main/java/at/hannibal2/skyhanni/config/features/event/hoppity/HoppityWarpMenuConfig.java create mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityRabbitTheFishChecker.kt diff --git a/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt b/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt index f6d6c72de14d..8228ae025274 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt +++ b/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt @@ -12,7 +12,7 @@ import com.google.gson.JsonPrimitive object ConfigUpdaterMigrator { val logger = LorenzLogger("ConfigMigration") - const val CONFIG_VERSION = 61 + const val CONFIG_VERSION = 62 fun JsonElement.at(chain: List, init: Boolean): JsonElement? { if (chain.isEmpty()) return this if (this !is JsonObject) return null diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/event/hoppity/HoppityEggsConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/event/hoppity/HoppityEggsConfig.java index 3fd83db69655..f34959bd8a97 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/event/hoppity/HoppityEggsConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/event/hoppity/HoppityEggsConfig.java @@ -24,6 +24,11 @@ public class HoppityEggsConfig { @Accordion public HoppityEventSummaryConfig eventSummary = new HoppityEventSummaryConfig(); + @Expose + @ConfigOption(name = "Warp Menu", desc = "") + @Accordion + public HoppityWarpMenuConfig warpMenu = new HoppityWarpMenuConfig(); + @Expose @ConfigOption(name = "Hoppity Waypoints", desc = "Toggle guess waypoints for Hoppity's Hunt.") @ConfigEditorBoolean @@ -213,13 +218,8 @@ public String toString() { public boolean petWarning = false; @Expose - @ConfigOption(name = "Show uniques in Warp Menu", desc = "Shows your unique eggs in the Warp Menu during the hoppity event.") + @ConfigOption(name = "Prevent Missing Fish the Rabbit", desc = "Prevent closing a Meal Egg's inventory if Fish the Rabbit is present.") @ConfigEditorBoolean @FeatureToggle - public boolean uniquesWarpMenu = true; - - @Expose - @ConfigOption(name = "Hide when maxed", desc = "Stops the above feature from working when the island is complete.") - @ConfigEditorBoolean - public boolean uniquesWarpMenuHideMax = true; + public boolean preventMissingFish = true; } diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/event/hoppity/HoppityWarpMenuConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/event/hoppity/HoppityWarpMenuConfig.java new file mode 100644 index 000000000000..680b2918e876 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/config/features/event/hoppity/HoppityWarpMenuConfig.java @@ -0,0 +1,20 @@ +package at.hannibal2.skyhanni.config.features.event.hoppity; + +import at.hannibal2.skyhanni.config.FeatureToggle; +import com.google.gson.annotations.Expose; +import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean; +import io.github.notenoughupdates.moulconfig.annotations.ConfigOption; + +public class HoppityWarpMenuConfig { + + @Expose + @ConfigOption(name = "Show uniques in Warp Menu", desc = "Shows your unique eggs in the Warp Menu during the hoppity event.") + @ConfigEditorBoolean + @FeatureToggle + public boolean enabled = true; + + @Expose + @ConfigOption(name = "Hide when maxed", desc = "Stops the above feature from working when the island is complete.") + @ConfigEditorBoolean + public boolean hideWhenMaxed = true; +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggsManager.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggsManager.kt index a69366931886..4b3451514839 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggsManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggsManager.kt @@ -259,6 +259,8 @@ object HoppityEggsManager { ) event.move(44, "event.chocolateFactory.hoppityEggs", "event.hoppityEggs") event.move(50, "event.hoppityEggs.showDuringContest", "event.hoppityEggs.showWhileBusy") + event.move(62, "event.hoppityEggs.uniquesWarpMenu", "event.hoppityEggs.warpMenu.enabled") + event.move(62, "event.hoppityEggs.uniquesWarpMenuHideMax", "event.hoppityEggs.warpMenu.hideWhenMaxed") } fun isActive() = (LorenzUtils.inSkyBlock || (LorenzUtils.onHypixel && config.showOutsideSkyblock)) && diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityRabbitTheFishChecker.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityRabbitTheFishChecker.kt new file mode 100644 index 000000000000..50608954ae67 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityRabbitTheFishChecker.kt @@ -0,0 +1,99 @@ +package at.hannibal2.skyhanni.features.event.hoppity + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.events.GuiContainerEvent +import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent +import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryAPI +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.utils.InventoryUtils +import at.hannibal2.skyhanni.utils.ItemUtils.getLore +import at.hannibal2.skyhanni.utils.LorenzColor +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.RegexUtils.anyMatches +import at.hannibal2.skyhanni.utils.RegexUtils.matches +import at.hannibal2.skyhanni.utils.RenderUtils.highlight +import at.hannibal2.skyhanni.utils.SoundUtils +import net.minecraft.client.Minecraft +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import org.lwjgl.input.Keyboard + +@SkyHanniModule +object HoppityRabbitTheFishChecker { + + // + /** + * REGEX-TEST: Chocolate Breakfast Egg + * REGEX-TEST: Chocolate Lunch Egg + * REGEX-TEST: Chocolate Dinner Egg + */ + private val mealEggInventoryPattern by ChocolateFactoryAPI.patternGroup.pattern( + "inventory.mealegg.name", + "(?:§.)*Chocolate (?:Breakfast|Lunch|Dinner) Egg.*", + ) + + /** + * REGEX-TEST: §cRabbit the Fish + */ + private val rabbitTheFishItemPattern by ChocolateFactoryAPI.patternGroup.pattern( + "item.rabbitthefish", + "(?:§.)*Rabbit the Fish", + ) + + /** + * REGEX-TEST: Click to open Chocolate Factory! + */ + private val openCfSlotLorePattern by ChocolateFactoryAPI.patternGroup.pattern( + "inventory.mealegg.continue", + "(?:§.)*Click to open Chocolate Factory!", + ) + // + + private val config get() = SkyHanniMod.feature.event.hoppityEggs + private var rabbitTheFishIndex: Int? = null + + @SubscribeEvent + fun onBackgroundDrawn(event: GuiContainerEvent.BackgroundDrawnEvent) { + if (!isEnabled()) return + + rabbitTheFishIndex?.let { + InventoryUtils.getItemsInOpenChest()[it] highlight LorenzColor.RED + } + } + + @SubscribeEvent + fun onInventoryOpen(event: InventoryFullyOpenedEvent) { + if (!isEnabled() || !mealEggInventoryPattern.matches(event.inventoryName)) return + + rabbitTheFishIndex = event.inventoryItems.filter { + it.value.hasDisplayName() + }.entries.firstOrNull { + rabbitTheFishItemPattern.matches(it.value.displayName) + }?.key + } + + @SubscribeEvent + fun onSlotClick(event: GuiContainerEvent.SlotClickEvent) { + if (!isEnabled() || rabbitTheFishIndex == null) return + + // Prevent opening chocolate factory when Rabbit the Fish is present + val stack = event.slot?.stack ?: return + if (openCfSlotLorePattern.anyMatches(stack.getLore())) { + event.cancel() + SoundUtils.playErrorSound() + } else if (rabbitTheFishIndex == event.slot.slotNumber) { + rabbitTheFishIndex = null + } + } + + private fun Int.isInventoryClosure(): Boolean = + this == Minecraft.getMinecraft().gameSettings.keyBindInventory.keyCode || this == Keyboard.KEY_ESCAPE + + @JvmStatic + fun shouldContinueWithKeypress(keycode: Int): Boolean { + val shouldContinue = !keycode.isInventoryClosure() || !isEnabled() || rabbitTheFishIndex == null + if (!shouldContinue) SoundUtils.playErrorSound() + return shouldContinue + } + + private fun isEnabled() = LorenzUtils.inSkyBlock && HoppityAPI.isHoppityEvent() && config.preventMissingFish +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/WarpMenuUniques.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/WarpMenuUniques.kt index 939dea1b702f..dfd22de9a88f 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/WarpMenuUniques.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/WarpMenuUniques.kt @@ -27,12 +27,12 @@ object WarpMenuUniques { private val collectedEggStorage: MutableMap>? get() = ChocolateFactoryAPI.profileStorage?.collectedEggLocations - private val config get() = SkyHanniMod.feature.event.hoppityEggs + private val config get() = SkyHanniMod.feature.event.hoppityEggs.warpMenu @SubscribeEvent fun onTooltip(event: LorenzToolTipEvent) { if (!LorenzUtils.inSkyBlock) return - if (!config.uniquesWarpMenu) return + if (!config.enabled) return if (!HoppityAPI.isHoppityEvent()) return if (event.slot.inventory.name != "Fast Travel") return @@ -51,7 +51,7 @@ object WarpMenuUniques { val maxEggs = 15 val collectedEggs = collectedEggStorage?.get(island)?.size ?: 0 - if (collectedEggs >= maxEggs && config.uniquesWarpMenuHideMax) return + if (collectedEggs >= maxEggs && config.hideWhenMaxed) return event.toolTip.add(2, "§7Collected Hoppity Eggs: ${if (collectedEggs == maxEggs) "§a" else ""}$collectedEggs/$maxEggs") } diff --git a/src/main/java/at/hannibal2/skyhanni/mixins/transformers/gui/MixinGuiContainer.java b/src/main/java/at/hannibal2/skyhanni/mixins/transformers/gui/MixinGuiContainer.java index 0c58469cd12e..071d399adc91 100644 --- a/src/main/java/at/hannibal2/skyhanni/mixins/transformers/gui/MixinGuiContainer.java +++ b/src/main/java/at/hannibal2/skyhanni/mixins/transformers/gui/MixinGuiContainer.java @@ -1,6 +1,7 @@ package at.hannibal2.skyhanni.mixins.transformers.gui; import at.hannibal2.skyhanni.data.ToolTipData; +import at.hannibal2.skyhanni.features.event.hoppity.HoppityRabbitTheFishChecker; import at.hannibal2.skyhanni.mixins.hooks.GuiContainerHook; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.inventory.GuiContainer; @@ -26,6 +27,13 @@ private void closeWindowPressed(CallbackInfo ci) { skyHanni$hook.closeWindowPressed(ci); } + @Inject(method = "keyTyped", at = @At("HEAD"), cancellable = true) + private void onKeyTyped(char typedChar, int keyCode, CallbackInfo ci) { + if (!HoppityRabbitTheFishChecker.shouldContinueWithKeypress(keyCode)) { + ci.cancel(); + } + } + @Inject(method = "drawScreen", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GlStateManager;color(FFFF)V", ordinal = 1)) private void backgroundDrawn(int mouseX, int mouseY, float partialTicks, CallbackInfo ci) { skyHanni$hook.backgroundDrawn(mouseX, mouseY, partialTicks); From e883d0c027e602348416398ba9b14d295ee6b7b4 Mon Sep 17 00:00:00 2001 From: CalMWolfs <94038482+CalMWolfs@users.noreply.github.com> Date: Thu, 17 Oct 2024 05:13:35 +1100 Subject: [PATCH 14/26] Backend: Add backup repo (#2673) Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com> --- build.gradle.kts | 8 ++ .../skyhannibuildsystem/DownloadBackupRepo.kt | 34 ++++++ .../skyhanni/data/repo/RepoManager.kt | 114 +++++++++++------- .../hannibal2/skyhanni/test/DebugCommand.kt | 28 ++--- .../utils/repopatterns/RepoPatternManager.kt | 4 +- 5 files changed, 129 insertions(+), 59 deletions(-) create mode 100644 buildSrc/src/main/kotlin/skyhannibuildsystem/DownloadBackupRepo.kt diff --git a/build.gradle.kts b/build.gradle.kts index dde5ac410ed2..31aeef427d1c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -9,6 +9,7 @@ import net.fabricmc.loom.task.RunGameTask import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import skyhannibuildsystem.ChangelogVerification +import skyhannibuildsystem.DownloadBackupRepo plugins { idea @@ -96,6 +97,12 @@ val headlessLwjgl by configurations.creating { isTransitive = false isVisible = false } + +val includeBackupRepo by tasks.registering(DownloadBackupRepo::class) { + this.outputDirectory.set(layout.buildDirectory.dir("downloadedRepo")) + this.branch = "main" +} + tasks.runClient { this.javaLauncher.set( javaToolchains.launcherFor { @@ -213,6 +220,7 @@ kotlin { // Tasks: tasks.processResources { + from(includeBackupRepo) inputs.property("version", version) filesMatching(listOf("mcmod.info", "fabric.mod.json")) { expand("version" to version) diff --git a/buildSrc/src/main/kotlin/skyhannibuildsystem/DownloadBackupRepo.kt b/buildSrc/src/main/kotlin/skyhannibuildsystem/DownloadBackupRepo.kt new file mode 100644 index 000000000000..f59bf34a8c10 --- /dev/null +++ b/buildSrc/src/main/kotlin/skyhannibuildsystem/DownloadBackupRepo.kt @@ -0,0 +1,34 @@ +package skyhannibuildsystem + +import org.gradle.api.DefaultTask +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Internal +import org.gradle.api.tasks.OutputDirectory +import org.gradle.api.tasks.TaskAction +import java.net.URL + +// Code taken from NotEnoughUpdates +abstract class DownloadBackupRepo : DefaultTask() { + + @get:OutputDirectory + abstract val outputDirectory: DirectoryProperty + + @get:Input + abstract var branch: String + + @get:Internal + val repoFile get() = outputDirectory.get().asFile.resolve("assets/skyhanni/repo.zip") + + @TaskAction + fun downloadRepo() { + val downloadUrl = URL("https://github.com/hannibal002/SkyHanni-Repo/archive/refs/heads/$branch.zip") + val file = repoFile + file.parentFile.mkdirs() + file.outputStream().use { out -> + downloadUrl.openStream().use { inp -> + inp.copyTo(out) + } + } + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/data/repo/RepoManager.kt b/src/main/java/at/hannibal2/skyhanni/data/repo/RepoManager.kt index babbb2558def..1d81502f3f61 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/repo/RepoManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/repo/RepoManager.kt @@ -2,7 +2,6 @@ package at.hannibal2.skyhanni.data.repo import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.config.ConfigManager -import at.hannibal2.skyhanni.events.DebugDataCollectEvent import at.hannibal2.skyhanni.events.NeuRepositoryReloadEvent import at.hannibal2.skyhanni.events.RepositoryReloadEvent import at.hannibal2.skyhanni.test.command.ErrorManager @@ -26,6 +25,8 @@ import java.io.InputStreamReader import java.io.OutputStreamWriter import java.net.URL import java.nio.charset.StandardCharsets +import java.nio.file.Files +import java.nio.file.StandardCopyOption import java.util.concurrent.CompletableFuture import java.util.concurrent.atomic.AtomicBoolean import kotlin.time.Duration.Companion.minutes @@ -33,10 +34,10 @@ import kotlin.time.Duration.Companion.minutes class RepoManager(private val configLocation: File) { private val gson get() = ConfigManager.gson - private var latestRepoCommit: String? = null val repoLocation: File = File(configLocation, "repo") private var error = false private var lastRepoUpdate = SimpleTimeMark.now() + private var repoDownloadFailed = false companion object { @@ -44,6 +45,7 @@ class RepoManager(private val configLocation: File) { val successfulConstants = mutableListOf() val unsuccessfulConstants = mutableListOf() + var usingBackupRepo = false private var lastConstant: String? = null @@ -62,7 +64,11 @@ class RepoManager(private val configLocation: File) { fun loadRepoInformation() { atomicShouldManuallyReload.set(true) if (config.repoAutoUpdate) { - fetchRepository(false).thenRun(this::reloadRepository) + fetchRepository(false).thenRun { + if (repoDownloadFailed) { + switchToBackupRepo() + } + }.thenRun { reloadRepository() } } else { reloadRepository() } @@ -73,7 +79,10 @@ class RepoManager(private val configLocation: File) { fun updateRepo() { atomicShouldManuallyReload.set(true) checkRepoLocation() - fetchRepository(true).thenRun { this.reloadRepository("Repo updated successfully.") } + fetchRepository(true).thenRun { + if (unsuccessfulConstants.isNotEmpty() || usingBackupRepo) return@thenRun + this.reloadRepository("Repo updated successfully.") + } } fun reloadLocalRepo() { @@ -84,8 +93,8 @@ class RepoManager(private val configLocation: File) { private fun fetchRepository(command: Boolean): CompletableFuture { return CompletableFuture.supplyAsync { try { - val currentCommitJSON: JsonObject? = getJsonFromFile(File(configLocation, "currentCommit.json")) - latestRepoCommit = null + val currentDownloadedCommit = readCurrentCommit() + var latestRepoCommit: String? try { InputStreamReader(URL(getCommitApiUrl()).openStream()) .use { inReader -> @@ -97,13 +106,15 @@ class RepoManager(private val configLocation: File) { e, "Error while loading data from repo", "command" to command, - "currentCommitJSON" to currentCommitJSON, + "currentDownloadedCommit" to currentDownloadedCommit, ) + repoDownloadFailed = true + return@supplyAsync false } - if (latestRepoCommit == null || latestRepoCommit!!.isEmpty()) return@supplyAsync false + val file = File(configLocation, "repo") if (file.exists() && - currentCommitJSON?.get("sha")?.asString == latestRepoCommit && + currentDownloadedCommit == latestRepoCommit && unsuccessfulConstants.isEmpty() && lastRepoUpdate.passedSince() < 1.minutes ) { @@ -114,18 +125,19 @@ class RepoManager(private val configLocation: File) { return@supplyAsync false } lastRepoUpdate = SimpleTimeMark.now() - RepoUtils.recursiveDelete(repoLocation) + repoLocation.mkdirs() val itemsZip = File(repoLocation, "sh-repo-main.zip") - try { - itemsZip.createNewFile() - } catch (e: IOException) { - return@supplyAsync false - } + itemsZip.createNewFile() + val url = URL(getDownloadUrl(latestRepoCommit)) val urlConnection = url.openConnection() urlConnection.connectTimeout = 15000 urlConnection.readTimeout = 30000 + + RepoUtils.recursiveDelete(repoLocation) + repoLocation.mkdirs() + try { urlConnection.getInputStream().use { `is` -> FileUtils.copyInputStreamToFile( @@ -140,19 +152,15 @@ class RepoManager(private val configLocation: File) { "url" to url, "command" to command, ) + repoDownloadFailed = true return@supplyAsync false } RepoUtils.unzipIgnoreFirstFolder( itemsZip.absolutePath, repoLocation.absolutePath, ) - if (currentCommitJSON == null || currentCommitJSON["sha"].asString != latestRepoCommit) { - val newCurrentCommitJSON = JsonObject() - newCurrentCommitJSON.addProperty("sha", latestRepoCommit) - try { - writeJson(newCurrentCommitJSON, File(configLocation, "currentCommit.json")) - } catch (ignored: IOException) { - } + if (currentDownloadedCommit == null || currentDownloadedCommit != latestRepoCommit) { + writeCurrentCommit(latestRepoCommit) } } catch (e: Exception) { ErrorManager.logErrorWithData( @@ -160,7 +168,10 @@ class RepoManager(private val configLocation: File) { "Failed to download SkyHanni Repo", "command" to command, ) + repoDownloadFailed = true } + repoDownloadFailed = false + usingBackupRepo = false true } } @@ -203,28 +214,18 @@ class RepoManager(private val configLocation: File) { return comp } - @SubscribeEvent - fun onDebugDataCollect(event: DebugDataCollectEvent) { - event.title("Repo Status") - - if (unsuccessfulConstants.isEmpty() && successfulConstants.isNotEmpty()) { - event.addIrrelevant("Repo working fine") - return + private fun writeCurrentCommit(commit: String?) { + val newCurrentCommitJSON = JsonObject() + newCurrentCommitJSON.addProperty("sha", commit) + try { + writeJson(newCurrentCommitJSON, File(configLocation, "currentCommit.json")) + } catch (ignored: IOException) { } + } - event.addData { - add("Successful Constants (${successfulConstants.size}):") - - add("Unsuccessful Constants (${unsuccessfulConstants.size}):") - - for ((i, constant) in unsuccessfulConstants.withIndex()) { - add(" - $constant") - if (i == 5) { - add("...") - break - } - } - } + private fun readCurrentCommit(): String? { + val currentCommitJSON: JsonObject? = getJsonFromFile(File(configLocation, "currentCommit.json")) + return currentCommitJSON?.get("sha")?.asString } fun displayRepoStatus(joinEvent: Boolean) { @@ -238,6 +239,7 @@ class RepoManager(private val configLocation: File) { ).asComponent(), ) text.add("§7Repo Auto Update Value: §c${config.repoAutoUpdate}".asComponent()) + text.add("§7Backup Repo Value: §c${usingBackupRepo}".asComponent()) text.add("§7If you have Repo Auto Update turned off, please try turning that on.".asComponent()) text.add("§cUnsuccessful Constants §7(${unsuccessfulConstants.size}):".asComponent()) @@ -248,11 +250,12 @@ class RepoManager(private val configLocation: File) { } return } + val currentCommit = readCurrentCommit() if (unsuccessfulConstants.isEmpty() && successfulConstants.isNotEmpty()) { - ChatUtils.chat("Repo working fine! Commit hash: $latestRepoCommit", prefixColor = "§a") + ChatUtils.chat("Repo working fine! Commit hash: $currentCommit", prefixColor = "§a") return } - ChatUtils.chat("Repo has errors! Commit has: ${latestRepoCommit ?: "null"}", prefixColor = "§c") + ChatUtils.chat("Repo has errors! Commit hash: $currentCommit", prefixColor = "§c") if (successfulConstants.isNotEmpty()) ChatUtils.chat( "Successful Constants §7(${successfulConstants.size}):", prefixColor = "§a", @@ -348,4 +351,27 @@ class RepoManager(private val configLocation: File) { resetRepositoryLocation() } } + + // Code taken from NotEnoughUpdates + private fun switchToBackupRepo() { + usingBackupRepo = true + println("Attempting to switch to backup repo") + + try { + repoLocation.mkdirs() + val destinationFile = File(repoLocation, "sh-repo-main.zip").apply { createNewFile() } + val destinationPath = destinationFile.toPath() + + val inputStream = RepoManager::class.java.classLoader.getResourceAsStream("assets/skyhanni/repo.zip") + ?: throw IOException("Failed to find backup repo") + + Files.copy(inputStream, destinationPath, StandardCopyOption.REPLACE_EXISTING) + RepoUtils.unzipIgnoreFirstFolder(destinationPath.toAbsolutePath().toString(), repoLocation.absolutePath) + writeCurrentCommit("backup-repo") + + println("Successfully switched to backup repo") + } catch (e: Exception) { + ErrorManager.logErrorWithData(e, "Failed to switch to backup repo") + } + } } diff --git a/src/main/java/at/hannibal2/skyhanni/test/DebugCommand.kt b/src/main/java/at/hannibal2/skyhanni/test/DebugCommand.kt index 76b729ae76bd..f464a66ce191 100644 --- a/src/main/java/at/hannibal2/skyhanni/test/DebugCommand.kt +++ b/src/main/java/at/hannibal2/skyhanni/test/DebugCommand.kt @@ -30,15 +30,14 @@ object DebugCommand { if (search.equalsIgnoreColor("all")) { "search for everything:" } else "search '$search':" - } else "no search specified, only showing interesting stuff:" + } else "no search specified, only showing interesting stuff:", ) val event = DebugDataCollectEvent(list, search) // calling default debug stuff player(event) - repoAutoUpdate(event) - repoLocation(event) + repoData(event) globalRender(event) skyblockStatus(event) profileName(event) @@ -144,20 +143,21 @@ object DebugCommand { } } - private fun repoAutoUpdate(event: DebugDataCollectEvent) { - event.title("Repo Auto Update") - if (SkyHanniMod.feature.dev.repo.repoAutoUpdate) { - event.addIrrelevant("normal enabled") - } else { - event.addData("The repo does not auto update because auto update is disabled!") + private fun repoData(event: DebugDataCollectEvent) { + event.title("Repo Information") + event.addIrrelevant { + add(" repoAutoUpdate: ${SkyHanniMod.feature.dev.repo.repoAutoUpdate}") + add(" usingBackupRepo: ${RepoManager.usingBackupRepo}") + add(" repoLocation: '${RepoManager.getRepoLocation()}'") + if (RepoManager.unsuccessfulConstants.isNotEmpty()) { + add(" unsuccessful constants:") + for (constant in RepoManager.unsuccessfulConstants) { + add(" - $constant") + } + } } } - private fun repoLocation(event: DebugDataCollectEvent) { - event.title("Repo Location") - event.addIrrelevant("repo location: '${RepoManager.getRepoLocation()}'") - } - private fun player(event: DebugDataCollectEvent) { event.title("Player") event.addIrrelevant { diff --git a/src/main/java/at/hannibal2/skyhanni/utils/repopatterns/RepoPatternManager.kt b/src/main/java/at/hannibal2/skyhanni/utils/repopatterns/RepoPatternManager.kt index 57a5852a3a81..505793300559 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/repopatterns/RepoPatternManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/repopatterns/RepoPatternManager.kt @@ -4,6 +4,7 @@ import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.api.event.HandleEvent import at.hannibal2.skyhanni.config.ConfigManager import at.hannibal2.skyhanni.config.features.dev.RepoPatternConfig +import at.hannibal2.skyhanni.data.repo.RepoManager import at.hannibal2.skyhanni.events.ConfigLoadEvent import at.hannibal2.skyhanni.events.LorenzEvent import at.hannibal2.skyhanni.events.RepositoryReloadEvent @@ -78,7 +79,8 @@ object RepoPatternManager { } } - val localLoading: Boolean get() = config.forceLocal.get() || (!insideTest && PlatformUtils.isDevEnvironment) + private val localLoading: Boolean + get() = config.forceLocal.get() || (!insideTest && PlatformUtils.isDevEnvironment) || RepoManager.usingBackupRepo private val logger = LogManager.getLogger("SkyHanni") From 28086af0aa4ade91b6e1c46f29b659230d45af57 Mon Sep 17 00:00:00 2001 From: Empa <42304516+ItsEmpa@users.noreply.github.com> Date: Wed, 16 Oct 2024 20:22:57 +0200 Subject: [PATCH 15/26] Backend: Event Objects (#2744) Co-authored-by: Empa Co-authored-by: Cal --- src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt | 2 +- src/main/java/at/hannibal2/skyhanni/api/CollectionAPI.kt | 4 ++-- src/main/java/at/hannibal2/skyhanni/api/FmlEventApi.kt | 2 +- .../java/at/hannibal2/skyhanni/data/EntityMovementData.kt | 4 ++-- .../java/at/hannibal2/skyhanni/data/GardenCropMilestones.kt | 2 +- src/main/java/at/hannibal2/skyhanni/data/GuiData.kt | 2 +- src/main/java/at/hannibal2/skyhanni/data/SackAPI.kt | 2 +- src/main/java/at/hannibal2/skyhanni/data/SlayerAPI.kt | 2 +- .../at/hannibal2/skyhanni/events/CollectionUpdateEvent.kt | 4 +++- .../hannibal2/skyhanni/events/CropMilestoneUpdateEvent.kt | 4 +++- .../hannibal2/skyhanni/events/DungeonBossRoomEnterEvent.kt | 4 +++- .../java/at/hannibal2/skyhanni/events/LorenzWarpEvent.kt | 3 --- .../java/at/hannibal2/skyhanni/events/NEURenderEvent.kt | 5 ++--- .../at/hannibal2/skyhanni/events/SackDataUpdateEvent.kt | 4 +++- .../java/at/hannibal2/skyhanni/events/SkyHanniWarpEvent.kt | 5 +++++ .../hannibal2/skyhanni/events/SlayerQuestCompleteEvent.kt | 4 +++- .../hannibal2/skyhanni/events/bingo/BingoCardUpdateEvent.kt | 2 +- .../skyhanni/events/garden/pests/PestUpdateEvent.kt | 2 +- .../skyhanni/events/minecraft/ClientDisconnectEvent.kt | 2 +- .../hannibal2/skyhanni/events/utils/PreInitFinishedEvent.kt | 2 +- .../skyhanni/features/bingo/card/BingoCardReader.kt | 4 ++-- .../at/hannibal2/skyhanni/features/dungeon/DungeonAPI.kt | 2 +- .../hannibal2/skyhanni/features/dungeon/DungeonCopilot.kt | 3 ++- .../skyhanni/features/garden/farming/CropSpeedMeter.kt | 3 ++- .../features/garden/farming/GardenCropMilestoneDisplay.kt | 3 ++- .../garden/inventory/GardenCropMilestoneInventory.kt | 3 ++- .../at/hannibal2/skyhanni/features/garden/pests/PestAPI.kt | 2 +- .../features/garden/visitor/GardenVisitorFeatures.kt | 3 ++- .../at/hannibal2/skyhanni/features/mining/TunnelsMaps.kt | 6 +++--- .../skyhanni/features/slayer/SlayerProfitTracker.kt | 3 ++- .../skyhanni/mixins/transformers/MixinNEUOverlay.java | 2 +- 31 files changed, 56 insertions(+), 39 deletions(-) delete mode 100644 src/main/java/at/hannibal2/skyhanni/events/LorenzWarpEvent.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/events/SkyHanniWarpEvent.kt diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt index 12ad96191083..2c14076a93ba 100644 --- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt +++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt @@ -61,7 +61,7 @@ class SkyHanniMod { CommandRegistrationEvent.post() - PreInitFinishedEvent().post() + PreInitFinishedEvent.post() } @Mod.EventHandler diff --git a/src/main/java/at/hannibal2/skyhanni/api/CollectionAPI.kt b/src/main/java/at/hannibal2/skyhanni/api/CollectionAPI.kt index 1f5adacf70ab..2584b6616406 100644 --- a/src/main/java/at/hannibal2/skyhanni/api/CollectionAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/api/CollectionAPI.kt @@ -60,7 +60,7 @@ object CollectionAPI { val internalName = incorrectCollectionNames[name] ?: NEUInternalName.fromItemName(name) collectionValue[internalName] = counter } - CollectionUpdateEvent().postAndCatch() + CollectionUpdateEvent.post() } if (inventoryName.endsWith(" Collections")) { @@ -83,7 +83,7 @@ object CollectionAPI { collectionValue[internalName] = counter } } - CollectionUpdateEvent().postAndCatch() + CollectionUpdateEvent.post() } } diff --git a/src/main/java/at/hannibal2/skyhanni/api/FmlEventApi.kt b/src/main/java/at/hannibal2/skyhanni/api/FmlEventApi.kt index c2b1571f4792..0adb824a5a6a 100644 --- a/src/main/java/at/hannibal2/skyhanni/api/FmlEventApi.kt +++ b/src/main/java/at/hannibal2/skyhanni/api/FmlEventApi.kt @@ -12,7 +12,7 @@ object FmlEventApi { @SubscribeEvent fun onDisconnect(event: FMLNetworkEvent.ClientDisconnectionFromServerEvent) { - ClientDisconnectEvent().post() + ClientDisconnectEvent.post() } @SubscribeEvent diff --git a/src/main/java/at/hannibal2/skyhanni/data/EntityMovementData.kt b/src/main/java/at/hannibal2/skyhanni/data/EntityMovementData.kt index d38b6824b864..db9044ef2e35 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/EntityMovementData.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/EntityMovementData.kt @@ -4,7 +4,7 @@ import at.hannibal2.skyhanni.events.EntityMoveEvent import at.hannibal2.skyhanni.events.IslandChangeEvent import at.hannibal2.skyhanni.events.LorenzChatEvent import at.hannibal2.skyhanni.events.LorenzTickEvent -import at.hannibal2.skyhanni.events.LorenzWarpEvent +import at.hannibal2.skyhanni.events.SkyHanniWarpEvent import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.DelayedRun @@ -104,7 +104,7 @@ object EntityMovementData { if (!LorenzUtils.inSkyBlock) return if (!warpingPattern.matches(event.message)) return DelayedRun.runNextTick { - LorenzWarpEvent().postAndCatch() + SkyHanniWarpEvent.post() } } diff --git a/src/main/java/at/hannibal2/skyhanni/data/GardenCropMilestones.kt b/src/main/java/at/hannibal2/skyhanni/data/GardenCropMilestones.kt index 5e236c4c5f64..d8fab21f44cf 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/GardenCropMilestones.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/GardenCropMilestones.kt @@ -51,7 +51,7 @@ object GardenCropMilestones { crop.setCounter(amount) } } - CropMilestoneUpdateEvent().postAndCatch() + CropMilestoneUpdateEvent.post() GardenCropMilestonesCommunityFix.openInventory(event.inventoryItems) } diff --git a/src/main/java/at/hannibal2/skyhanni/data/GuiData.kt b/src/main/java/at/hannibal2/skyhanni/data/GuiData.kt index 5f2ca510bfef..688f8cc18c08 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/GuiData.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/GuiData.kt @@ -24,7 +24,7 @@ object GuiData { var preDrawEventCancelled = false - @SubscribeEvent(priority = EventPriority.HIGH) + @HandleEvent(priority = HandleEvent.HIGH) fun onNeuRenderEvent(event: NEURenderEvent) { if (preDrawEventCancelled) event.cancel() } diff --git a/src/main/java/at/hannibal2/skyhanni/data/SackAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/SackAPI.kt index 24dacafbd2ee..5235284ffefc 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/SackAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/SackAPI.kt @@ -334,7 +334,7 @@ object SackAPI { ProfileStorageData.sackProfiles?.sackContents = sackData SkyHanniMod.configManager.saveConfig(ConfigFileType.SACKS, "saving-data") - SackDataUpdateEvent().postAndCatch() + SackDataUpdateEvent.post() } data class SackGemstone( diff --git a/src/main/java/at/hannibal2/skyhanni/data/SlayerAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/SlayerAPI.kt index 0d91c7f62856..2eb2bc293e33 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/SlayerAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/SlayerAPI.kt @@ -82,7 +82,7 @@ object SlayerAPI { } if (event.message == " §r§a§lSLAYER QUEST COMPLETE!") { - SlayerQuestCompleteEvent().postAndCatch() + SlayerQuestCompleteEvent.post() } } diff --git a/src/main/java/at/hannibal2/skyhanni/events/CollectionUpdateEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/CollectionUpdateEvent.kt index f4c46d0b75d5..2dd016e95754 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/CollectionUpdateEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/CollectionUpdateEvent.kt @@ -1,3 +1,5 @@ package at.hannibal2.skyhanni.events -class CollectionUpdateEvent : LorenzEvent() +import at.hannibal2.skyhanni.api.event.SkyHanniEvent + +object CollectionUpdateEvent : SkyHanniEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/CropMilestoneUpdateEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/CropMilestoneUpdateEvent.kt index 8da8b20f75ce..feebc16afb54 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/CropMilestoneUpdateEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/CropMilestoneUpdateEvent.kt @@ -1,3 +1,5 @@ package at.hannibal2.skyhanni.events -class CropMilestoneUpdateEvent : LorenzEvent() +import at.hannibal2.skyhanni.api.event.SkyHanniEvent + +object CropMilestoneUpdateEvent : SkyHanniEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/DungeonBossRoomEnterEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/DungeonBossRoomEnterEvent.kt index 9f372d5c31c2..ec1f35412f58 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/DungeonBossRoomEnterEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/DungeonBossRoomEnterEvent.kt @@ -1,3 +1,5 @@ package at.hannibal2.skyhanni.events -class DungeonBossRoomEnterEvent : LorenzEvent() +import at.hannibal2.skyhanni.api.event.SkyHanniEvent + +object DungeonBossRoomEnterEvent : SkyHanniEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/LorenzWarpEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/LorenzWarpEvent.kt deleted file mode 100644 index 170dcabe941d..000000000000 --- a/src/main/java/at/hannibal2/skyhanni/events/LorenzWarpEvent.kt +++ /dev/null @@ -1,3 +0,0 @@ -package at.hannibal2.skyhanni.events - -class LorenzWarpEvent : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/NEURenderEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/NEURenderEvent.kt index c2bcc9b49a0e..af85871783d4 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/NEURenderEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/NEURenderEvent.kt @@ -1,6 +1,5 @@ package at.hannibal2.skyhanni.events -import net.minecraftforge.fml.common.eventhandler.Cancelable +import at.hannibal2.skyhanni.api.event.CancellableSkyHanniEvent -@Cancelable -class NEURenderEvent : LorenzEvent() +class NEURenderEvent : CancellableSkyHanniEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/SackDataUpdateEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/SackDataUpdateEvent.kt index f9e3831d15f0..f156d31fc5cb 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/SackDataUpdateEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/SackDataUpdateEvent.kt @@ -1,3 +1,5 @@ package at.hannibal2.skyhanni.events -class SackDataUpdateEvent : LorenzEvent() +import at.hannibal2.skyhanni.api.event.SkyHanniEvent + +object SackDataUpdateEvent : SkyHanniEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/SkyHanniWarpEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/SkyHanniWarpEvent.kt new file mode 100644 index 000000000000..18560da4c4c0 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/events/SkyHanniWarpEvent.kt @@ -0,0 +1,5 @@ +package at.hannibal2.skyhanni.events + +import at.hannibal2.skyhanni.api.event.SkyHanniEvent + +object SkyHanniWarpEvent : SkyHanniEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/SlayerQuestCompleteEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/SlayerQuestCompleteEvent.kt index b7e0edfedd59..6b0185fe10bf 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/SlayerQuestCompleteEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/SlayerQuestCompleteEvent.kt @@ -1,3 +1,5 @@ package at.hannibal2.skyhanni.events -class SlayerQuestCompleteEvent : LorenzEvent() +import at.hannibal2.skyhanni.api.event.SkyHanniEvent + +object SlayerQuestCompleteEvent : SkyHanniEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/bingo/BingoCardUpdateEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/bingo/BingoCardUpdateEvent.kt index de9a83214a85..eed37ff0a6a0 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/bingo/BingoCardUpdateEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/bingo/BingoCardUpdateEvent.kt @@ -2,4 +2,4 @@ package at.hannibal2.skyhanni.events.bingo import at.hannibal2.skyhanni.api.event.SkyHanniEvent -class BingoCardUpdateEvent : SkyHanniEvent() +object BingoCardUpdateEvent : SkyHanniEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/garden/pests/PestUpdateEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/garden/pests/PestUpdateEvent.kt index c4c299b1338f..54df3b20b0ae 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/garden/pests/PestUpdateEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/garden/pests/PestUpdateEvent.kt @@ -2,4 +2,4 @@ package at.hannibal2.skyhanni.events.garden.pests import at.hannibal2.skyhanni.api.event.SkyHanniEvent -class PestUpdateEvent : SkyHanniEvent() +object PestUpdateEvent : SkyHanniEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/minecraft/ClientDisconnectEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/minecraft/ClientDisconnectEvent.kt index 6c7a5e8a1b4c..1a6b31c4c9bf 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/minecraft/ClientDisconnectEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/minecraft/ClientDisconnectEvent.kt @@ -2,4 +2,4 @@ package at.hannibal2.skyhanni.events.minecraft import at.hannibal2.skyhanni.api.event.SkyHanniEvent -class ClientDisconnectEvent : SkyHanniEvent() +object ClientDisconnectEvent : SkyHanniEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/utils/PreInitFinishedEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/utils/PreInitFinishedEvent.kt index 1d52761ed2dd..e2ab833a7643 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/utils/PreInitFinishedEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/utils/PreInitFinishedEvent.kt @@ -2,4 +2,4 @@ package at.hannibal2.skyhanni.events.utils import at.hannibal2.skyhanni.api.event.SkyHanniEvent -class PreInitFinishedEvent : SkyHanniEvent() +object PreInitFinishedEvent : SkyHanniEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardReader.kt b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardReader.kt index 1afa6859dc3f..98b266053e04 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardReader.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardReader.kt @@ -96,7 +96,7 @@ object BingoCardReader { } BingoAPI.lastBingoCardOpenTime = SimpleTimeMark.now() - BingoCardUpdateEvent().post() + BingoCardUpdateEvent.post() } private fun bingoGoalDifference(bingoGoal: BingoGoal, new: Double) { @@ -163,7 +163,7 @@ object BingoCardReader { val goal = BingoAPI.personalGoals.firstOrNull { it.displayName == name } ?: return goal.done = true BingoGoalReachedEvent(goal).post() - BingoCardUpdateEvent().post() + BingoCardUpdateEvent.post() } private fun BingoData.getDescriptionLine() = "§7" + note.joinToString(" ") diff --git a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonAPI.kt index 254e04dca523..95c7a3f87487 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonAPI.kt @@ -123,7 +123,7 @@ object DungeonAPI { val message = rawMessage.removeColor() val bossName = message.substringAfter("[BOSS] ").substringBefore(":").trim() if ((bossName != "The Watcher") && dungeonFloor != null && checkBossName(bossName) && !inBossRoom) { - DungeonBossRoomEnterEvent().postAndCatch() + DungeonBossRoomEnterEvent.post() inBossRoom = true } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonCopilot.kt b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonCopilot.kt index 11d749b668fa..e4bc9b0fc838 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonCopilot.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonCopilot.kt @@ -1,6 +1,7 @@ package at.hannibal2.skyhanni.features.dungeon import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.api.event.HandleEvent import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator import at.hannibal2.skyhanni.events.CheckRenderEntityEvent import at.hannibal2.skyhanni.events.DungeonBossRoomEnterEvent @@ -133,7 +134,7 @@ object DungeonCopilot { searchForKey = true } - @SubscribeEvent + @HandleEvent fun onDungeonBossRoomEnter(event: DungeonBossRoomEnterEvent) { changeNextStep("Defeat the boss! Good luck :)") } diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/CropSpeedMeter.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/CropSpeedMeter.kt index 9a47acaa1064..924ea00f7f8d 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/CropSpeedMeter.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/CropSpeedMeter.kt @@ -1,5 +1,6 @@ package at.hannibal2.skyhanni.features.garden.farming +import at.hannibal2.skyhanni.api.event.HandleEvent import at.hannibal2.skyhanni.data.GardenCropMilestones.getCounter import at.hannibal2.skyhanni.events.CropClickEvent import at.hannibal2.skyhanni.events.CropMilestoneUpdateEvent @@ -76,7 +77,7 @@ object CropSpeedMeter { return list } - @SubscribeEvent + @HandleEvent fun onCropMilestoneUpdate(event: CropMilestoneUpdateEvent) { if (!isEnabled()) return val counters = mutableMapOf() diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenCropMilestoneDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenCropMilestoneDisplay.kt index aca1751b0082..734df7630c47 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenCropMilestoneDisplay.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenCropMilestoneDisplay.kt @@ -1,5 +1,6 @@ package at.hannibal2.skyhanni.features.garden.farming +import at.hannibal2.skyhanni.api.event.HandleEvent import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator import at.hannibal2.skyhanni.config.features.garden.cropmilestones.CropMilestonesConfig.MilestoneTextEntry import at.hannibal2.skyhanni.config.features.garden.cropmilestones.CropMilestonesConfig.TimeFormatEntry @@ -99,7 +100,7 @@ object GardenCropMilestoneDisplay { } } - @SubscribeEvent + @HandleEvent fun onCropMilestoneUpdate(event: CropMilestoneUpdateEvent) { needsInventory = false GardenBestCropTime.updateTimeTillNextCrop() diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/inventory/GardenCropMilestoneInventory.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/inventory/GardenCropMilestoneInventory.kt index e0cb070739b9..826913669b01 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/inventory/GardenCropMilestoneInventory.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/inventory/GardenCropMilestoneInventory.kt @@ -1,5 +1,6 @@ package at.hannibal2.skyhanni.features.garden.inventory +import at.hannibal2.skyhanni.api.event.HandleEvent import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator import at.hannibal2.skyhanni.data.GardenCropMilestones import at.hannibal2.skyhanni.data.GardenCropMilestones.getCounter @@ -24,7 +25,7 @@ object GardenCropMilestoneInventory { private var average = -1.0 private val config get() = GardenAPI.config - @SubscribeEvent + @HandleEvent fun onCropMilestoneUpdate(event: CropMilestoneUpdateEvent) { if (!config.number.averageCropMilestone) return diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/pests/PestAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/pests/PestAPI.kt index d49de324c851..e239caeab5b3 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/pests/PestAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/pests/PestAPI.kt @@ -155,7 +155,7 @@ object PestAPI { private fun updatePests() { if (!firstScoreboardCheck) return fixPests() - PestUpdateEvent().post() + PestUpdateEvent.post() } @HandleEvent(onlyOnIsland = IslandType.GARDEN) diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorFeatures.kt index 641ad717e403..c9f8b22b2dbc 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorFeatures.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorFeatures.kt @@ -1,5 +1,6 @@ package at.hannibal2.skyhanni.features.garden.visitor +import at.hannibal2.skyhanni.api.event.HandleEvent import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator import at.hannibal2.skyhanni.config.features.garden.visitor.VisitorConfig.HighlightMode import at.hannibal2.skyhanni.data.IslandType @@ -336,7 +337,7 @@ object GardenVisitorFeatures { } } - @SubscribeEvent + @HandleEvent fun onSackUpdate(event: SackDataUpdateEvent) { update() } diff --git a/src/main/java/at/hannibal2/skyhanni/features/mining/TunnelsMaps.kt b/src/main/java/at/hannibal2/skyhanni/features/mining/TunnelsMaps.kt index 2d7487ddcb15..c3d89d98e183 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/mining/TunnelsMaps.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/mining/TunnelsMaps.kt @@ -17,7 +17,7 @@ import at.hannibal2.skyhanni.events.LorenzKeyPressEvent import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent import at.hannibal2.skyhanni.events.LorenzTickEvent import at.hannibal2.skyhanni.events.LorenzToolTipEvent -import at.hannibal2.skyhanni.events.LorenzWarpEvent +import at.hannibal2.skyhanni.events.SkyHanniWarpEvent import at.hannibal2.skyhanni.events.RepositoryReloadEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.test.command.ErrorManager @@ -502,8 +502,8 @@ object TunnelsMaps { } } - @SubscribeEvent - fun onLorenzWarp(event: LorenzWarpEvent) { + @HandleEvent + fun onWarp(event: SkyHanniWarpEvent) { if (!isEnabled()) return if (goal != null) { DelayedRun.runNextTick { diff --git a/src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerProfitTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerProfitTracker.kt index defde1cf2b73..63c0adbc88a1 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerProfitTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerProfitTracker.kt @@ -1,6 +1,7 @@ package at.hannibal2.skyhanni.features.slayer import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.api.event.HandleEvent import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator import at.hannibal2.skyhanni.config.storage.ProfileSpecificStorage import at.hannibal2.skyhanni.data.ItemAddManager @@ -143,7 +144,7 @@ object SlayerProfitTracker { } } - @SubscribeEvent + @HandleEvent fun onQuestComplete(event: SlayerQuestCompleteEvent) { getTracker()?.modify { it.slayerCompletedCount++ diff --git a/src/main/java/at/hannibal2/skyhanni/mixins/transformers/MixinNEUOverlay.java b/src/main/java/at/hannibal2/skyhanni/mixins/transformers/MixinNEUOverlay.java index 9ac228f29cd4..9f6e1bb1fc96 100644 --- a/src/main/java/at/hannibal2/skyhanni/mixins/transformers/MixinNEUOverlay.java +++ b/src/main/java/at/hannibal2/skyhanni/mixins/transformers/MixinNEUOverlay.java @@ -12,7 +12,7 @@ public class MixinNEUOverlay { @Inject(method = "render", at = @At("HEAD"), cancellable = true, remap = false) private void render(boolean hoverInv, CallbackInfo ci) { - if (new NEURenderEvent().postAndCatch()) { + if (new NEURenderEvent().post()) { ci.cancel(); } } From be1e1758c21329e1daec2446f2907d69cae14b3b Mon Sep 17 00:00:00 2001 From: hannibal2 <24389977+hannibal00212@users.noreply.github.com> Date: Wed, 16 Oct 2024 20:27:17 +0200 Subject: [PATCH 16/26] cleanup debug --- src/main/java/at/hannibal2/skyhanni/data/SlayerAPI.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/at/hannibal2/skyhanni/data/SlayerAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/SlayerAPI.kt index 2eb2bc293e33..20dbcdfd1a83 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/SlayerAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/SlayerAPI.kt @@ -17,6 +17,7 @@ import at.hannibal2.skyhanni.utils.NEUItems.getPrice import at.hannibal2.skyhanni.utils.NumberUtil.shortFormat import at.hannibal2.skyhanni.utils.RecalculatingValue import at.hannibal2.skyhanni.utils.SimpleTimeMark +import at.hannibal2.skyhanni.utils.StringUtils.removeColor import at.hannibal2.skyhanni.utils.TimeLimitedCache import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import kotlin.time.Duration.Companion.minutes @@ -69,7 +70,7 @@ object SlayerAPI { add("activeSlayer: $activeSlayer") add("isInCorrectArea: $isInCorrectArea") add("isInAnyArea: $isInAnyArea") - add("latestSlayerProgress: $latestSlayerProgress") + add("latestSlayerProgress: ${latestSlayerProgress.removeColor()}") } } From d7941ebf223837faadca8a911066411eca97cb7b Mon Sep 17 00:00:00 2001 From: hannibal2 <24389977+hannibal00212@users.noreply.github.com> Date: Wed, 16 Oct 2024 21:29:12 +0200 Subject: [PATCH 17/26] Version 0.28 Beta 4 --- docs/CHANGELOG.md | 27 +++++++++++++++++++++++++++ docs/FEATURES.md | 2 ++ root.gradle.kts | 2 +- 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 41750a866eb3..09734937ee97 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -10,6 +10,8 @@ + Shows your progress in the Warp Menu. + Can be automatically hidden when an island is complete. + Added the ability to block opening the Chocolate Factory when Booster Cookie is inactive. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2713) ++ Added a feature to block opening Hoppity's trade menu from Abiphone calls if you do not have coins in your purse. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2664) ++ Added the ability to prevent closing Meal Eggs that have Rabbit the Fish inside. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2712) #### Inventory Features @@ -66,6 +68,14 @@ + Added support for detecting and handling Inquisitor spawn messages from other mods from chat. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2720) +#### Fishing Improvements + ++ Added an option to always display the Barn Fishing Timer anywhere. - NeoNyaa (https://github.com/hannibal002/SkyHanni/pull/2735) + +#### Hoppity Improvements + ++ Improved the Time Tower Usage Warning so it doesn't spam messages. - MTOnline (https://github.com/hannibal002/SkyHanni/pull/2730) + #### Misc Improvements + Added distance display to waypoints created by Patcher's Send Coords feature. - jani (https://github.com/hannibal002/SkyHanni/pull/2704) @@ -88,12 +98,15 @@ + Fixed the debug feature that allows you to add/remove stars being enabled by default. - CalMWolfs (https://github.com/hannibal002/SkyHanni/pull/2715) + Fixed displaying the Guardian warning text in the Experimentation Table even when using a Guardian Pet. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2718) + Fixed locked Ultimate enchantments being hidden by Enchant Parsing. - martimavocado (https://github.com/hannibal002/SkyHanni/pull/2732) ++ Fixed Chest Value Display on Carpentry Chests. - fazfoxy (https://github.com/hannibal002/SkyHanni/pull/2743) ++ Fixed Compact Item Stars. - Empa, Fazfoxy (https://github.com/hannibal002/SkyHanni/pull/2741) #### Combat Fixes + Fixed Ghost Counter display appearing while in incorrect areas on the map. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2696) + Fixed Ashfang Blazes sometimes being highlighted with the wrong color. - Empa (https://github.com/hannibal002/SkyHanni/pull/2112) + Fixed Ashfang Reset Cooldown counting in the wrong direction. - Empa (https://github.com/hannibal002/SkyHanni/pull/2112) ++ Fixed Millennia-Aged Blaze not being highlighted by the Area Boss Highlight feature. - jani (https://github.com/hannibal002/SkyHanni/pull/2707) #### Custom Scoreboard Fixes @@ -102,6 +115,7 @@ #### Hoppity Fixes + Fixed the chocolate egg share message sometimes displaying the wrong location name. - martimavocado (https://github.com/hannibal002/SkyHanni/pull/2711) ++ Fixed El Dorado not receiving a compacted chat message. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2742) #### Garden Fixes @@ -119,6 +133,14 @@ + Fixed /shtranslate not working in most cases. - Obsidian (https://github.com/hannibal002/SkyHanni/pull/2693) +#### Mining Fixes + ++ Fixed a crash when attempting to edit the Flowstate Helper config. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2740) + +#### Misc Fixes + ++ Fixed SkyHanni messages being sent twice. - CalMWolfs (https://github.com/hannibal002/SkyHanni/pull/2736) + ### Technical Details + Assigned 'backend' label to PRs with 'backend' in the title. - CalMWolfs (https://github.com/hannibal002/SkyHanni/pull/2690) @@ -136,6 +158,11 @@ + Added EntityLeaveWorldEvent. - Empa (https://github.com/hannibal002/SkyHanni/pull/2112) + Made command registration event-based. - j10a1n15, ThatGravyBoat (https://github.com/hannibal002/SkyHanni/pull/2642) + Added "line to the mob" handler. - Thunderblade73 (https://github.com/hannibal002/SkyHanni/pull/2717) ++ No longer use NEU GUI elements for the auto-update button. - CalMWolfs (https://github.com/hannibal002/SkyHanni/pull/2725) ++ Added SkyHanni notifications. - CalMWolfs (https://github.com/hannibal002/SkyHanni/pull/2630) ++ Moved Hoppity Warp Menu config to `HoppityWarpMenuConfig`. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2712) ++ Migrated some LorenzEvents without parameters to SkyHanniEvents. - Empa (https://github.com/hannibal002/SkyHanni/pull/2744) ++ Changed SkyHanniEvents without parameters to be objects. - Empa (https://github.com/hannibal002/SkyHanni/pull/2744) ## Version 0.27 diff --git a/docs/FEATURES.md b/docs/FEATURES.md index 5f6b36d1c048..e84276478bcd 100644 --- a/docs/FEATURES.md +++ b/docs/FEATURES.md @@ -1022,6 +1022,8 @@ Use `/sh` or `/skyhanni` to open the SkyHanni config in game. + Shows your progress in the Warp Menu. + Can be automatically hidden when an island is complete. + Added the ability to block opening the Chocolate Factory when Booster Cookie is inactive. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2713) ++ Added a feature to block opening Hoppity's trade menu from Abiphone calls if you do not have coins in your purse. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2664) ++ Added the ability to prevent closing Meal Eggs that have Rabbit the Fish inside. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2712) ### The Carnival diff --git a/root.gradle.kts b/root.gradle.kts index 521a10cdac42..ba687910cd70 100644 --- a/root.gradle.kts +++ b/root.gradle.kts @@ -14,7 +14,7 @@ plugins { allprojects { group = "at.hannibal2.skyhanni" - version = "0.28.Beta.3" + version = "0.28.Beta.4" repositories { mavenCentral() mavenLocal() From f4fa81ebd56882bf25261427f3ca6672e2782e0b Mon Sep 17 00:00:00 2001 From: hannibal2 <24389977+hannibal002@users.noreply.github.com> Date: Wed, 16 Oct 2024 22:52:12 +0200 Subject: [PATCH 18/26] Fixed a simple typo (#2748) --- .../at/hannibal2/skyhanni/features/combat/BestiaryData.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/at/hannibal2/skyhanni/features/combat/BestiaryData.kt b/src/main/java/at/hannibal2/skyhanni/features/combat/BestiaryData.kt index f40e437e5403..fd4ca137db36 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/combat/BestiaryData.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/combat/BestiaryData.kt @@ -448,7 +448,8 @@ object BestiaryData { return true } else if (name == "Search Results") { val loreList = stack.getLore() - if (loreList.size >= 2 && loreList[0].startsWith("§7Query: §a") && + if (loreList.size >= 2 && + loreList[0].startsWith("§7Query: §a") && loreList[1].startsWith("§7Results: §a") ) { return true @@ -464,7 +465,7 @@ object BestiaryData { enum class NumberType(val type: String) { INT("Normal (1, 2, 3)"), - ROMAN("Roman (I, II, III") + ROMAN("Roman (I, II, III)") } enum class DisplayType(val type: String) { From ef2ca6fbbdf89e56c71e9425f887450d362d13a4 Mon Sep 17 00:00:00 2001 From: Cal Date: Fri, 18 Oct 2024 23:17:34 +1100 Subject: [PATCH 19/26] fix wrong post type --- .../skyhanni/features/inventory/wardrobe/CustomWardrobe.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/wardrobe/CustomWardrobe.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/wardrobe/CustomWardrobe.kt index 32f0c6d0efcb..0c1d00c2b50a 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/wardrobe/CustomWardrobe.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/wardrobe/CustomWardrobe.kt @@ -246,7 +246,7 @@ object CustomWardrobe { val mcSlotId = slot.inventorySlots[armorIndex] // if the slot is null, we don't fire LorenzToolTipEvent at all. val mcSlot = InventoryUtils.getSlotAtIndex(mcSlotId) ?: return toolTips - LorenzToolTipEvent(mcSlot, stack, toolTips).postWithoutCatch() + LorenzToolTipEvent(mcSlot, stack, toolTips).postAndCatch() return toolTips } catch (e: Exception) { From cacff66c3d86b80f5868e70aad26eff41ad0092d Mon Sep 17 00:00:00 2001 From: hannibal2 <24389977+hannibal002@users.noreply.github.com> Date: Fri, 18 Oct 2024 16:29:51 +0200 Subject: [PATCH 20/26] Backend: More precise repo debug (#2747) Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com> --- .../skyhanni/data/repo/RepoManager.kt | 14 +++++++----- .../hannibal2/skyhanni/test/DebugCommand.kt | 22 ++++++++++++++++--- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/main/java/at/hannibal2/skyhanni/data/repo/RepoManager.kt b/src/main/java/at/hannibal2/skyhanni/data/repo/RepoManager.kt index 1d81502f3f61..3b5915fee01f 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/repo/RepoManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/repo/RepoManager.kt @@ -2,6 +2,7 @@ package at.hannibal2.skyhanni.data.repo import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.config.ConfigManager +import at.hannibal2.skyhanni.config.features.dev.RepositoryConfig import at.hannibal2.skyhanni.events.NeuRepositoryReloadEvent import at.hannibal2.skyhanni.events.RepositoryReloadEvent import at.hannibal2.skyhanni.test.command.ErrorManager @@ -59,6 +60,12 @@ class RepoManager(private val configLocation: File) { fun getRepoLocation(): String { return "${config.location.user}/${config.location.name}/${config.location.branch}" } + + private val defaultUser = "hannibal002" + private val defaultName = "SkyHanni-REPO" + private val defaultBranch = "main" + + fun RepositoryConfig.RepositoryLocation.hasDefaultSettings() = user == defaultUser && name == defaultName && branch == defaultBranch } fun loadRepoInformation() { @@ -317,12 +324,9 @@ class RepoManager(private val configLocation: File) { } fun resetRepositoryLocation(manual: Boolean = false) { - val defaultUser = "hannibal002" - val defaultName = "SkyHanni-Repo" - val defaultBranch = "main" with(config.location) { - if (user == defaultUser && name == defaultName && branch == defaultBranch) { + if (hasDefaultSettings()) { if (manual) { ChatUtils.chat("Repo settings are already on default!") } @@ -346,7 +350,7 @@ class RepoManager(private val configLocation: File) { } private fun checkRepoLocation() { - if (config.location.user.isEmpty() || config.location.name.isEmpty() || config.location.branch.isEmpty()) { + if (config.location.run { user.isEmpty() || name.isEmpty() || branch.isEmpty() }) { ChatUtils.userError("Invalid Repo settings detected, resetting default settings.") resetRepositoryLocation() } diff --git a/src/main/java/at/hannibal2/skyhanni/test/DebugCommand.kt b/src/main/java/at/hannibal2/skyhanni/test/DebugCommand.kt index f464a66ce191..d75b5abc6a57 100644 --- a/src/main/java/at/hannibal2/skyhanni/test/DebugCommand.kt +++ b/src/main/java/at/hannibal2/skyhanni/test/DebugCommand.kt @@ -5,6 +5,7 @@ import at.hannibal2.skyhanni.data.HypixelData import at.hannibal2.skyhanni.data.IslandType import at.hannibal2.skyhanni.data.ProfileStorageData import at.hannibal2.skyhanni.data.repo.RepoManager +import at.hannibal2.skyhanni.data.repo.RepoManager.Companion.hasDefaultSettings import at.hannibal2.skyhanni.events.DebugDataCollectEvent import at.hannibal2.skyhanni.utils.ChatUtils import at.hannibal2.skyhanni.utils.LorenzUtils @@ -145,10 +146,18 @@ object DebugCommand { private fun repoData(event: DebugDataCollectEvent) { event.title("Repo Information") - event.addIrrelevant { - add(" repoAutoUpdate: ${SkyHanniMod.feature.dev.repo.repoAutoUpdate}") + val config = SkyHanniMod.feature.dev.repo + + val hasDefaultSettings = config.location.hasDefaultSettings() + val list = buildList { + add(" repoAutoUpdate: ${config.repoAutoUpdate}") add(" usingBackupRepo: ${RepoManager.usingBackupRepo}") - add(" repoLocation: '${RepoManager.getRepoLocation()}'") + if (hasDefaultSettings) { + add((" repo location: default")) + } else { + add(" non-default repo location: '${RepoManager.getRepoLocation()}'") + } + if (RepoManager.unsuccessfulConstants.isNotEmpty()) { add(" unsuccessful constants:") for (constant in RepoManager.unsuccessfulConstants) { @@ -156,6 +165,13 @@ object DebugCommand { } } } + + val isRelevant = RepoManager.usingBackupRepo || RepoManager.unsuccessfulConstants.isNotEmpty() || !hasDefaultSettings + if (isRelevant) { + event.addData(list) + } else { + event.addIrrelevant(list) + } } private fun player(event: DebugDataCollectEvent) { From ead1f9ebf3882a6a65b6dd879d01c725c80f7e73 Mon Sep 17 00:00:00 2001 From: hannibal2 <24389977+hannibal002@users.noreply.github.com> Date: Fri, 18 Oct 2024 16:30:04 +0200 Subject: [PATCH 21/26] Backend: GraphAreaChangeEvent (#2754) Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com> --- .../skyhanni/events/skyblock/AreaChangeEvents.kt | 1 + .../features/combat/ghostcounter/GhostCounter.kt | 10 +++++----- .../features/event/hoppity/NucleusBarriersBox.kt | 10 +++++----- .../skyhanni/features/misc/IslandAreas.kt | 16 +++++++++++++--- 4 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/main/java/at/hannibal2/skyhanni/events/skyblock/AreaChangeEvents.kt b/src/main/java/at/hannibal2/skyhanni/events/skyblock/AreaChangeEvents.kt index b262ea9fbe44..340187030f2d 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/skyblock/AreaChangeEvents.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/skyblock/AreaChangeEvents.kt @@ -4,3 +4,4 @@ import at.hannibal2.skyhanni.api.event.SkyHanniEvent // Detect area changes by looking at the scoreboard. class ScoreboardAreaChangeEvent(val area: String, val previousArea: String?) : SkyHanniEvent() +class GraphAreaChangeEvent(val area: String, val previousArea: String?) : SkyHanniEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/features/combat/ghostcounter/GhostCounter.kt b/src/main/java/at/hannibal2/skyhanni/features/combat/ghostcounter/GhostCounter.kt index fe14093ef9d7..e0d3ba6d4d51 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/combat/ghostcounter/GhostCounter.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/combat/ghostcounter/GhostCounter.kt @@ -1,6 +1,7 @@ package at.hannibal2.skyhanni.features.combat.ghostcounter import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.api.event.HandleEvent import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator import at.hannibal2.skyhanni.config.features.combat.ghostcounter.GhostCounterConfig.GhostDisplayEntry import at.hannibal2.skyhanni.data.IslandType @@ -11,11 +12,11 @@ import at.hannibal2.skyhanni.events.ConfigLoadEvent import at.hannibal2.skyhanni.events.GuiRenderEvent import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent import at.hannibal2.skyhanni.events.LorenzChatEvent -import at.hannibal2.skyhanni.events.LorenzTickEvent import at.hannibal2.skyhanni.events.PurseChangeCause import at.hannibal2.skyhanni.events.PurseChangeEvent import at.hannibal2.skyhanni.events.SecondPassedEvent import at.hannibal2.skyhanni.events.TabListUpdateEvent +import at.hannibal2.skyhanni.events.skyblock.GraphAreaChangeEvent import at.hannibal2.skyhanni.features.combat.ghostcounter.GhostData.Option import at.hannibal2.skyhanni.features.combat.ghostcounter.GhostData.Option.KILLS import at.hannibal2.skyhanni.features.combat.ghostcounter.GhostData.bestiaryData @@ -25,7 +26,6 @@ import at.hannibal2.skyhanni.features.combat.ghostcounter.GhostUtil.isUsingCTGho import at.hannibal2.skyhanni.features.combat.ghostcounter.GhostUtil.preFormat import at.hannibal2.skyhanni.features.combat.ghostcounter.GhostUtil.prettyTime import at.hannibal2.skyhanni.features.inventory.bazaar.BazaarApi.getBazaarData -import at.hannibal2.skyhanni.features.misc.IslandAreas import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.ChatUtils import at.hannibal2.skyhanni.utils.ChatUtils.chat @@ -345,9 +345,9 @@ object GhostCounter { } } - @SubscribeEvent - fun onTick(event: LorenzTickEvent) { - inMist = IslandAreas.currentAreaName == "The Mist" + @HandleEvent + fun onAreaChange(event: GraphAreaChangeEvent) { + inMist = event.area == "The Mist" } @SubscribeEvent diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/NucleusBarriersBox.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/NucleusBarriersBox.kt index 47ab47a38240..562e67eb7dbf 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/NucleusBarriersBox.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/NucleusBarriersBox.kt @@ -1,10 +1,10 @@ package at.hannibal2.skyhanni.features.event.hoppity import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.api.event.HandleEvent import at.hannibal2.skyhanni.data.IslandType import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent -import at.hannibal2.skyhanni.events.LorenzTickEvent -import at.hannibal2.skyhanni.features.misc.IslandAreas +import at.hannibal2.skyhanni.events.skyblock.GraphAreaChangeEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.LorenzColor import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland @@ -58,9 +58,9 @@ object NucleusBarriersBox { ), } - @SubscribeEvent - fun onTick(event: LorenzTickEvent) { - inNucleus = IslandAreas.currentAreaName == "Crystal Nucleus" + @HandleEvent + fun onAreaChange(event: GraphAreaChangeEvent) { + inNucleus = event.area == "Crystal Nucleus" } @SubscribeEvent diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/IslandAreas.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/IslandAreas.kt index dfa60478a6c2..2176fc2a076f 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/IslandAreas.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/IslandAreas.kt @@ -1,6 +1,7 @@ package at.hannibal2.skyhanni.features.misc import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.api.event.HandleEvent import at.hannibal2.skyhanni.data.IslandGraphs import at.hannibal2.skyhanni.data.IslandGraphs.pathFind import at.hannibal2.skyhanni.data.model.Graph @@ -13,6 +14,7 @@ import at.hannibal2.skyhanni.events.GuiRenderEvent import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent import at.hannibal2.skyhanni.events.LorenzTickEvent import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent +import at.hannibal2.skyhanni.events.skyblock.GraphAreaChangeEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.CollectionUtils.addSearchString import at.hannibal2.skyhanni.utils.CollectionUtils.sorted @@ -171,10 +173,9 @@ object IslandAreas { } } if (name != currentAreaName) { - if (inAnArea && config.enterTitle) { - LorenzUtils.sendTitle("§aEntered $name!", 3.seconds) - } + val oldArea = currentAreaName currentAreaName = name + GraphAreaChangeEvent(name, oldArea).post() } addSearchString("§eAreas nearby:") @@ -223,6 +224,15 @@ object IslandAreas { } } + @HandleEvent + fun onAreaChange(event: GraphAreaChangeEvent) { + val name = event.area + val inAnArea = name != "no_area" + if (inAnArea && config.enterTitle) { + LorenzUtils.sendTitle("§aEntered $name!", 3.seconds) + } + } + @SubscribeEvent fun onRenderWorld(event: LorenzRenderWorldEvent) { if (!LorenzUtils.inSkyBlock) return From 83efbb3341edc3266bc2a4b89b3570c1a303ccba Mon Sep 17 00:00:00 2001 From: J10a1n15 <45315647+j10a1n15@users.noreply.github.com> Date: Fri, 18 Oct 2024 18:01:39 +0200 Subject: [PATCH 22/26] Improvement: Custom Scoreboard Refactor (#2162) Co-authored-by: CalMWolfs <94038482+CalMWolfs@users.noreply.github.com> Co-authored-by: J10a1n15 <45315647+j10a1n15@users.noreply.github.com> Co-authored-by: Empa <42304516+ItsEmpa@users.noreply.github.com> Co-authored-by: Cal Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com> Co-authored-by: ItsEmpa --- .../at/hannibal2/skyhanni/api/SkillAPI.kt | 2 +- .../skyhanni/config/ConfigUpdaterMigrator.kt | 2 +- .../customscoreboard/ChunkedStatsConfig.java | 4 +- .../CustomScoreboardConfig.java | 20 +- .../gui/customscoreboard/DisplayConfig.java | 14 +- .../gui/customscoreboard/EventsConfig.java | 11 +- .../gui/customscoreboard/PartyConfig.java | 7 +- .../TitleAndFooterConfig.java | 26 +- .../at/hannibal2/skyhanni/data/HypixelData.kt | 18 +- .../at/hannibal2/skyhanni/data/MaxwellAPI.kt | 15 +- .../at/hannibal2/skyhanni/data/MiningAPI.kt | 17 +- .../at/hannibal2/skyhanni/data/WinterAPI.kt | 3 + .../skyhanni/data/model/TabWidget.kt | 2 +- .../skyhanni/features/combat/SpidersDenAPI.kt | 21 +- .../{ChunkedStat.kt => ChunkedStatsLine.kt} | 65 +- .../gui/customscoreboard/CustomScoreboard.kt | 248 ++--- .../CustomScoreboardConfigFix.kt | 119 +++ .../customscoreboard/CustomScoreboardUtils.kt | 76 +- .../ScoreboardConfigElement.kt | 125 +++ .../ScoreboardConfigEventElement.kt | 98 ++ .../customscoreboard/ScoreboardElements.kt | 863 ------------------ .../gui/customscoreboard/ScoreboardEvent.kt | 576 ------------ .../gui/customscoreboard/ScoreboardLine.kt | 18 + .../gui/customscoreboard/ScoreboardPattern.kt | 205 ++--- .../customscoreboard/UnknownLinesHandler.kt | 23 +- .../elements/ScoreboardElement.kt | 33 + .../elements/ScoreboardElementBank.kt | 26 + .../elements/ScoreboardElementBits.kt | 32 + .../elements/ScoreboardElementChunkedStats.kt | 19 + .../elements/ScoreboardElementCold.kt | 25 + .../elements/ScoreboardElementCookie.kt | 24 + .../elements/ScoreboardElementCopper.kt | 27 + .../elements/ScoreboardElementDate.kt | 12 + .../elements/ScoreboardElementEmptyLine.kt | 9 + .../elements/ScoreboardElementEvents.kt | 19 + .../elements/ScoreboardElementFooter.kt | 18 + .../elements/ScoreboardElementGems.kt | 25 + .../elements/ScoreboardElementHeat.kt | 24 + .../elements/ScoreboardElementIsland.kt | 13 + .../elements/ScoreboardElementLobbyCode.kt | 16 + .../elements/ScoreboardElementLocation.kt | 17 + .../elements/ScoreboardElementMayor.kt | 59 ++ .../elements/ScoreboardElementMotes.kt | 25 + .../elements/ScoreboardElementNorthStars.kt | 25 + .../elements/ScoreboardElementObjective.kt | 29 + .../elements/ScoreboardElementParty.kt | 40 + .../elements/ScoreboardElementPlayerAmount.kt | 20 + .../elements/ScoreboardElementPowder.kt | 50 + .../elements/ScoreboardElementPower.kt | 24 + .../elements/ScoreboardElementProfile.kt | 15 + .../elements/ScoreboardElementPurse.kt | 30 + .../elements/ScoreboardElementQuiver.kt | 48 + .../elements/ScoreboardElementSlayer.kt | 19 + .../elements/ScoreboardElementSoulflow.kt | 23 + .../elements/ScoreboardElementTime.kt | 23 + .../elements/ScoreboardElementTitle.kt | 31 + .../elements/ScoreboardElementTuning.kt | 42 + .../elements/ScoreboardElementUnknown.kt | 16 + .../elements/ScoreboardElementVisiting.kt | 20 + .../events/ScoreboardEvent.kt | 5 + .../events/ScoreboardEventActiveTablist.kt | 31 + .../events/ScoreboardEventAnniversary.kt | 13 + .../events/ScoreboardEventBroodmother.kt | 15 + .../events/ScoreboardEventCarnival.kt | 35 + .../events/ScoreboardEventDamage.kt | 23 + .../events/ScoreboardEventDarkAuction.kt | 27 + .../events/ScoreboardEventDojo.kt | 28 + .../events/ScoreboardEventDungeons.kt | 29 + .../events/ScoreboardEventEssence.kt | 13 + .../events/ScoreboardEventFlightDuration.kt | 22 + .../events/ScoreboardEventGarden.kt | 19 + .../events/ScoreboardEventJacobContest.kt | 25 + .../events/ScoreboardEventJacobMedals.kt | 17 + .../events/ScoreboardEventKuudra.kt | 27 + .../events/ScoreboardEventMagmaBoss.kt | 32 + .../events/ScoreboardEventMining.kt | 74 ++ .../events/ScoreboardEventNewYear.kt | 13 + .../events/ScoreboardEventQueue.kt | 20 + .../events/ScoreboardEventRedstone.kt | 17 + .../events/ScoreboardEventRift.kt | 30 + .../events/ScoreboardEventServerClose.kt | 14 + .../events/ScoreboardEventSpooky.kt | 29 + .../ScoreboardEventStartingSoonTablist.kt | 25 + .../events/ScoreboardEventTrapper.kt | 25 + .../events/ScoreboardEventVoting.kt | 26 + .../events/ScoreboardEventWinter.kt | 26 + .../inventory/AuctionOutbidWarning.kt | 2 +- .../skyhanni/utils/CollectionUtils.kt | 23 +- .../hannibal2/skyhanni/utils/LorenzUtils.kt | 5 +- .../skyhanni/utils/SizeLimitedCache.kt | 37 + .../skyhanni/utils/SizeLimitedSet.kt | 35 + .../hannibal2/skyhanni/utils/StringUtils.kt | 53 +- .../skyhanni/utils/TimeLimitedCache.kt | 10 +- .../skyhanni/utils/TimeLimitedSet.kt | 5 +- 94 files changed, 2403 insertions(+), 1883 deletions(-) rename src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/{ChunkedStat.kt => ChunkedStatsLine.kt} (52%) create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/CustomScoreboardConfigFix.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardConfigElement.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardConfigEventElement.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardElements.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardEvent.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardLine.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/elements/ScoreboardElement.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/elements/ScoreboardElementBank.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/elements/ScoreboardElementBits.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/elements/ScoreboardElementChunkedStats.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/elements/ScoreboardElementCold.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/elements/ScoreboardElementCookie.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/elements/ScoreboardElementCopper.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/elements/ScoreboardElementDate.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/elements/ScoreboardElementEmptyLine.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/elements/ScoreboardElementEvents.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/elements/ScoreboardElementFooter.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/elements/ScoreboardElementGems.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/elements/ScoreboardElementHeat.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/elements/ScoreboardElementIsland.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/elements/ScoreboardElementLobbyCode.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/elements/ScoreboardElementLocation.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/elements/ScoreboardElementMayor.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/elements/ScoreboardElementMotes.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/elements/ScoreboardElementNorthStars.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/elements/ScoreboardElementObjective.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/elements/ScoreboardElementParty.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/elements/ScoreboardElementPlayerAmount.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/elements/ScoreboardElementPowder.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/elements/ScoreboardElementPower.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/elements/ScoreboardElementProfile.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/elements/ScoreboardElementPurse.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/elements/ScoreboardElementQuiver.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/elements/ScoreboardElementSlayer.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/elements/ScoreboardElementSoulflow.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/elements/ScoreboardElementTime.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/elements/ScoreboardElementTitle.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/elements/ScoreboardElementTuning.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/elements/ScoreboardElementUnknown.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/elements/ScoreboardElementVisiting.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/events/ScoreboardEvent.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/events/ScoreboardEventActiveTablist.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/events/ScoreboardEventAnniversary.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/events/ScoreboardEventBroodmother.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/events/ScoreboardEventCarnival.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/events/ScoreboardEventDamage.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/events/ScoreboardEventDarkAuction.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/events/ScoreboardEventDojo.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/events/ScoreboardEventDungeons.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/events/ScoreboardEventEssence.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/events/ScoreboardEventFlightDuration.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/events/ScoreboardEventGarden.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/events/ScoreboardEventJacobContest.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/events/ScoreboardEventJacobMedals.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/events/ScoreboardEventKuudra.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/events/ScoreboardEventMagmaBoss.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/events/ScoreboardEventMining.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/events/ScoreboardEventNewYear.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/events/ScoreboardEventQueue.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/events/ScoreboardEventRedstone.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/events/ScoreboardEventRift.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/events/ScoreboardEventServerClose.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/events/ScoreboardEventSpooky.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/events/ScoreboardEventStartingSoonTablist.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/events/ScoreboardEventTrapper.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/events/ScoreboardEventVoting.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/events/ScoreboardEventWinter.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/utils/SizeLimitedCache.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/utils/SizeLimitedSet.kt diff --git a/src/main/java/at/hannibal2/skyhanni/api/SkillAPI.kt b/src/main/java/at/hannibal2/skyhanni/api/SkillAPI.kt index 95e39d1f73a7..aa930adb1dc0 100644 --- a/src/main/java/at/hannibal2/skyhanni/api/SkillAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/api/SkillAPI.kt @@ -28,8 +28,8 @@ import at.hannibal2.skyhanni.utils.NumberUtil.formatDouble import at.hannibal2.skyhanni.utils.NumberUtil.formatLong import at.hannibal2.skyhanni.utils.NumberUtil.formatLongOrUserError import at.hannibal2.skyhanni.utils.NumberUtil.romanToDecimalIfNecessary +import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher import at.hannibal2.skyhanni.utils.SimpleTimeMark -import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher import at.hannibal2.skyhanni.utils.StringUtils.removeColor import at.hannibal2.skyhanni.utils.TabListData import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern diff --git a/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt b/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt index 8228ae025274..93c7d3407235 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt +++ b/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt @@ -12,7 +12,7 @@ import com.google.gson.JsonPrimitive object ConfigUpdaterMigrator { val logger = LorenzLogger("ConfigMigration") - const val CONFIG_VERSION = 62 + const val CONFIG_VERSION = 63 fun JsonElement.at(chain: List, init: Boolean): JsonElement? { if (chain.isEmpty()) return this if (this !is JsonObject) return null diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/ChunkedStatsConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/ChunkedStatsConfig.java index 4293dd168f8b..8e0941d30198 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/ChunkedStatsConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/ChunkedStatsConfig.java @@ -1,6 +1,6 @@ package at.hannibal2.skyhanni.config.features.gui.customscoreboard; -import at.hannibal2.skyhanni.features.gui.customscoreboard.ChunkedStat; +import at.hannibal2.skyhanni.features.gui.customscoreboard.ChunkedStatsLine; import com.google.gson.annotations.Expose; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorDraggableList; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorSlider; @@ -17,7 +17,7 @@ public class ChunkedStatsConfig { desc = "Select the stats you want to display chunked on the scoreboard." ) @ConfigEditorDraggableList - public List chunkedStats = new ArrayList<>(ChunkedStat.getEntries()); + public List chunkedStats = new ArrayList<>(ChunkedStatsLine.getEntries()); @Expose @ConfigOption( diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/CustomScoreboardConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/CustomScoreboardConfig.java index 38a749f35029..944b44cd4a86 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/CustomScoreboardConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/CustomScoreboardConfig.java @@ -2,7 +2,8 @@ import at.hannibal2.skyhanni.config.FeatureToggle; import at.hannibal2.skyhanni.config.core.config.Position; -import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardElement; +import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard; +import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardConfigElement; import com.google.gson.annotations.Expose; import io.github.notenoughupdates.moulconfig.annotations.Accordion; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean; @@ -28,17 +29,14 @@ public class CustomScoreboardConfig { @Expose @ConfigOption( name = "Appearance", - desc = "Drag text to change the appearance of the advanced scoreboard." // supporting both custom & advanced search + desc = "Drag text to change the appearance of the advanced scoreboard." ) - @ConfigEditorDraggableList() - public List scoreboardEntries = new ArrayList<>(ScoreboardElement.defaultOption); + @ConfigEditorDraggableList + public Property> scoreboardEntries = Property.of(new ArrayList<>(ScoreboardConfigElement.defaultOptions)); @ConfigOption(name = "Reset Appearance", desc = "Reset the appearance of the advanced scoreboard.") @ConfigEditorButton(buttonText = "Reset") - public Runnable reset = () -> { - scoreboardEntries.clear(); - scoreboardEntries.addAll(ScoreboardElement.defaultOption); - }; + public Runnable reset = CustomScoreboard::resetAppearance; @Expose @ConfigOption(name = "Display Options", desc = "") @@ -56,7 +54,11 @@ public class CustomScoreboardConfig { public InformationFilteringConfig informationFiltering = new InformationFilteringConfig(); @Expose - @ConfigOption(name = "Unknown Lines warning", desc = "Give a chat warning when unknown lines are found in the scoreboard.") + @ConfigOption( + name = "Unknown Lines warning", + desc = "Give a chat warning when unknown lines are found in the scoreboard." + + "\n§cReporting these in the Discord Server are very important, so we can know what lines are missing." + ) @ConfigEditorBoolean public boolean unknownLinesWarning = true; 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 2f0eb502e509..39d8c09bfd7a 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 @@ -1,6 +1,7 @@ package at.hannibal2.skyhanni.config.features.gui.customscoreboard; import at.hannibal2.skyhanni.config.FeatureToggle; +import at.hannibal2.skyhanni.utils.RenderUtils; import com.google.gson.annotations.Expose; import io.github.notenoughupdates.moulconfig.annotations.Accordion; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean; @@ -51,7 +52,6 @@ public class DisplayConfig { @Accordion public TitleAndFooterConfig titleAndFooter = new TitleAndFooterConfig(); - @Expose @ConfigOption(name = "Hide Vanilla Scoreboard", desc = "Hide the vanilla scoreboard.\n" + "§cMods that add their own scoreboard will not be affected by this setting!") @@ -145,8 +145,16 @@ public String toString() { public int lineSpacing = 10; @Expose - @ConfigOption(name = "Cache Scoreboard on Island Switch", - desc = "Will stop the Scoreboard from updating while switching islands.\nRemoves the shaking when loading data.") + @ConfigOption(name = "Text Alignment", desc = "Will align the text to the left, center or right, while not overriding certain lines, like title or footer.") + @ConfigEditorDropdown + public RenderUtils.HorizontalAlignment textAlignment = RenderUtils.HorizontalAlignment.LEFT; + + @Expose + @ConfigOption( + name = "Cache Scoreboard on Island Switch", + desc = "Will stop the Scoreboard from updating while switching islands.\n" + + "Removes the shaking when loading data." + ) @ConfigEditorBoolean public boolean cacheScoreboardOnIslandSwitch = false; } diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/EventsConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/EventsConfig.java index e2663bf55c29..b091c8e90fee 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/EventsConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/EventsConfig.java @@ -1,11 +1,12 @@ package at.hannibal2.skyhanni.config.features.gui.customscoreboard; -import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardEvent; +import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardConfigEventElement; import com.google.gson.annotations.Expose; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorButton; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorDraggableList; import io.github.notenoughupdates.moulconfig.annotations.ConfigOption; +import io.github.notenoughupdates.moulconfig.observer.Property; import java.util.ArrayList; import java.util.List; @@ -18,13 +19,15 @@ public class EventsConfig { desc = "Drag your list to select the priority of each event." ) @ConfigEditorDraggableList() - public List eventEntries = new ArrayList<>(ScoreboardEvent.defaultOption); + public Property> eventEntries = Property.of(new ArrayList<>(ScoreboardConfigEventElement.defaultOption)); @ConfigOption(name = "Reset Events Priority", desc = "Reset the priority of all events.") @ConfigEditorButton(buttonText = "Reset") + // TODO move into kotlin public Runnable reset = () -> { - eventEntries.clear(); - eventEntries.addAll(ScoreboardEvent.defaultOption); + eventEntries.get().clear(); + eventEntries.get().addAll(ScoreboardConfigEventElement.defaultOption); + eventEntries.notifyObservers(); }; @Expose diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/PartyConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/PartyConfig.java index 670e9b16b7f5..5a553369f37c 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/PartyConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/PartyConfig.java @@ -11,7 +11,7 @@ public class PartyConfig { @ConfigOption(name = "Max Party List", desc = "Max number of party members to show in the party list (you are not included).") @ConfigEditorSlider( minValue = 1, - maxValue = 25, // why do I even set it so high + maxValue = 25, minStep = 1 ) public Property maxPartyList = Property.of(4); @@ -21,4 +21,9 @@ public class PartyConfig { "If disabled, it will only show in Dungeon Hub, Crimson Isle & Kuudra.") @ConfigEditorBoolean public boolean showPartyEverywhere = false; + + @Expose + @ConfigOption(name = "Show Party Leader", desc = "Show the party leader in the party list.") + @ConfigEditorBoolean + public boolean showPartyLeader = true; } diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/TitleAndFooterConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/TitleAndFooterConfig.java index 1c3bb4304509..aae9fe026376 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/TitleAndFooterConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/TitleAndFooterConfig.java @@ -6,21 +6,19 @@ import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorDropdown; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorText; import io.github.notenoughupdates.moulconfig.annotations.ConfigOption; -import io.github.notenoughupdates.moulconfig.observer.Property; public class TitleAndFooterConfig { @Expose - @ConfigOption(name = "Title and Footer Alignment", desc = "Align the title and footer in the scoreboard.") + @ConfigOption(name = "Title Alignment", desc = "Align the title in the scoreboard.") @ConfigEditorDropdown - // TODO rename to "horizontalAlignment" or "alignment" - public RenderUtils.HorizontalAlignment alignTitleAndFooter = RenderUtils.HorizontalAlignment.CENTER; + public RenderUtils.HorizontalAlignment alignTitle = RenderUtils.HorizontalAlignment.CENTER; @Expose @ConfigOption(name = "Custom Title", desc = "What should be displayed as the title of the scoreboard." + - "\nUse & for colors." + + "\nUse && for colors." + "\nUse \"\\n\" for new line.") @ConfigEditorText - public Property customTitle = Property.of("&6&lSKYBLOCK"); + public String customTitle = "&&6&&lSKYBLOCK"; @Expose @ConfigOption(name = "Use Custom Title", desc = "Use a custom title instead of the default Hypixel title.") @@ -32,10 +30,22 @@ public class TitleAndFooterConfig { @ConfigEditorBoolean public boolean useCustomTitleOutsideSkyBlock = false; + @Expose + @ConfigOption(name = "Footer Alignment", desc = "Align the footer in the scoreboard.") + @ConfigEditorDropdown + public RenderUtils.HorizontalAlignment alignFooter = RenderUtils.HorizontalAlignment.LEFT; + @Expose @ConfigOption(name = "Custom Footer", desc = "What should be displayed as the footer of the scoreboard." + - "\nUse & for colors." + + "\nUse && for colors." + + "\nUse \"\\n\" for new line.") + @ConfigEditorText + public String customFooter = "&&ewww.hypixel.net"; + + @Expose + @ConfigOption(name = "Custom Alpha Footer", desc = "What should be displayed as the footer of the scoreboard when on the Alpha Server." + + "\nUse && for colors." + "\nUse \"\\n\" for new line.") @ConfigEditorText - public Property customFooter = Property.of("&ewww.hypixel.net"); + public String customAlphaFooter = "&&ealpha.hypixel.net"; } diff --git a/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt b/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt index 3707d10af0a7..20ed572765d5 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt @@ -485,12 +485,12 @@ object HypixelData { } private fun checkIsland(event: WidgetUpdateEvent) { - val islandType: IslandType + val newIsland: IslandType val foundIsland: String if (event.isClear()) { TabListData.fullyLoaded = false - islandType = IslandType.NONE + newIsland = IslandType.NONE foundIsland = "" } else { @@ -498,19 +498,21 @@ object HypixelData { // Can not use color coding, because of the color effect (§f§lSKYB§6§lL§e§lOCK§A§L GUEST) val guesting = guestPattern.matches(ScoreboardData.objectiveTitle.removeColor()) foundIsland = TabWidget.AREA.matchMatcherFirstLine { group("island").removeColor() } ?: "" - islandType = getIslandType(foundIsland, guesting) + newIsland = getIslandType(foundIsland, guesting) } // TODO don't send events when one of the arguments is none, at least when not on sb anymore - if (skyBlockIsland != islandType) { - IslandChangeEvent(islandType, skyBlockIsland).postAndCatch() - if (islandType == IslandType.UNKNOWN) { + if (skyBlockIsland != newIsland) { + val oldIsland = skyBlockIsland + skyBlockIsland = newIsland + IslandChangeEvent(newIsland, oldIsland).postAndCatch() + + if (newIsland == IslandType.UNKNOWN) { ChatUtils.debug("Unknown island detected: '$foundIsland'") loggerIslandChange.log("Unknown: '$foundIsland'") } else { - loggerIslandChange.log(islandType.name) + loggerIslandChange.log(newIsland.name) } - skyBlockIsland = islandType if (TabListData.fullyLoaded) { TabWidget.reSendEvents() } diff --git a/src/main/java/at/hannibal2/skyhanni/data/MaxwellAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/MaxwellAPI.kt index 776a7c808103..5fd644818903 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/MaxwellAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/MaxwellAPI.kt @@ -6,7 +6,7 @@ import at.hannibal2.skyhanni.events.LorenzChatEvent import at.hannibal2.skyhanni.events.RepositoryReloadEvent import at.hannibal2.skyhanni.features.dungeon.DungeonAPI import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard -import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardElement +import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardConfigElement import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.test.command.ErrorManager import at.hannibal2.skyhanni.utils.ChatUtils @@ -135,14 +135,11 @@ object MaxwellAPI { chatPowerPattern.tryReadPower(message) chatPowerUnlockedPattern.tryReadPower(message) - tuningAutoAssignedPattern.matchMatcher(event.message) { - if (tunings.isNullOrEmpty()) return - val tuningsInScoreboard = ScoreboardElement.TUNING in CustomScoreboard.config.scoreboardEntries - if (tuningsInScoreboard) { - ChatUtils.chat( - "Talk to Maxwell and open the Tuning Page again to update the tuning data in scoreboard.", - ) - } + if (!tuningAutoAssignedPattern.matches(event.message)) return + if (tunings.isNullOrEmpty()) return + with(CustomScoreboard.config) { + if (!enabled.get() || ScoreboardConfigElement.TUNING !in scoreboardEntries.get()) return + ChatUtils.chat("Talk to Maxwell and open the Tuning Page again to update the tuning data in scoreboard.") } } diff --git a/src/main/java/at/hannibal2/skyhanni/data/MiningAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/MiningAPI.kt index 54d186ae52c3..fbe304098299 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/MiningAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/MiningAPI.kt @@ -14,7 +14,6 @@ import at.hannibal2.skyhanni.events.ServerBlockChangeEvent import at.hannibal2.skyhanni.events.mining.OreMinedEvent import at.hannibal2.skyhanni.events.player.PlayerDeathEvent import at.hannibal2.skyhanni.events.skyblock.ScoreboardAreaChangeEvent -import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardPattern import at.hannibal2.skyhanni.features.mining.OreBlock import at.hannibal2.skyhanni.features.mining.isTitanium import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule @@ -46,12 +45,20 @@ object MiningAPI { private val glaciteAreaPattern by group.pattern("area.glacite", "Glacite Tunnels|Great Glacite Lake") private val dwarvenBaseCampPattern by group.pattern("area.basecamp", "Dwarven Base Camp") - // TODO add regex test + // TODO add regex tests private val coldResetPattern by group.pattern( "cold.reset", "§6The warmth of the campfire reduced your §r§b❄ Cold §r§6to §r§a0§r§6!|§c ☠ §r§7You froze to death§r§7\\.", ) + /** + * REGEX-TEST: Cold: §b-1❄ + */ + val coldPattern by group.pattern( + "cold", + "(?:§.)*Cold: §.(?-?\\d+)❄", + ) + private val pickbobulusGroup = group.group("pickobulus") /** @@ -150,11 +157,15 @@ object MiningAPI { IslandType.SPIDER_DEN, ) + fun inAdvancedMiningIsland() = inAnyIsland(IslandType.DWARVEN_MINES, IslandType.CRYSTAL_HOLLOWS, IslandType.MINESHAFT) + + fun inMiningIsland() = inAdvancedMiningIsland() || inAnyIsland(IslandType.GOLD_MINES, IslandType.DEEP_CAVERNS) + fun inColdIsland() = inAnyIsland(IslandType.DWARVEN_MINES, IslandType.MINESHAFT) @SubscribeEvent fun onScoreboardChange(event: ScoreboardUpdateEvent) { - val newCold = ScoreboardPattern.coldPattern.firstMatcher(event.scoreboard) { + val newCold = coldPattern.firstMatcher(event.scoreboard) { group("cold").toInt().absoluteValue } ?: return diff --git a/src/main/java/at/hannibal2/skyhanni/data/WinterAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/WinterAPI.kt index 9e3a7a9e6ea9..4b430b9c55a6 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/WinterAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/WinterAPI.kt @@ -1,9 +1,12 @@ package at.hannibal2.skyhanni.data +import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland import at.hannibal2.skyhanni.utils.TimeUtils import java.time.Month object WinterAPI { + fun inWorkshop() = IslandType.WINTER.isInIsland() + fun isDecember() = TimeUtils.getCurrentLocalDate().month == Month.DECEMBER } diff --git a/src/main/java/at/hannibal2/skyhanni/data/model/TabWidget.kt b/src/main/java/at/hannibal2/skyhanni/data/model/TabWidget.kt index e5939c3f758d..7a57de667dd1 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/model/TabWidget.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/model/TabWidget.kt @@ -95,7 +95,7 @@ enum class TabWidget( ), EVENT( // language=RegExp - "(?:§.)*Event: (?:§.)*(?.*)", + "(?:§.)*Event: (?(?:§.)*)(?.*)", ), SKILLS( // language=RegExp diff --git a/src/main/java/at/hannibal2/skyhanni/features/combat/SpidersDenAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/combat/SpidersDenAPI.kt index af1dd8430186..8b9ff035e662 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/combat/SpidersDenAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/combat/SpidersDenAPI.kt @@ -1,11 +1,26 @@ package at.hannibal2.skyhanni.features.combat +import at.hannibal2.skyhanni.data.IslandType import at.hannibal2.skyhanni.data.ScoreboardData -import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardPattern import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule -import at.hannibal2.skyhanni.utils.RegexUtils.matches +import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland +import at.hannibal2.skyhanni.utils.RegexUtils.anyMatches +import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern @SkyHanniModule object SpidersDenAPI { - fun isAtTopOfNest(): Boolean = ScoreboardData.sidebarLinesFormatted.any { ScoreboardPattern.broodmotherPattern.matches(it) } + + private val repoGroup = RepoPattern.group("combat.spidersden") + + /** + * REGEX-TEST: §4Broodmother§7: §6Soon + */ + val broodmotherPattern by repoGroup.pattern( + "broodmother", + "§4Broodmother§7: §[e64](?:Slain|Dormant|Soon|Awakening|Imminent|Alive!)", + ) + + fun inSpidersDen() = IslandType.SPIDER_DEN.isInIsland() + + fun isAtTopOfNest() = inSpidersDen() && broodmotherPattern.anyMatches(ScoreboardData.sidebarLinesFormatted) } diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ChunkedStat.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ChunkedStatsLine.kt similarity index 52% rename from src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ChunkedStat.kt rename to src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ChunkedStatsLine.kt index 4acfcb81db57..57000be68b86 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ChunkedStat.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ChunkedStatsLine.kt @@ -4,67 +4,86 @@ import at.hannibal2.skyhanni.data.MiningAPI import at.hannibal2.skyhanni.data.PurseAPI import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard.chunkedConfig import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard.informationFilteringConfig -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.formatNum +import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.formatNumber import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getBank import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getBits +import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getBitsAvailable import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getBitsLine -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getBitsToClaim import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getCopper import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getGems import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getHeat import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getMotes import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getNorthStars +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementBank +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementBits +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementCold +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementCopper +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementGems +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementHeat +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementMotes +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementNorthStars +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementPurse private val hideEmptyLines get() = informationFilteringConfig.hideEmptyLines -enum class ChunkedStat( +enum class ChunkedStatsLine( private val displayPair: () -> String, - val showWhen: () -> Boolean, + private val showWhen: () -> Boolean, + private val showIsland: () -> Boolean, private val configLine: String, ) { PURSE( - displayPair = { "§6${PurseAPI.currentPurse.formatNum()}" }, - showWhen = { !(hideEmptyLines && PurseAPI.currentPurse.toInt() == 0) && ScoreboardElement.PURSE.showWhen() }, + displayPair = { "§6${formatNumber(PurseAPI.currentPurse)}" }, + showWhen = { !(hideEmptyLines && PurseAPI.currentPurse.toInt() == 0) && ScoreboardElementPurse.showWhen() }, + showIsland = { ScoreboardElementPurse.showIsland() }, configLine = "§6Purse", ), MOTES( displayPair = { "§b${getMotes()}" }, - showWhen = { !(hideEmptyLines && getMotes() == "0") && ScoreboardElement.MOTES.showWhen() }, + showWhen = { !(hideEmptyLines && getMotes() == "0") && ScoreboardElementMotes.showWhen() }, + showIsland = { ScoreboardElementMotes.showIsland() }, configLine = "§dMotes", ), BANK( displayPair = { "§6${getBank()}" }, - showWhen = { !(hideEmptyLines && (getBank() == "0" || getBank() == "0§7 / §60")) && ScoreboardElement.BANK.showWhen() }, + showWhen = { !(hideEmptyLines && (getBank() == "0" || getBank() == "0§7 / §60")) && ScoreboardElementBank.showWhen() }, + showIsland = { ScoreboardElementBank.showIsland() }, configLine = "§6Bank", ), BITS( displayPair = { getBitsLine() }, - showWhen = { !(hideEmptyLines && getBits() == "0" && getBitsToClaim() == "0") && ScoreboardElement.BITS.showWhen() }, + showWhen = { !(hideEmptyLines && getBits() == "0" && getBitsAvailable() == "0") && ScoreboardElementBits.showWhen() }, + showIsland = { ScoreboardElementBits.showIsland() }, configLine = "§bBits", ), COPPER( displayPair = { "§c${getCopper()}" }, - showWhen = { !(hideEmptyLines && getCopper() == "0") && ScoreboardElement.COPPER.showWhen() }, + showWhen = { !(hideEmptyLines && getCopper() == "0") && ScoreboardElementCopper.showWhen() }, + showIsland = { ScoreboardElementCopper.showIsland() }, configLine = "§cCopper", ), GEMS( displayPair = { "§a${getGems()}" }, - showWhen = { !(hideEmptyLines && getGems() == "0") && ScoreboardElement.GEMS.showWhen() }, + showWhen = { !(hideEmptyLines && getGems() == "0") && ScoreboardElementGems.showWhen() }, + showIsland = { ScoreboardElementGems.showIsland() }, configLine = "§aGems", ), HEAT( displayPair = { "§c${getHeat()}" }, - showWhen = { !(hideEmptyLines && getHeat() == "§c♨ 0") && ScoreboardElement.HEAT.showWhen() }, + showWhen = { !(hideEmptyLines && getHeat() == "§c♨ 0") && ScoreboardElementHeat.showWhen() }, + showIsland = { ScoreboardElementHeat.showIsland() }, configLine = "§cHeat", ), COLD( displayPair = { "§b${MiningAPI.cold}❄" }, - showWhen = { !(hideEmptyLines && MiningAPI.cold == 0) && ScoreboardElement.COLD.showWhen() }, + showWhen = { !(hideEmptyLines && MiningAPI.cold == 0) && ScoreboardElementCold.showWhen() }, + showIsland = { ScoreboardElementCold.showIsland() }, configLine = "§bCold", ), NORTH_STARS( displayPair = { "§d${getNorthStars()}" }, - showWhen = { !(hideEmptyLines && getNorthStars() == "0") && ScoreboardElement.NORTH_STARS.showWhen() }, + showWhen = { !(hideEmptyLines && getNorthStars() == "0") && ScoreboardElementNorthStars.showWhen() }, + showIsland = { ScoreboardElementNorthStars.showIsland() }, configLine = "§dNorth Stars", ), ; @@ -72,10 +91,22 @@ enum class ChunkedStat( override fun toString() = configLine companion object { - fun getChunkedStats() = chunkedConfig.chunkedStats.mapNotNull { - it.takeIf { it.showWhen() }?.displayPair?.invoke() + + private var currentIslandStats = listOf() + + fun getChunkedStats() = buildList { + currentIslandStats.forEach { stat -> + if (stat.showWhen()) { + add(stat.displayPair.invoke()) + } + } } - fun shouldShowChunkedStats() = chunkedConfig.chunkedStats.any { it.showWhen() } + fun shouldShowChunkedStats() = currentIslandStats.any { it.showWhen() } + + fun showChunkedStatsIsland(): Boolean { + currentIslandStats = chunkedConfig.chunkedStats.filter { it.showIsland() } + return currentIslandStats.isNotEmpty() + } } } 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 4a86519c374e..14f311aad281 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,28 +1,33 @@ -// -// TODO LIST -// V2 RELEASE -// - Bank API (actually maybe not, I like the current design) -// - countdown events like fishing festival + fiesta when its not on tablist -// - 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 -// +/** + * TODO LIST + * - Bank API (actually maybe not, I like the current design) + * - countdown events like fishing festival + fiesta when its not on tablist + * - 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 + * - heavily optimize elements and events by only updating them when absolutely needed + */ package at.hannibal2.skyhanni.features.gui.customscoreboard import at.hannibal2.skyhanni.SkyHanniMod -import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator import at.hannibal2.skyhanni.config.enums.OutsideSbFeature import at.hannibal2.skyhanni.data.ScoreboardData import at.hannibal2.skyhanni.events.ConfigLoadEvent import at.hannibal2.skyhanni.events.DebugDataCollectEvent import at.hannibal2.skyhanni.events.GuiPositionMovedEvent import at.hannibal2.skyhanni.events.GuiRenderEvent +import at.hannibal2.skyhanni.events.IslandChangeEvent import at.hannibal2.skyhanni.events.LorenzTickEvent import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent import at.hannibal2.skyhanni.events.ScoreboardUpdateEvent +import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardLine.Companion.align +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElement +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementTitle +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.ChatUtils +import at.hannibal2.skyhanni.utils.CollectionUtils.takeIfNotEmpty import at.hannibal2.skyhanni.utils.ConditionalUtils import at.hannibal2.skyhanni.utils.DelayedRun.runDelayed import at.hannibal2.skyhanni.utils.LorenzUtils @@ -34,21 +39,22 @@ import at.hannibal2.skyhanni.utils.SimpleTimeMark.Companion.fromNow 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 import net.minecraftforge.client.event.RenderGameOverlayEvent import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.seconds -typealias ScoreboardElementType = Pair - @SkyHanniModule object CustomScoreboard { - private var display = emptyList() - private var cache = emptyList() + private var display: Renderable? = null + private var cache: Renderable? = null + + private var currentIslandEntries = listOf() + var currentIslandEvents = listOf() + private set + private const val GUI_NAME = "Custom Scoreboard" private var nextScoreboardUpdate = SimpleTimeMark.farFuture() @@ -56,25 +62,16 @@ object CustomScoreboard { @SubscribeEvent fun onRenderOverlay(event: GuiRenderEvent.GuiOverlayRenderEvent) { if (!isEnabled()) return - if (display.isEmpty()) return + display ?: return val render = - if (LorenzUtils.inSkyBlock && !TabListData.fullyLoaded && displayConfig.cacheScoreboardOnIslandSwitch && cache.isNotEmpty()) { - cache - } else { - display - } - - val textRenderable = Renderable.verticalContainer( - render.map { Renderable.string(it.first, horizontalAlign = it.second) }, - displayConfig.lineSpacing - 10, - horizontalAlign = HorizontalAlignment.CENTER, - verticalAlign = VerticalAlignment.CENTER, - ) + if (LorenzUtils.inSkyBlock && !TabListData.fullyLoaded && displayConfig.cacheScoreboardOnIslandSwitch && cache != null) cache + else display - val finalRenderable = RenderBackground.addBackground(textRenderable) + render ?: return - RenderBackground.updatePosition(finalRenderable) + // We want to update the background every time, so we can have a smooth transition when using chroma as the color + val finalRenderable = RenderBackground.addBackground(render) config.position.renderRenderable(finalRenderable, posLabel = GUI_NAME) } @@ -110,9 +107,9 @@ object CustomScoreboard { if (dirty || nextScoreboardUpdate.isInPast()) { nextScoreboardUpdate = 250.milliseconds.fromNow() dirty = false - display = createLines().removeEmptyLinesFromEdges() + display = createLines().removeEmptyLinesFromEdges().createRenderable() if (TabListData.fullyLoaded) { - cache = display.toList() + cache = display } } @@ -144,53 +141,47 @@ object CustomScoreboard { } private fun addAllNonSkyBlockLines() = buildList { - addAll(ScoreboardElement.TITLE.getVisiblePair()) - addAll(ScoreboardData.sidebarLinesFormatted.map { it to HorizontalAlignment.LEFT }) + addAll(ScoreboardElementTitle.getLines()) + addAll(ScoreboardData.sidebarLinesFormatted.map { it.align() }) } private fun addDefaultSkyBlockLines() = buildList { - add(ScoreboardData.objectiveTitle to displayConfig.titleAndFooter.alignTitleAndFooter) - addAll(ScoreboardData.sidebarLinesFormatted.map { it to HorizontalAlignment.LEFT }) + add(ScoreboardData.objectiveTitle align displayConfig.titleAndFooter.alignTitle) + addAll(ScoreboardData.sidebarLinesFormatted.map { it.align() }) } - private fun addCustomSkyBlockLines() = buildList { - for (element in config.scoreboardEntries) { - val lines = element.getVisiblePair() + private fun addCustomSkyBlockLines() = buildList { + for (element in currentIslandEntries) { + val lines = element.getLines() if (lines.isEmpty()) continue if ( informationFilteringConfig.hideConsecutiveEmptyLines && - lines.first().first == "" && - lastOrNull()?.first?.isEmpty() == true + lines.first().display.isEmpty() && + lastOrNull()?.display?.isEmpty() == true ) { continue } - if (lines.first().first == "") { - add("" to HorizontalAlignment.LEFT) - continue - } - - if (lines.any { it.first == "" }) { - continue - } - addAll(lines) } } - private fun List.removeEmptyLinesFromEdges(): List { - if (config.informationFiltering.hideEmptyLinesAtTopAndBottom) { - return this - .dropWhile { it.first.isEmpty() } - .dropLastWhile { it.first.isEmpty() } - } - return this - } + private fun List.createRenderable() = Renderable.verticalContainer( + map { Renderable.string(it.display, horizontalAlign = it.alignment) }, + displayConfig.lineSpacing - 10, + horizontalAlign = HorizontalAlignment.CENTER, + verticalAlign = VerticalAlignment.CENTER, + ) + + private fun List.removeEmptyLinesFromEdges(): List = + takeIf { !informationFilteringConfig.hideEmptyLinesAtTopAndBottom } + ?: dropWhile { it.display.isBlank() }.dropLastWhile { it.display.isBlank() } private var dirty = false - // Thank you Apec for showing that the ElementType of the stupid scoreboard is FUCKING HELMET WTF + // The ElementType for the Vanilla Scoreboard is called HELMET + // Thanks to APEC for showing this @SubscribeEvent fun onRenderScoreboard(event: RenderGameOverlayEvent.Post) { if (event.type == RenderGameOverlayEvent.ElementType.HELMET) { @@ -213,6 +204,12 @@ object CustomScoreboard { ) { if (!isHideVanillaScoreboardEnabled()) dirty = true } + ConditionalUtils.onToggle( + config.scoreboardEntries, + eventsConfig.eventEntries, + ) { + updateIslandEntries() + } } @SubscribeEvent @@ -222,6 +219,16 @@ object CustomScoreboard { } } + @SubscribeEvent + fun onIslandChange(event: IslandChangeEvent) { + updateIslandEntries() + } + + private fun updateIslandEntries() { + currentIslandEntries = config.scoreboardEntries.get().map { it.element }.filter { it.showIsland() } + currentIslandEvents = eventsConfig.eventEntries.get().map { it.event }.filter { it.showIsland() } + } + @SubscribeEvent fun onDebugDataCollect(event: DebugDataCollectEvent) { event.title("Custom Scoreboard") @@ -229,117 +236,34 @@ object CustomScoreboard { if (!config.enabled.get()) { add("Custom Scoreboard disabled.") } else { - ScoreboardElement.entries.map { element -> + add("Custom Scoreboard Lines:") + ScoreboardConfigElement.entries.forEach { entry -> add( - "${element.name.firstLetterUppercase()} - " + - "${element.showWhen.invoke()} - " + - "${element.getVisiblePair().map { it.first }}", + " ${entry.name.firstLetterUppercase()} - " + + "island: ${entry.element.showIsland()} - " + + "show: ${entry.element.showWhen()} - " + + "${entry.element.getLines().map { it.display }}", ) } + allUnknownLines.takeIfNotEmpty()?.let { set -> + add("Recent Unknown Lines:") + set.forEach { add(" ${it.line}") } + } } } } + @JvmStatic + fun resetAppearance() { + with(config.scoreboardEntries) { + get().clear() + get().addAll(ScoreboardConfigElement.defaultOptions) + notifyObservers() + } + } + private fun isEnabled() = (LorenzUtils.inSkyBlock || (OutsideSbFeature.CUSTOM_SCOREBOARD.isSelected() && LorenzUtils.onHypixel)) && config.enabled.get() private fun isHideVanillaScoreboardEnabled() = isEnabled() && displayConfig.hideVanillaScoreboard.get() - - @SubscribeEvent - fun onConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) { - val prefix = "gui.customScoreboard" - val displayConfigPrefix = "$prefix.displayConfig" - val displayPrefix = "$prefix.display" - - event.move( - 28, - "$prefix.displayConfig.showAllActiveEvents", - "$prefix.displayConfig.eventsConfig.showAllActiveEvents", - ) - - event.move(31, "$displayConfigPrefix.arrowAmountDisplay", "$displayPrefix.arrow.amountDisplay") - event.move(31, "$displayConfigPrefix.colorArrowAmount", "$displayPrefix.arrow.colorArrowAmount") - event.move(31, "$displayConfigPrefix.showMagicalPower", "$displayPrefix.maxwell.showMagicalPower") - event.move(31, "$displayConfigPrefix.compactTuning", "$displayPrefix.maxwell.compactTuning") - event.move(31, "$displayConfigPrefix.tuningAmount", "$displayPrefix.maxwell.tuningAmount") - event.move(31, "$displayConfigPrefix.hideVanillaScoreboard", "$displayPrefix.hideVanillaScoreboard") - event.move(31, "$displayConfigPrefix.displayNumbersFirst", "$displayPrefix.displayNumbersFirst") - event.move(31, "$displayConfigPrefix.showUnclaimedBits", "$displayPrefix.showUnclaimedBits") - event.move(31, "$displayConfigPrefix.showMaxIslandPlayers", "$displayPrefix.showMaxIslandPlayers") - event.move(31, "$displayConfigPrefix.numberFormat", "$displayPrefix.numberFormat") - event.move(31, "$displayConfigPrefix.lineSpacing", "$displayPrefix.lineSpacing") - event.move( - 31, - "$displayConfigPrefix.cacheScoreboardOnIslandSwitch", - "$displayPrefix.cacheScoreboardOnIslandSwitch", - ) - // Categories - event.move(31, "$displayConfigPrefix.alignment", "$displayPrefix.alignment") - event.move(31, "$displayConfigPrefix.titleAndFooter", "$displayPrefix.titleAndFooter") - event.move(31, "$prefix.backgroundConfig", "$prefix.background") - event.move(31, "$prefix.informationFilteringConfig", "$prefix.informationFiltering") - event.move(31, "$displayConfigPrefix.eventsConfig", "$displayPrefix.events") - event.move(31, "$prefix.mayorConfig", "$displayPrefix.mayor") - event.move(31, "$prefix.partyConfig", "$displayPrefix.party") - - event.transform(37, "$displayPrefix.events.eventEntries") { element -> - val array = element.asJsonArray - array.add(JsonPrimitive(ScoreboardEvent.QUEUE.name)) - array - } - event.transform(40, "$displayPrefix.events.eventEntries") { element -> - val jsonArray = element.asJsonArray - val newArray = JsonArray() - - for (jsonElement in jsonArray) { - val stringValue = jsonElement.asString - if (stringValue !in listOf("HOT_DOG_CONTEST", "EFFIGIES")) { - newArray.add(jsonElement) - } - } - - if (jsonArray.any { it.asString in listOf("HOT_DOG_CONTEST", "EFFIGIES") }) { - newArray.add(JsonPrimitive(ScoreboardEvent.RIFT.name)) - } - - newArray - } - - event.move(43, "$displayPrefix.alignment.alignRight", "$displayPrefix.alignment.horizontalAlignment") { - JsonPrimitive( - if (it.asBoolean) { - HorizontalAlignment.RIGHT.name - } else { - HorizontalAlignment.DONT_ALIGN.name - }, - ) - } - event.move(43, "$displayPrefix.alignment.alignCenterVertically", "$displayPrefix.alignment.verticalAlignment") { - JsonPrimitive( - if (it.asBoolean) { - VerticalAlignment.CENTER.name - } else { - VerticalAlignment.DONT_ALIGN.name - }, - ) - } - event.transform(50, "$displayPrefix.events.eventEntries") { element -> - val array = element.asJsonArray - array.add(JsonPrimitive(ScoreboardEvent.ANNIVERSARY.name)) - array.add(JsonPrimitive(ScoreboardEvent.CARNIVAL.name)) - array - } - event.transform(51, "$displayPrefix.events.eventEntries") { element -> - val array = element.asJsonArray - array.add(JsonPrimitive(ScoreboardEvent.NEW_YEAR.name)) - array - } - event.move( - 57, - "$displayPrefix.titleAndFooter.useHypixelTitleAnimation", - "$displayPrefix.titleAndFooter.useCustomTitle", - ) { - JsonPrimitive(!it.asBoolean) - } - } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/CustomScoreboardConfigFix.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/CustomScoreboardConfigFix.kt new file mode 100644 index 000000000000..44dac812764e --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/CustomScoreboardConfigFix.kt @@ -0,0 +1,119 @@ +package at.hannibal2.skyhanni.features.gui.customscoreboard + +import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.utils.RenderUtils.HorizontalAlignment +import at.hannibal2.skyhanni.utils.RenderUtils.VerticalAlignment +import com.google.gson.JsonArray +import com.google.gson.JsonElement +import com.google.gson.JsonPrimitive +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +@SkyHanniModule +object CustomScoreboardConfigFix { + + private const val PREFIX = "gui.customScoreboard" + private const val DISPLAY_PREFIX = "$PREFIX.display" + private const val DISPLAY_CONFIG_PREFIX = "$PREFIX.displayConfig" + private const val EVENTS_CONFIG_KEY = "$DISPLAY_CONFIG_PREFIX.eventsConfig" + private const val ALIGNMENT_KEY = "$DISPLAY_PREFIX.alignment" + private const val TITLE_AND_FOOTER_KEY = "$DISPLAY_PREFIX.titleAndFooter" + private const val EVENT_ENTRIES_KEY = "$DISPLAY_PREFIX.events.eventEntries" + + @SubscribeEvent + fun onConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) { + + event.move(28, "$DISPLAY_CONFIG_PREFIX.showAllActiveEvents", "$EVENTS_CONFIG_KEY.showAllActiveEvents") + + val configPrefixMappings = mapOf( + "$DISPLAY_CONFIG_PREFIX.showAllActiveEvents" to "$EVENTS_CONFIG_KEY.showAllActiveEvents", + "$DISPLAY_CONFIG_PREFIX.arrowAmountDisplay" to "$DISPLAY_PREFIX.arrow.amountDisplay", + "$DISPLAY_CONFIG_PREFIX.colorArrowAmount" to "$DISPLAY_PREFIX.arrow.colorArrowAmount", + "$DISPLAY_CONFIG_PREFIX.showMagicalPower" to "$DISPLAY_PREFIX.maxwell.showMagicalPower", + "$DISPLAY_CONFIG_PREFIX.compactTuning" to "$DISPLAY_PREFIX.maxwell.compactTuning", + "$DISPLAY_CONFIG_PREFIX.tuningAmount" to "$DISPLAY_PREFIX.maxwell.tuningAmount", + "$DISPLAY_CONFIG_PREFIX.hideVanillaScoreboard" to "$DISPLAY_PREFIX.hideVanillaScoreboard", + "$DISPLAY_CONFIG_PREFIX.displayNumbersFirst" to "$DISPLAY_PREFIX.displayNumbersFirst", + "$DISPLAY_CONFIG_PREFIX.showUnclaimedBits" to "$DISPLAY_PREFIX.showUnclaimedBits", + "$DISPLAY_CONFIG_PREFIX.showMaxIslandPlayers" to "$DISPLAY_PREFIX.showMaxIslandPlayers", + "$DISPLAY_CONFIG_PREFIX.numberFormat" to "$DISPLAY_PREFIX.numberFormat", + "$DISPLAY_CONFIG_PREFIX.lineSpacing" to "$DISPLAY_PREFIX.lineSpacing", + "$DISPLAY_CONFIG_PREFIX.cacheScoreboardOnIslandSwitch" to "$DISPLAY_PREFIX.cacheScoreboardOnIslandSwitch", + "$DISPLAY_CONFIG_PREFIX.alignment" to ALIGNMENT_KEY, + "$PREFIX.backgroundConfig" to "$PREFIX.background", + "$PREFIX.informationFilteringConfig" to "$PREFIX.informationFiltering", + EVENTS_CONFIG_KEY to "$DISPLAY_PREFIX.events", + "$PREFIX.mayorConfig" to "$DISPLAY_PREFIX.mayor", + "$PREFIX.partyConfig" to "$DISPLAY_PREFIX.party", + ) + + configPrefixMappings.forEach { (oldKey, newKey) -> + event.move(31, oldKey, newKey) + } + + event.transform(37, EVENT_ENTRIES_KEY) { + it.asJsonArray.apply { + add(JsonPrimitive(ScoreboardConfigEventElement.QUEUE.name)) + } + } + + event.transform(40, EVENT_ENTRIES_KEY) { element -> + replaceElements(element, listOf("HOT_DOG_CONTEST", "EFFIGIES"), ScoreboardConfigEventElement.RIFT.name) + } + + event.move(43, "$ALIGNMENT_KEY.alignRight", "$ALIGNMENT_KEY.horizontalAlignment") { + JsonPrimitive( + if (it.asBoolean) HorizontalAlignment.RIGHT.name + else HorizontalAlignment.DONT_ALIGN.name, + ) + } + event.move(43, "$ALIGNMENT_KEY.alignCenterVertically", "$ALIGNMENT_KEY.verticalAlignment") { + JsonPrimitive( + if (it.asBoolean) VerticalAlignment.CENTER.name + else VerticalAlignment.DONT_ALIGN.name, + ) + } + + event.transform(50, EVENT_ENTRIES_KEY) { + it.asJsonArray.apply { + add(JsonPrimitive(ScoreboardConfigEventElement.ANNIVERSARY.name)) + add(JsonPrimitive(ScoreboardConfigEventElement.CARNIVAL.name)) + } + } + + event.transform(51, EVENT_ENTRIES_KEY) { + it.asJsonArray.apply { + add(JsonPrimitive(ScoreboardConfigEventElement.NEW_YEAR.name)) + } + } + + event.move(57, "$TITLE_AND_FOOTER_KEY.useHypixelTitleAnimation", "$TITLE_AND_FOOTER_KEY.useCustomTitle") { + JsonPrimitive(!it.asBoolean) + } + + event.transform(63, EVENT_ENTRIES_KEY) { element -> + replaceElements(element, listOf("GARDEN_CLEAN_UP", "GARDEN_PASTING"), ScoreboardConfigEventElement.GARDEN.name) + } + listOf("customTitle", "customFooter").forEach { key -> + event.transform(63, "$TITLE_AND_FOOTER_KEY.$key") { + JsonPrimitive(it.asString.replace("&", "&&")) + } + } + listOf("alignTitle", "alignFooter").forEach { key -> + event.move(63, "$TITLE_AND_FOOTER_KEY.alignTitleAndFooter", "$TITLE_AND_FOOTER_KEY.$key") + } + } + + private fun replaceElements(element: JsonElement, oldElements: List, newElement: String): JsonArray { + val jsonArray = element.asJsonArray + val newArray = JsonArray() + + jsonArray.filterNot { it.asString in oldElements }.forEach(newArray::add) + + if (jsonArray.any { it.asString in oldElements }) { + newArray.add(JsonPrimitive(newElement)) + } + + return newArray + } +} 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 99fdc4f3fcf6..b90c239878ab 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 @@ -3,71 +3,87 @@ package at.hannibal2.skyhanni.features.gui.customscoreboard import at.hannibal2.skyhanni.config.features.gui.customscoreboard.DisplayConfig import at.hannibal2.skyhanni.data.BitsAPI import at.hannibal2.skyhanni.data.HypixelData +import at.hannibal2.skyhanni.data.PurseAPI +import at.hannibal2.skyhanni.data.model.TabWidget import at.hannibal2.skyhanni.data.ScoreboardData import at.hannibal2.skyhanni.features.bingo.BingoAPI import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard.displayConfig +import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardLine.Companion.align import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators import at.hannibal2.skyhanni.utils.NumberUtil.formatDouble import at.hannibal2.skyhanni.utils.NumberUtil.shortFormat -import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher +import at.hannibal2.skyhanni.utils.RegexUtils.groupOrNull +import at.hannibal2.skyhanni.utils.RegexUtils.matchGroup import at.hannibal2.skyhanni.utils.StringUtils.removeResets import at.hannibal2.skyhanni.utils.StringUtils.trimWhiteSpace -import at.hannibal2.skyhanni.utils.TabListData import java.util.regex.Pattern object CustomScoreboardUtils { - internal fun getGroupFromPattern(list: List, pattern: Pattern, group: String) = list.map { - it.removeResets().trimWhiteSpace() - }.firstNotNullOfOrNull { line -> - pattern.matchMatcher(line) { - group(group) + private fun getGroup(pattern: Pattern, list: List, group: String) = + list.map { it.removeResets().trimWhiteSpace() }.firstNotNullOfOrNull { line -> + pattern.matchGroup(line, group) } - } fun getProfileTypeSymbol() = when { HypixelData.ironman -> "§7♲ " HypixelData.stranded -> "§a☀ " HypixelData.bingo -> ScoreboardData.sidebarLinesFormatted.firstNotNullOfOrNull { - BingoAPI.getIconFromScoreboard(it)?.plus(" ") + BingoAPI.getIconFromScoreboard(it)?.plus(" ") // TODO: add bingo rank to bingo api } ?: "§e❤ " else -> "§e" } - // TODO change to a non extended function - internal fun Number.formatNum(): String = when (displayConfig.numberFormat) { - DisplayConfig.NumberFormat.SHORT -> this.shortFormat() - DisplayConfig.NumberFormat.LONG -> this.addSeparators() + internal fun formatNumber(number: Number): String = when (displayConfig.numberFormat) { + DisplayConfig.NumberFormat.SHORT -> number.shortFormat() + DisplayConfig.NumberFormat.LONG -> number.addSeparators() else -> "0" } - internal fun String.formatNum() = this.formatDouble().formatNum() + internal fun formatStringNum(string: String) = formatNumber(string.formatDouble()) + + internal fun getMotes() = getGroup(ScoreboardPattern.motesPattern, getSbLines(), "motes") ?: "0" + + internal fun getSoulflow() = TabWidget.SOULFLOW.matchMatcherFirstLine { group("amount") } ?: "0" - internal fun getMotes() = getGroupFromPattern(ScoreboardData.sidebarLinesFormatted, ScoreboardPattern.motesPattern, "motes") - internal fun getBank() = getGroupFromPattern(TabListData.getTabList(), ScoreboardPattern.bankPattern, "bank") + internal fun getPurseEarned() = getGroup(PurseAPI.coinsPattern, getSbLines(), "earned")?.let { " §7(§e+$it§7)§6" } - internal fun getBits() = BitsAPI.bits.coerceAtLeast(0).formatNum() + internal fun getBank() = TabWidget.BANK.matchMatcherFirstLine { + group("amount") + (groupOrNull("personal")?.let { " §7/ §6$it" } ?: "") + } ?: "0" - internal fun getBitsToClaim() = BitsAPI.bitsAvailable.coerceAtLeast(0).formatNum() + internal fun getBits() = formatNumber(BitsAPI.bits.coerceAtLeast(0)) + + internal fun getBitsAvailable() = formatNumber(BitsAPI.bitsAvailable.coerceAtLeast(0)) internal fun getBitsLine() = if (displayConfig.showUnclaimedBits) { - "§b${getBits()}§7/§b${getBitsToClaim()}" - } else { - "§b${getBits()}" - } + "§b${getBits()}§7/§b${getBitsAvailable()}" + } else "§b${getBits()}" - internal fun getCopper() = - getGroupFromPattern(ScoreboardData.sidebarLinesFormatted, ScoreboardPattern.copperPattern, "copper") + internal fun getCopper() = getGroup(ScoreboardPattern.copperPattern, getSbLines(), "copper") ?: "0" - internal fun getGems() = getGroupFromPattern(TabListData.getTabList(), ScoreboardPattern.gemsPattern, "gems") + internal fun getGems() = TabWidget.GEMS.matchMatcherFirstLine { group("gems") } ?: "0" - internal fun getHeat() = - getGroupFromPattern(ScoreboardData.sidebarLinesFormatted, ScoreboardPattern.heatPattern, "heat") + internal fun getHeat() = getGroup(ScoreboardPattern.heatPattern, getSbLines(), "heat") - internal fun getNorthStars() = - getGroupFromPattern(ScoreboardData.sidebarLinesFormatted, ScoreboardPattern.northstarsPattern, "northstars") + internal fun getNorthStars() = getGroup(ScoreboardPattern.northstarsPattern, getSbLines(), "northStars") ?: "0" + internal fun getTimeSymbol() = getGroup(ScoreboardPattern.timePattern, getSbLines(), "symbol") ?: "" + + internal fun getTablistEvent() = TabWidget.EVENT.matchMatcherFirstLine { groupOrNull("color") + group("event") } + + internal fun getElementsFromAny(element: Any?): List = when (element) { + null -> listOf() + is List<*> -> element.mapNotNull { it?.toScoreboardElement() } + else -> listOfNotNull(element.toScoreboardElement()) + } + + private fun Any.toScoreboardElement(): ScoreboardLine? = when (this) { + is String -> this.align() + is ScoreboardLine -> this + else -> null + } - class UndetectedScoreboardLines(message: String) : Exception(message) + internal fun getSbLines() = ScoreboardData.sidebarLinesFormatted } diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardConfigElement.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardConfigElement.kt new file mode 100644 index 000000000000..9d9dcb378617 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardConfigElement.kt @@ -0,0 +1,125 @@ +package at.hannibal2.skyhanni.features.gui.customscoreboard + +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElement +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementBank +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementBits +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementChunkedStats +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementCold +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementCookie +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementCopper +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementDate +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementEmptyLine +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementEvents +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementFooter +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementGems +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementHeat +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementIsland +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementLobbyCode +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementLocation +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementMayor +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementMotes +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementNorthStars +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementObjective +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementParty +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementPlayerAmount +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementPowder +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementPower +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementProfile +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementPurse +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementQuiver +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementSlayer +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementSoulflow +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementTime +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementTitle +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementTuning +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementUnknown +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementVisiting + +// TODO once the config can support dynamic lists, remove this enum +enum class ScoreboardConfigElement(val element: ScoreboardElement) { + TITLE(ScoreboardElementTitle), + PROFILE(ScoreboardElementProfile), + PURSE(ScoreboardElementPurse), + MOTES(ScoreboardElementMotes), + BANK(ScoreboardElementBank), + BITS(ScoreboardElementBits), + COPPER(ScoreboardElementCopper), + GEMS(ScoreboardElementGems), + HEAT(ScoreboardElementHeat), + COLD(ScoreboardElementCold), + NORTH_STARS(ScoreboardElementNorthStars), + CHUNKED_STATS(ScoreboardElementChunkedStats), + SOULFLOW(ScoreboardElementSoulflow), + ISLAND(ScoreboardElementIsland), + LOCATION(ScoreboardElementLocation), + PLAYER_AMOUNT(ScoreboardElementPlayerAmount), + VISITING(ScoreboardElementVisiting), + DATE(ScoreboardElementDate), + TIME(ScoreboardElementTime), + LOBBY_CODE(ScoreboardElementLobbyCode), + POWER(ScoreboardElementPower), + TUNING(ScoreboardElementTuning), + COOKIE(ScoreboardElementCookie), + OBJECTIVE(ScoreboardElementObjective), + SLAYER(ScoreboardElementSlayer), + QUIVER(ScoreboardElementQuiver), + POWDER(ScoreboardElementPowder), + EVENTS(ScoreboardElementEvents), + MAYOR(ScoreboardElementMayor), + PARTY(ScoreboardElementParty), + FOOTER(ScoreboardElementFooter), + EXTRA(ScoreboardElementUnknown), + EMPTY_LINE(ScoreboardElementEmptyLine), + EMPTY_LINE2(ScoreboardElementEmptyLine), + EMPTY_LINE3(ScoreboardElementEmptyLine), + EMPTY_LINE4(ScoreboardElementEmptyLine), + EMPTY_LINE5(ScoreboardElementEmptyLine), + EMPTY_LINE6(ScoreboardElementEmptyLine), + EMPTY_LINE7(ScoreboardElementEmptyLine), + EMPTY_LINE8(ScoreboardElementEmptyLine), + EMPTY_LINE9(ScoreboardElementEmptyLine), + EMPTY_LINE10(ScoreboardElementEmptyLine), + ; + + override fun toString() = element.configLine + + companion object { + @JvmField + val defaultOptions = listOf( + TITLE, + PROFILE, + PURSE, + BANK, + MOTES, + BITS, + COPPER, + GEMS, + NORTH_STARS, + HEAT, + COLD, + EMPTY_LINE, + ISLAND, + LOCATION, + LOBBY_CODE, + PLAYER_AMOUNT, + VISITING, + EMPTY_LINE2, + DATE, + TIME, + EVENTS, + COOKIE, + EMPTY_LINE3, + QUIVER, + POWER, + TUNING, + EMPTY_LINE4, + OBJECTIVE, + SLAYER, + POWDER, + MAYOR, + PARTY, + FOOTER, + EXTRA, + ) + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardConfigEventElement.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardConfigEventElement.kt new file mode 100644 index 000000000000..aff6013465aa --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardConfigEventElement.kt @@ -0,0 +1,98 @@ +package at.hannibal2.skyhanni.features.gui.customscoreboard + +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventActiveTablist +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventAnniversary +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventBroodmother +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventCarnival +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventDamage +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventDarkAuction +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventDojo +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventDungeons +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventEssence +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventFlightDuration +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventGarden +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventJacobContest +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventJacobMedals +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventKuudra +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventMagmaBoss +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventMining +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventNewYear +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventQueue +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventRedstone +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventRift +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEvent +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventServerClose +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventSpooky +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventStartingSoonTablist +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventTrapper +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventVoting +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventWinter + +/** + * This enum contains all the lines that either are events or other lines that are so rare/not often seen that they + * don't fit in the normal [ScoreboardConfigElement] enum. + * + * We for example have the [ScoreboardEventVoting] Event, while this is clearly not an event, I don't consider them as normal lines + * because they are visible for a maximum of like 1 minute every 5 days and ~12 hours. + */ + +enum class ScoreboardConfigEventElement(val event: ScoreboardEvent) { + VOTING(ScoreboardEventVoting), + SERVER_CLOSE(ScoreboardEventServerClose), + DUNGEONS(ScoreboardEventDungeons), + KUUDRA(ScoreboardEventKuudra), + DOJO(ScoreboardEventDojo), + DARK_AUCTION(ScoreboardEventDarkAuction), + JACOB_CONTEST(ScoreboardEventJacobContest), + JACOB_MEDALS(ScoreboardEventJacobMedals), + TRAPPER(ScoreboardEventTrapper), + GARDEN(ScoreboardEventGarden), + FLIGHT_DURATION(ScoreboardEventFlightDuration), + WINTER(ScoreboardEventWinter), + NEW_YEAR(ScoreboardEventNewYear), + SPOOKY(ScoreboardEventSpooky), + BROODMOTHER(ScoreboardEventBroodmother), + MINING_EVENTS(ScoreboardEventMining), + DAMAGE(ScoreboardEventDamage), + MAGMA_BOSS(ScoreboardEventMagmaBoss), + CARNIVAL(ScoreboardEventCarnival), + RIFT(ScoreboardEventRift), + ESSENCE(ScoreboardEventEssence), + QUEUE(ScoreboardEventQueue), + ANNIVERSARY(ScoreboardEventAnniversary), + ACTIVE_TABLIST_EVENTS(ScoreboardEventActiveTablist), + STARTING_SOON_TABLIST_EVENTS(ScoreboardEventStartingSoonTablist), + REDSTONE(ScoreboardEventRedstone), + ; + + override fun toString() = event.configLine + + companion object { + @JvmField + val defaultOption = listOf( + VOTING, + SERVER_CLOSE, + DUNGEONS, + KUUDRA, + DOJO, + DARK_AUCTION, + JACOB_CONTEST, + JACOB_MEDALS, + TRAPPER, + GARDEN, + FLIGHT_DURATION, + NEW_YEAR, + WINTER, + SPOOKY, + BROODMOTHER, + MINING_EVENTS, + DAMAGE, + MAGMA_BOSS, + CARNIVAL, + RIFT, + ESSENCE, + ACTIVE_TABLIST_EVENTS, + REDSTONE, + ) + } +} 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 deleted file mode 100644 index f20479b65e44..000000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardElements.kt +++ /dev/null @@ -1,863 +0,0 @@ -package at.hannibal2.skyhanni.features.gui.customscoreboard - -import at.hannibal2.skyhanni.api.HotmAPI -import at.hannibal2.skyhanni.config.features.gui.customscoreboard.ArrowConfig.ArrowAmountDisplay -import at.hannibal2.skyhanni.config.features.gui.customscoreboard.DisplayConfig.PowderDisplay -import at.hannibal2.skyhanni.data.BitsAPI -import at.hannibal2.skyhanni.data.HypixelData -import at.hannibal2.skyhanni.data.HypixelData.getMaxPlayersForCurrentServer -import at.hannibal2.skyhanni.data.HypixelData.getPlayersOnCurrentServer -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 -import at.hannibal2.skyhanni.data.QuiverAPI.NONE_ARROW_TYPE -import at.hannibal2.skyhanni.data.QuiverAPI.asArrowPercentage -import at.hannibal2.skyhanni.data.ScoreboardData -import at.hannibal2.skyhanni.data.SlayerAPI -import at.hannibal2.skyhanni.features.dungeon.DungeonAPI -import at.hannibal2.skyhanni.features.gui.customscoreboard.ChunkedStat.Companion.getChunkedStats -import at.hannibal2.skyhanni.features.gui.customscoreboard.ChunkedStat.Companion.shouldShowChunkedStats -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard.arrowConfig -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard.chunkedConfig -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard.config -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard.displayConfig -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard.informationFilteringConfig -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard.maxwellConfig -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard.mayorConfig -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard.partyConfig -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.formatNum -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getBank -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getBitsLine -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getCopper -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getGems -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getGroupFromPattern -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getHeat -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getMotes -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getNorthStars -import at.hannibal2.skyhanni.utils.CollectionUtils.nextAfter -import at.hannibal2.skyhanni.utils.LorenzUtils -import at.hannibal2.skyhanni.utils.LorenzUtils.inAdvancedMiningIsland -import at.hannibal2.skyhanni.utils.LorenzUtils.inAnyIsland -import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators -import at.hannibal2.skyhanni.utils.NumberUtil.percentageColor -import at.hannibal2.skyhanni.utils.RegexUtils.anyMatches -import at.hannibal2.skyhanni.utils.RegexUtils.matches -import at.hannibal2.skyhanni.utils.RenderUtils.HorizontalAlignment -import at.hannibal2.skyhanni.utils.SimpleTimeMark -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.TimeUtils.format -import at.hannibal2.skyhanni.utils.TimeUtils.formatted -import kotlin.time.Duration.Companion.seconds - -internal var allUnknownLines = listOf() -internal var lastRecentAlarmWarning = SimpleTimeMark.farPast() - -internal fun recentUnknownLines() = allUnknownLines.filter { it.lastFound.passedSince() < 3.seconds } - -internal class UnknownLine(val line: String) { - val firstFound = SimpleTimeMark.now() - var lastFound = SimpleTimeMark.now() - var lastWarned = SimpleTimeMark.farPast() -} - -enum class ScoreboardElement( - private val displayPair: () -> List, - val showWhen: () -> Boolean, - private val configLine: String, -) { - TITLE( - ::getTitleDisplayPair, - { true }, - "§6§lSKYBLOCK", - ), - PROFILE( - ::getProfileDisplayPair, - { true }, - "§7♲ Blueberry", - ), - PURSE( - ::getPurseDisplayPair, - ::getPurseShowWhen, - "Purse: §652,763,737", - ), - MOTES( - ::getMotesDisplayPair, - ::getMotesShowWhen, - "Motes: §d64,647", - ), - BANK( - ::getBankDisplayPair, - ::getBankShowWhen, - "Bank: §6249M", - ), - BITS( - ::getBitsDisplayPair, - ::getBitsShowWhen, - "Bits: §b59,264", - ), - COPPER( - ::getCopperDisplayPair, - ::getCopperShowWhen, - "Copper: §c23,495", - ), - GEMS( - ::getGemsDisplayPair, - ::getGemsShowWhen, - "Gems: §a57,873", - ), - HEAT( - ::getHeatDisplayPair, - ::getHeatShowWhen, - "Heat: §c♨ 0", - ), - COLD( - ::getColdDisplayPair, - ::getColdShowWhen, - "Cold: §b0❄", - ), - NORTH_STARS( - ::getNorthStarsDisplayPair, - ::getNorthStarsShowWhen, - "North Stars: §d756", - ), - CHUNKED_STATS( - ::getChunkedStatsDisplayPair, - ::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 }, - "", - ), - ISLAND( - ::getIslandDisplayPair, - { true }, - "§7㋖ §aHub", - ), - LOCATION( - ::getLocationDisplayPair, - { true }, - "§7⏣ §bVillage", - ), - PLAYER_AMOUNT( - ::getPlayerAmountDisplayPair, - { true }, - "§7Players: §a69§7/§a80", - ), - VISITING( - ::getVisitDisplayPair, - ::getVisitShowWhen, - " §a✌ §7(§a1§7/6)", - ), - DATE( - ::getDateDisplayPair, - { true }, - "Late Summer 11th", - ), - TIME( - ::getTimeDisplayPair, - { true }, - "§710:40pm §b☽", - ), - LOBBY_CODE( - ::getLobbyDisplayPair, - { true }, - "§8mega77CK", - ), - POWER( - ::getPowerDisplayPair, - ::getPowerShowWhen, - "Power: §aSighted §7(§61.263§7)", - ), - TUNING( - ::getTuningDisplayPair, - ::getPowerShowWhen, - "Tuning: §c❁34§7, §e⚔20§7, and §9☣7", - ), - COOKIE( - ::getCookieDisplayPair, - ::getCookieShowWhen, - "§dCookie Buff§f: 3d 17h", - ), - EMPTY_LINE2( - ::getEmptyLineDisplayPair, - { true }, - "", - ), - OBJECTIVE( - ::getObjectiveDisplayPair, - ::getObjectiveShowWhen, - "Objective:\n§eStar SkyHanni on Github", - ), - SLAYER( - ::getSlayerDisplayPair, - ::getSlayerShowWhen, - "Slayer Quest\n §7- §cVoidgloom Seraph III\n §7- §e12§7/§c120 §7Kills", - ), - EMPTY_LINE3( - ::getEmptyLineDisplayPair, - { true }, - "", - ), - QUIVER( - ::getQuiverDisplayPair, - ::getQuiverShowWhen, - "Flint Arrow: §f1,234", - ), - POWDER( - ::getPowderDisplayPair, - ::getPowderShowWhen, - "§9§lPowder\n §7- §fMithril: §254,646\n §7- §fGemstone: §d51,234", - ), - EVENTS( - ::getEventsDisplayPair, - ::getEventsShowWhen, - "§7Wide Range of Events\n§7(too much to show all)", - ), - MAYOR( - ::getMayorDisplayPair, - ::getMayorShowWhen, - "§2Diana:\n §7- §eLucky!\n §7- §eMythological Ritual\n §7- §ePet XP Buff", - ), - PARTY( - ::getPartyDisplayPair, - ::getPartyShowWhen, - "§9§lParty (4):\n §7- §fhannibal2\n §7- §fMoulberry\n §7- §fVahvl\n §7- §fSkirtwearer", - ), - FOOTER( - ::getFooterDisplayPair, - { true }, - "§ewww.hypixel.net", - ), - EXTRA( - ::getExtraDisplayPair, - ::getExtraShowWhen, - "§cUnknown lines the mod is not detecting", - ), - EMPTY_LINE4( - ::getEmptyLineDisplayPair, - { true }, - "", - ), - EMPTY_LINE5( - ::getEmptyLineDisplayPair, - { true }, - "", - ), - EMPTY_LINE6( - ::getEmptyLineDisplayPair, - { true }, - "", - ), - EMPTY_LINE7( - ::getEmptyLineDisplayPair, - { true }, - "", - ), - EMPTY_LINE8( - ::getEmptyLineDisplayPair, - { true }, - "", - ), - EMPTY_LINE9( - ::getEmptyLineDisplayPair, - { true }, - "", - ), - EMPTY_LINE10( - ::getEmptyLineDisplayPair, - { true }, - "", - ), - ; - - override fun toString() = configLine - - fun getVisiblePair() = if (isVisible()) getPair() else listOf("" to HorizontalAlignment.LEFT) - - private fun getPair(): List { - return try { - displayPair() - } catch (e: NoSuchElementException) { - listOf("" to HorizontalAlignment.LEFT) - } - } - - private fun isVisible(): Boolean { - if (!informationFilteringConfig.hideIrrelevantLines) return true - return showWhen() - } - - companion object { - // I don't know why, but this field is needed for it to work - @JvmField - val defaultOption = listOf( - TITLE, - PROFILE, - PURSE, - BANK, - MOTES, - BITS, - COPPER, - GEMS, - NORTH_STARS, - HEAT, - COLD, - EMPTY_LINE, - ISLAND, - LOCATION, - LOBBY_CODE, - PLAYER_AMOUNT, - VISITING, - EMPTY_LINE2, - DATE, - TIME, - EVENTS, - COOKIE, - EMPTY_LINE3, - QUIVER, - POWER, - TUNING, - EMPTY_LINE4, - OBJECTIVE, - SLAYER, - POWDER, - MAYOR, - PARTY, - FOOTER, - EXTRA, - ) - } -} - -private fun getTitleDisplayPair(): List { - val alignment = displayConfig.titleAndFooter.alignTitleAndFooter - - if (!LorenzUtils.inSkyBlock && !displayConfig.titleAndFooter.useCustomTitleOutsideSkyBlock) { - return listOf(ScoreboardData.objectiveTitle to alignment) - } - - return if (displayConfig.titleAndFooter.useCustomTitle) { - listOf( - displayConfig.titleAndFooter.customTitle.get().toString() - .replace("&", "§") - .split("\\n") - .map { it to alignment } - ).flatten() - } else { - listOf(ScoreboardData.objectiveTitle to alignment) - } -} - -private fun getProfileDisplayPair() = listOf( - CustomScoreboardUtils.getProfileTypeSymbol() + HypixelData.profileName.firstLetterUppercase() - to HorizontalAlignment.LEFT, -) - -private fun getPurseDisplayPair(): List { - var purse = PurseAPI.currentPurse.formatNum() - - if (!displayConfig.hideCoinsDifference) { - val earned = getGroupFromPattern(ScoreboardData.sidebarLinesFormatted, PurseAPI.coinsPattern, "earned") - if (earned != null) purse += " §7(§e+$earned§7)§6" - } - - return listOf( - when { - informationFilteringConfig.hideEmptyLines && purse == "0" -> "" - displayConfig.displayNumbersFirst -> "§6$purse Purse" - else -> "Purse: §6$purse" - } to HorizontalAlignment.LEFT, - ) -} - -private fun getPurseShowWhen() = !inAnyIsland(IslandType.THE_RIFT) - -private fun getMotesDisplayPair(): List { - val motes = getMotes()?.formatNum() ?: "0" - - return listOf( - when { - informationFilteringConfig.hideEmptyLines && motes == "0" -> "" - displayConfig.displayNumbersFirst -> "§d$motes Motes" - else -> "Motes: §d$motes" - } to HorizontalAlignment.LEFT, - ) -} - -private fun getMotesShowWhen() = inAnyIsland(IslandType.THE_RIFT) - -private fun getBankDisplayPair(): List { - val bank = getBank() ?: "0" - - return listOf( - when { - informationFilteringConfig.hideEmptyLines && (bank == "0" || bank == "0§7 / §60") -> "" - displayConfig.displayNumbersFirst -> "§6$bank Bank" - else -> "Bank: §6$bank" - } to HorizontalAlignment.LEFT, - ) -} - -private fun getBankShowWhen() = !inAnyIsland(IslandType.THE_RIFT) - -private fun getBitsDisplayPair(): List { - val bits = BitsAPI.bits.coerceAtLeast(0).formatNum() - val bitsToClaim = if (BitsAPI.bitsAvailable == -1) { - "§cOpen Sbmenu§b" - } else { - BitsAPI.bitsAvailable.coerceAtLeast(0).formatNum() - } - - return listOf( - when { - informationFilteringConfig.hideEmptyLines && bits == "0" && bitsToClaim == "0" -> "" - displayConfig.displayNumbersFirst -> "${getBitsLine()} Bits" - else -> "Bits: ${getBitsLine()}" - } to HorizontalAlignment.LEFT, - ) -} - -private fun getBitsShowWhen() = !HypixelData.bingo && !inAnyIsland(IslandType.CATACOMBS, IslandType.KUUDRA_ARENA) - -private fun getCopperDisplayPair(): List { - val copper = getCopper()?.formatNum() ?: "0" - - return listOf( - when { - informationFilteringConfig.hideEmptyLines && copper == "0" -> "" - displayConfig.displayNumbersFirst -> "§c$copper Copper" - else -> "Copper: §c$copper" - } to HorizontalAlignment.LEFT, - ) -} - -private fun getCopperShowWhen() = inAnyIsland(IslandType.GARDEN) - -private fun getGemsDisplayPair(): List { - val gems = getGems() - - return listOf( - when { - informationFilteringConfig.hideEmptyLines && gems == "0" -> "" - displayConfig.displayNumbersFirst -> "§a$gems Gems" - else -> "Gems: §a$gems" - } to HorizontalAlignment.LEFT, - ) -} - -private fun getGemsShowWhen() = !inAnyIsland(IslandType.THE_RIFT, IslandType.CATACOMBS, IslandType.KUUDRA_ARENA) - -private fun getHeatDisplayPair(): List { - val heat = getHeat() - - return listOf( - when { - informationFilteringConfig.hideEmptyLines && heat == "§c♨ 0" -> "" - displayConfig.displayNumbersFirst -> heat?.let { "$heat Heat" } ?: "§c♨ 0 Heat" - else -> heat?.let { "Heat: $heat" } ?: "§c♨ 0 Heat" - } to HorizontalAlignment.LEFT, - ) -} - -private fun getHeatShowWhen() = inAnyIsland(IslandType.CRYSTAL_HOLLOWS) && - ScoreboardData.sidebarLinesFormatted.any { ScoreboardPattern.heatPattern.matches(it) } - -private fun getColdDisplayPair(): List { - val cold = -MiningAPI.cold - - return listOf( - when { - informationFilteringConfig.hideEmptyLines && cold == 0 -> "" - displayConfig.displayNumbersFirst -> "§b$cold❄ Cold" - else -> "Cold: §b$cold❄" - } to HorizontalAlignment.LEFT, - ) -} - -private fun getColdShowWhen() = inAnyIsland(IslandType.DWARVEN_MINES, IslandType.MINESHAFT) && - ScoreboardData.sidebarLinesFormatted.any { ScoreboardPattern.coldPattern.matches(it) } - -private fun getNorthStarsDisplayPair(): List { - val northStars = getNorthStars()?.formatNum() ?: "0" - - return listOf( - when { - informationFilteringConfig.hideEmptyLines && northStars == "0" -> "" - displayConfig.displayNumbersFirst -> "§d$northStars North Stars" - else -> "North Stars: §d$northStars" - } to HorizontalAlignment.LEFT, - ) -} - -private fun getNorthStarsShowWhen() = inAnyIsland(IslandType.WINTER) - -private fun getChunkedStatsDisplayPair(): List = - getChunkedStats() - .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() = - listOf("§7㋖ §a" + LorenzUtils.skyBlockIsland.displayName to HorizontalAlignment.LEFT) - -private fun getLocationDisplayPair() = buildList { - HypixelData.skyBlockAreaWithSymbol?.let { add(it to HorizontalAlignment.LEFT) } - - ScoreboardData.sidebarLinesFormatted.firstOrNull { ScoreboardPattern.plotPattern.matches(it) } - ?.let { add(it to HorizontalAlignment.LEFT) } -} - -fun getPlayerAmountDisplayPair() = buildList { - val max = if (displayConfig.showMaxIslandPlayers) { - "§7/§a${getMaxPlayersForCurrentServer()}" - } else { - "" - } - if (displayConfig.displayNumbersFirst) - add("§a${getPlayersOnCurrentServer()}$max Players" to HorizontalAlignment.LEFT) - else - add("§7Players: §a${getPlayersOnCurrentServer()}$max" to HorizontalAlignment.LEFT) -} - -private fun getVisitDisplayPair() = - listOf( - ScoreboardData.sidebarLinesFormatted.first { ScoreboardPattern.visitingPattern.matches(it) } to - HorizontalAlignment.LEFT, - ) - -private fun getVisitShowWhen() = - ScoreboardData.sidebarLinesFormatted.any { ScoreboardPattern.visitingPattern.matches(it) } - -private fun getDateDisplayPair() = - listOf( - SkyBlockTime.now().formatted(yearElement = false, hoursAndMinutesElement = false) to HorizontalAlignment.LEFT, - ) - -private fun getTimeDisplayPair(): List { - val symbol = - getGroupFromPattern(ScoreboardData.sidebarLinesFormatted, ScoreboardPattern.timePattern, "symbol") ?: "" - return listOf( - "§7" + SkyBlockTime.now() - .formatted( - dayAndMonthElement = false, - yearElement = false, - timeFormat24h = config.display.skyblockTime24hFormat, - exactMinutes = config.display.skyblockTimeExactMinutes, - ) + - " $symbol" to HorizontalAlignment.LEFT, - ) -} - -private fun getLobbyDisplayPair(): List { - val lobbyCode = HypixelData.serverId - val roomId = DungeonAPI.getRoomID()?.let { "§8$it" } ?: "" - val lobbyDisplay = lobbyCode?.let { "§8$it $roomId" } ?: "" - return listOf(lobbyDisplay to HorizontalAlignment.LEFT) -} - -private fun getPowerDisplayPair() = listOf( - ( - MaxwellAPI.currentPower?.let { - val mp = if (maxwellConfig.showMagicalPower) "§7(§6${MaxwellAPI.magicalPower?.addSeparators()}§7)" else "" - if (displayConfig.displayNumbersFirst) { - "§a${it.replace(" Power", "")} Power $mp" - } else { - "Power: §a$it $mp" - } - } ?: "§cOpen \"Your Bags\"!" - ) to HorizontalAlignment.LEFT, -) - -private fun getTuningDisplayPair(): List> { - val tunings = MaxwellAPI.tunings ?: return listOf("§cTalk to \"Maxwell\"!" to HorizontalAlignment.LEFT) - if (tunings.isEmpty()) return listOf("§cNo Maxwell Tunings :(" to HorizontalAlignment.LEFT) - - val title = pluralize(tunings.size, "Tuning", "Tunings") - return if (maxwellConfig.compactTuning) { - val tuning = tunings - .take(3) - .joinToString("§7, ") { tuning -> - with(tuning) { - if (displayConfig.displayNumbersFirst) { - "$color$value$icon" - } else { - "$color$icon$value" - } - } - - } - listOf( - if (displayConfig.displayNumbersFirst) { - "$tuning §f$title" - } else { - "$title: $tuning" - } to HorizontalAlignment.LEFT, - ) - } else { - val tuning = tunings - .take(maxwellConfig.tuningAmount.coerceAtLeast(1)) - .map { tuning -> - with(tuning) { - " §7- §f" + if (displayConfig.displayNumbersFirst) { - "$color$value $icon $name" - } else { - "$name: $color$value$icon" - } - } - - }.toTypedArray() - listOf("$title:", *tuning).map { it to HorizontalAlignment.LEFT } - } -} - -private fun getPowerShowWhen() = !inAnyIsland(IslandType.THE_RIFT) - -private fun getCookieDisplayPair() = listOf( - "§dCookie Buff§f: " + ( - BitsAPI.cookieBuffTime?.let { - if (!BitsAPI.hasCookieBuff()) "§cNot Active" else it.timeUntil().format(maxUnits = 2) - } ?: "§cOpen SbMenu!" - ) to HorizontalAlignment.LEFT, -) - -private fun getCookieShowWhen(): Boolean { - if (HypixelData.bingo) return false - return informationFilteringConfig.hideEmptyLines && BitsAPI.hasCookieBuff() -} - -private fun getObjectiveDisplayPair() = buildList { - val formattedLines = ScoreboardData.sidebarLinesFormatted - val objective = formattedLines.firstOrNull { ScoreboardPattern.objectivePattern.matches(it) } - if (objective != null) { - add(objective to HorizontalAlignment.LEFT) - - val secondLine = formattedLines.nextAfter(objective) ?: "" - add(secondLine to HorizontalAlignment.LEFT) - - formattedLines.nextAfter(objective, 2)?.let { - if (ScoreboardPattern.thirdObjectiveLinePattern.matches(it)) add(it to HorizontalAlignment.LEFT) - } - - formattedLines.nextAfter(objective, 3)?.let { - if (ScoreboardPattern.thirdObjectiveLinePattern.matches(it)) add(it to HorizontalAlignment.LEFT) - } - } -} - -private fun getObjectiveShowWhen(): Boolean = - ScoreboardPattern.objectivePattern.anyMatches(ScoreboardData.sidebarLinesFormatted) - -private fun getSlayerDisplayPair(): List = buildList { - add((if (SlayerAPI.hasActiveSlayerQuest()) "Slayer Quest" else "") to HorizontalAlignment.LEFT) - add(" §7- §e${SlayerAPI.latestSlayerCategory.trim()}" to HorizontalAlignment.LEFT) - add(" §7- §e${SlayerAPI.latestSlayerProgress.trim()}" to HorizontalAlignment.LEFT) -} - -private fun getSlayerShowWhen() = - if (informationFilteringConfig.hideIrrelevantLines) SlayerAPI.isInCorrectArea else true - -private fun getQuiverDisplayPair(): List { - if (QuiverAPI.currentArrow == null) - return listOf("§cChange your Arrow once" to HorizontalAlignment.LEFT) - 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) { - "∞" - } else { - when (arrowConfig.arrowAmountDisplay) { - ArrowAmountDisplay.NUMBER -> QuiverAPI.currentAmount.addSeparators() - ArrowAmountDisplay.PERCENTAGE -> "${QuiverAPI.currentAmount.asArrowPercentage()}%" - else -> QuiverAPI.currentAmount.addSeparators() - } - } - - return listOf( - if (displayConfig.displayNumbersFirst) { - "$amountString ${QuiverAPI.currentArrow?.arrow}s" - } else { - "Arrows: $amountString ${QuiverAPI.currentArrow?.arrow?.replace(" Arrow", "")}" - } to HorizontalAlignment.LEFT, - ) -} - -private fun getQuiverShowWhen(): Boolean { - if (informationFilteringConfig.hideIrrelevantLines && !QuiverAPI.hasBowInInventory()) return false - return !inAnyIsland(IslandType.THE_RIFT) -} - -private fun getPowderDisplayPair() = buildList { - val powderTypes = HotmAPI.PowderType.values() - if (informationFilteringConfig.hideEmptyLines && powderTypes.all { it.getTotal() == 0L }) { - return listOf("" to HorizontalAlignment.LEFT) - } - - add("§9§lPowder" to HorizontalAlignment.LEFT) - - val displayNumbersFirst = displayConfig.displayNumbersFirst - - for (type in powderTypes) { - val name = type.displayName - val color = type.color - val current = type.getCurrent().formatNum() - val total = type.getTotal().formatNum() - - when (displayConfig.powderDisplay) { - PowderDisplay.AVAILABLE -> { - add(" §7- ${if (displayNumbersFirst) "$color$current $name" else "§f$name: $color$current"}" to HorizontalAlignment.LEFT) - } - - PowderDisplay.TOTAL -> { - add(" §7- ${if (displayNumbersFirst) "$color$total $name" else "§f$name: $color$total"}" to HorizontalAlignment.LEFT) - } - - PowderDisplay.BOTH -> { - add( - " §7- ${if (displayNumbersFirst) "$color$current/$total $name" else "§f$name: $color$current/$total"}" - to HorizontalAlignment.LEFT, - ) - } - - null -> {} - } - } -} - -private fun getPowderShowWhen() = inAdvancedMiningIsland() - -private fun getEventsDisplayPair(): List = ScoreboardEvent.getEvent() - .filterNotNull() - .flatMap { it.getLines().map { i -> i to HorizontalAlignment.LEFT } } - .takeIf { it.isNotEmpty() } ?: listOf("" to HorizontalAlignment.LEFT) - - -private fun getEventsShowWhen() = ScoreboardEvent.getEvent().isNotEmpty() - -private fun getMayorDisplayPair() = buildList { - val currentMayorName = MayorAPI.currentMayor?.mayorName?.let { MayorAPI.mayorNameWithColorCode(it) } ?: return@buildList - val timeTillNextMayor = if (mayorConfig.showTimeTillNextMayor) { - "§7 (§e${MayorAPI.nextMayorTimestamp.timeUntil().format(maxUnits = 2)}§7)" - } else { - "" - } - - add((currentMayorName + timeTillNextMayor) to HorizontalAlignment.LEFT) - - if (mayorConfig.showMayorPerks) { - MayorAPI.currentMayor?.activePerks?.forEach { perk -> - add(" §7- §e${perk.perkName}" to HorizontalAlignment.LEFT) - } - } - - if (!mayorConfig.showExtraMayor) return@buildList - addAll(addMinister()) - addAll(addPerkpocalypseMayor()) -} - -private fun addMinister() = buildList { - val ministerName = MayorAPI.currentMinister?.mayorName?.let { MayorAPI.mayorNameWithColorCode(it) } ?: return@buildList - add(ministerName to HorizontalAlignment.LEFT) - - if (mayorConfig.showMayorPerks) { - MayorAPI.currentMinister?.activePerks?.forEach { perk -> - add(" §7- §e${perk.perkName}" to HorizontalAlignment.LEFT) - } - } -} - -private fun addPerkpocalypseMayor() = buildList { - val jerryExtraMayor = MayorAPI.jerryExtraMayor - val extraMayor = jerryExtraMayor.first ?: return@buildList - - val extraMayorName = extraMayor.mayorName.let { MayorAPI.mayorNameWithColorCode(it) } - val extraTimeTillNextMayor = if (mayorConfig.showTimeTillNextMayor) { - "§7 (§6${jerryExtraMayor.second.timeUntil().format(maxUnits = 2)}§7)" - } else { - "" - } - - add((extraMayorName + extraTimeTillNextMayor) to HorizontalAlignment.LEFT) -} - -private fun getMayorShowWhen() = - !inAnyIsland(IslandType.THE_RIFT) && MayorAPI.currentMayor != null - -private fun getPartyDisplayPair() = - if (PartyAPI.partyMembers.isEmpty() && informationFilteringConfig.hideEmptyLines) { - listOf("" to HorizontalAlignment.LEFT) - } else { - val title = - if (PartyAPI.partyMembers.isEmpty()) "§9§lParty" else "§9§lParty (${PartyAPI.partyMembers.size})" - val partyList = PartyAPI.partyMembers - .take(partyConfig.maxPartyList.get()) - .map { - " §7- §f$it" - } - .toTypedArray() - listOf(title, *partyList).map { it to HorizontalAlignment.LEFT } - } - -private fun getPartyShowWhen() = if (DungeonAPI.inDungeon()) { - false // Hidden bc the scoreboard lines already exist -} else { - if (partyConfig.showPartyEverywhere) { - true - } else { - inAnyIsland(IslandType.DUNGEON_HUB, IslandType.KUUDRA_ARENA, IslandType.CRIMSON_ISLE) || inGlaciteArea() - } -} - -private fun getFooterDisplayPair(): List = listOf( - displayConfig.titleAndFooter.customFooter.get().toString() - .replace("&", "§") - .split("\\n") - .map { it to displayConfig.titleAndFooter.alignTitleAndFooter }, -).flatten() - -private fun getExtraDisplayPair(): List { - val lines = recentUnknownLines() - if (lines.isEmpty()) return listOf("" to HorizontalAlignment.LEFT) - - return listOf("§cUndetected Lines:" to HorizontalAlignment.LEFT) + lines.map { - it.line to HorizontalAlignment.LEFT - } -} - -private fun getExtraShowWhen(): Boolean = recentUnknownLines().isNotEmpty() diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardEvent.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardEvent.kt deleted file mode 100644 index 8dd3af9f7aec..000000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardEvent.kt +++ /dev/null @@ -1,576 +0,0 @@ -package at.hannibal2.skyhanni.features.gui.customscoreboard - -import at.hannibal2.skyhanni.data.HypixelData -import at.hannibal2.skyhanni.data.IslandType -import at.hannibal2.skyhanni.data.ScoreboardData -import at.hannibal2.skyhanni.data.model.TabWidget -import at.hannibal2.skyhanni.features.combat.SpidersDenAPI.isAtTopOfNest -import at.hannibal2.skyhanni.features.dungeon.DungeonAPI -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard.eventsConfig -import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardEvent.VOTING -import at.hannibal2.skyhanni.features.misc.ServerRestartTitle -import at.hannibal2.skyhanni.features.rift.area.stillgorechateau.RiftBloodEffigies -import at.hannibal2.skyhanni.utils.CollectionUtils.nextAfter -import at.hannibal2.skyhanni.utils.LorenzUtils.inAdvancedMiningIsland -import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland -import at.hannibal2.skyhanni.utils.RegexUtils.anyMatches -import at.hannibal2.skyhanni.utils.RegexUtils.firstMatcher -import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher -import at.hannibal2.skyhanni.utils.RegexUtils.matches -import at.hannibal2.skyhanni.utils.StringUtils.removeColor -import at.hannibal2.skyhanni.utils.StringUtils.removeResets -import at.hannibal2.skyhanni.utils.TabListData -import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardPattern as SbPattern - -/** - * This enum contains all the lines that either are events or other lines that are so rare/not often seen that they - * don't fit in the normal [ScoreboardElement] enum. - * - * We for example have the [VOTING] Event, while this is clearly not an event, I don't consider them as normal lines - * because they are visible for a maximum of like 1 minute every 5 days and ~12 hours. - */ - -private fun getSbLines(): List = ScoreboardData.sidebarLinesFormatted - -enum class ScoreboardEvent( - private val displayLine: () -> List, - private val showWhen: () -> Boolean, - private val configLine: String, -) { - VOTING( - ::getVotingLines, - ::getVotingShowWhen, - "§7(All Voting Lines)", - ), - SERVER_CLOSE( - ::getServerCloseLines, - ::getServerCloseShowWhen, - "§cServer closing soon!", - ), - DUNGEONS( - ::getDungeonsLines, - ::getDungeonsShowWhen, - "§7(All Dungeons Lines)", - ), - KUUDRA( - ::getKuudraLines, - ::getKuudraShowWhen, - "§7(All Kuudra Lines)", - ), - DOJO( - ::getDojoLines, - ::getDojoShowWhen, - "§7(All Dojo Lines)", - ), - DARK_AUCTION( - ::getDarkAuctionLines, - ::getDarkAuctionShowWhen, - "Time Left: §b11\n" + - "Current Item:\n" + - " §5Travel Scroll to Sirius", - ), - JACOB_CONTEST( - ::getJacobContestLines, - ::getJacobContestShowWhen, - "§eJacob's Contest\n" + - "§e○ §fCarrot §a18m17s\n" + - " Collected §e8,264", - ), - JACOB_MEDALS( - ::getJacobMedalsLines, - ::getJacobMedalsShowWhen, - "§6§lGOLD §fmedals: §613\n" + - "§f§lSILVER §fmedals: §f3\n" + - "§c§lBRONZE §fmedals: §c4", - ), - TRAPPER( - ::getTrapperLines, - ::getTrapperShowWhen, - "Pelts: §5711\n" + - "Tracker Mob Location:\n" + - "§bMushroom Gorge", - ), - GARDEN_CLEAN_UP( - ::getGardenCleanUpLines, - ::getGardenCleanUpShowWhen, - "Cleanup: §c12.6%", - ), - GARDEN_PASTING( - ::getGardenPastingLines, - ::getGardenPastingShowWhen, - "§fBarn Pasting§7: §e12.3%", - ), - FLIGHT_DURATION( - ::getFlightDurationLines, - ::getFlightDurationShowWhen, - "Flight Duration: §a10m 0s", - ), - WINTER( - ::getWinterLines, - ::getWinterShowWhen, - "§7(All Winter Event Lines)", - ), - NEW_YEAR( - ::getNewYearLines, - ::getNewYearShowWhen, - "§dNew Year Event!§f 24:25", - ), - SPOOKY( - ::getSpookyLines, - ::getSpookyShowWhen, - "§6Spooky Festival§f 50:54\n" + - "§7Your Candy:\n" + - "§a1 Green§7, §50 Purple §7(§61 §7pts.)", - ), - BROODMOTHER( - ::getBroodmotherLines, - ::isAtTopOfNest, - "§4Broodmother§7: §eDormant", - ), - MINING_EVENTS( - ::getMiningEventsLines, - { inAdvancedMiningIsland() }, - "§7(All Mining Event Lines)", - ), - DAMAGE( - ::getDamageLines, - ::getDamageShowWhen, - "Dragon HP: §a6,180,925 §c❤\n" + - "Your Damage: §c375,298.5", - ), - MAGMA_BOSS( - ::getMagmaBossLines, - ::getMagmaBossShowWhen, - "§7(All Magma Boss Lines)\n" + - "§7Boss: §c0%\n" + - "§7Damage Soaked:\n" + - "§e▎▎▎▎▎▎▎▎▎▎▎▎▎▎▎▎▎▎▎▎§7▎▎▎▎▎", - ), - CARNIVAL( - ::getCarnivalLines, - ::getCarnivalShowWhen, - "§7(All Carnival Lines)", - ), - RIFT( - ::getRiftLines, - { IslandType.THE_RIFT.isInIsland() }, - "§7(All Rift Lines)", - ), - ESSENCE( - ::getEssenceLines, - ::getEssenceShowWhen, - "Dragon Essence: §d1,285", - ), - QUEUE( - ::getQueueLines, - ::getQueueShowWhen, - "Queued: Glacite Mineshafts\n" + - "Position: §b#45 §fSince: §a00:00", - ), - ACTIVE_TABLIST_EVENTS( - ::getActiveEventLine, - ::getActiveEventShowWhen, - "§7(All Active Tablist Events)\n§dHoppity's Hunt\n §fEnds in: §e26h", - ), - STARTING_SOON_TABLIST_EVENTS( - ::getSoonEventLine, - ::getSoonEventShowWhen, - "§7(All Starting Soon Tablist Events)\n§6Mining Fiesta\n §fStarts in: §e52min", - ), - REDSTONE( - ::getRedstoneLines, - ::getRedstoneShowWhen, - "§e§l⚡ §cRedstone: §e§b7%", - ), - ANNIVERSARY( - ::getAnniversaryLines, - ::getAnniversaryShowWhen, - "§d5th Anniversary§f 167:59:54", - ), - ; - - override fun toString() = configLine - - fun getLines(): List = displayLine() - - companion object { - fun getEvent() = buildList { - if (eventsConfig.showAllActiveEvents) { - for (event in eventsConfig.eventEntries) { - if (event.showWhen()) { - add(event) - } - } - } else { - add(eventsConfig.eventEntries.firstOrNull { it.showWhen() && it.getLines().isNotEmpty() }) - } - } - - // I don't know why, but this field is needed for it to work - @JvmField - val defaultOption = listOf( - VOTING, - SERVER_CLOSE, - DUNGEONS, - KUUDRA, - DOJO, - DARK_AUCTION, - JACOB_CONTEST, - JACOB_MEDALS, - TRAPPER, - GARDEN_CLEAN_UP, - GARDEN_PASTING, - FLIGHT_DURATION, - NEW_YEAR, - WINTER, - SPOOKY, - BROODMOTHER, - MINING_EVENTS, - DAMAGE, - MAGMA_BOSS, - CARNIVAL, - RIFT, - ESSENCE, - ACTIVE_TABLIST_EVENTS, - ) - } -} - -private fun getVotingLines() = buildList { - val sbLines = getSbLines() - - val yearLine = sbLines.firstOrNull { SbPattern.yearVotesPattern.matches(it) } ?: return emptyList() - add(yearLine) - - if (sbLines.nextAfter(yearLine) == "§7Waiting for") { - add("§7Waiting for") - add("§7your vote...") - } else { - if (SbPattern.votesPattern.anyMatches(sbLines)) { - addAll(sbLines.filter { SbPattern.votesPattern.matches(it) }) - } - } -} - -private fun getVotingShowWhen(): Boolean = SbPattern.yearVotesPattern.anyMatches(getSbLines()) - -private fun getServerCloseLines() = buildList { - val matchingLine = getSbLines().first { ServerRestartTitle.restartingGreedyPattern.matches(it) } - add(matchingLine.split("§8")[0]) -} - -private fun getServerCloseShowWhen(): Boolean = ServerRestartTitle.restartingGreedyPattern.anyMatches(getSbLines()) - -private fun getDungeonsLines() = listOf( - SbPattern.m7dragonsPattern, - SbPattern.autoClosingPattern, - SbPattern.startingInPattern, - SbPattern.keysPattern, - SbPattern.timeElapsedPattern, - SbPattern.clearedPattern, - SbPattern.soloPattern, - SbPattern.teammatesPattern, - SbPattern.floor3GuardiansPattern, -).let { patterns -> - // BetterMap adds a random §r at the start, making the line go black - getSbLines().filter { line -> patterns.any { it.matches(line) } }.map { it.removePrefix("§r") } -} - -private fun getDungeonsShowWhen(): Boolean = DungeonAPI.inDungeon() - -private fun getKuudraLines() = listOf( - SbPattern.autoClosingPattern, - SbPattern.startingInPattern, - SbPattern.timeElapsedPattern, - SbPattern.instanceShutdownPattern, - SbPattern.wavePattern, - SbPattern.tokensPattern, - SbPattern.submergesPattern, -) - .mapNotNull { pattern -> - getSbLines().firstOrNull { pattern.matches(it) } - } - -private fun getKuudraShowWhen(): Boolean = IslandType.KUUDRA_ARENA.isInIsland() - -private fun getDojoLines() = listOf( - SbPattern.dojoChallengePattern, - SbPattern.dojoDifficultyPattern, - SbPattern.dojoPointsPattern, - SbPattern.dojoTimePattern, -) - .mapNotNull { pattern -> - getSbLines().firstOrNull { pattern.matches(it) } - } - -private fun getDojoShowWhen(): Boolean = SbPattern.dojoChallengePattern.anyMatches(getSbLines()) - -private fun getDarkAuctionLines() = buildList { - getSbLines().firstOrNull { SbPattern.startingInPattern.matches(it) }?.let { add(it) } - getSbLines().firstOrNull { SbPattern.timeLeftPattern.matches(it) }?.let { add(it) } - - val darkAuctionCurrentItemLine = getSbLines().firstOrNull { SbPattern.darkAuctionCurrentItemPattern.matches(it) } - - if (darkAuctionCurrentItemLine != null) { - add(darkAuctionCurrentItemLine) - getSbLines().nextAfter(darkAuctionCurrentItemLine)?.let { add(it) } - } -} - -private fun getDarkAuctionShowWhen(): Boolean = IslandType.DARK_AUCTION.isInIsland() - -private fun getJacobContestLines() = buildList { - getSbLines().firstOrNull { SbPattern.jacobsContestPattern.matches(it) }?.let { line -> - add(line) - getSbLines().nextAfter(line)?.let { add(it) } - getSbLines().nextAfter(line, 2)?.let { add(it) } - getSbLines().nextAfter(line, 3)?.let { - if (!SbPattern.footerPattern.matches(it)) add(it) - } - } -} - -private fun getJacobContestShowWhen(): Boolean = SbPattern.jacobsContestPattern.anyMatches(getSbLines()) - -private fun getJacobMedalsLines(): List = getSbLines().filter { SbPattern.medalsPattern.matches(it) } - -private fun getJacobMedalsShowWhen(): Boolean = SbPattern.medalsPattern.anyMatches(getSbLines()) - -private fun getTrapperLines() = buildList { - getSbLines().firstOrNull { SbPattern.peltsPattern.matches(it) }?.let { add(it) } - - val trapperMobLocationLine = getSbLines().firstOrNull { SbPattern.mobLocationPattern.matches(it) } - if (trapperMobLocationLine != null) { - add("Tracker Mob Location:") - getSbLines().nextAfter(trapperMobLocationLine)?.let { add(it) } - } -} - -private fun getTrapperShowWhen(): Boolean = - getSbLines().any { SbPattern.peltsPattern.matches(it) || SbPattern.mobLocationPattern.matches(it) } - -private fun getGardenCleanUpLines(): List = - listOf(getSbLines().first { SbPattern.cleanUpPattern.matches(it) }.trim()) - -private fun getGardenCleanUpShowWhen(): Boolean = SbPattern.cleanUpPattern.anyMatches(getSbLines()) - -private fun getGardenPastingLines(): List = - listOf(getSbLines().first { SbPattern.pastingPattern.matches(it) }.trim()) - -private fun getGardenPastingShowWhen(): Boolean = SbPattern.pastingPattern.anyMatches(getSbLines()) - -private fun getFlightDurationLines(): List = - listOf(getSbLines().first { SbPattern.flightDurationPattern.matches(it) }.trim()) - -private fun getFlightDurationShowWhen(): Boolean = SbPattern.flightDurationPattern.anyMatches(getSbLines()) - -private fun getWinterLines() = buildList { - getSbLines().firstOrNull { SbPattern.winterEventStartPattern.matches(it) }?.let { add(it) } - getSbLines().firstOrNull { SbPattern.winterNextWavePattern.matches(it) && !it.endsWith("Soon!") }?.let { add(it) } - getSbLines().firstOrNull { SbPattern.winterWavePattern.matches(it) }?.let { add(it) } - getSbLines().firstOrNull { SbPattern.winterMagmaLeftPattern.matches(it) }?.let { add(it) } - getSbLines().firstOrNull { SbPattern.winterTotalDmgPattern.matches(it) }?.let { add(it) } - getSbLines().firstOrNull { SbPattern.winterCubeDmgPattern.matches(it) }?.let { add(it) } -} - -private fun getWinterShowWhen(): Boolean = getSbLines().any { - SbPattern.winterEventStartPattern.matches(it) || - (SbPattern.winterNextWavePattern.matches(it) && !it.endsWith("Soon!")) || - SbPattern.winterWavePattern.matches(it) -} - -private fun getNewYearLines() = listOf(getSbLines().first { SbPattern.newYearPattern.matches(it) }) - -private fun getNewYearShowWhen(): Boolean = SbPattern.newYearPattern.anyMatches(getSbLines()) - -private fun getSpookyLines() = buildList { - getSbLines().firstOrNull { SbPattern.spookyPattern.matches(it) }?.let { add(it) } // Time - add("§7Your Candy: ") - add( - TabListData.getFooter() - .removeResets() - .split("\n") - .firstOrNull { it.startsWith("§7Your Candy:") } - ?.removePrefix("§7Your Candy:") ?: "§cCandy not found", - ) // Candy -} - -private fun getSpookyShowWhen(): Boolean = getSbLines().any { SbPattern.spookyPattern.matches(it) } - -private fun getTablistEvent(): String? = - TabListData.getTabList().firstOrNull { SbPattern.eventNamePattern.matches(it) } - ?.let { - SbPattern.eventNamePattern.matchMatcher(it) { - group("name") - } - } - -private fun getActiveEventLine(): List { - val currentActiveEvent = getTablistEvent() ?: return emptyList() - - // Some Active Events are better not shown from the tablist, - // but from other locations like the scoreboard - val blockedEvents = listOf("Spooky Festival", "Carnival", "5th SkyBlock Anniversary", "New Year Celebration") - if (blockedEvents.contains(currentActiveEvent.removeColor())) return emptyList() - - val currentActiveEventTime = SbPattern.eventTimeEndsPattern.firstMatcher(TabWidget.EVENT.lines) { - group("time") - } ?: return emptyList() - - return listOf(currentActiveEvent, " Ends in: §e$currentActiveEventTime") -} - -private fun getActiveEventShowWhen(): Boolean = - getTablistEvent() != null && TabListData.getTabList().any { SbPattern.eventTimeEndsPattern.matches(it) } - -private fun getSoonEventLine(): List { - val soonActiveEvent = getTablistEvent() ?: return emptyList() - val soonActiveEventTime = SbPattern.eventTimeStartsPattern.firstMatcher(TabWidget.EVENT.lines) { - group("time") - } ?: return emptyList() - - return listOf(soonActiveEvent, " Starts in: §e$soonActiveEventTime") -} - -private fun getSoonEventShowWhen(): Boolean = - getTablistEvent() != null && TabListData.getTabList().any { SbPattern.eventTimeStartsPattern.matches(it) } - -private fun getBroodmotherLines(): List = - listOf(getSbLines().first { SbPattern.broodmotherPattern.matches(it) }) - -private fun getMiningEventsLines() = buildList { - // Wind - if (getSbLines().any { SbPattern.windCompassPattern.matches(it) } && - getSbLines().any { SbPattern.windCompassArrowPattern.matches(it) } - ) { - add(getSbLines().first { SbPattern.windCompassPattern.matches(it) }) - add("| ${getSbLines().first { SbPattern.windCompassArrowPattern.matches(it) }} §f|") - } - - // Better Together - if (getSbLines().any { SbPattern.nearbyPlayersPattern.matches(it) }) { - add("§dBetter Together") - add(" ${getSbLines().first { SbPattern.nearbyPlayersPattern.matches(it) }}") - } - - // Zone Events - if (getSbLines().any { SbPattern.miningEventPattern.matches(it) } && - getSbLines().any { SbPattern.miningEventZonePattern.matches(it) } - ) { - add(getSbLines().first { SbPattern.miningEventPattern.matches(it) }.removePrefix("Event: ")) - add("in ${getSbLines().first { SbPattern.miningEventZonePattern.matches(it) }.removePrefix("Zone: ")}") - } - - // Zone Events but no Zone Line - if (getSbLines().any { SbPattern.miningEventPattern.matches(it) } && - getSbLines().none { SbPattern.miningEventZonePattern.matches(it) } - ) { - add( - getSbLines().first { SbPattern.miningEventPattern.matches(it) } - .removePrefix("Event: "), - ) - } - - // Mithril Gourmand - if (getSbLines().any { SbPattern.mithrilRemainingPattern.matches(it) } && - getSbLines().any { SbPattern.mithrilYourMithrilPattern.matches(it) } - ) { - add(getSbLines().first { SbPattern.mithrilRemainingPattern.matches(it) }) - add(getSbLines().first { SbPattern.mithrilYourMithrilPattern.matches(it) }) - } - - // Raffle - if (getSbLines().any { SbPattern.raffleTicketsPattern.matches(it) } && - getSbLines().any { SbPattern.rafflePoolPattern.matches(it) } - ) { - add(getSbLines().first { SbPattern.raffleTicketsPattern.matches(it) }) - add(getSbLines().first { SbPattern.rafflePoolPattern.matches(it) }) - } - - // Raid - if (getSbLines().any { SbPattern.yourGoblinKillsPattern.matches(it) } && - getSbLines().any { SbPattern.remainingGoblinPattern.matches(it) } - ) { - add(getSbLines().first { SbPattern.yourGoblinKillsPattern.matches(it) }) - add(getSbLines().first { SbPattern.remainingGoblinPattern.matches(it) }) - } - - // Fortunate Freezing - if (getSbLines().any { SbPattern.fortunateFreezingBonusPattern.matches(it) }) { - add(getSbLines().first { SbPattern.fortunateFreezingBonusPattern.matches(it) }) - } - - // Fossil Dust - if (getSbLines().any { SbPattern.fossilDustPattern.matches(it) }) { - add(getSbLines().first { SbPattern.fossilDustPattern.matches(it) }) - } -} - -private fun getDamageLines(): List = - listOf(getSbLines().first { SbPattern.bossHPPattern.matches(it) }) + - (getSbLines().first { SbPattern.bossDamagePattern.matches(it) }) - -private fun getDamageShowWhen(): Boolean = - getSbLines().any { SbPattern.bossHPPattern.matches(it) } && - getSbLines().any { SbPattern.bossDamagePattern.matches(it) } - -private fun getMagmaBossLines() = getSbLines().filter { line -> - SbPattern.magmaBossPattern.matches(line) || - SbPattern.damageSoakedPattern.matches(line) || - SbPattern.killMagmasPattern.matches(line) || - SbPattern.killMagmasDamagedSoakedBarPattern.matches(line) || - SbPattern.reformingPattern.matches(line) || - SbPattern.bossHealthPattern.matches(line) || - SbPattern.bossHealthBarPattern.matches(line) -} - -private fun getMagmaBossShowWhen(): Boolean = SbPattern.magmaChamberPattern.matches(HypixelData.skyBlockArea) - -private fun getCarnivalLines() = listOf( - SbPattern.carnivalPattern, - SbPattern.carnivalTokensPattern, - SbPattern.carnivalTasksPattern, - SbPattern.timeLeftPattern, - SbPattern.carnivalCatchStreakPattern, - SbPattern.carnivalFruitsPattern, - SbPattern.carnivalAccuracyPattern, - SbPattern.carnivalKillsPattern, - SbPattern.carnivalScorePattern, -) - .mapNotNull { pattern -> - getSbLines().firstOrNull { pattern.matches(it) } - } - -private fun getCarnivalShowWhen() = - listOf(SbPattern.carnivalPattern, SbPattern.carnivalTokensPattern, SbPattern.carnivalTasksPattern).anyMatches(getSbLines()) - -private fun getRiftLines() = getSbLines().filter { line -> - RiftBloodEffigies.heartsPattern.matches(line) || - SbPattern.riftHotdogTitlePattern.matches(line) || - SbPattern.timeLeftPattern.matches(line) || - SbPattern.riftHotdogEatenPattern.matches(line) || - SbPattern.riftAveikxPattern.matches(line) || - SbPattern.riftHayEatenPattern.matches(line) || - SbPattern.cluesPattern.matches(line) || - SbPattern.barryProtestorsQuestlinePattern.matches(line) || - SbPattern.barryProtestorsHandledPattern.matches(line) -} - -private fun getEssenceLines(): List = listOf(getSbLines().first { SbPattern.essencePattern.matches(it) }) - -private fun getEssenceShowWhen(): Boolean = SbPattern.essencePattern.anyMatches(getSbLines()) - -private fun getQueueLines(): List = - listOf(getSbLines().first { SbPattern.queuePattern.matches(it) }) + - (getSbLines().first { SbPattern.queueTierPattern.matches(it) }) + - (getSbLines().first { SbPattern.queuePositionPattern.matches(it) }) - -private fun getQueueShowWhen(): Boolean = SbPattern.queuePattern.anyMatches(getSbLines()) - -private fun getRedstoneLines(): List = listOf(getSbLines().first { SbPattern.redstonePattern.matches(it) }) - -private fun getRedstoneShowWhen(): Boolean = SbPattern.redstonePattern.anyMatches(getSbLines()) - -private fun getAnniversaryLines() = listOf(getSbLines().first { SbPattern.anniversaryPattern.matches(it) }) - -private fun getAnniversaryShowWhen(): Boolean = SbPattern.anniversaryPattern.anyMatches(getSbLines()) diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardLine.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardLine.kt new file mode 100644 index 000000000000..3231f2bdf11b --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardLine.kt @@ -0,0 +1,18 @@ +package at.hannibal2.skyhanni.features.gui.customscoreboard + +import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard.displayConfig +import at.hannibal2.skyhanni.utils.RenderUtils + +data class ScoreboardLine( + val display: String, + val alignment: RenderUtils.HorizontalAlignment = DEFAULT_ALIGNMENT, +) { + + companion object { + private val DEFAULT_ALIGNMENT get() = displayConfig.textAlignment + + fun String.align(): ScoreboardLine = ScoreboardLine(this, DEFAULT_ALIGNMENT) + + infix fun String.align(alignment: RenderUtils.HorizontalAlignment): ScoreboardLine = ScoreboardLine(this, alignment) + } +} 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 5170bd910d2b..259e983f9fd0 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 @@ -9,7 +9,7 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent object ScoreboardPattern { private val group = RepoPattern.group("features.gui.customscoreboard") - // Stats from the scoreboard + // Lines from the scoreboard private val scoreboardGroup by group.exclusiveGroup("scoreboard") @SubscribeEvent @@ -17,35 +17,33 @@ object ScoreboardPattern { UnknownLinesHandler.remoteOnlyPatterns = scoreboardGroup.getUnusedPatterns().toTypedArray() } - // main scoreboard + // Main scoreboard private val mainSb = scoreboardGroup.group("main") + + //TODO add regex tests val motesPattern by mainSb.pattern( "motes", - "^(§.)*Motes: (§.)*(?[\\d,]+).*$", + "(?:§.)*Motes: (?:§.)*(?[\\d,]+).*", ) val heatPattern by mainSb.pattern( "heat", - "^Heat: (?.*)$", - ) // this line is weird (either text or number), ill leave it as is; it even has different colors? - val coldPattern by mainSb.pattern( - "cold", - "^(?:§.)*Cold: §.(?-?\\d+)❄$", + "Heat: (?.*)", ) val copperPattern by mainSb.pattern( "copper", - "^(§.)*Copper: (§.)*(?[\\d,]+).*$", + "(?:§.)*Copper: (?:§.)*(?[\\d,]+).*", ) val locationPattern by mainSb.pattern( "location", - "^\\s*(?(§7⏣|§5ф) .*)$", + "\\s*(?(?:§7⏣|§5ф) .*)", ) val lobbyCodePattern by mainSb.pattern( "lobbycode", - "^\\s*§.((\\d{2}/\\d{2}/\\d{2})|Server closing: [\\d:]+) §8(?.*)\$", + "\\s*§.(?:\\d{2}/?){3} §8(?.*)", ) val datePattern by mainSb.pattern( "date", - "^\\s*(Late |Early )?(Spring|Summer|Autumn|Winter) \\d{1,2}(st|nd|rd|th)?.*", + "\\s*(?:(?:Late|Early) )?(?:Spring|Summer|Autumn|Winter) \\d+(?:st|nd|rd|th)?.*", ) /** @@ -54,15 +52,15 @@ object ScoreboardPattern { */ val timePattern by mainSb.pattern( "time", - "^\\s*§7\\d{1,2}:\\d{2}(?:am|pm)\\s*(?(§b☽|§e☀|§.⚡|§.☔))?.*$", + "\\s*§7\\d+:\\d+(?:am|pm)\\s*(?§b☽|§e☀|§.⚡|§.☔)?.*", ) val footerPattern by mainSb.pattern( "footer", - "§e(www|alpha).hypixel.net\$", + "§e(?:www|alpha).hypixel.net", ) val yearVotesPattern by mainSb.pattern( "yearvotes", - "(?^§6Year \\d+ Votes\$)", + "§6Year \\d+ Votes", ) /** @@ -75,66 +73,63 @@ object ScoreboardPattern { ) val waitingForVotePattern by mainSb.pattern( "waitingforvote", - "(§7Waiting for|§7your vote\\.\\.\\.)$", + "§7Waiting for|§7your vote\\.\\.\\.", ) val northstarsPattern by mainSb.pattern( "northstars", - "North Stars: §d(?[\\w,]+).*$", + "North Stars: §d(?[\\w,]+).*", ) val profileTypePattern by mainSb.pattern( "profiletype", - "^\\s*(§7♲ §7Ironman|§a☀ §aStranded|§.Ⓑ §.Bingo).*$", - ) - val emptyLinesPattern by mainSb.pattern( - "emptylines", - "^\\s*$", + "\\s*(?:§7♲ §7Ironman|§a☀ §aStranded|§.Ⓑ §.Bingo).*", ) // multi use private val multiUseSb = scoreboardGroup.group("multiuse") val autoClosingPattern by multiUseSb.pattern( "autoclosing", - "(§.)*Auto-closing in: §c(\\d{1,2}:)?\\d{1,2}$", + "(?:§.)*Auto-closing in: §c(?:\\d+:)?\\d+", ) val startingInPattern by multiUseSb.pattern( "startingin", - "(§.)*Starting in: §.(\\d{1,2}:)?\\d{1,2}$", + "(?:§.)*Starting in: §.(?:\\d+:)?\\d+", ) val timeElapsedPattern by multiUseSb.pattern( "timeelapsed", - "(§.)*Time Elapsed: (§.)*(?