From 3877c95879944d62a026ea45026862976573572b Mon Sep 17 00:00:00 2001 From: J10a1n15 <45315647+j10a1n15@users.noreply.github.com> Date: Wed, 29 May 2024 09:31:16 +0200 Subject: [PATCH 01/34] Feature: Add Custom Scoreboard FaQ (#1902) --- docs/DISCORD_FAQ.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/DISCORD_FAQ.md b/docs/DISCORD_FAQ.md index f231e2edbad3..a2b01e519600 100644 --- a/docs/DISCORD_FAQ.md +++ b/docs/DISCORD_FAQ.md @@ -52,6 +52,13 @@ _Frequently Asked Questions_ > - To reset a tracker, use the in-game command `/shcommands `. > - Execute the obtained command to reset the tracker. +> **12: Why can I still see the normal Scoreboard when using Custom Scoreboard?** +> Most of the time, this is a mod conflict. +> If you are using [Sidebar Mod](https://github.com/Alexdoru/SidebarMod), please remove this mod. +> If you are using [VanillaHUD](https://modrinth.com/mod/vanillahud), please disable its Scoreboard by clicking on the blue bar below "Scoreboard" in the OneConfig Menu. +> If you are using [Apec](https://github.com/BananaFructa/Apec/) and want to remove their Scoreboard, you need to remove Apec since they don't have an option to disable their Scoreboard. +> If you don't use any of these mods, make sure the option to "Hide Vanilla Scoreboard" is actually enabled. -*This FAQ was last updated on April 22nd, 2024. + +*This FAQ was last updated on May 27th, 2024. If you believe there's something that should be added to this list, please tell us, so we can add it.* From efc71b6847f252cccd0ccf536a6db6e9fe6fad96 Mon Sep 17 00:00:00 2001 From: NopoTheGamer <40329022+NopoTheGamer@users.noreply.github.com> Date: Wed, 29 May 2024 17:36:09 +1000 Subject: [PATCH 02/34] Get ascension rope at selectable cold level (#1905) --- .../mining/MiningNotificationsConfig.java | 10 +++++++++- .../features/mining/MiningNotifications.kt | 16 +++++----------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/mining/MiningNotificationsConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/mining/MiningNotificationsConfig.java index 30394ba34eb7..f5a1d0b766b8 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/mining/MiningNotificationsConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/mining/MiningNotificationsConfig.java @@ -47,9 +47,17 @@ public class MiningNotificationsConfig { @Expose @ConfigOption( name = "Get Ascension Rope", - desc = "Click on a chat message to get an Ascension Rope when you're at 90 Cold and in the §bMineshaft§7. " + + desc = "Click on a chat message to get an Ascension Rope when you're at a certain amount of Cold and in the §bMineshaft§7. " + "§cOnly works if you have an Ascension Rope in your sacks." ) @ConfigEditorBoolean public boolean getAscensionRope = true; + + @Expose + @ConfigOption( + name = "Cold Amount to Show Message", + desc = "Customise the amount of Cold you need to have to get the Ascension Rope message." + ) + @ConfigEditorSlider(minValue = 1, maxValue = 100, minStep = 1) + public int coldAmount = 90; } diff --git a/src/main/java/at/hannibal2/skyhanni/features/mining/MiningNotifications.kt b/src/main/java/at/hannibal2/skyhanni/features/mining/MiningNotifications.kt index 012a13240a48..370fd1815417 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/mining/MiningNotifications.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/mining/MiningNotifications.kt @@ -54,10 +54,6 @@ object MiningNotifications { "goblin.diamondspawn", "§6A §r§bDiamond Goblin §r§6has spawned!" ) - private val frostbitePattern by patternGroup.pattern( - "cold.frostbite", - "§9§lBRRR! §r§bYou're freezing! All you can think about is getting out of here to a warm campfire\\.\\.\\." - ) private val config get() = SkyHanniMod.feature.mining.notifications @@ -73,13 +69,6 @@ object MiningNotifications { scrapDrop.matches(message) -> sendNotification(MiningNotificationList.SCRAP) goldenGoblinSpawn.matches(message) -> sendNotification(MiningNotificationList.GOLDEN_GOBLIN) diamondGoblinSpawn.matches(message) -> sendNotification(MiningNotificationList.DIAMOND_GOBLIN) - frostbitePattern.matches(message) -> { - if (IslandType.MINESHAFT.isInIsland() && config.getAscensionRope) { - runDelayed(0.5.seconds) { - GetFromSackAPI.getFromChatMessageSackItems(ASCENSION_ROPE) - } - } - } } } @@ -93,6 +82,11 @@ object MiningNotifications { hasSentCold = true sendNotification(MiningNotificationList.COLD) } + if (IslandType.MINESHAFT.isInIsland() && config.getAscensionRope && config.coldAmount == event.cold) { + runDelayed(0.5.seconds) { + GetFromSackAPI.getFromChatMessageSackItems(ASCENSION_ROPE) + } + } } @SubscribeEvent From 8081f9d7a395960880114c4a2fd9f9fb169ff385 Mon Sep 17 00:00:00 2001 From: Empa <42304516+ItsEmpa@users.noreply.github.com> Date: Wed, 29 May 2024 09:36:51 +0200 Subject: [PATCH 03/34] Improvement: Oringo Pet Rarity Message (#1862) --- .../skyhanni/features/chat/RareDropMessages.kt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/at/hannibal2/skyhanni/features/chat/RareDropMessages.kt b/src/main/java/at/hannibal2/skyhanni/features/chat/RareDropMessages.kt index 48bc9093495a..e4145c98fff6 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/chat/RareDropMessages.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/chat/RareDropMessages.kt @@ -46,8 +46,17 @@ class RareDropMessages { "(?.*has obtained (?:§.)*\\[Lvl 1] )(?:§.)*§(?.)(?[^§(.]+)(?.*)" ) + /** + * REGEX-TEST: §e[NPC] Oringo§f: §b✆ §f§r§8• §fBlue Whale Pet + * REGEX-TEST: §e[NPC] Oringo§f: §b✆ §f§r§8• §5Giraffe Pet + */ + private val oringoPattern by chatGroup.pattern( + "pet.oringopattern", + "(?§e\\[NPC] Oringo§f: §b✆ §f§r§8• )§(?.)(?[^§(.]+)(? Pet)" + ) + private val patterns = listOf( - petDroppedPattern, petFishedPattern, petClaimedPattern, petObtainedPattern + petDroppedPattern, petFishedPattern, petClaimedPattern, petObtainedPattern, oringoPattern ) private val config get() = SkyHanniMod.feature.chat.petRarityDropMessage From 5c991d02019249a42d8221fe7605f87e46164bb0 Mon Sep 17 00:00:00 2001 From: hannibal2 <24389977+hannibal002@users.noreply.github.com> Date: Wed, 29 May 2024 09:37:42 +0200 Subject: [PATCH 04/34] Improvement: Dungeon End Reminder (#1917) Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com> --- .../java/at/hannibal2/skyhanni/features/dungeon/DungeonAPI.kt | 3 +++ .../java/at/hannibal2/skyhanni/features/fame/ReminderUtils.kt | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) 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 d3eae0a2b4c6..86def886ded9 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonAPI.kt @@ -46,6 +46,7 @@ object DungeonAPI { var dungeonFloor: String? = null var started = false + var completed = false var inBossRoom = false var playerClass: DungeonClass? = null var playerClassLevel = -1 @@ -206,6 +207,7 @@ object DungeonAPI { isUniqueClass = false playerClass = null playerClassLevel = -1 + completed = false DungeonBlessings.reset() } @@ -230,6 +232,7 @@ object DungeonAPI { return } dungeonComplete.matchMatcher(event.message) { + completed = true DungeonCompleteEvent(floor).postAndCatch() return } diff --git a/src/main/java/at/hannibal2/skyhanni/features/fame/ReminderUtils.kt b/src/main/java/at/hannibal2/skyhanni/features/fame/ReminderUtils.kt index 0cd7bc0da1f8..19e0399ad269 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/fame/ReminderUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/fame/ReminderUtils.kt @@ -11,7 +11,7 @@ object ReminderUtils { // TODO: add arachne fight, add slayer boss spawned, add dragon fight fun isBusy(ignoreFarmingContest: Boolean = false): Boolean = - DungeonAPI.inDungeon() || LorenzUtils.inKuudraFight || (FarmingContestAPI.inContest && !ignoreFarmingContest) || + (DungeonAPI.inDungeon() && !DungeonAPI.completed) || LorenzUtils.inKuudraFight || (FarmingContestAPI.inContest && !ignoreFarmingContest) || RiftAPI.inRift() || IslandType.DARK_AUCTION.isInIsland() || IslandType.MINESHAFT.isInIsland() || IslandType.NONE.isInIsland() || IslandType.UNKNOWN.isInIsland() } From f8d12759270b23339c276f28863254bb84156686 Mon Sep 17 00:00:00 2001 From: appable Date: Wed, 29 May 2024 00:42:08 -0700 Subject: [PATCH 05/34] Feature: reminder to open hoppity shop each year (#1843) Co-authored-by: CalMWolfs <94038482+CalMWolfs@users.noreply.github.com> Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com> --- .../features/event/HoppityEggsConfig.java | 6 +++ .../storage/ProfileSpecificStorage.java | 3 ++ .../features/event/hoppity/HoppityNpc.kt | 51 +++++++++++++++++-- 3 files changed, 55 insertions(+), 5 deletions(-) diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/event/HoppityEggsConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/event/HoppityEggsConfig.java index 2bfe65a49638..345b3fb830aa 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/event/HoppityEggsConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/event/HoppityEggsConfig.java @@ -87,6 +87,12 @@ public class HoppityEggsConfig { @FeatureToggle public boolean highlightHoppityShop = true; + @Expose + @ConfigOption(name = "Hoppity Shop Reminder", desc = "Reminds you to open the Hoppity Shop each year.") + @ConfigEditorBoolean + @FeatureToggle + public boolean hoppityShopReminder = true; + @Expose @ConfigOption(name = "Time in Chat", desc = "When the Egglocator can't find an egg, show the time until the next Hoppity event or egg spawn.") @ConfigEditorBoolean diff --git a/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java b/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java index d2a38831aa0e..e25d725ec37c 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java +++ b/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java @@ -127,6 +127,9 @@ public static class PositionChange { @Expose public Map rabbitCounts = new HashMap(); + + @Expose + public Integer hoppityShopYearOpened = null; } @Expose diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityNpc.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityNpc.kt index 1995352798a8..aaa4c365dd90 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityNpc.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityNpc.kt @@ -5,30 +5,60 @@ import at.hannibal2.skyhanni.events.InventoryCloseEvent import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent import at.hannibal2.skyhanni.events.InventoryUpdatedEvent import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent +import at.hannibal2.skyhanni.events.SecondPassedEvent +import at.hannibal2.skyhanni.features.fame.ReminderUtils +import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryAPI +import at.hannibal2.skyhanni.utils.ChatUtils 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.RenderUtils.highlight +import at.hannibal2.skyhanni.utils.SimpleTimeMark +import at.hannibal2.skyhanni.utils.SkyBlockTime +import at.hannibal2.skyhanni.utils.SkyblockSeason import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import kotlin.time.Duration.Companion.seconds object HoppityNpc { private val config get() = HoppityEggsManager.config + private var lastReminderSent = SimpleTimeMark.farPast() + private var hoppityYearOpened + get() = ChocolateFactoryAPI.profileStorage?.hoppityShopYearOpened ?: -1 + set(value) { + ChocolateFactoryAPI.profileStorage?.hoppityShopYearOpened = value + } + private var slotsToHighlight = mutableSetOf() private var inShop = false @SubscribeEvent fun onInventoryOpen(event: InventoryFullyOpenedEvent) { - if (!isEnabled()) return if (event.inventoryName != "Hoppity") return + hoppityYearOpened = SkyBlockTime.now().year inShop = true } - private fun clear() { - inShop = false - slotsToHighlight.clear() + @SubscribeEvent + fun onSecondPassed(event: SecondPassedEvent) { + if (!isReminderEnabled()) return + if (ReminderUtils.isBusy()) return + if (hoppityYearOpened == SkyBlockTime.now().year) return + if (!ChocolateFactoryAPI.isHoppityEvent()) return + if (lastReminderSent.passedSince() <= 30.seconds) return + + ChatUtils.clickableChat( + "New rabbits are available at §aHoppity's Shop§e! §c(Click to disable this reminder)", + onClick = { + disableReminder() + ChatUtils.chat("§eHoppity's Shop reminder disabled.") + }, + oneTimeClick = true + ) + + lastReminderSent = SimpleTimeMark.now() } @SubscribeEvent @@ -54,6 +84,7 @@ object HoppityNpc { @SubscribeEvent fun onBackgroundDrawn(event: GuiContainerEvent.BackgroundDrawnEvent) { + if (!isHighlightEnabled()) return if (!inShop) return for (slot in InventoryUtils.getItemsInOpenChest()) { if (slot.slotIndex in slotsToHighlight) { @@ -62,5 +93,15 @@ object HoppityNpc { } } - fun isEnabled() = LorenzUtils.inSkyBlock && config.highlightHoppityShop + private fun isHighlightEnabled() = LorenzUtils.inSkyBlock && config.highlightHoppityShop + private fun isReminderEnabled() = LorenzUtils.inSkyBlock && config.hoppityShopReminder + + private fun clear() { + inShop = false + slotsToHighlight.clear() + } + + private fun disableReminder() { + config.hoppityShopReminder = false + } } From a2c73ff23ddcf11113cfdd31a6d3d66af3d0ca90 Mon Sep 17 00:00:00 2001 From: hannibal2 <24389977+hannibal00212@users.noreply.github.com> Date: Wed, 29 May 2024 09:46:40 +0200 Subject: [PATCH 06/34] added todo --- .../hannibal2/skyhanni/features/event/hoppity/HoppityNpc.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityNpc.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityNpc.kt index aaa4c365dd90..98362bc28620 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityNpc.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityNpc.kt @@ -16,7 +16,6 @@ import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.RenderUtils.highlight import at.hannibal2.skyhanni.utils.SimpleTimeMark import at.hannibal2.skyhanni.utils.SkyBlockTime -import at.hannibal2.skyhanni.utils.SkyblockSeason import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import kotlin.time.Duration.Companion.seconds @@ -37,6 +36,9 @@ object HoppityNpc { @SubscribeEvent fun onInventoryOpen(event: InventoryFullyOpenedEvent) { if (event.inventoryName != "Hoppity") return + // TODO maybe we could add an annoying chat message that tells you how many years you have skipped + // or the last year you have opened the shop before. + // that way we verbally punish non active users in a funny and non harmful way hoppityYearOpened = SkyBlockTime.now().year inShop = true } From 8ce2c5c720a69380816484805d971f919f2d0c59 Mon Sep 17 00:00:00 2001 From: HiZe Date: Wed, 29 May 2024 09:47:53 +0200 Subject: [PATCH 07/34] Feature: Toggle for limbo in detailed /playtime (#1863) --- .../skyhanni/config/features/misc/MiscConfig.java | 8 ++++++++ .../skyhanni/features/misc/limbo/LimboPlaytime.kt | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/misc/MiscConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/misc/MiscConfig.java index 5e9a82e0303e..6e4fe4f12110 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/misc/MiscConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/misc/MiscConfig.java @@ -222,6 +222,14 @@ public class MiscConfig { @ConfigLink(owner = MiscConfig.class, field = "showTimeInLimbo") public Position showTimeInLimboPosition = new Position(400, 200, 1.3f); + @Expose + @ConfigOption( + name = "Limbo Playtime Detailed", + desc = "Show your total time in limbo in the detailed /playtime.") + @ConfigEditorBoolean + @FeatureToggle + public boolean showLimboTimeInPlaytimeDetailed = true; + @Expose @ConfigOption( name = "Lesser Orb of Healing Hider", diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/limbo/LimboPlaytime.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/limbo/LimboPlaytime.kt index 8d4b3489f1ef..d5a8a3765373 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/limbo/LimboPlaytime.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/limbo/LimboPlaytime.kt @@ -1,5 +1,6 @@ package at.hannibal2.skyhanni.features.misc.limbo +import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.data.ProfileStorageData import at.hannibal2.skyhanni.events.InventoryOpenEvent import at.hannibal2.skyhanni.events.LorenzToolTipEvent @@ -37,6 +38,7 @@ object LimboPlaytime { private var hoursString: String = "" private val storage get() = ProfileStorageData.playerSpecific?.limbo + private val enabled get() = SkyHanniMod.feature.misc.showLimboTimeInPlaytimeDetailed private val itemID = "ENDER_PEARL".asInternalName() private val itemName = "§aLimbo" @@ -45,6 +47,7 @@ object LimboPlaytime { @SubscribeEvent fun replaceItem(event: ReplaceItemEvent) { + if (!enabled) return if (event.inventory !is ContainerLocalMenu) return if (event.inventory.name != "Detailed /playtime") return if (event.slotNumber != 43) return @@ -76,6 +79,7 @@ object LimboPlaytime { @SubscribeEvent fun onTooltip(event: LorenzToolTipEvent) { if (!LorenzUtils.inSkyBlock) return + if (!enabled) return if (!event.slot.inventory.name.startsWith("Detailed /playtime")) return if (event.slot.slotIndex != 4) return val playtime = storage?.playtime ?: 0 From 8fcc5125090660daccb30c34f5d15b44e97ae304 Mon Sep 17 00:00:00 2001 From: saga <45262877+saga-00@users.noreply.github.com> Date: Wed, 29 May 2024 04:49:44 -0300 Subject: [PATCH 08/34] Feature: Croesus Limit (#1908) --- .../config/features/dungeon/DungeonChestConfig.java | 6 ++++++ .../skyhanni/features/dungeon/CroesusChestTracker.kt | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/dungeon/DungeonChestConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/dungeon/DungeonChestConfig.java index 2c3d973cf155..b71e628b4849 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/dungeon/DungeonChestConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/dungeon/DungeonChestConfig.java @@ -19,4 +19,10 @@ public class DungeonChestConfig { @ConfigEditorBoolean @FeatureToggle public boolean kismetStackSize = true; + + @Expose + @ConfigOption(name = "Croesus Limit Warning", desc = "Gives a warning when you are close to being past Croesus limit.") + @ConfigEditorBoolean + @FeatureToggle + public boolean croesusLimit = true; } diff --git a/src/main/java/at/hannibal2/skyhanni/features/dungeon/CroesusChestTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/dungeon/CroesusChestTracker.kt index fa297d6fa932..d87e02796590 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/dungeon/CroesusChestTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/dungeon/CroesusChestTracker.kt @@ -230,6 +230,10 @@ class CroesusChestTracker { if ((croesusChests?.size ?: 0) > maxChests) { croesusChests?.dropLast(1) } + + if (config.croesusLimit && getLastActiveChest() >= 55) { + ChatUtils.chat("You are close to the Croesus Limit. Please open your chests!") + } } private fun Int.getRun() = getRun0(this) From 12bb18a5ca346c1933037aef2e6242c49b7381a6 Mon Sep 17 00:00:00 2001 From: hannibal2 <24389977+hannibal00212@users.noreply.github.com> Date: Wed, 29 May 2024 09:52:36 +0200 Subject: [PATCH 09/34] code cleanup --- .../skyhanni/features/dungeon/CroesusChestTracker.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/at/hannibal2/skyhanni/features/dungeon/CroesusChestTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/dungeon/CroesusChestTracker.kt index d87e02796590..b565c0210f71 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/dungeon/CroesusChestTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/dungeon/CroesusChestTracker.kt @@ -272,10 +272,10 @@ class CroesusChestTracker { ChatUtils.chat("Kismet State was cleared!") } - fun generateMaxChest() = generateSequence { DungeonRunInfo() }.take(maxChests) - fun generateMaxChestAsList() = generateMaxChest().toList() + fun generateMaxChest(): Sequence = generateSequence { DungeonRunInfo() }.take(maxChests) + fun generateMaxChestAsList(): List = generateMaxChest().toList() - fun getLastActiveChest(includeDungeonKey: Boolean = false) = + fun getLastActiveChest(includeDungeonKey: Boolean = false): Int = (croesusChests?.indexOfLast { it.floor != null && (it.openState == OpenedState.UNOPENED || (includeDungeonKey && it.openState == OpenedState.OPENED)) From b2157a247521d702915b4a2629118c7792bc1793 Mon Sep 17 00:00:00 2001 From: hannibal2 <24389977+hannibal00212@users.noreply.github.com> Date: Wed, 29 May 2024 12:07:42 +0200 Subject: [PATCH 10/34] Version 0.26 Beta 3 --- build.gradle.kts | 2 +- docs/CHANGELOG.md | 63 ++++++++++++++++++- docs/FEATURES.md | 18 ++++++ .../java/at/hannibal2/skyhanni/SkyHanniMod.kt | 2 +- 4 files changed, 82 insertions(+), 3 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 1fb2fc67203f..8e769413e13d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,7 +15,7 @@ plugins { } group = "at.hannibal2.skyhanni" -version = "0.26.Beta.2" +version = "0.26.Beta.3" val gitHash by lazy { val baos = ByteArrayOutputStream() diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 6476b3d55f5d..aec372972b9c 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -17,12 +17,48 @@ #### Garden Features + New "Craftable!" message when Visitor Items Needed are craftable. - Paloys (https://github.com/hannibal002/SkyHanni/pull/1891) ++ Added crop last farmed waypoint. - appable (https://github.com/hannibal002/SkyHanni/pull/1335) + + Accessible in the Crop Start Locations section. -#### ChatFeatures +#### Dungeon Features + ++ Added Croesus Limit Warning. - saga (https://github.com/hannibal002/SkyHanni/pull/1908) + + Sends a warning when you are close to the Croesus Chest Limit. + +#### Command Features + ++ Option to toggle limbo time in detailed /playtime. - HiZe (https://github.com/hannibal002/SkyHanni/pull/1863) + +#### Chat Features + Added new chat filters. - Mikecraft1224 (https://github.com/hannibal002/SkyHanni/pull/1750) + Filters for rare dungeon chest rewards and sacrifice messages from other players. +#### Event Features + ++ Chat reminder to check Hoppity Shop each year. - appable (https://github.com/hannibal002/SkyHanni/pull/1843) + +#### Mining Features + ++ Configurable cold amount for the ascension rope message in Glacite Mines. - nopo (https://github.com/hannibal002/SkyHanni/pull/1905) + +#### Inventory Features + ++ Warning when outbid on an auction. - seraid (https://github.com/hannibal002/SkyHanni/pull/1818) + +#### Fishing Features + ++ Added Trophy Fishing Display. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/1754) + + Similar to Skytils, but with more options. + + Option to sort by item rarity, total amount, rarity amount, the highest rarity, or name alphabetically. + + Option to change what information is displayed (rarity, name, icon, total caught). + + Option to show only missing trophies. + + Option to highlight new catches in green. + + Options for when to show the display: always in Crimson Isle, in inventory, with rod in hand, or on keybind press. + + Option to show only when wearing a full hunter armor set. + + Options to show checkmarks or crosses instead of numbers. + + Hover over a trophy fish to see the percentage caught and how to gain progress. + #### Misc Features + Click on breakdown display in /playtimedetailed to copy the stats into the clipboard. - seraid (https://github.com/hannibal002/SkyHanni/pull/1807) @@ -36,11 +72,16 @@ #### Garden Improvements + Added `/shtpinfested` command to teleport to nearest infested plot. - Empa (https://github.com/hannibal002/SkyHanni/pull/1763) ++ Warp to Infested Plot warps to garden home when no pests are found. - saga (https://github.com/hannibal002/SkyHanni/pull/1910) + + Affects both hotkey and command. #### Hoppity Event Improvements + Renamed "Unfound Eggs" to "Unclaimed Eggs" for the Hoppity event. - Luna (https://github.com/hannibal002/SkyHanni/pull/1876) + Added Compact Hoppity Chat option. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/1748) ++ Hoppity Collection Stats are now persistent. - appable (https://github.com/hannibal002/SkyHanni/pull/1836) + + No longer reset on profile swap or game restart. ++ Merged duplicate times in compacted Hoppity's messages. - DavidArthurCole (https://github.com/hannibal002/SkyHanni/pull/1887) #### Mining Improvements @@ -52,6 +93,19 @@ + Now has pages for better navigation. + Improved visual appearance. +#### Dungeon Improvements + ++ Changed reminders to show at the end of a dungeon run. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/1917) + + E.g. Composter empty, Hoppity Eggs ready, New Year Cake, etc. + +#### Chat Improvements + ++ Added Pet Rarity to Oringo Abiphone messages. - Empa (https://github.com/hannibal002/SkyHanni/pull/1862) + +#### Inventory Improvements + ++ Adjusted and added Rabbit Uncle & Dog Keybinds. - raven (https://github.com/hannibal002/SkyHanni/pull/1907) + #### Misc Improvements + Added a toggle for 24-hour time. - seraid (https://github.com/hannibal002/SkyHanni/pull/1804) @@ -66,6 +120,8 @@ + Fixed Tunnel Maps GUI position not saving. - Thunderblade73 (https://github.com/hannibal002/SkyHanni/pull/1882) + Fixed Glacite Walkers not being highlighted during commissions. - Luna (https://github.com/hannibal002/SkyHanni/pull/1850) ++ Fixed warping to Base in Glacite Tunnels when pressing the keybind while inside any GUI. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/1911) ++ Fixed Custom Scoreboard error in Mineshaft. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/1909) #### Garden Fixes @@ -75,6 +131,7 @@ #### Chocolate Factory Fixes + Fixed some Chocolate Factory issues caused by a Hypixel update. - CalMWolfs (https://github.com/hannibal002/SkyHanni/pull/1860) ++ Fixed a bug where the chocolate factory leaderboard position was not showing when the position had many digits. - sayomaki (https://github.com/hannibal002/SkyHanni/pull/1918) #### Custom Scoreboard Fixes @@ -89,6 +146,10 @@ + Fixed a typo in Tunnels Maps. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/1883) +#### Commands Fixes + ++ Fixed typo in /shclearkismet command. - fahr-plan (https://github.com/hannibal002/SkyHanni/pull/1912) + #### Performance Fixes + Fixed small memory leaks when staying in one island for extended periods. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/1890) diff --git a/docs/FEATURES.md b/docs/FEATURES.md index f143e448efc3..2c73b9eed830 100644 --- a/docs/FEATURES.md +++ b/docs/FEATURES.md @@ -86,6 +86,8 @@ Use `/sh` or `/skyhanni` to open the SkyHanni config in game. + Hide the golden fairy that follows the healer in dungeon. + Catacombs class level color in party finder inventory. + Visual highlight chests that have not yet been opened in the Croesus inventory. ++ Croesus Limit Warning. - saga (https://github.com/hannibal002/SkyHanni/pull/1908) + + Sends a warning when you are close to the Croesus Chest Limit. + Outline Dungeon Teammates. - Cad + Dungeon Colored Class Level. - hannibal2 + Color class levels in the tab list. (Also hide rank colors and emblems because who needs that in dungeons anyway?) @@ -141,6 +143,7 @@ Use `/sh` or `/skyhanni` to open the SkyHanni config in game. + Highlight depleted Bonzo's Masks in your inventory. + Highlight stuff that is missing in the SkyBlock level guide inventory. + **Auction Highlighter** - Highlight own items that are sold in green and that are expired in red. ++ Warning when outbid on an auction. - seraid (https://github.com/hannibal002/SkyHanni/pull/1818) + Highlight your own lowest BIN auctions that are outbid. - hannibal2 + **Unclaimed Rewards** - Highlight contests with unclaimed rewards in the jacob inventory. + **Contest Time** - Show the real time format to the farming contest description. @@ -328,6 +331,16 @@ Use `/sh` or `/skyhanni` to open the SkyHanni config in game. + Option to hide Totem Particles. + Option to show the effective area of a totem. + Option to get reminded when a totem is about to expire. ++ Trophy Fishing Display. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/1754) + + Similar to Skytils, but with more options. + + Option to sort by item rarity, total amount, rarity amount, the highest rarity, or name alphabetically. + + Option to change what information is displayed (rarity, name, icon, total caught). + + Option to show only missing trophies. + + Option to highlight new catches in green. + + Options for when to show the display: always in Crimson Isle, in inventory, with rod in hand, or on keybind press. + + Option to show only when wearing a full hunter armor set. + + Options to show checkmarks or crosses instead of numbers. + + Hover over a trophy fish to see the percentage caught and how to gain progress.
@@ -596,6 +609,8 @@ Use `/sh` or `/skyhanni` to open the SkyHanni config in game. + Show the start waypoint for your farm with the currently holding tool. + Auto-detects the start of the farm when farming for the first time + Option to manually set the waypoint with /shcropstartlocation ++ Crop last farmed waypoint. - appable (https://github.com/hannibal002/SkyHanni/pull/1335) + + Accessible in the Crop Start Locations section. + Jacob Contest Stats Summary + Showing Blocks per Second and total Blocks clicked after a farming contest in chat + **Contest Time Needed** @@ -808,6 +823,7 @@ Use `/sh` or `/skyhanni` to open the SkyHanni config in game. + Track Fossil Dust and use it for profit calculation. + Mining Notifications. - martimavocado (https://github.com/hannibal002/SkyHanni/pull/1429) + Mining events, including Mineshaft spawning, Suspicious Scrap drops, and Cold going above a threshold. ++ Configurable cold amount for the ascension rope message in Glacite Mines. - nopo (https://github.com/hannibal002/SkyHanni/pull/1905) + Profit Per Excavation. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/1439) + Show profit/loss in chat after each excavation. + Also include breakdown information on hover. @@ -889,6 +905,7 @@ Use `/sh` or `/skyhanni` to open the SkyHanni config in game. + Ability to adjust the opacity of players near shared and guessed egg waypoints. - RobotHanzo (https://github.com/hannibal002/SkyHanni/pull/1582) + Time until the next Hoppity event in chat message for egg locator. - seraid (https://github.com/hannibal002/SkyHanni/pull/1625) + Warning before the Time Tower in the Chocolate Factory ends. - seraid (https://github.com/hannibal002/SkyHanni/pull/1816) ++ Chat reminder to check Hoppity Shop each year. - appable (https://github.com/hannibal002/SkyHanni/pull/1843)
@@ -1144,6 +1161,7 @@ Use `/sh` or `/skyhanni` to open the SkyHanni config in game. martimavocado (https://github.com/hannibal002/SkyHanni/pull/848) + Support for `/playtime` and `/pt` while in Limbo. + Added your playtime to Hypixel's `/playtimedetailed`. ++ Option to toggle limbo time in detailed /playtime. - HiZe (https://github.com/hannibal002/SkyHanni/pull/1863) + Click on breakdown display in /playtimedetailed to copy the stats into the clipboard. - seraid (https://github.com/hannibal002/SkyHanni/pull/1807) + Custom Scoreboard - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/893) + Customizable; New, never seen before lines like the current mayor with perks, your party, and more! diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt index f389feeea472..c8a4c04dc324 100644 --- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt +++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt @@ -493,7 +493,7 @@ import org.apache.logging.log4j.Logger clientSideOnly = true, useMetadata = true, guiFactory = "at.hannibal2.skyhanni.config.ConfigGuiForgeInterop", - version = "0.26.Beta.2", + version = "0.26.Beta.3", ) class SkyHanniMod { From 56f13597822b45caea4167d7d75258078e06c1b3 Mon Sep 17 00:00:00 2001 From: hannibal2 <24389977+hannibal00212@users.noreply.github.com> Date: Wed, 29 May 2024 22:11:50 +0200 Subject: [PATCH 11/34] cant use multi lines without clipboard --- .../at/hannibal2/skyhanni/test/command/TestChatCommand.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/at/hannibal2/skyhanni/test/command/TestChatCommand.kt b/src/main/java/at/hannibal2/skyhanni/test/command/TestChatCommand.kt index e5ed69064411..38db097a28bb 100644 --- a/src/main/java/at/hannibal2/skyhanni/test/command/TestChatCommand.kt +++ b/src/main/java/at/hannibal2/skyhanni/test/command/TestChatCommand.kt @@ -18,10 +18,11 @@ object TestChatCommand { SkyHanniMod.launchCoroutine { val mutArgs = args.toMutableList() + val multiLines = mutArgs.remove("-lines") val isComplex = mutArgs.remove("-complex") - val isClipboard = mutArgs.remove("-clipboard") + // cant use multi lines without clipboard + val isClipboard = mutArgs.remove("-clipboard") || multiLines val isHidden = mutArgs.remove("-s") - val multiLines = mutArgs.remove("-lines") val text = if (isClipboard) { OSUtils.readFromClipboard() ?: return@launchCoroutine ChatUtils.userError("Clipboard does not contain a string!") From 28efe42942ead21fb4ba9fa16e132975e34f65fb Mon Sep 17 00:00:00 2001 From: CalMWolfs <94038482+CalMWolfs@users.noreply.github.com> Date: Thu, 30 May 2024 06:17:41 +1000 Subject: [PATCH 12/34] Fix: tooltip event (#1920) --- .../java/at/hannibal2/skyhanni/data/ToolTipData.kt | 2 ++ .../mixins/transformers/MixinItemStack.java | 13 ------------- .../mixins/transformers/gui/MixinGuiScreen.java | 12 ++++++++++++ 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/main/java/at/hannibal2/skyhanni/data/ToolTipData.kt b/src/main/java/at/hannibal2/skyhanni/data/ToolTipData.kt index 709961ce6cdf..258cb244e156 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/ToolTipData.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/ToolTipData.kt @@ -11,6 +11,8 @@ import net.minecraft.item.ItemStack // Please use LorenzToolTipEvent over ItemTooltipEvent if no special EventPriority is necessary object ToolTipData { + + @JvmStatic fun getTooltip(stack: ItemStack, toolTip: MutableList): List { onHover(stack, toolTip) return onTooltip(toolTip) diff --git a/src/main/java/at/hannibal2/skyhanni/mixins/transformers/MixinItemStack.java b/src/main/java/at/hannibal2/skyhanni/mixins/transformers/MixinItemStack.java index 75c94b0b6e12..b96075d625e7 100644 --- a/src/main/java/at/hannibal2/skyhanni/mixins/transformers/MixinItemStack.java +++ b/src/main/java/at/hannibal2/skyhanni/mixins/transformers/MixinItemStack.java @@ -1,17 +1,10 @@ package at.hannibal2.skyhanni.mixins.transformers; -import at.hannibal2.skyhanni.data.ToolTipData; import at.hannibal2.skyhanni.mixins.hooks.ItemStackCachedData; import at.hannibal2.skyhanni.utils.CachedItemData; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import java.util.List; @Mixin(ItemStack.class) public class MixinItemStack implements ItemStackCachedData { @@ -22,10 +15,4 @@ public class MixinItemStack implements ItemStackCachedData { public CachedItemData getSkyhanni_cachedData() { return skyhanni_cachedData; } - - @Inject(method = "getTooltip", at = @At("RETURN")) - public void getTooltip(EntityPlayer playerIn, boolean advanced, CallbackInfoReturnable> ci) { - ItemStack stack = (ItemStack) (Object) this; - ToolTipData.INSTANCE.getTooltip(stack, ci.getReturnValue()); - } } diff --git a/src/main/java/at/hannibal2/skyhanni/mixins/transformers/gui/MixinGuiScreen.java b/src/main/java/at/hannibal2/skyhanni/mixins/transformers/gui/MixinGuiScreen.java index 9da6faf3a269..dee6be23e6c0 100644 --- a/src/main/java/at/hannibal2/skyhanni/mixins/transformers/gui/MixinGuiScreen.java +++ b/src/main/java/at/hannibal2/skyhanni/mixins/transformers/gui/MixinGuiScreen.java @@ -1,5 +1,6 @@ package at.hannibal2.skyhanni.mixins.transformers.gui; +import at.hannibal2.skyhanni.data.ToolTipData; import at.hannibal2.skyhanni.mixins.hooks.GuiScreenHookKt; import net.minecraft.client.gui.GuiScreen; import net.minecraft.item.ItemStack; @@ -7,6 +8,9 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +import java.util.List; @Mixin(GuiScreen.class) public class MixinGuiScreen { @@ -15,4 +19,12 @@ public class MixinGuiScreen { public void renderToolTip(ItemStack stack, int x, int y, CallbackInfo ci) { GuiScreenHookKt.renderToolTip(stack); } + + @Inject(method = "renderToolTip", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;getRarity()Lnet/minecraft/item/EnumRarity;", shift = At.Shift.AFTER), locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true) + public void getTooltip(ItemStack stack, int x, int y, CallbackInfo ci, List list, int i) { + ToolTipData.getTooltip(stack, list); + if (list.isEmpty()) { + ci.cancel(); + } + } } From 97f4433127b9a0e9963eb727a0c5fd8594ac70f5 Mon Sep 17 00:00:00 2001 From: appable Date: Wed, 29 May 2024 13:23:59 -0700 Subject: [PATCH 13/34] Fix: sigma bonus ignored in hoppity collection stats (#1925) --- .../event/hoppity/HoppityCollectionStats.kt | 31 ++++++------------- .../chocolatefactory/ChocolateFactoryAPI.kt | 15 +++++++-- .../ChocolateFactoryTimeTowerManager.kt | 2 +- 3 files changed, 23 insertions(+), 25 deletions(-) diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCollectionStats.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCollectionStats.kt index 6807a712faf0..f8ef5ac62061 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCollectionStats.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCollectionStats.kt @@ -63,7 +63,6 @@ object HoppityCollectionStats { inInventory = true display = buildDisplay(event) - checkSpecialRabbits() } @SubscribeEvent @@ -107,7 +106,7 @@ object HoppityCollectionStats { } private fun getRabbitStats(): MutableList { - var totalAmountFound = 0 + var totalUniquesFound = 0 var totalDuplicates = 0 var totalChocolatePerSecond = 0 var totalChocolateMultiplier = 0.0 @@ -121,8 +120,8 @@ object HoppityCollectionStats { } val title = "${rarity.displayName} Rabbits" - val amountFound = foundOfRarity.size - val duplicates = foundOfRarity.values.sum() - amountFound + val uniquesFound = foundOfRarity.size + val duplicates = foundOfRarity.values.sum() - uniquesFound val chocolateBonuses = foundOfRarity.keys.map { HoppityCollectionData.getChocolateBonuses(it) @@ -131,14 +130,18 @@ object HoppityCollectionStats { val chocolatePerSecond = chocolateBonuses.sumOf { it.chocolate } val chocolateMultiplier = chocolateBonuses.sumOf { it.multiplier } + if (hasFoundRabbit("Sigma") && rarity == RabbitCollectionRarity.MYTHIC) { + totalChocolatePerSecond += uniquesFound * 5 + } + if (!isTotal) { - totalAmountFound += amountFound + totalUniquesFound += uniquesFound totalDuplicates += duplicates totalChocolatePerSecond += chocolatePerSecond totalChocolateMultiplier += chocolateMultiplier } - val displayFound = if (isTotal) totalAmountFound else amountFound + val displayFound = if (isTotal) totalUniquesFound else uniquesFound val displayTotal = if (isTotal) { HoppityCollectionData.knownRabbitCount } else { @@ -175,7 +178,6 @@ object HoppityCollectionStats { val rabbit = name.removeColor() if (!HoppityCollectionData.isKnownRabbit(rabbit)) return loggedRabbits[rabbit] = (loggedRabbits[rabbit] ?: 0) + 1 - checkSpecialRabbits() } // Gets the found rabbits according to the Hypixel progress bar @@ -215,20 +217,7 @@ object HoppityCollectionStats { ChatUtils.chat("Cleared saved rabbit data.") } - - // checks special rabbits whenever loggedRabbits is modified to update misc stored values - // TODO: make this better than hard-coded checks - private fun checkSpecialRabbits() { - if (hasFoundRabbit("Einstein")) { - ChocolateFactoryAPI.profileStorage?.timeTowerCooldown = 7 - } - - if (hasFoundRabbit("Mu")) { - ChocolateFactoryAPI.profileStorage?.hasMuRabbit = true - } - } - - private fun hasFoundRabbit(rabbit: String): Boolean = loggedRabbits.containsKey(rabbit) + fun hasFoundRabbit(rabbit: String): Boolean = loggedRabbits.containsKey(rabbit) private fun isEnabled() = LorenzUtils.inSkyBlock && config.hoppityCollectionStats diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryAPI.kt index fa532dab6ca8..8b9ef3f2ac07 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryAPI.kt @@ -8,6 +8,7 @@ import at.hannibal2.skyhanni.data.ProfileStorageData import at.hannibal2.skyhanni.data.jsonobjects.repo.HoppityEggLocationsJson import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent import at.hannibal2.skyhanni.events.RepositoryReloadEvent +import at.hannibal2.skyhanni.features.event.hoppity.HoppityCollectionStats import at.hannibal2.skyhanni.features.event.hoppity.HoppityEggLocator import at.hannibal2.skyhanni.utils.CollectionUtils.nextAfter import at.hannibal2.skyhanni.utils.DelayedRun @@ -21,6 +22,7 @@ import at.hannibal2.skyhanni.utils.UtilsPatterns import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import kotlin.time.Duration +import kotlin.time.Duration.Companion.hours import kotlin.time.Duration.Companion.seconds object ChocolateFactoryAPI { @@ -149,20 +151,27 @@ object ChocolateFactoryAPI { fun isMaxPrestige() = currentPrestige >= maxPrestige + fun timeTowerChargeDuration() = + if (HoppityCollectionStats.hasFoundRabbit("Einstein")) 7.hours else 8.hours + + private fun timeTowerMultiplier(): Double { + var multiplier = (profileStorage?.timeTowerLevel ?: 0) * 0.1 + if (HoppityCollectionStats.hasFoundRabbit("Mu")) multiplier += 0.7 + return multiplier + } + fun timeUntilNeed(goal: Long): Duration { var needed = goal val profileStorage = profileStorage ?: return Duration.ZERO val baseMultiplier = profileStorage.rawChocolateMultiplier val rawChocolatePerSecond = profileStorage.rawChocPerSecond - var timeTowerMultiplier = baseMultiplier + profileStorage.timeTowerLevel * 0.1 - if (profileStorage.hasMuRabbit) timeTowerMultiplier += 0.7 if (rawChocolatePerSecond == 0) return Duration.INFINITE val secondsUntilTowerExpires = ChocolateFactoryTimeTowerManager.timeTowerActiveDuration().inWholeSeconds - val timeTowerChocPerSecond = rawChocolatePerSecond * timeTowerMultiplier + val timeTowerChocPerSecond = rawChocolatePerSecond * (baseMultiplier + timeTowerMultiplier()) val secondsAtRate = needed / timeTowerChocPerSecond if (secondsAtRate < secondsUntilTowerExpires) { 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 530bd7558d6f..94ebe2dacaae 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 @@ -128,7 +128,7 @@ object ChocolateFactoryTimeTowerManager { if (timeTowerFull()) return SimpleTimeMark.farPast() val nextChargeDuration = SimpleTimeMark(profileStorage.nextTimeTower) val remainingChargesAfter = profileStorage.maxTimeTowerUses - (profileStorage.currentTimeTowerUses + 1) - val endTime = nextChargeDuration + (profileStorage.timeTowerCooldown).hours * remainingChargesAfter + val endTime = nextChargeDuration + ChocolateFactoryAPI.timeTowerChargeDuration() * remainingChargesAfter return endTime } From 568a3a864ef6970a8fb7b31b6cc65d117f749681 Mon Sep 17 00:00:00 2001 From: Empa <42304516+ItsEmpa@users.noreply.github.com> Date: Wed, 29 May 2024 22:34:18 +0200 Subject: [PATCH 14/34] Improvement + Fix: Sea Creature Alert (#1858) Co-authored-by: Thunderblade73 <85900443+Thunderblade73@users.noreply.github.com> --- .../features/fishing/RareCatchesConfig.java | 5 + .../features/fishing/SeaCreatureFeatures.kt | 96 +++++++------------ .../features/fishing/SeaCreatureManager.kt | 4 +- 3 files changed, 44 insertions(+), 61 deletions(-) diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/fishing/RareCatchesConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/fishing/RareCatchesConfig.java index 03a965844c3e..ae5de833a382 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/fishing/RareCatchesConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/fishing/RareCatchesConfig.java @@ -18,6 +18,11 @@ public class RareCatchesConfig { @ConfigEditorBoolean public boolean alertOtherCatches = false; + @Expose + @ConfigOption(name = "Creature Name", desc = "Say what creature was caught in the alert.") + @ConfigEditorBoolean + public boolean creatureName = true; + @Expose @ConfigOption(name = "Play Sound Alert", desc = "Play a sound effect when rare sea creature alerts are displayed.") @ConfigEditorBoolean diff --git a/src/main/java/at/hannibal2/skyhanni/features/fishing/SeaCreatureFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/fishing/SeaCreatureFeatures.kt index bbead46b42ec..5bebcfe276be 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/fishing/SeaCreatureFeatures.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/fishing/SeaCreatureFeatures.kt @@ -2,77 +2,75 @@ package at.hannibal2.skyhanni.features.fishing import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator -import at.hannibal2.skyhanni.events.EntityMaxHealthUpdateEvent +import at.hannibal2.skyhanni.config.features.combat.damageindicator.DamageIndicatorConfig import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent +import at.hannibal2.skyhanni.events.MobEvent import at.hannibal2.skyhanni.events.RenderEntityOutlineEvent import at.hannibal2.skyhanni.events.SeaCreatureFishEvent -import at.hannibal2.skyhanni.features.combat.damageindicator.DamageIndicatorManager import at.hannibal2.skyhanni.features.dungeon.DungeonAPI -import at.hannibal2.skyhanni.mixins.hooks.RenderLivingEntityHelper -import at.hannibal2.skyhanni.utils.CollectionUtils.editCopy -import at.hannibal2.skyhanni.utils.ColorUtils.withAlpha -import at.hannibal2.skyhanni.utils.EntityUtils.hasMaxHealth -import at.hannibal2.skyhanni.utils.EntityUtils.hasNameTagWith import at.hannibal2.skyhanni.utils.LocationUtils.distanceToPlayer import at.hannibal2.skyhanni.utils.LorenzColor import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.LorenzUtils.baseMaxHealth -import at.hannibal2.skyhanni.utils.LorenzUtils.ignoreDerpy import at.hannibal2.skyhanni.utils.SimpleTimeMark import at.hannibal2.skyhanni.utils.SoundUtils +import at.hannibal2.skyhanni.utils.TimeLimitedSet import net.minecraft.entity.Entity import net.minecraft.entity.EntityLivingBase -import net.minecraft.entity.monster.EntityGuardian -import net.minecraft.entity.monster.EntityIronGolem -import net.minecraft.entity.monster.EntitySkeleton -import net.minecraft.entity.monster.EntityZombie -import net.minecraft.entity.passive.EntitySquid -import net.minecraft.entity.player.EntityPlayer import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import kotlin.time.Duration.Companion.minutes import kotlin.time.Duration.Companion.seconds class SeaCreatureFeatures { private val config get() = SkyHanniMod.feature.fishing.rareCatches + private val damageIndicatorConfig get() = SkyHanniMod.feature.combat.damageIndicator private var rareSeaCreatures = listOf() private var lastRareCatch = SimpleTimeMark.farPast() + private var armorStandIds = TimeLimitedSet(6.minutes) @SubscribeEvent - fun onEntityHealthUpdate(event: EntityMaxHealthUpdateEvent) { + fun onMobSpawn(event: MobEvent.Spawn.SkyblockMob) { if (!isEnabled()) return - val entity = event.entity as? EntityLivingBase ?: return - if (DamageIndicatorManager.isBoss(entity)) return - - // TODO remove workaround by change derpy logic either in hasMaxHealth or in EntityMaxHealthUpdateEvent - val maxHealth = event.maxHealth.ignoreDerpy() - for (creatureType in RareSeaCreatureType.entries) { - if (!creatureType.health.any { entity.hasMaxHealth(it, false, maxHealth) }) continue - if (!creatureType.clazz.isInstance(entity)) continue - if (!entity.hasNameTagWith(3, creatureType.nametag)) continue - - rareSeaCreatures = rareSeaCreatures.editCopy { add(entity) } - RenderLivingEntityHelper.setEntityColorWithNoHurtTime(entity, LorenzColor.RED.toColor().withAlpha(50)) - { config.highlight } + val creature = SeaCreatureManager.allFishingMobs[event.mob.name] ?: return + if (!creature.rare) return + + if (config.highlight && !(damageIndicatorConfig.enabled && damageIndicatorConfig.bossesToShow.contains( + DamageIndicatorConfig.BossCategory.SEA_CREATURES + )) + ) { + event.mob.highlight(LorenzColor.GREEN.toColor()) + rareSeaCreatures += event.mob.baseEntity + } + val id = event.mob.armorStand?.entityId ?: return + if (armorStandIds.contains(id)) return + armorStandIds.add(id) - // Water hydra splitting in two - if (creatureType == RareSeaCreatureType.WATER_HYDRA && entity.health == (entity.baseMaxHealth.toFloat() / 2)) continue + if (lastRareCatch.passedSince() < 1.seconds) return + if (event.mob.name == "Water Hydra" && event.mob.baseEntity.health == (event.mob.baseEntity.baseMaxHealth.toFloat() / 2)) return - if (config.alertOtherCatches && lastRareCatch.passedSince() > 1.seconds) { - val creature = SeaCreatureManager.allFishingMobs[creatureType.nametag] - val text = "${creature?.rarity?.chatColorCode ?: "§6"}RARE SEA CREATURE!" - LorenzUtils.sendTitle(text, 1.5.seconds, 3.6, 7f) - if (config.playSound) SoundUtils.playBeepSound() - } + if (config.alertOtherCatches) { + val text = if (config.creatureName) "${creature.displayName} NEARBY!" + else "${creature.rarity.chatColorCode}RARE SEA CREATURE!" + LorenzUtils.sendTitle(text, 1.5.seconds, 3.6, 7f) + if (config.playSound) SoundUtils.playBeepSound() } } + @SubscribeEvent + fun onMobDeSpawn(event: MobEvent.DeSpawn.SkyblockMob) { + rareSeaCreatures.filter { it != event.mob.baseEntity } + } + @SubscribeEvent fun onSeaCreatureFish(event: SeaCreatureFishEvent) { if (!LorenzUtils.inSkyBlock) return if (!config.alertOwnCatches) return if (event.seaCreature.rare) { - LorenzUtils.sendTitle("${event.seaCreature.rarity.chatColorCode}RARE CATCH!", 3.seconds, 2.8, 7f) + val text = if (config.creatureName) "${event.seaCreature.displayName}!" + else "${event.seaCreature.rarity.chatColorCode}RARE CATCH!" + LorenzUtils.sendTitle(text, 3.seconds, 2.8, 7f) if (config.playSound) SoundUtils.playBeepSound() lastRareCatch = SimpleTimeMark.now() } @@ -80,7 +78,8 @@ class SeaCreatureFeatures { @SubscribeEvent fun onWorldChange(event: LorenzWorldChangeEvent) { - rareSeaCreatures = emptyList() + rareSeaCreatures = listOf() + armorStandIds.clear() } @SubscribeEvent @@ -102,25 +101,4 @@ class SeaCreatureFeatures { LorenzColor.GREEN.toColor().rgb } else null } - - enum class RareSeaCreatureType( - val clazz: Class, - val nametag: String, - vararg val health: Int, - ) { - - WATER_HYDRA(EntityZombie::class.java, "Water Hydra", 500_000), - SEA_EMPEROR(EntityGuardian::class.java, "Sea Emperor", 750_000, 800_000), - SEA_EMPEROR_RIDER(EntitySkeleton::class.java, "Sea Emperor", 750_000, 800_000), - ZOMBIE_MINER(EntityPlayer::class.java, "Zombie Miner", 2_000_000), - PHANTOM_FISHERMAN(EntityPlayer::class.java, "Phantom Fisher", 1_000_000), - GRIM_REAPER(EntityPlayer::class.java, "Grim Reaper", 3_000_000), - YETI(EntityPlayer::class.java, "Yeti", 2_000_000), - NUTCRACKER(EntityZombie::class.java, "Nutcracker", 4_000_000), - GREAT_WHITE_SHARK(EntityPlayer::class.java, "Great White Shark", 1_500_000), - THUNDER(EntityGuardian::class.java, "Thunder", 35_000_000), - LORD_JAWBUS(EntityIronGolem::class.java, "Lord Jawbus", 100_000_000), - PLHLEGBLAST(EntitySquid::class.java, "Plhlegblast", 500_000_000), - ; - } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/fishing/SeaCreatureManager.kt b/src/main/java/at/hannibal2/skyhanni/features/fishing/SeaCreatureManager.kt index bfff1d7be852..59d9d818b240 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/fishing/SeaCreatureManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/fishing/SeaCreatureManager.kt @@ -21,7 +21,7 @@ class SeaCreatureManager { } doubleHook = true } else { - val seaCreature = getSeaCreature(event.message) + val seaCreature = getSeaCreatureFromMessage(event.message) if (seaCreature != null) { SeaCreatureFishEvent(seaCreature, event, doubleHook).postAndCatch() } @@ -72,7 +72,7 @@ class SeaCreatureManager { "§eIt's a §r§aDouble Hook§r§e!" ) - fun getSeaCreature(message: String): SeaCreature? { + fun getSeaCreatureFromMessage(message: String): SeaCreature? { return seaCreatureMap.getOrDefault(message, null) } } From cbaed5b6865d169ce7d49bb16b8c42aa5d68be94 Mon Sep 17 00:00:00 2001 From: hannibal2 <24389977+hannibal00212@users.noreply.github.com> Date: Wed, 29 May 2024 22:36:55 +0200 Subject: [PATCH 15/34] code cleanup --- .../skyhanni/features/fishing/SeaCreatureFeatures.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/at/hannibal2/skyhanni/features/fishing/SeaCreatureFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/fishing/SeaCreatureFeatures.kt index 5bebcfe276be..827b58fd8d21 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/fishing/SeaCreatureFeatures.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/fishing/SeaCreatureFeatures.kt @@ -35,9 +35,8 @@ class SeaCreatureFeatures { val creature = SeaCreatureManager.allFishingMobs[event.mob.name] ?: return if (!creature.rare) return - if (config.highlight && !(damageIndicatorConfig.enabled && damageIndicatorConfig.bossesToShow.contains( - DamageIndicatorConfig.BossCategory.SEA_CREATURES - )) + if (config.highlight && !(damageIndicatorConfig.enabled && + DamageIndicatorConfig.BossCategory.SEA_CREATURES in damageIndicatorConfig.bossesToShow) ) { event.mob.highlight(LorenzColor.GREEN.toColor()) rareSeaCreatures += event.mob.baseEntity From 21f92de676710c0c39d37056dada80af8266a9ba Mon Sep 17 00:00:00 2001 From: raaaaaven <168305416+raaaaaven@users.noreply.github.com> Date: Wed, 29 May 2024 21:44:20 +0100 Subject: [PATCH 16/34] Feature: Added ULTRA RARE Book Notification. (#1738) Co-authored-by: CalMWolfs <94038482+CalMWolfs@users.noreply.github.com> Co-authored-by: raven Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com> --- .../java/at/hannibal2/skyhanni/SkyHanniMod.kt | 4 +- .../skyhanni/config/ConfigUpdaterMigrator.kt | 2 +- .../inventory/helper/HelperConfig.java | 20 ++++ .../config/features/misc/MiscConfig.java | 6 -- .../SuperpairsClicksAlert.kt | 10 +- .../features/inventory/UltraRareBookAlert.kt | 102 ++++++++++++++++++ 6 files changed, 134 insertions(+), 10 deletions(-) rename src/main/java/at/hannibal2/skyhanni/features/{misc => inventory}/SuperpairsClicksAlert.kt (86%) create mode 100644 src/main/java/at/hannibal2/skyhanni/features/inventory/UltraRareBookAlert.kt diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt index c8a4c04dc324..0374024e0d3c 100644 --- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt +++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt @@ -275,6 +275,8 @@ import at.hannibal2.skyhanni.features.inventory.ShiftClickNPCSell import at.hannibal2.skyhanni.features.inventory.SkyblockGuideHighlightFeature import at.hannibal2.skyhanni.features.inventory.StatsTuning import at.hannibal2.skyhanni.features.inventory.SuperCraftFeatures +import at.hannibal2.skyhanni.features.inventory.SuperpairsClicksAlert +import at.hannibal2.skyhanni.features.inventory.UltraRareBookAlert import at.hannibal2.skyhanni.features.inventory.auctionhouse.AuctionHouseCopyUnderbidPrice import at.hannibal2.skyhanni.features.inventory.auctionhouse.AuctionHouseOpenPriceWebsite import at.hannibal2.skyhanni.features.inventory.bazaar.BazaarApi @@ -362,7 +364,6 @@ import at.hannibal2.skyhanni.features.misc.ReplaceRomanNumerals import at.hannibal2.skyhanni.features.misc.RestorePieceOfWizardPortalLore import at.hannibal2.skyhanni.features.misc.ServerRestartTitle import at.hannibal2.skyhanni.features.misc.SkyBlockKickDuration -import at.hannibal2.skyhanni.features.misc.SuperpairsClicksAlert import at.hannibal2.skyhanni.features.misc.TabWidgetSettings import at.hannibal2.skyhanni.features.misc.TimeFeatures import at.hannibal2.skyhanni.features.misc.TpsCounter @@ -888,6 +889,7 @@ class SkyHanniMod { loadModule(Translator()) loadModule(CosmeticFollowingLine()) loadModule(SuperpairsClicksAlert()) + loadModule(UltraRareBookAlert) loadModule(PowderTracker) loadModule(ModifyVisualWords) loadModule(TabListReader) diff --git a/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt b/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt index fadaec07ffb5..b44153e7913b 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 = 45 + const val CONFIG_VERSION = 46 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/inventory/helper/HelperConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/helper/HelperConfig.java index 0960c46b52e4..e117004a4e2a 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/helper/HelperConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/helper/HelperConfig.java @@ -51,4 +51,24 @@ public static class HarpConfig { @ConfigOption(name = "Tia Relay Abiphone Network Maintenance", desc = "") @Accordion public TiaRelayConfig tiaRelay = new TiaRelayConfig(); + + @Expose + @ConfigOption(name = "Enchanting", desc = "") + @Accordion + public EnchantingConfig enchanting = new EnchantingConfig(); + + public static class EnchantingConfig { + @Expose + @ConfigOption(name = "Superpairs Clicks Alert", desc = "Display an alert when you reach the maximum clicks gained from Chronomatron or Ultrasequencer.") + @ConfigEditorBoolean + @FeatureToggle + public boolean superpairsClicksAlert = false; + + @Expose + @ConfigOption(name = "ULTRA-RARE Book Alert", desc = "Sends a chat message, title and sound when you find an ULTRA-RARE book.") + @ConfigEditorBoolean + @FeatureToggle + public boolean ultraRareBookAlert = false; + } + } diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/misc/MiscConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/misc/MiscConfig.java index 6e4fe4f12110..1921d64b3b40 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/misc/MiscConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/misc/MiscConfig.java @@ -198,12 +198,6 @@ public class MiscConfig { @FeatureToggle public boolean accountUpgradeReminder = true; - @Expose - @ConfigOption(name = "Superpairs Clicks Alert", desc = "Display an alert when you reach the maximum clicks gained from Chronomatron or Ultrasequencer.") - @ConfigEditorBoolean - @FeatureToggle - public boolean superpairsClicksAlert = false; - @Expose @ConfigOption(name = "NEU Heavy Pearls", desc = "Fixing NEU Heavy Pearl detection.") @ConfigEditorBoolean diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/SuperpairsClicksAlert.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/SuperpairsClicksAlert.kt similarity index 86% rename from src/main/java/at/hannibal2/skyhanni/features/misc/SuperpairsClicksAlert.kt rename to src/main/java/at/hannibal2/skyhanni/features/inventory/SuperpairsClicksAlert.kt index b09a1dbffc7e..e9c8a717b39e 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/SuperpairsClicksAlert.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/SuperpairsClicksAlert.kt @@ -1,6 +1,7 @@ -package at.hannibal2.skyhanni.features.misc +package at.hannibal2.skyhanni.features.inventory import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator import at.hannibal2.skyhanni.events.InventoryOpenEvent import at.hannibal2.skyhanni.events.InventoryUpdatedEvent import at.hannibal2.skyhanni.utils.ChatUtils @@ -11,7 +12,7 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent class SuperpairsClicksAlert { - private val config get() = SkyHanniMod.feature.misc + private val config get() = SkyHanniMod.feature.inventory.helper.enchanting private var roundsNeeded = -1 private val roundsNeededRegex = Regex("""(?:Chain|Series) of (\d+):""") @@ -59,4 +60,9 @@ class SuperpairsClicksAlert { roundsNeeded = -1 } } + + @SubscribeEvent + fun onConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) { + event.move(46, "misc.superpairsClicksAlert", "inventory.helper.enchanting.superpairsClicksAlert") + } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/UltraRareBookAlert.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/UltraRareBookAlert.kt new file mode 100644 index 000000000000..1d6af4e8969a --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/UltraRareBookAlert.kt @@ -0,0 +1,102 @@ +package at.hannibal2.skyhanni.features.inventory + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.events.GuiRenderEvent +import at.hannibal2.skyhanni.events.InventoryCloseEvent +import at.hannibal2.skyhanni.events.InventoryUpdatedEvent +import at.hannibal2.skyhanni.utils.ChatUtils +import at.hannibal2.skyhanni.utils.ColorUtils.withAlpha +import at.hannibal2.skyhanni.utils.InventoryUtils +import at.hannibal2.skyhanni.utils.ItemUtils.getLore +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher +import at.hannibal2.skyhanni.utils.RegexUtils.matches +import at.hannibal2.skyhanni.utils.RenderUtils +import at.hannibal2.skyhanni.utils.SimpleTimeMark +import at.hannibal2.skyhanni.utils.SoundUtils.createSound +import at.hannibal2.skyhanni.utils.SoundUtils.playSound +import at.hannibal2.skyhanni.utils.renderables.Renderable +import at.hannibal2.skyhanni.utils.renderables.RenderableUtils.renderXYAligned +import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern +import net.minecraft.client.Minecraft +import net.minecraft.client.gui.inventory.GuiContainer +import net.minecraft.client.renderer.GlStateManager +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import java.awt.Color +import kotlin.time.Duration.Companion.seconds + +object UltraRareBookAlert { + + private val config get() = SkyHanniMod.feature.inventory.helper.enchanting + private val dragonSound by lazy { createSound("mob.enderdragon.growl", 1f) } + + private val patternGroup = RepoPattern.group("data.enchanting") + private val superpairsGui by patternGroup.pattern( + "inventory.experimentstable.gui", + "Superpairs.*" + ) + private val ultraRarePattern by patternGroup.pattern( + "inventory.experimentstable.ultrarare", + "§d§kXX§5 ULTRA-RARE BOOK! §d§kXX" + ) + private val bookPattern by patternGroup.pattern( + "inventory.experimentstable.book", + "§9(?.*)" + ) + + private var enchantsFound = false + + private var lastNotificationTime = SimpleTimeMark.farPast() + + private fun notification(enchantsName: String) { + lastNotificationTime = SimpleTimeMark.now() + dragonSound.playSound() + ChatUtils.chat("You have uncovered a §d§kXX§5 ULTRA-RARE BOOK! §d§kXX§e! You found: §9$enchantsName") + } + + @SubscribeEvent + fun onRenderOverlay(event: GuiRenderEvent.ChestGuiOverlayRenderEvent) { + if (!LorenzUtils.inSkyBlock) return + if (!config.ultraRareBookAlert) return + if (!superpairsGui.matches(InventoryUtils.openInventoryName())) return + if (lastNotificationTime.passedSince() > 5.seconds) return + val gui = Minecraft.getMinecraft().currentScreen as? GuiContainer ?: return + + GlStateManager.pushMatrix() + GlStateManager.translate(0f, -150f, 500f) + + Renderable.drawInsideRoundedRect( + Renderable.string("§d§kXX§5 ULTRA-RARE BOOK! §d§kXX", 1.5), + Color(Color.DARK_GRAY.withAlpha(0), true), + horizontalAlign = RenderUtils.HorizontalAlignment.CENTER, + verticalAlign = RenderUtils.VerticalAlignment.CENTER, + ).renderXYAligned(0, 125, gui.width, gui.height) + + GlStateManager.translate(0f, 150f, -500f) + GlStateManager.popMatrix() + } + + @SubscribeEvent + fun onInventoryUpdated(event: InventoryUpdatedEvent) { + if (!LorenzUtils.inSkyBlock) return + if (!config.ultraRareBookAlert) return + if (enchantsFound) return + if (!superpairsGui.matches(event.inventoryName)) return + + for (lore in event.inventoryItems.map { it.value.getLore() }) { + val firstLine = lore.firstOrNull() ?: continue + if (!ultraRarePattern.matches(firstLine)) continue + val bookNameLine = lore.getOrNull(2) ?: continue + bookPattern.matchMatcher(bookNameLine) { + val enchantsName = group("enchant") + notification(enchantsName) + enchantsFound = true + } + } + } + + @SubscribeEvent + fun onInventoryClose(event: InventoryCloseEvent) { + enchantsFound = false + } +} From 2af916371b2edf71fb055a3f8de2bcd7b99b2251 Mon Sep 17 00:00:00 2001 From: Thunderblade73 <85900443+Thunderblade73@users.noreply.github.com> Date: Wed, 29 May 2024 23:00:20 +0200 Subject: [PATCH 17/34] Improvement: Added Mining Event Icons (#1305) Co-authored-by: Cal --- .../features/mining/MiningEventConfig.java | 9 +- .../mining/eventtracker/MiningEventDisplay.kt | 74 ++++++++-- .../mining/eventtracker/MiningEventType.kt | 132 ++++++++++++++++-- .../skyhanni/features/misc/DarkenShader.kt | 17 +++ .../hannibal2/skyhanni/utils/ConfigUtils.kt | 13 ++ .../skyhanni/utils/renderables/Renderable.kt | 17 +++ .../skyhanni/utils/shader/ShaderHelper.kt | 4 + .../skyhanni/utils/shader/ShaderManager.kt | 5 + .../skyhanni/utils/shader/Uniform.kt | 2 + .../assets/skyhanni/shaders/darken.fsh | 13 ++ .../assets/skyhanni/shaders/darken.vsh | 9 ++ 11 files changed, 271 insertions(+), 24 deletions(-) create mode 100644 src/main/java/at/hannibal2/skyhanni/features/misc/DarkenShader.kt create mode 100644 src/main/resources/assets/skyhanni/shaders/darken.fsh create mode 100644 src/main/resources/assets/skyhanni/shaders/darken.vsh diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/mining/MiningEventConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/mining/MiningEventConfig.java index 81eeb2b1abc2..8f5dac292dc3 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/mining/MiningEventConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/mining/MiningEventConfig.java @@ -2,6 +2,7 @@ import at.hannibal2.skyhanni.config.FeatureToggle; import at.hannibal2.skyhanni.config.core.config.Position; +import at.hannibal2.skyhanni.features.mining.eventtracker.MiningEventType.Companion.CompressFormat; import com.google.gson.annotations.Expose; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorDropdown; @@ -29,8 +30,13 @@ public class MiningEventConfig { @Expose @ConfigOption(name = "Compressed Format", desc = "Compresses the event names so that they are shorter.") + @ConfigEditorDropdown + public CompressFormat compressedFormat = CompressFormat.DEFAULT; + + @Expose + @ConfigOption(name = "Compressed Island", desc = "Shows the islands only as icon.") @ConfigEditorBoolean - public boolean compressedFormat = false; + public boolean islandAsIcon = false; @Expose @ConfigOption(name = "Show Passed Events", desc = "Shows the most recent passed event at the start greyed out. " + @@ -38,6 +44,7 @@ public class MiningEventConfig { @ConfigEditorBoolean public boolean passedEvents = false; + public enum ShowType { ALL("All Mining Islands"), CRYSTAL("Crystal Hollows Only"), diff --git a/src/main/java/at/hannibal2/skyhanni/features/mining/eventtracker/MiningEventDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/mining/eventtracker/MiningEventDisplay.kt index 6a65b6302815..18251dfb34c6 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/mining/eventtracker/MiningEventDisplay.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/mining/eventtracker/MiningEventDisplay.kt @@ -1,20 +1,28 @@ package at.hannibal2.skyhanni.features.mining.eventtracker import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator import at.hannibal2.skyhanni.config.features.mining.MiningEventConfig import at.hannibal2.skyhanni.data.IslandType import at.hannibal2.skyhanni.events.GuiRenderEvent import at.hannibal2.skyhanni.events.LorenzTickEvent import at.hannibal2.skyhanni.features.fame.ReminderUtils +import at.hannibal2.skyhanni.features.mining.eventtracker.MiningEventType.Companion.CompressFormat +import at.hannibal2.skyhanni.utils.ConfigUtils import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland -import at.hannibal2.skyhanni.utils.RenderUtils.renderStrings +import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName +import at.hannibal2.skyhanni.utils.NEUItems.getItemStack +import at.hannibal2.skyhanni.utils.RenderUtils.renderRenderables import at.hannibal2.skyhanni.utils.SimpleTimeMark.Companion.asTimeMark +import at.hannibal2.skyhanni.utils.renderables.Renderable +import net.minecraft.init.Blocks +import net.minecraft.item.ItemStack import net.minecraftforge.fml.common.eventhandler.SubscribeEvent object MiningEventDisplay { private val config get() = SkyHanniMod.feature.mining.miningEvent - private var display = listOf() + private var display = listOf() private val islandEventData: MutableMap = mutableMapOf() @@ -27,7 +35,7 @@ object MiningEventDisplay { @SubscribeEvent fun onRenderOverlay(event: GuiRenderEvent.GuiOverlayRenderEvent) { if (!shouldDisplay()) return - config.position.renderStrings(display, posLabel = "Upcoming Events Display") + config.position.renderRenderables(display, posLabel = "Upcoming Events Display") } private fun updateDisplay() { @@ -36,12 +44,12 @@ object MiningEventDisplay { } private fun updateEvents() { - val list = mutableListOf() + val list = mutableListOf() if (MiningEventTracker.apiError) { val count = MiningEventTracker.apiErrorCount - list.add("§cMining Event API Error! ($count)") - list.add("§cSwap servers to try again!") + list.add(Renderable.string("§cMining Event API Error! ($count)")) + list.add(Renderable.string("§cSwap servers to try again!")) } islandEventData.forEach { (islandType, eventDetails) -> @@ -61,19 +69,52 @@ object MiningEventDisplay { if (shouldShow) { val upcomingEvents = formatUpcomingEvents(eventDetails.islandEvents, eventDetails.lastEvent) - list.add("§a${islandType.displayName}§8: $upcomingEvents") + val island = + if (!config.islandAsIcon) Renderable.string("§a${islandType.displayName}§8:") else + Renderable.horizontalContainer( + listOf( + when (islandType) { + IslandType.DWARVEN_MINES -> Renderable.itemStack( + "PERFECT_RUBY_GEM".asInternalName().getItemStack() + ) + + IslandType.CRYSTAL_HOLLOWS -> Renderable.itemStack( + "MITHRIL_ORE".asInternalName().getItemStack() + ) + + IslandType.MINESHAFT -> Renderable.itemStack(ItemStack(Blocks.packed_ice)) + else -> unknownDisplay + }, + Renderable.string("§8:") + ) + ) + list.add( + Renderable.horizontalContainer( + listOf( + island, + *upcomingEvents + ), 3 + ) + ) } } display = list } - private fun formatUpcomingEvents(events: List, lastEvent: MiningEventType?): String { - val upcoming = events.filter { !it.endsAt.asTimeMark().isInPast() } - .map { if (it.isDoubleEvent) "${it.event} §8-> ${it.event}" else it.event.toString() }.toMutableList() + private val unknownDisplay = Renderable.string("§7???") + private val transitionDisplay = Renderable.string("§8->") - if (upcoming.isEmpty()) upcoming.add("§7???") - if (config.passedEvents && upcoming.size < 4) lastEvent?.let { upcoming.add(0, it.toPastString()) } - return upcoming.joinToString(" §8-> ") + private fun formatUpcomingEvents(events: List, lastEvent: MiningEventType?): Array { + val upcoming = events.filter { !it.endsAt.asTimeMark().isInPast() } + .flatMap { + if (it.isDoubleEvent) listOf(it.event, it.event) else listOf(it.event) + /* if (it.isDoubleEvent) "${it.event} §8-> ${it.event}" else it.event.toString() */ + }.map { it.getRenderable() }.toMutableList() + + if (upcoming.isEmpty()) upcoming.add(unknownDisplay) + if (config.passedEvents && upcoming.size < 4) lastEvent?.let { upcoming.add(0, it.getRenderableAsPast()) } + return upcoming.flatMap { listOf(it, transitionDisplay) }.dropLast(1).toTypedArray() + /* return upcoming.joinToString(" §8-> ") */ } fun updateData(eventData: MiningEventData) { @@ -95,6 +136,13 @@ object MiningEventDisplay { private fun shouldDisplay() = LorenzUtils.inSkyBlock && config.enabled && !ReminderUtils.isBusy() && !(!config.outsideMining && !LorenzUtils.inAdvancedMiningIsland()) + + @SubscribeEvent + fun onConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) { + event.transform(46, "mining.miningEvent.compressedFormat") { + ConfigUtils.migrateBooleanToEnum(it, CompressFormat.COMPACT_TEXT, CompressFormat.DEFAULT) + } + } } private class MiningIslandEventInfo(var islandEvents: List, var lastEvent: MiningEventType? = null) diff --git a/src/main/java/at/hannibal2/skyhanni/features/mining/eventtracker/MiningEventType.kt b/src/main/java/at/hannibal2/skyhanni/features/mining/eventtracker/MiningEventType.kt index b71f8431f97e..312f291de505 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/mining/eventtracker/MiningEventType.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/mining/eventtracker/MiningEventType.kt @@ -1,35 +1,147 @@ package at.hannibal2.skyhanni.features.mining.eventtracker import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.utils.ItemUtils +import at.hannibal2.skyhanni.utils.RenderUtils +import at.hannibal2.skyhanni.utils.StringUtils.allLettersFirstUppercase import at.hannibal2.skyhanni.utils.StringUtils.removeColor +import at.hannibal2.skyhanni.utils.renderables.Renderable +import at.hannibal2.skyhanni.utils.renderables.Renderable.Companion.darken +import net.minecraft.client.renderer.GlStateManager +import net.minecraft.init.Items +import net.minecraft.item.Item +import net.minecraft.item.ItemStack import kotlin.time.Duration import kotlin.time.Duration.Companion.minutes import kotlin.time.Duration.Companion.seconds +private fun Item.toItemStack(meta: Int = 0): ItemStack = ItemStack(this, 1, meta) + enum class MiningEventType( val eventName: String, private val shortName: String, val defaultLength: Duration, private val colourCode: Char, val dwarvenSpecific: Boolean, + iconInput: Renderable, ) { - GONE_WITH_THE_WIND("GONE WITH THE WIND", "Wind", 18.minutes, '9', false), - DOUBLE_POWDER("2X POWDER", "2x", 15.minutes, 'b', false), - GOBLIN_RAID("GOBLIN RAID", "Raid", 5.minutes, 'c', true), - BETTER_TOGETHER("BETTER TOGETHER", "Better", 18.minutes, 'd', false), - RAFFLE("RAFFLE", "Raffle", 160.seconds, '6', true), - MITHRIL_GOURMAND("MITHRIL GOURMAND", "Gourmand", 10.minutes, 'b', true), + GONE_WITH_THE_WIND("GONE WITH THE WIND", "Wind", 18.minutes, '9', false, object : Renderable { + override val width = 10 + override val height = 10 + override val horizontalAlign = RenderUtils.HorizontalAlignment.LEFT + override val verticalAlign = RenderUtils.VerticalAlignment.CENTER + + val compass = Renderable.itemStack(Items.compass.toItemStack(), 0.45) + val wind = Renderable.string("§9≈", scale = 0.75) + + override fun render(posX: Int, posY: Int) { + GlStateManager.translate(1f, 1f, -2f) + compass.render(posX, posY) + GlStateManager.translate(-1f, -2f, 2f) + wind.render(posX, posY) + GlStateManager.translate(0f, 1f, 0f) + } + }), + DOUBLE_POWDER("2X POWDER", "2x", 15.minutes, 'b', false, object : Renderable { + override val width = 10 + override val height = 10 + override val horizontalAlign = RenderUtils.HorizontalAlignment.LEFT + override val verticalAlign = RenderUtils.VerticalAlignment.CENTER + + val dyeGreen = Renderable.itemStack(Items.dye.toItemStack(10), 0.45) + val dyePink = Renderable.itemStack(Items.dye.toItemStack(9), 0.45) + + override fun render(posX: Int, posY: Int) { + GlStateManager.translate(1f, 0f, 0f) + dyePink.render(posX + 1, posY - 1) + GlStateManager.translate(-2f, 1.5f, 0f) + dyeGreen.render(posX, posY) + GlStateManager.translate(1f, -1.5f, 0f) + } + + }), + GOBLIN_RAID( + "GOBLIN RAID", "Raid", 5.minutes, 'c', true, ItemUtils.createSkull( + "Goblin", + "32518c29-6127-3c71-b2a7-be4c3251e76f", + "ewogICJ0aW1lc3RhbXAiIDogMTYwNzQ2NDg4MTMwOCwKICAicHJvZmlsZUlkIiA6ICJhMmY4MzQ1OTVjODk0YTI3YWRkMzA0OTcxNmNhOTEwYyIsCiAgInByb2ZpbGVOYW1lIiA6ICJiUHVuY2giLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTcyODUwOTA2YjdmMGQ5NTJjMGU1MDgwNzNjYzQzOWZkMzM3NGNjZjViODg5YzA2ZjdlOGQ5MGNjMGNjMjU1YyIKICAgIH0KICB9Cn0=" + ) + ), + BETTER_TOGETHER("BETTER TOGETHER", "Better", 18.minutes, 'd', false, object : Renderable { + override val width = 10 + override val height = 10 + override val horizontalAlign = RenderUtils.HorizontalAlignment.LEFT + override val verticalAlign = RenderUtils.VerticalAlignment.CENTER + + val steveHead = Renderable.itemStack(Items.skull.toItemStack(3), 0.36) + val alexHead = Renderable.itemStack( + ItemUtils.createSkull( + "Alex", + "6ab43178-89fd-4905-97f6-0f67d9d76fd9", + "fRBfVNlIWW6cL478st/8NsNEHVxjvwQDp4+MbKbFj1tPZvxXgpIXRaQsLeDl/0+E4tipPKNANAbmqj9EKAVx3b3gDqLLrTTk/NfuH2RD3I5ppzio8w5oYk1022SopaayGBP4+kuwktDHzlR8IgAUb1RiavldKp+TGRdCbqw8vHHBm9pnuOePzTOOADQgdanRj98bOcfIXe69tSS/VHxDe9tkpYFPkQR8zsJcjUxf+nS83iFU9CW9lKtQlyoU6/BPbHFILvcR1KDR5Imj7GJe2OJefghI6OqtHNZP2tzkia2IDU0Yc4ikwC+7yN3i6I3Do4G3gTtCZVfNXiSdFyU9nCMyBxggTaG9zaljZpN0BynG4FzYMujIVgeNa6FLqwoaFT0iELW2w9JgJFgyVlaDKEqMSGyxgqtcQMPBuvCwMFFjeFd2EhtfTjQ4hcpva+NXXoYPP7yfTk/0DErNZV2dUTasekar8lH6U58B7ECNxDUwcon4z7sSO5mdlPJoiT7zllgpwQn5NUPaxZxaKkGdUIFEGzjmBfnCmk6MOqzi05Rr18wnkdic9hz/fIzzTMhn9mbMG6VF9eBkE4mNu1K5jai6II5Mz9BV49U0ZcA874N1VHpJpQE6762TYv+u7ICTRIOf2LD9wEgu3py/nX+IHma5j22ClUtXH3hYdZmHg+s=\",Value:\"ewogICJ0aW1lc3RhbXAiIDogMTcxMTY1OTI2NDg1NSwKICAicHJvZmlsZUlkIiA6ICI2YWI0MzE3ODg5ZmQ0OTA1OTdmNjBmNjdkOWQ3NmZkOSIsCiAgInByb2ZpbGVOYW1lIiA6ICJNSEZfQWxleCIsCiAgInNpZ25hdHVyZVJlcXVpcmVkIiA6IHRydWUsCiAgInRleHR1cmVzIiA6IHsKICAgICJTS0lOIiA6IHsKICAgICAgInVybCIgOiAiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS84M2NlZTVjYTZhZmNkYjE3MTI4NWFhMDBlODA0OWMyOTdiMmRiZWJhMGVmYjhmZjk3MGE1Njc3YTFiNjQ0MDMyIiwKICAgICAgIm1ldGFkYXRhIiA6IHsKICAgICAgICAibW9kZWwiIDogInNsaW0iCiAgICAgIH0KICAgIH0KICB9Cn0=" + ), 0.36 + ) + + override fun render(posX: Int, posY: Int) { + GlStateManager.translate(-1f, 0f, 0f) + alexHead.render(posX, posY) + GlStateManager.translate(+4f, +3f, 0f) + steveHead.render(posX, posY) + GlStateManager.translate(-3f, -3f, 0f) + } + + }), + RAFFLE( + "RAFFLE", "Raffle", 160.seconds, '6', true, Items.name_tag.toItemStack() + ), + MITHRIL_GOURMAND("MITHRIL GOURMAND", "Gourmand", 10.minutes, 'b', true, Items.dye.toItemStack(6)), ; - override fun toString() = - if (config.compressedFormat) "§$colourCode$shortName" else "§$colourCode$eventName" + constructor( + eventName: String, + shortName: String, + defaultLength: Duration, + colourCode: Char, + dwarvenSpecific: Boolean, + iconInput: ItemStack, + ) : this( + eventName, shortName, defaultLength, colourCode, dwarvenSpecific, Renderable.itemStack( + iconInput, xSpacing = 0 + ) + ) + + val icon = Renderable.hoverTips(iconInput, listOf(eventName)) + val compactText = Renderable.string("§$colourCode$shortName") + val normalText = Renderable.string("§$colourCode$eventName") - fun toPastString() = - if (config.compressedFormat) "§7$shortName" else "§7$eventName" + val compactTextWithIcon = Renderable.horizontalContainer(listOf(icon, compactText), 0) + val normalTextWithIcon = Renderable.horizontalContainer(listOf(icon, normalText), 0) + + fun getRenderable(): Renderable = when (config.compressedFormat) { + CompressFormat.COMPACT_TEXT -> compactTextWithIcon + CompressFormat.ICON_ONLY -> icon + CompressFormat.TEXT_WITHOUT_ICON -> normalText + CompressFormat.COMPACT_TEXT_WITHOUT_ICON -> compactText + CompressFormat.DEFAULT, null -> normalTextWithIcon + } + + fun getRenderableAsPast(): Renderable = getRenderable().darken(0.4f) companion object { private val config get() = SkyHanniMod.feature.mining.miningEvent + enum class CompressFormat { + DEFAULT, + COMPACT_TEXT, + ICON_ONLY, + TEXT_WITHOUT_ICON, + COMPACT_TEXT_WITHOUT_ICON; + + override fun toString(): String { + return name.lowercase().allLettersFirstUppercase() + } + } + fun fromEventName(bossbarName: String): MiningEventType? { return MiningEventType.entries.find { it.eventName == bossbarName.removeColor() } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/DarkenShader.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/DarkenShader.kt new file mode 100644 index 000000000000..1a42522de49f --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/DarkenShader.kt @@ -0,0 +1,17 @@ +package at.hannibal2.skyhanni.features.misc + +import at.hannibal2.skyhanni.utils.shader.Shader +import at.hannibal2.skyhanni.utils.shader.Uniform + +object DarkenShader : Shader("darken", "darken") { + + val INSTANCE: DarkenShader + get() = this + + var darknessLevel = 0f + + override fun registerUniforms() { + registerUniform(Uniform.UniformType.FLOAT, "darknessLevel") { darknessLevel } + } +} + diff --git a/src/main/java/at/hannibal2/skyhanni/utils/ConfigUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/ConfigUtils.kt index 239f250a06ee..94d981d8ef61 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/ConfigUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/ConfigUtils.kt @@ -65,6 +65,19 @@ object ConfigUtils { return JsonPrimitive(getEnumConstantFromLegacyId(element.asInt, enumClass)?.name) } + /** + * Migrates a Boolean to an Enum Constant. + * + * @param element The JsonElement to migrate + * @param trueValue The enum value it should map to if the value is true + * @param falseValue The enum value it should map to if the value is false + * @return The migrated JsonElement + */ + fun > migrateBooleanToEnum(element: JsonElement, trueValue: T, falseValue: T): JsonElement { + require(element is JsonPrimitive) { "Expected a JsonPrimitive but got ${element.javaClass.simpleName}" } + return JsonPrimitive(if (element.asBoolean) trueValue.name else falseValue.name) + } + fun KMutableProperty0<*>.tryFindEditor(editor: MoulConfigEditor<*>): ProcessedOption? { return editor.processedConfig.getOptionFromField(this.javaField ?: return null) } diff --git a/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt b/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt index d893cef5294a..88b291844fab 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt @@ -7,6 +7,7 @@ import at.hannibal2.skyhanni.data.HighlightOnHoverSlot import at.hannibal2.skyhanni.data.ToolTipData import at.hannibal2.skyhanni.features.chroma.ChromaShaderManager import at.hannibal2.skyhanni.features.chroma.ChromaType +import at.hannibal2.skyhanni.features.misc.DarkenShader import at.hannibal2.skyhanni.utils.CollectionUtils.contains import at.hannibal2.skyhanni.utils.ColorUtils import at.hannibal2.skyhanni.utils.ColorUtils.darker @@ -23,7 +24,9 @@ import at.hannibal2.skyhanni.utils.renderables.RenderableUtils.calculateTableYOf import at.hannibal2.skyhanni.utils.renderables.RenderableUtils.renderXAligned import at.hannibal2.skyhanni.utils.renderables.RenderableUtils.renderXYAligned import at.hannibal2.skyhanni.utils.renderables.RenderableUtils.renderYAligned +import at.hannibal2.skyhanni.utils.shader.ShaderManager import io.github.notenoughupdates.moulconfig.gui.GuiScreenElementWrapper +import io.github.moulberry.notenoughupdates.util.Utils import net.minecraft.client.Minecraft import net.minecraft.client.gui.Gui import net.minecraft.client.gui.GuiIngameMenu @@ -327,6 +330,20 @@ interface Renderable { } } + fun Renderable.darken(amount: Float = 1.0f) = object : Renderable { + override val width = this@darken.width + override val height = this@darken.height + override val horizontalAlign = this@darken.horizontalAlign + override val verticalAlign = this@darken.verticalAlign + + override fun render(posX: Int, posY: Int) { + DarkenShader.darknessLevel = amount + ShaderManager.enableShader("darken") + this@darken.render(posX, posY) + ShaderManager.disableShader() + } + } + fun singeltonString(string: String): List { return Collections.singletonList(string(string)) } diff --git a/src/main/java/at/hannibal2/skyhanni/utils/shader/ShaderHelper.kt b/src/main/java/at/hannibal2/skyhanni/utils/shader/ShaderHelper.kt index fdc34f0ae4ff..89efd7d9f183 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/shader/ShaderHelper.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/shader/ShaderHelper.kt @@ -137,6 +137,10 @@ class ShaderHelper { if (USING_ARB_SHADERS) ARBShaderObjects.glUniform1fARB(location, v0) else GL20.glUniform1f(location, v0) } + fun glUniform1i(location: Int, v0: Int) { + if (USING_ARB_SHADERS) ARBShaderObjects.glUniform1iARB(location, v0) else GL20.glUniform1i(location, v0) + } + fun glUniform2f(location: Int, v0: Float, v1: Float) { if (USING_ARB_SHADERS) ARBShaderObjects.glUniform2fARB(location, v0, v1) else GL20.glUniform2f( location, diff --git a/src/main/java/at/hannibal2/skyhanni/utils/shader/ShaderManager.kt b/src/main/java/at/hannibal2/skyhanni/utils/shader/ShaderManager.kt index 3efcb0b77cf7..b32e3fa26dc3 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/shader/ShaderManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/shader/ShaderManager.kt @@ -2,6 +2,7 @@ package at.hannibal2.skyhanni.utils.shader import at.hannibal2.skyhanni.features.chroma.StandardChromaShader import at.hannibal2.skyhanni.features.chroma.TexturedChromaShader +import at.hannibal2.skyhanni.features.misc.DarkenShader import at.hannibal2.skyhanni.features.misc.RoundedRectangleOutlineShader import at.hannibal2.skyhanni.features.misc.RoundedRectangleShader import at.hannibal2.skyhanni.test.command.ErrorManager @@ -27,8 +28,11 @@ object ShaderManager { TEXTURED_CHROMA(TexturedChromaShader.INSTANCE), ROUNDED_RECTANGLE(RoundedRectangleShader.INSTANCE), ROUNDED_RECT_OUTLINE(RoundedRectangleOutlineShader.INSTANCE), + DARKEN(DarkenShader.INSTANCE) ; + fun enableShader() = ShaderManager.enableShader(name.lowercase()) + companion object { fun getShaderInstance(shaderName: String): Shader? = when (shaderName) { @@ -36,6 +40,7 @@ object ShaderManager { "textured_chroma" -> TEXTURED_CHROMA.shader "rounded_rect" -> ROUNDED_RECTANGLE.shader "rounded_rect_outline" -> ROUNDED_RECT_OUTLINE.shader + "darken" -> DARKEN.shader else -> { null } diff --git a/src/main/java/at/hannibal2/skyhanni/utils/shader/Uniform.kt b/src/main/java/at/hannibal2/skyhanni/utils/shader/Uniform.kt index 78f9ef569f35..e3adf2b4d23b 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/shader/Uniform.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/shader/Uniform.kt @@ -24,6 +24,7 @@ class Uniform( val VEC2: UniformType = UniformType() val VEC3: UniformType = UniformType() val BOOL: UniformType = UniformType() + val INT: UniformType = UniformType() } } @@ -49,6 +50,7 @@ class Uniform( } UniformType.BOOL -> ShaderHelper.glUniform1f(uniformID, if (newUniformValue as Boolean) 1f else 0f) + UniformType.INT -> ShaderHelper.glUniform1i(uniformID, (newUniformValue as Int)) } previousUniformValue = newUniformValue } diff --git a/src/main/resources/assets/skyhanni/shaders/darken.fsh b/src/main/resources/assets/skyhanni/shaders/darken.fsh new file mode 100644 index 000000000000..cfc118eefba6 --- /dev/null +++ b/src/main/resources/assets/skyhanni/shaders/darken.fsh @@ -0,0 +1,13 @@ +#version 120 + +// Fragment Shader +uniform sampler2D texture; +uniform float darknessLevel; + +varying vec4 outColor; + +void main() { + vec4 color = texture2D(texture, gl_TexCoord[0].st) * outColor; + vec3 darkenedColor = color.rgb * darknessLevel; + gl_FragColor = vec4(darkenedColor, color.a); +} diff --git a/src/main/resources/assets/skyhanni/shaders/darken.vsh b/src/main/resources/assets/skyhanni/shaders/darken.vsh new file mode 100644 index 000000000000..210bee8725f7 --- /dev/null +++ b/src/main/resources/assets/skyhanni/shaders/darken.vsh @@ -0,0 +1,9 @@ +#version 120 + +varying vec4 outColor; + +void main() { + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; + gl_TexCoord[0] = gl_MultiTexCoord0; + outColor = gl_Color; +} From 0ae9e19f99e329858acf1154735b9c32aa72e049 Mon Sep 17 00:00:00 2001 From: sayomaki Date: Thu, 30 May 2024 05:08:34 +0800 Subject: [PATCH 18/34] Feature: Show total amount of chocolate spent in chocolate shop (#1921) --- .../chocolatefactory/ChocolateShopPrice.kt | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateShopPrice.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateShopPrice.kt index bbd4e6747743..8152271fe7b5 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateShopPrice.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateShopPrice.kt @@ -15,8 +15,11 @@ import at.hannibal2.skyhanni.utils.NEUInternalName import at.hannibal2.skyhanni.utils.NEUItems.getPrice import at.hannibal2.skyhanni.utils.NEUItems.getPriceOrNull import at.hannibal2.skyhanni.utils.NumberUtil +import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators +import at.hannibal2.skyhanni.utils.NumberUtil.formatInt import at.hannibal2.skyhanni.utils.NumberUtil.million import at.hannibal2.skyhanni.utils.RegexUtils.groupOrNull +import at.hannibal2.skyhanni.utils.RegexUtils.matchFirst import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher import at.hannibal2.skyhanni.utils.RegexUtils.matches import at.hannibal2.skyhanni.utils.RenderUtils.renderRenderables @@ -40,11 +43,18 @@ object ChocolateShopPrice { "shop.bought", "§aYou bought §r§.(?[\\w ]+)§r(?:§8 x(?\\d+)§r)?§a!" ) + private val chocolateSpentPattern by ChocolateFactoryAPI.patternGroup.pattern( + "shop.spent", + "§7Chocolate Spent: §6(?[\\d,]+)" + ) var inInventory = false private var callUpdate = false var inventoryItems = emptyMap() + private const val MILESTONE_INDEX = 50 + private var chocolateSpent = 0 + @SubscribeEvent fun onSecondPassed(event: SecondPassedEvent) { if (inInventory) { @@ -74,8 +84,14 @@ object ChocolateShopPrice { private fun updateProducts() { val newProducts = mutableListOf() for ((slot, item) in inventoryItems) { - val lore = item.getLore() + + if (slot == MILESTONE_INDEX) { + lore.matchFirst(chocolateSpentPattern) { + chocolateSpent = group("amount").formatInt() + } + } + val chocolate = ChocolateFactoryAPI.getChocolateBuyCost(lore) ?: continue val internalName = item.getInternalName() val itemPrice = internalName.getPriceOrNull() ?: continue @@ -132,6 +148,8 @@ object ChocolateShopPrice { // TODO update this value every second // TODO add time until can afford newList.add(Renderable.string("§eChocolate available: §6${ChocolateAmount.CURRENT.formatted}")) + // TODO add chocolate spend needed for next milestone + newList.add(Renderable.string("§eChocolate spent: §6${chocolateSpent.addSeparators()}")) newList.add(LorenzUtils.fillTable(table, padding = 5, itemScale = config.itemScale)) display = newList } From 3abd085de6a31c24a92b05012a3b81e686065edc Mon Sep 17 00:00:00 2001 From: hannibal2 <24389977+hannibal00212@users.noreply.github.com> Date: Wed, 29 May 2024 23:09:00 +0200 Subject: [PATCH 19/34] code cleanup and added regex test --- .../chocolatefactory/ChocolateShopPrice.kt | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateShopPrice.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateShopPrice.kt index 8152271fe7b5..1d977d22d670 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateShopPrice.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateShopPrice.kt @@ -43,6 +43,9 @@ object ChocolateShopPrice { "shop.bought", "§aYou bought §r§.(?[\\w ]+)§r(?:§8 x(?\\d+)§r)?§a!" ) + /** + * REGEX-TEST: §7Chocolate Spent: §60 + */ private val chocolateSpentPattern by ChocolateFactoryAPI.patternGroup.pattern( "shop.spent", "§7Chocolate Spent: §6(?[\\d,]+)" @@ -143,15 +146,15 @@ object ChocolateShopPrice { ) } - val newList = mutableListOf() - newList.add(Renderable.string("§e§lCoins per million chocolate§f:")) - // TODO update this value every second - // TODO add time until can afford - newList.add(Renderable.string("§eChocolate available: §6${ChocolateAmount.CURRENT.formatted}")) - // TODO add chocolate spend needed for next milestone - newList.add(Renderable.string("§eChocolate spent: §6${chocolateSpent.addSeparators()}")) - newList.add(LorenzUtils.fillTable(table, padding = 5, itemScale = config.itemScale)) - display = newList + display = buildList { + add(Renderable.string("§e§lCoins per million chocolate§f:")) + // TODO update this value every second + // TODO add time until can afford + add(Renderable.string("§eChocolate available: §6${ChocolateAmount.CURRENT.formatted}")) + // TODO add chocolate spend needed for next milestone + add(Renderable.string("§eChocolate spent: §6${chocolateSpent.addSeparators()}")) + add(LorenzUtils.fillTable(table, padding = 5, itemScale = config.itemScale)) + } } @SubscribeEvent From 29ddd9d05a59c9540869c0f96648cda8ad9364df Mon Sep 17 00:00:00 2001 From: Thunderblade73 <85900443+Thunderblade73@users.noreply.github.com> Date: Wed, 29 May 2024 23:42:34 +0200 Subject: [PATCH 20/34] Feature: Moveable and Scaleable Hotbar (#1903) Co-authored-by: CalMWolfs <94038482+CalMWolfs@users.noreply.github.com> Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com> --- .../java/at/hannibal2/skyhanni/SkyHanniMod.kt | 2 + .../config/features/gui/GUIConfig.java | 5 +++ .../config/features/gui/HotbarConfig.java | 31 ++++++++++++++ .../skyhanni/features/gui/MovableHotBar.kt | 41 +++++++++++++++++++ 4 files changed, 79 insertions(+) create mode 100644 src/main/java/at/hannibal2/skyhanni/config/features/gui/HotbarConfig.java create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/MovableHotBar.kt diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt index 0374024e0d3c..794a7a568803 100644 --- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt +++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt @@ -251,6 +251,7 @@ import at.hannibal2.skyhanni.features.garden.visitor.NPCVisitorFix import at.hannibal2.skyhanni.features.garden.visitor.VisitorAPI import at.hannibal2.skyhanni.features.garden.visitor.VisitorListener import at.hannibal2.skyhanni.features.garden.visitor.VisitorRewardWarning +import at.hannibal2.skyhanni.features.gui.MovableHotBar import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardPattern import at.hannibal2.skyhanni.features.gui.quiver.QuiverDisplay @@ -532,6 +533,7 @@ class SkyHanniMod { loadModule(RenderData()) loadModule(GardenCropMilestones) loadModule(GardenCropMilestonesCommunityFix) + loadModule(MovableHotBar()) loadModule(GardenCropUpgrades) loadModule(VisitorListener()) loadModule(VisitorRewardWarning()) diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/gui/GUIConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/gui/GUIConfig.java index 1309780a8c72..b259fd26d703 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/gui/GUIConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/gui/GUIConfig.java @@ -61,6 +61,11 @@ public class GUIConfig { @Accordion public DiscordRPCConfig discordRPC = new DiscordRPCConfig(); + @Expose + @ConfigOption(name = "Hotbar", desc = "Settings for adjusting the hotbar") + @Accordion + public HotbarConfig hotbar = new HotbarConfig(); + @Expose @ConfigOption(name = "Marked Players", desc = "Players that got marked with §e/shmarkplayer§7.") @Accordion diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/gui/HotbarConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/gui/HotbarConfig.java new file mode 100644 index 000000000000..e13c18a8d71c --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/config/features/gui/HotbarConfig.java @@ -0,0 +1,31 @@ +package at.hannibal2.skyhanni.config.features.gui; + +import at.hannibal2.skyhanni.config.FeatureToggle; +import at.hannibal2.skyhanni.config.core.config.Position; +import com.google.gson.annotations.Expose; +import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean; +import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorInfoText; +import io.github.notenoughupdates.moulconfig.annotations.ConfigLink; +import io.github.notenoughupdates.moulconfig.annotations.ConfigOption; + +public class HotbarConfig { + + @Expose + @ConfigOption(name = "Editable", desc = "Adds the hotbar to the gui editor. Allows for moving and scaling of the hotbar.") + @ConfigEditorBoolean + @FeatureToggle + public boolean editable = false; + + @ConfigOption(name = "§cNotice", desc = "This option will be §c§lincompatible §r§7with mods that change the hotbar. Eg: §eApec§7.") + @ConfigEditorInfoText + public String notice = ""; + + @Expose + @ConfigLink(owner = HotbarConfig.class, field = "editable") + public Position hotbar = new Position(20, 20); + + @Expose + @ConfigOption(name = "Show Outside Skyblock", desc = "Enables the hotbar to be edited even outside of SkyBlock.") + @ConfigEditorBoolean + public boolean showOutsideSkyblock = false; +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/MovableHotBar.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/MovableHotBar.kt new file mode 100644 index 000000000000..37a86eb2262c --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/gui/MovableHotBar.kt @@ -0,0 +1,41 @@ +package at.hannibal2.skyhanni.features.gui + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.data.GuiEditManager +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.RenderUtils.transform +import net.minecraft.client.Minecraft +import net.minecraft.client.renderer.GlStateManager +import net.minecraftforge.client.event.RenderGameOverlayEvent +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +class MovableHotBar { + + private val config get() = SkyHanniMod.feature.gui.hotbar + + private var post = false + + @SubscribeEvent + fun onRenderHotbar(event: RenderGameOverlayEvent.Pre) { + if (event.type != RenderGameOverlayEvent.ElementType.HOTBAR || !isEnabled()) return + post = true + GlStateManager.pushMatrix() + val scaled = event.resolution + val x = scaled.scaledWidth / 2 - 91 + val y = scaled.scaledHeight - 22 + config.hotbar.transform() + GlStateManager.translate(-x.toFloat(), -y.toFloat(), 0f) // Must be after transform to work with scaling + GuiEditManager.add(config.hotbar, "Hotbar", 182 - 1, 22 - 1) // -1 since the editor for some reason add +1 + } + + @SubscribeEvent + fun onRenderHotbar(event: RenderGameOverlayEvent.Post) { + if (event.type != RenderGameOverlayEvent.ElementType.HOTBAR || !post) return + GlStateManager.popMatrix() + post = false + } + + fun isEnabled(): Boolean = + (LorenzUtils.inSkyBlock || (Minecraft.getMinecraft().thePlayer != null && config.showOutsideSkyblock)) + && config.editable +} From bd8c3ac5b05c60e36969406de3f6d9df7601161c Mon Sep 17 00:00:00 2001 From: Empa <42304516+ItsEmpa@users.noreply.github.com> Date: Thu, 30 May 2024 08:25:13 +0200 Subject: [PATCH 21/34] Backend: Remove LorenzUtils.runDelayed (#1778) Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com> --- .../skyhanni/features/garden/GardenLevelDisplay.kt | 4 ++-- .../skyhanni/features/mining/MiningNotifications.kt | 4 ++-- .../java/at/hannibal2/skyhanni/utils/LorenzUtils.kt | 10 ---------- 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenLevelDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenLevelDisplay.kt index a60ebc7ff66d..7bdf46dd0e6f 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenLevelDisplay.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenLevelDisplay.kt @@ -10,11 +10,11 @@ import at.hannibal2.skyhanni.events.LorenzToolTipEvent import at.hannibal2.skyhanni.events.ProfileJoinEvent import at.hannibal2.skyhanni.utils.ChatUtils import at.hannibal2.skyhanni.utils.ConditionalUtils +import at.hannibal2.skyhanni.utils.DelayedRun import at.hannibal2.skyhanni.utils.HypixelCommands import at.hannibal2.skyhanni.utils.InventoryUtils import at.hannibal2.skyhanni.utils.ItemUtils.getLore import at.hannibal2.skyhanni.utils.ItemUtils.name -import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators import at.hannibal2.skyhanni.utils.NumberUtil.format import at.hannibal2.skyhanni.utils.NumberUtil.formatLong @@ -91,7 +91,7 @@ class GardenLevelDisplay { if (!config.overflowChat) return val newLevel = GardenAPI.getGardenLevel() if (newLevel != oldLevel + 1 || newLevel <= 15) return - LorenzUtils.runDelayed(50.milliseconds) { + DelayedRun.runDelayed(50.milliseconds) { // TODO utils function that is shared with Crop Milestone Display ChatUtils.clickableChat( " \n§b§lGARDEN LEVEL UP §8$oldLevel ➜ §b$newLevel\n" + diff --git a/src/main/java/at/hannibal2/skyhanni/features/mining/MiningNotifications.kt b/src/main/java/at/hannibal2/skyhanni/features/mining/MiningNotifications.kt index 370fd1815417..e3168e4b10cb 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/mining/MiningNotifications.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/mining/MiningNotifications.kt @@ -11,9 +11,9 @@ import at.hannibal2.skyhanni.events.ConfigLoadEvent import at.hannibal2.skyhanni.events.LorenzChatEvent import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent import at.hannibal2.skyhanni.utils.ConditionalUtils +import at.hannibal2.skyhanni.utils.DelayedRun import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland -import at.hannibal2.skyhanni.utils.LorenzUtils.runDelayed import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName import at.hannibal2.skyhanni.utils.PrimitiveItemStack.Companion.makePrimitiveStack import at.hannibal2.skyhanni.utils.RegexUtils.matches @@ -83,7 +83,7 @@ object MiningNotifications { sendNotification(MiningNotificationList.COLD) } if (IslandType.MINESHAFT.isInIsland() && config.getAscensionRope && config.coldAmount == event.cold) { - runDelayed(0.5.seconds) { + DelayedRun.runDelayed(0.5.seconds) { GetFromSackAPI.getFromChatMessageSackItems(ASCENSION_ROPE) } } diff --git a/src/main/java/at/hannibal2/skyhanni/utils/LorenzUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/LorenzUtils.kt index 2a351a7d99b1..0dc0047a55b3 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/LorenzUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/LorenzUtils.kt @@ -34,8 +34,6 @@ import java.text.DecimalFormat import java.text.SimpleDateFormat import java.time.LocalDate import java.time.Month -import java.util.Timer -import java.util.TimerTask import java.util.regex.Matcher import kotlin.time.Duration import kotlin.time.Duration.Companion.seconds @@ -309,14 +307,6 @@ object LorenzUtils { fun Int.ignoreDerpy() = if (isDerpy) this * 2 else this - fun runDelayed(duration: Duration, runnable: () -> Unit) { - Timer().schedule(object : TimerTask() { - override fun run() { - runnable() - } - }, duration.inWholeMilliseconds) - } - val JsonPrimitive.asIntOrNull get() = takeIf { it.isNumber }?.asInt fun sendTitle(text: String, duration: Duration, height: Double = 1.8, fontSize: Float = 4f) { From 1b45880779262ddfb01c7f18975e4890c4f20511 Mon Sep 17 00:00:00 2001 From: CalMWolfs <94038482+CalMWolfs@users.noreply.github.com> Date: Thu, 30 May 2024 16:26:37 +1000 Subject: [PATCH 22/34] Fix: Ct Crash (#1932) --- .../skyhanni/mixins/transformers/gui/MixinGuiScreen.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/at/hannibal2/skyhanni/mixins/transformers/gui/MixinGuiScreen.java b/src/main/java/at/hannibal2/skyhanni/mixins/transformers/gui/MixinGuiScreen.java index dee6be23e6c0..b14d225cf180 100644 --- a/src/main/java/at/hannibal2/skyhanni/mixins/transformers/gui/MixinGuiScreen.java +++ b/src/main/java/at/hannibal2/skyhanni/mixins/transformers/gui/MixinGuiScreen.java @@ -21,7 +21,7 @@ public void renderToolTip(ItemStack stack, int x, int y, CallbackInfo ci) { } @Inject(method = "renderToolTip", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;getRarity()Lnet/minecraft/item/EnumRarity;", shift = At.Shift.AFTER), locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true) - public void getTooltip(ItemStack stack, int x, int y, CallbackInfo ci, List list, int i) { + public void getTooltip(ItemStack stack, int x, int y, CallbackInfo ci, List list) { ToolTipData.getTooltip(stack, list); if (list.isEmpty()) { ci.cancel(); From 47b1fdce5577204bfef7a34dfe25af7374909ef6 Mon Sep 17 00:00:00 2001 From: appable Date: Wed, 29 May 2024 23:56:36 -0700 Subject: [PATCH 23/34] Feature: mark duplicate egg locations (#1929) Co-authored-by: Cal Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com> --- .../features/event/HoppityEggsConfig.java | 18 ++++++ .../storage/ProfileSpecificStorage.java | 5 ++ .../event/hoppity/HoppityEggLocator.kt | 57 ++++++++++++------- .../event/hoppity/HoppityEggsManager.kt | 18 ++++++ .../hoppity/HoppityUniqueEggLocations.kt | 40 +++++++++++++ 5 files changed, 118 insertions(+), 20 deletions(-) create mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityUniqueEggLocations.kt diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/event/HoppityEggsConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/event/HoppityEggsConfig.java index 345b3fb830aa..5361991e1ebc 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/event/HoppityEggsConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/event/HoppityEggsConfig.java @@ -38,12 +38,30 @@ public class HoppityEggsConfig { @ConfigEditorBoolean public boolean showAllWaypoints = false; + @Expose + @ConfigOption(name = "Mark Duplicate Locations", desc = "Marks egg location waypoints which you have already found in red.") + @ConfigEditorBoolean + @FeatureToggle + public boolean highlightDuplicateEggLocations = false; + + @Expose + @ConfigOption(name = "Mark Nearby Duplicates", desc = "Always show duplicate egg locations when nearby.") + @ConfigEditorBoolean + @FeatureToggle + public boolean showNearbyDuplicateEggLocations = false; + @Expose @ConfigOption(name = "Show Unclaimed Eggs", desc = "Displays which eggs haven't been found in the last SkyBlock day.") @ConfigEditorBoolean @FeatureToggle public boolean showClaimedEggs = false; + @Expose + @ConfigOption(name = "Show Collected Locations", desc = "Shows the number of found egg locations on this island. §eThis is not retroactive and may not be fully synced with Hypixel's count.") + @ConfigEditorBoolean + @FeatureToggle + public boolean showCollectedLocationCount = false; + @Expose @ConfigOption(name = "Warn When Unclaimed", desc = "Warn when all three eggs are ready to be found.") @ConfigEditorBoolean diff --git a/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java b/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java index e25d725ec37c..747d5c116e6d 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java +++ b/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java @@ -1,6 +1,7 @@ package at.hannibal2.skyhanni.config.storage; import at.hannibal2.skyhanni.api.SkillAPI; +import at.hannibal2.skyhanni.data.IslandType; import at.hannibal2.skyhanni.data.MaxwellAPI; import at.hannibal2.skyhanni.data.model.ComposterUpgrade; import at.hannibal2.skyhanni.features.combat.endernodetracker.EnderNodeTracker; @@ -41,6 +42,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; public class ProfileSpecificStorage { @@ -128,6 +130,9 @@ public static class PositionChange { @Expose public Map rabbitCounts = new HashMap(); + @Expose + public Map> collectedEggLocations = new HashMap(); + @Expose public Integer hoppityShopYearOpened = null; } diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggLocator.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggLocator.kt index 012532f3bfed..6b1f605076a9 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggLocator.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggLocator.kt @@ -14,6 +14,7 @@ import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactor import at.hannibal2.skyhanni.test.GriffinUtils.drawWaypointFilled import at.hannibal2.skyhanni.utils.InventoryUtils import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName +import at.hannibal2.skyhanni.utils.LocationUtils.distanceToPlayer import at.hannibal2.skyhanni.utils.LorenzColor import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.LorenzUtils.round @@ -21,6 +22,7 @@ import at.hannibal2.skyhanni.utils.LorenzVec import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName import at.hannibal2.skyhanni.utils.RecalculatingValue import at.hannibal2.skyhanni.utils.RenderUtils.draw3DLine +import at.hannibal2.skyhanni.utils.RenderUtils.drawColor import at.hannibal2.skyhanni.utils.RenderUtils.drawDynamicText import at.hannibal2.skyhanni.utils.RenderUtils.exactPlayerEyeLocation import at.hannibal2.skyhanni.utils.SimpleTimeMark @@ -99,15 +101,10 @@ object HoppityEggLocator { } } } + if (drawLocations) { for ((index, eggLocation) in possibleEggLocations.withIndex()) { - val eggLabel = "§aGuess #${index + 1}" - event.drawWaypointFilled( - eggLocation, - LorenzColor.GREEN.toColor(), - seeThroughBlocks = true, - ) - event.drawDynamicText(eggLocation.add(y = 1), eggLabel, 1.5) + drawEggWaypoint(event, eggLocation, "§aGuess #${index + 1}") if (config.showLine) { event.draw3DLine(eyeLocation, eggLocation.add(0.5, 0.5, 0.5), LorenzColor.GREEN.toColor(), 2, false) } @@ -117,27 +114,47 @@ object HoppityEggLocator { sharedEggLocation?.let { if (config.sharedWaypoints) { - event.drawWaypointFilled(it, LorenzColor.GREEN.toColor(), seeThroughBlocks = true,) - event.drawDynamicText(it.add(y = 1), "§aShared Egg", 1.5) + drawEggWaypoint(event, it, "§aShared Egg") return } } - if (!config.showAllWaypoints) return - if (hasLocatorInHotbar()) return - if (!HoppityEggType.eggsRemaining()) return - val islandEggsLocations = getCurrentIslandEggLocations() ?: return - for (eggLocation in islandEggsLocations) { - event.drawWaypointFilled( - eggLocation, - LorenzColor.GREEN.toColor(), - seeThroughBlocks = true, - ) - event.drawDynamicText(eggLocation.add(y = 1), "§aEgg", 1.5) + + if (shouldShowAllEggs()) { + for (eggLocation in islandEggsLocations) { + drawEggWaypoint(event, eggLocation, "§aEgg") + } + return } + + if (config.highlightDuplicateEggLocations && config.showNearbyDuplicateEggLocations) { + for (eggLocation in islandEggsLocations) { + val dist = eggLocation.distanceToPlayer() + if (dist < 10 && HoppityUniqueEggLocations.hasCollectedEgg(eggLocation)) { + val alpha = ((10 - dist) / 10).coerceAtMost(0.5).toFloat() + event.drawColor(eggLocation, LorenzColor.RED, false, alpha) + event.drawDynamicText(eggLocation.add(y = 1), "§cDuplicate Location!", 1.5) + } + } + } + } + + private fun drawEggWaypoint(event: LorenzRenderWorldEvent, location: LorenzVec, label: String) { + val shouldMarkDuplicate = config.highlightDuplicateEggLocations + && HoppityUniqueEggLocations.hasCollectedEgg(location) + val possibleDuplicateLabel = if (shouldMarkDuplicate) "$label §c(Duplicate Location)" else label + if (!shouldMarkDuplicate) { + event.drawWaypointFilled(location, LorenzColor.GREEN.toColor(), seeThroughBlocks = true) + } else { + event.drawColor(location, LorenzColor.RED.toColor(), false, 0.5f) + } + event.drawDynamicText(location.add(y = 1), possibleDuplicateLabel, 1.5) } + private fun shouldShowAllEggs() = + config.showAllWaypoints && !hasLocatorInHotbar() && HoppityEggType.eggsRemaining() + fun eggFound() { resetData() } 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 c085fcf16881..0660268db15a 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 @@ -108,6 +108,7 @@ object HoppityEggsManager { HoppityEggsCompactChat.handleChat(event) eggFoundPattern.matchMatcher(event.message) { + HoppityUniqueEggLocations.saveNearestEgg() HoppityEggLocator.eggFound() val meal = getEggType(event) val note = group("note").removeColor() @@ -188,11 +189,28 @@ object HoppityEggsManager { .map { "§7 - ${it.formattedName} ${it.timeUntil().format()}" } .toMutableList() displayList.add(0, "§bUnclaimed Eggs:") + + if (config.showCollectedLocationCount) { + val totalEggs = HoppityEggLocator.getCurrentIslandEggLocations()?.size + if (totalEggs != null) { + val collectedEggs = HoppityUniqueEggLocations.collectedEggsThisIsland() + val collectedFormat = formatEggsCollected(collectedEggs) + displayList.add("§7Locations: $collectedFormat$collectedEggs§7/§a$totalEggs") + } + } if (displayList.size == 1) return config.position.renderStrings(displayList, posLabel = "Hoppity Eggs") } + private fun formatEggsCollected(collectedEggs: Int): String = + when (collectedEggs) { + in 0 until 5 -> "§c" + in 5 until 10 -> "§6" + in 10 until 15 -> "§e" + else -> "§a" + } + @SubscribeEvent fun onSecondPassed(event: SecondPassedEvent) { if (!isActive()) return diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityUniqueEggLocations.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityUniqueEggLocations.kt new file mode 100644 index 000000000000..161cff80e44d --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityUniqueEggLocations.kt @@ -0,0 +1,40 @@ +package at.hannibal2.skyhanni.features.event.hoppity + +import at.hannibal2.skyhanni.data.IslandType +import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryAPI +import at.hannibal2.skyhanni.test.command.ErrorManager +import at.hannibal2.skyhanni.utils.LocationUtils +import at.hannibal2.skyhanni.utils.LocationUtils.distanceSqToPlayer +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.LorenzVec + +object HoppityUniqueEggLocations { + + private val collectedEggLocations: MutableMap>? + get() = ChocolateFactoryAPI.profileStorage?.collectedEggLocations + + private fun getCurrentIslandCollectedEggs(): MutableSet? = + collectedEggLocations?.getOrPut(LorenzUtils.skyBlockIsland) { mutableSetOf() } + + fun saveNearestEgg() { + val location = HoppityEggLocator.getCurrentIslandEggLocations() + ?.minByOrNull { it.distanceSqToPlayer() } ?: return + if (location.distanceSqToPlayer() > 100) { + ErrorManager.skyHanniError( + "Player far from any known egg location!", + "island" to LorenzUtils.skyBlockIsland, + "distanceSqToPlayer" to location.distanceSqToPlayer(), + "playerLocation" to LocationUtils.playerLocation(), + "closestKnownEgg" to location, + ) + } + + getCurrentIslandCollectedEggs()?.add(location) + } + + fun collectedEggsThisIsland() = getCurrentIslandCollectedEggs()?.size ?: 0 + + fun hasCollectedEgg(location: LorenzVec) = + getCurrentIslandCollectedEggs()?.contains(location) ?: false + +} From 294aad229547eb645e96ad9f847f03dbcee56dab Mon Sep 17 00:00:00 2001 From: hannibal2 <24389977+hannibal002@users.noreply.github.com> Date: Thu, 30 May 2024 09:02:50 +0200 Subject: [PATCH 24/34] =?UTF-8?q?Fixed=20compact=20chat=20breaking=20somet?= =?UTF-8?q?imes=20when=20obtaining=20legendary=20or=20hig=E2=80=A6=20(#192?= =?UTF-8?q?3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com> --- .../features/event/hoppity/HoppityEggsCompactChat.kt | 7 +++++-- .../skyhanni/features/event/hoppity/HoppityEggsManager.kt | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggsCompactChat.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggsCompactChat.kt index cfe229871de7..dc0c3b6ffc98 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggsCompactChat.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggsCompactChat.kt @@ -6,6 +6,7 @@ import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactor import at.hannibal2.skyhanni.utils.ChatUtils import at.hannibal2.skyhanni.utils.DelayedRun import at.hannibal2.skyhanni.utils.NumberUtil +import at.hannibal2.skyhanni.utils.RegexUtils.groupOrNull import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher import at.hannibal2.skyhanni.utils.SimpleTimeMark.Companion.fromNow import at.hannibal2.skyhanni.utils.TimeUtils.format @@ -84,10 +85,12 @@ object HoppityEggsCompactChat { compactChat(event) } HoppityEggsManager.newRabbitFound.matchMatcher(event.message) { - val chocolate = group("chocolate") + val chocolate = groupOrNull("chocolate") val perSecond = group("perSecond") newRabbit = true - lastProfit = "§6+$chocolate §7and §6+${perSecond}x c/s!" + lastProfit = chocolate?.let { + "§6+$it §7and §6+${perSecond}x c/s!" + } ?: "§6+${perSecond}x c/s!" compactChat(event) } } 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 0660268db15a..f6332219e1b6 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 @@ -45,6 +45,7 @@ object HoppityEggsManager { /** * REGEX-TEST: §D§LHOPPITY'S HUNT §7You found §fArnie §7(§F§LCOMMON§7)! * REGEX-TEST: §D§LHOPPITY'S HUNT §7You found §aPenelope §7(§A§LUNCOMMON§7)! + * REGEX-TEST: §D§LHOPPITY'S HUNT §7You found §6Solomon §7(§6§LLEGENDARY§7)! */ val rabbitFoundPattern by ChocolateFactoryAPI.patternGroup.pattern( "rabbit.found", @@ -53,6 +54,7 @@ object HoppityEggsManager { /** * REGEX-TEST: §d§lNEW RABBIT! §6+2 Chocolate §7and §6+0.003x Chocolate §7per second! + * REGEX-TEST: §d§lNEW RABBIT! §6+0.02x Chocolate §7per second! */ val newRabbitFound by ChocolateFactoryAPI.patternGroup.pattern( "rabbit.found.new", From a12bd4e2a0450c6ee739b05713d70e8fa497dc72 Mon Sep 17 00:00:00 2001 From: hannibal2 <24389977+hannibal00212@users.noreply.github.com> Date: Thu, 30 May 2024 09:08:31 +0200 Subject: [PATCH 25/34] extract render code into more functions --- .../event/hoppity/HoppityEggLocator.kt | 91 +++++++++++-------- 1 file changed, 51 insertions(+), 40 deletions(-) diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggLocator.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggLocator.kt index 6b1f605076a9..c358d36185ee 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggLocator.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggLocator.kt @@ -80,41 +80,16 @@ object HoppityEggLocator { fun onRenderWorld(event: LorenzRenderWorldEvent) { if (!isEnabled()) return - val eyeLocation = event.exactPlayerEyeLocation() - - if (config.waypointsImmediately && lastClick.passedSince() < 5.seconds) { - lastParticlePositionForever?.let { - if (lastChange.passedSince() < 300.milliseconds) { - if (eyeLocation.distance(it) > 2) { - event.drawWaypointFilled( - it, - LorenzColor.GREEN.toColor(), - seeThroughBlocks = true, - ) - event.drawDynamicText(it.add(y = 1), "§aGuess", 1.5) - } - if (!drawLocations) { - if (config.showLine) { - event.draw3DLine(eyeLocation, it.add(0.5, 0.5, 0.5), LorenzColor.GREEN.toColor(), 2, false) - } - } - } - } - } + event.drawGuessImmediately() if (drawLocations) { - for ((index, eggLocation) in possibleEggLocations.withIndex()) { - drawEggWaypoint(event, eggLocation, "§aGuess #${index + 1}") - if (config.showLine) { - event.draw3DLine(eyeLocation, eggLocation.add(0.5, 0.5, 0.5), LorenzColor.GREEN.toColor(), 2, false) - } - } + event.drawGuessLocations() return } sharedEggLocation?.let { if (config.sharedWaypoints) { - drawEggWaypoint(event, it, "§aShared Egg") + event.drawEggWaypoint(it, "§aShared Egg") return } } @@ -123,33 +98,69 @@ object HoppityEggLocator { if (shouldShowAllEggs()) { for (eggLocation in islandEggsLocations) { - drawEggWaypoint(event, eggLocation, "§aEgg") + event.drawEggWaypoint(eggLocation, "§aEgg") } return } - if (config.highlightDuplicateEggLocations && config.showNearbyDuplicateEggLocations) { - for (eggLocation in islandEggsLocations) { - val dist = eggLocation.distanceToPlayer() - if (dist < 10 && HoppityUniqueEggLocations.hasCollectedEgg(eggLocation)) { - val alpha = ((10 - dist) / 10).coerceAtMost(0.5).toFloat() - event.drawColor(eggLocation, LorenzColor.RED, false, alpha) - event.drawDynamicText(eggLocation.add(y = 1), "§cDuplicate Location!", 1.5) + event.drawDuplicateEggs(islandEggsLocations) + } + + private fun LorenzRenderWorldEvent.drawGuessLocations() { + val eyeLocation = exactPlayerEyeLocation() + for ((index, eggLocation) in possibleEggLocations.withIndex()) { + drawEggWaypoint(eggLocation, "§aGuess #${index + 1}") + if (config.showLine) { + draw3DLine(eyeLocation, eggLocation.add(0.5, 0.5, 0.5), LorenzColor.GREEN.toColor(), 2, false) + } + } + } + + private fun LorenzRenderWorldEvent.drawDuplicateEggs(islandEggsLocations: List, ) { + if (!config.highlightDuplicateEggLocations || !config.showNearbyDuplicateEggLocations) return + for (eggLocation in islandEggsLocations) { + val dist = eggLocation.distanceToPlayer() + if (dist < 10 && HoppityUniqueEggLocations.hasCollectedEgg(eggLocation)) { + val alpha = ((10 - dist) / 10).coerceAtMost(0.5).toFloat() + drawColor(eggLocation, LorenzColor.RED, false, alpha) + drawDynamicText(eggLocation.add(y = 1), "§cDuplicate Location!", 1.5) + } + } + } + + private fun LorenzRenderWorldEvent.drawGuessImmediately() { + if (config.waypointsImmediately && lastClick.passedSince() < 5.seconds) { + lastParticlePositionForever?.let { + if (lastChange.passedSince() < 300.milliseconds) { + val eyeLocation = exactPlayerEyeLocation() + if (eyeLocation.distance(it) > 2) { + drawWaypointFilled( + it, + LorenzColor.GREEN.toColor(), + seeThroughBlocks = true, + ) + drawDynamicText(it.add(y = 1), "§aGuess", 1.5) + } + if (!drawLocations) { + if (config.showLine) { + draw3DLine(eyeLocation, it.add(0.5, 0.5, 0.5), LorenzColor.GREEN.toColor(), 2, false) + } + } } } } } - private fun drawEggWaypoint(event: LorenzRenderWorldEvent, location: LorenzVec, label: String) { + private fun LorenzRenderWorldEvent.drawEggWaypoint(location: LorenzVec, label: String) { val shouldMarkDuplicate = config.highlightDuplicateEggLocations && HoppityUniqueEggLocations.hasCollectedEgg(location) val possibleDuplicateLabel = if (shouldMarkDuplicate) "$label §c(Duplicate Location)" else label if (!shouldMarkDuplicate) { - event.drawWaypointFilled(location, LorenzColor.GREEN.toColor(), seeThroughBlocks = true) + drawWaypointFilled(location, LorenzColor.GREEN.toColor(), seeThroughBlocks = true) } else { - event.drawColor(location, LorenzColor.RED.toColor(), false, 0.5f) + drawColor(location, LorenzColor.RED.toColor(), false, 0.5f) } - event.drawDynamicText(location.add(y = 1), possibleDuplicateLabel, 1.5) + drawDynamicText(location.add(y = 1), possibleDuplicateLabel, 1.5) } private fun shouldShowAllEggs() = From b2733f13841363c9417c0eb79d7240990eb36bcb Mon Sep 17 00:00:00 2001 From: CalMWolfs <94038482+CalMWolfs@users.noreply.github.com> Date: Thu, 30 May 2024 18:01:24 +1000 Subject: [PATCH 26/34] Backend: Make skyhanni ReplaceItemEvent (#1866) Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com> Co-authored-by: hannibal2 <24389977+hannibal002@users.noreply.github.com> --- .github/workflows/illegal-imports.txt | 1 + .../events/render/gui/ReplaceItemEvent.kt | 31 +++++++++++++++++++ .../garden/inventory/plots/GardenPlotIcon.kt | 12 +++---- .../garden/visitor/GardenVisitorSupercraft.kt | 6 ++-- .../AuctionHouseOpenPriceWebsite.kt | 6 ++-- .../bazaar/BazaarOpenPriceWebsite.kt | 6 ++-- .../ChocolateFactoryShortcut.kt | 6 ++-- .../features/mining/DeepCavernsGuide.kt | 6 ++-- .../features/misc/limbo/LimboPlaytime.kt | 6 ++-- .../rift/everywhere/EnigmaSoulWaypoints.kt | 6 ++-- .../transformers/gui/MixinInventoryBasic.java | 22 +++++++++++++ 11 files changed, 81 insertions(+), 27 deletions(-) create mode 100644 src/main/java/at/hannibal2/skyhanni/events/render/gui/ReplaceItemEvent.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/mixins/transformers/gui/MixinInventoryBasic.java diff --git a/.github/workflows/illegal-imports.txt b/.github/workflows/illegal-imports.txt index 4b09e1826651..7c3d58b77d74 100644 --- a/.github/workflows/illegal-imports.txt +++ b/.github/workflows/illegal-imports.txt @@ -7,3 +7,4 @@ at/hannibal2/skyhanni/ scala. at/hannibal2/skyhanni/ jline. at/hannibal2/skyhanni/ io.github.moulberry.notenoughupdates.util.Constants at/hannibal2/skyhanni/ io.github.moulberry.notenoughupdates.events.SlotClickEvent +at/hannibal2/skyhanni/ io.github.moulberry.notenoughupdates.events.ReplaceItemEvent diff --git a/src/main/java/at/hannibal2/skyhanni/events/render/gui/ReplaceItemEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/render/gui/ReplaceItemEvent.kt new file mode 100644 index 000000000000..ca2f2efbb6f4 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/events/render/gui/ReplaceItemEvent.kt @@ -0,0 +1,31 @@ +package at.hannibal2.skyhanni.events.render.gui + +import at.hannibal2.skyhanni.events.LorenzEvent +import net.minecraft.inventory.IInventory +import net.minecraft.inventory.InventoryBasic +import net.minecraft.item.ItemStack +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable + +class ReplaceItemEvent(val inventory: IInventory, val originalItem: ItemStack, val slot: Int) : LorenzEvent() { + var replacement: ItemStack? = null + private set + + fun replace(replacement: ItemStack?) { + this.replacement = replacement + } + + companion object { + @JvmStatic + fun postEvent( + inventory: InventoryBasic, + inventoryContents: Array, + slot: Int, + cir: CallbackInfoReturnable, + ) { + val originalItem = inventoryContents.getOrNull(slot) ?: return + val event = ReplaceItemEvent(inventory, originalItem, slot) + event.postAndCatch() + event.replacement?.let { cir.returnValue = it } + } + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/inventory/plots/GardenPlotIcon.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/inventory/plots/GardenPlotIcon.kt index 45a55824eff5..130de69264f8 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/inventory/plots/GardenPlotIcon.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/inventory/plots/GardenPlotIcon.kt @@ -4,12 +4,12 @@ import at.hannibal2.skyhanni.events.GuiContainerEvent import at.hannibal2.skyhanni.events.InventoryCloseEvent import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent import at.hannibal2.skyhanni.events.LorenzToolTipEvent +import at.hannibal2.skyhanni.events.render.gui.ReplaceItemEvent import at.hannibal2.skyhanni.features.garden.GardenAPI import at.hannibal2.skyhanni.utils.ChatUtils import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName import at.hannibal2.skyhanni.utils.ItemUtils.getLore import at.hannibal2.skyhanni.utils.NEUItems.getItemStack -import io.github.moulberry.notenoughupdates.events.ReplaceItemEvent import io.github.moulberry.notenoughupdates.util.Utils import net.minecraft.client.player.inventory.ContainerLocalMenu import net.minecraft.init.Items @@ -70,15 +70,15 @@ object GardenPlotIcon { } if (event.inventory is ContainerLocalMenu) { - if (event.slotNumber == 53) { - event.replaceWith(editStack) + if (event.slot == 53) { + event.replace(editStack) } - if (plotList.isNotEmpty() && plotList.contains(event.slotNumber)) { - if (lastClickedSlotId == event.slotNumber) { + if (plotList.isNotEmpty() && plotList.contains(event.slot)) { + if (lastClickedSlotId == event.slot) { lastClickedSlotId = -1 return } - event.replaceWith(cachedStack[event.slotNumber]) + event.replace(cachedStack[event.slot]) } } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorSupercraft.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorSupercraft.kt index 8fe8bee3c41f..406f85298d54 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorSupercraft.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorSupercraft.kt @@ -4,6 +4,7 @@ import at.hannibal2.skyhanni.data.SackAPI.getAmountInSacks import at.hannibal2.skyhanni.events.GuiContainerEvent import at.hannibal2.skyhanni.events.InventoryCloseEvent import at.hannibal2.skyhanni.events.garden.visitor.VisitorOpenEvent +import at.hannibal2.skyhanni.events.render.gui.ReplaceItemEvent import at.hannibal2.skyhanni.test.command.ErrorManager import at.hannibal2.skyhanni.utils.HypixelCommands import at.hannibal2.skyhanni.utils.ItemUtils.itemName @@ -14,7 +15,6 @@ import at.hannibal2.skyhanni.utils.NEUItems.allIngredients import at.hannibal2.skyhanni.utils.NEUItems.getItemStack import at.hannibal2.skyhanni.utils.SimpleTimeMark import at.hannibal2.skyhanni.utils.StringUtils.removeColor -import io.github.moulberry.notenoughupdates.events.ReplaceItemEvent import io.github.moulberry.notenoughupdates.util.Utils import net.minecraft.entity.player.InventoryPlayer import net.minecraftforge.fml.common.eventhandler.EventPriority @@ -95,8 +95,8 @@ class GardenVisitorSupercraft { if (!hasIngredients) return if (event.inventory is InventoryPlayer) return - if (event.slotNumber == 31) { - event.replaceWith(superCraftItem) + if (event.slot == 31) { + event.replace(superCraftItem) } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/auctionhouse/AuctionHouseOpenPriceWebsite.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/auctionhouse/AuctionHouseOpenPriceWebsite.kt index e28361188771..bc3d52a7f389 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/auctionhouse/AuctionHouseOpenPriceWebsite.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/auctionhouse/AuctionHouseOpenPriceWebsite.kt @@ -4,6 +4,7 @@ import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.events.GuiContainerEvent import at.hannibal2.skyhanni.events.InventoryCloseEvent import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent +import at.hannibal2.skyhanni.events.render.gui.ReplaceItemEvent import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName import at.hannibal2.skyhanni.utils.NEUItems.getItemStack @@ -11,7 +12,6 @@ import at.hannibal2.skyhanni.utils.OSUtils import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher import at.hannibal2.skyhanni.utils.SimpleTimeMark import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern -import io.github.moulberry.notenoughupdates.events.ReplaceItemEvent import io.github.moulberry.notenoughupdates.util.Utils import net.minecraft.entity.player.InventoryPlayer import net.minecraft.item.ItemStack @@ -65,9 +65,9 @@ class AuctionHouseOpenPriceWebsite { if (!isEnabled()) return if (event.inventory is InventoryPlayer) return - if (event.slotNumber == 8) { + if (event.slot == 8) { displayItem?.let { - event.replaceWith(it) + event.replace(it) } } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/bazaar/BazaarOpenPriceWebsite.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/bazaar/BazaarOpenPriceWebsite.kt index 395df582efbf..2e680450d549 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/bazaar/BazaarOpenPriceWebsite.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/bazaar/BazaarOpenPriceWebsite.kt @@ -2,12 +2,12 @@ package at.hannibal2.skyhanni.features.inventory.bazaar import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.events.GuiContainerEvent +import at.hannibal2.skyhanni.events.render.gui.ReplaceItemEvent import at.hannibal2.skyhanni.utils.NEUInternalName import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName import at.hannibal2.skyhanni.utils.NEUItems.getItemStack import at.hannibal2.skyhanni.utils.OSUtils import at.hannibal2.skyhanni.utils.SimpleTimeMark -import io.github.moulberry.notenoughupdates.events.ReplaceItemEvent import io.github.moulberry.notenoughupdates.util.Utils import net.minecraft.entity.player.InventoryPlayer import net.minecraftforge.fml.common.eventhandler.EventPriority @@ -36,8 +36,8 @@ class BazaarOpenPriceWebsite { BazaarApi.currentlyOpenedProduct ?: return if (event.inventory is InventoryPlayer) return - if (event.slotNumber == 22) { - event.replaceWith(item) + if (event.slot == 22) { + event.replace(item) } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryShortcut.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryShortcut.kt index d3bb031b2a0d..2e0f85edf487 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryShortcut.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryShortcut.kt @@ -4,11 +4,11 @@ import at.hannibal2.skyhanni.data.IslandType import at.hannibal2.skyhanni.events.GuiContainerEvent import at.hannibal2.skyhanni.events.InventoryCloseEvent import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent +import at.hannibal2.skyhanni.events.render.gui.ReplaceItemEvent import at.hannibal2.skyhanni.utils.HypixelCommands import at.hannibal2.skyhanni.utils.ItemUtils import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.SimpleTimeMark -import io.github.moulberry.notenoughupdates.events.ReplaceItemEvent import net.minecraft.client.player.inventory.ContainerLocalMenu import net.minecraftforge.fml.common.eventhandler.EventPriority import net.minecraftforge.fml.common.eventhandler.SubscribeEvent @@ -53,8 +53,8 @@ class ChocolateFactoryShortcut { @SubscribeEvent fun replaceItem(event: ReplaceItemEvent) { - if (event.inventory is ContainerLocalMenu && showItem && event.slotNumber == 15) { - event.replaceWith(item) + if (event.inventory is ContainerLocalMenu && showItem && event.slot == 15) { + event.replace(item) } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/mining/DeepCavernsGuide.kt b/src/main/java/at/hannibal2/skyhanni/features/mining/DeepCavernsGuide.kt index 94bb86d0359c..52549bee66db 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/mining/DeepCavernsGuide.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/mining/DeepCavernsGuide.kt @@ -11,6 +11,7 @@ import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent import at.hannibal2.skyhanni.events.IslandChangeEvent import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent import at.hannibal2.skyhanni.events.RepositoryReloadEvent +import at.hannibal2.skyhanni.events.render.gui.ReplaceItemEvent import at.hannibal2.skyhanni.utils.ChatUtils import at.hannibal2.skyhanni.utils.ColorUtils.toChromaColor import at.hannibal2.skyhanni.utils.ConditionalUtils @@ -19,7 +20,6 @@ import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName import at.hannibal2.skyhanni.utils.NEUItems.getItemStack import at.hannibal2.skyhanni.utils.ParkourHelper -import io.github.moulberry.notenoughupdates.events.ReplaceItemEvent import io.github.moulberry.notenoughupdates.util.Utils import net.minecraft.client.player.inventory.ContainerLocalMenu import net.minecraftforge.fml.common.eventhandler.EventPriority @@ -123,8 +123,8 @@ class DeepCavernsGuide { @SubscribeEvent fun replaceItem(event: ReplaceItemEvent) { if (show) return - if (event.inventory is ContainerLocalMenu && showStartIcon && event.slotNumber == 49) { - event.replaceWith(startIcon) + if (event.inventory is ContainerLocalMenu && showStartIcon && event.slot == 49) { + event.replace(startIcon) } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/limbo/LimboPlaytime.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/limbo/LimboPlaytime.kt index d5a8a3765373..2698c0e943cd 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/limbo/LimboPlaytime.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/limbo/LimboPlaytime.kt @@ -4,6 +4,7 @@ import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.data.ProfileStorageData import at.hannibal2.skyhanni.events.InventoryOpenEvent import at.hannibal2.skyhanni.events.LorenzToolTipEvent +import at.hannibal2.skyhanni.events.render.gui.ReplaceItemEvent import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.LorenzUtils.round import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName @@ -12,7 +13,6 @@ import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators import at.hannibal2.skyhanni.utils.RegexUtils.matches import at.hannibal2.skyhanni.utils.SimpleTimeMark import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern -import io.github.moulberry.notenoughupdates.events.ReplaceItemEvent import io.github.moulberry.notenoughupdates.util.Utils import net.minecraft.client.player.inventory.ContainerLocalMenu import net.minecraft.item.ItemStack @@ -50,7 +50,7 @@ object LimboPlaytime { if (!enabled) return if (event.inventory !is ContainerLocalMenu) return if (event.inventory.name != "Detailed /playtime") return - if (event.slotNumber != 43) return + if (event.slot != 43) return val playtime = storage?.playtime ?: 0 if (playtime < 60) return @@ -62,7 +62,7 @@ object LimboPlaytime { *createItemLore() ) } - event.replaceWith(limboItem) + event.replace(limboItem) } private fun createItemLore(): Array = when { diff --git a/src/main/java/at/hannibal2/skyhanni/features/rift/everywhere/EnigmaSoulWaypoints.kt b/src/main/java/at/hannibal2/skyhanni/features/rift/everywhere/EnigmaSoulWaypoints.kt index 01a16b6df4da..2f8ed7e1ae1e 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/rift/everywhere/EnigmaSoulWaypoints.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/rift/everywhere/EnigmaSoulWaypoints.kt @@ -7,6 +7,7 @@ import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent import at.hannibal2.skyhanni.events.LorenzChatEvent import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent import at.hannibal2.skyhanni.events.RepositoryReloadEvent +import at.hannibal2.skyhanni.events.render.gui.ReplaceItemEvent import at.hannibal2.skyhanni.features.rift.RiftAPI import at.hannibal2.skyhanni.test.GriffinUtils.drawWaypointFilled import at.hannibal2.skyhanni.utils.ChatUtils @@ -20,7 +21,6 @@ import at.hannibal2.skyhanni.utils.NEUItems.getItemStack import at.hannibal2.skyhanni.utils.RenderUtils.drawDynamicText import at.hannibal2.skyhanni.utils.RenderUtils.highlight import at.hannibal2.skyhanni.utils.StringUtils.removeColor -import io.github.moulberry.notenoughupdates.events.ReplaceItemEvent import io.github.moulberry.notenoughupdates.util.Utils import net.minecraft.client.gui.inventory.GuiChest import net.minecraft.client.player.inventory.ContainerLocalMenu @@ -53,8 +53,8 @@ object EnigmaSoulWaypoints { if (!isEnabled()) return if (inventoryUnfound.isEmpty()) return - if (event.inventory is ContainerLocalMenu && inInventory && event.slotNumber == 31) { - event.replaceWith(item) + if (event.inventory is ContainerLocalMenu && inInventory && event.slot == 31) { + event.replace(item) } } diff --git a/src/main/java/at/hannibal2/skyhanni/mixins/transformers/gui/MixinInventoryBasic.java b/src/main/java/at/hannibal2/skyhanni/mixins/transformers/gui/MixinInventoryBasic.java new file mode 100644 index 000000000000..7fdb2d604877 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/mixins/transformers/gui/MixinInventoryBasic.java @@ -0,0 +1,22 @@ +package at.hannibal2.skyhanni.mixins.transformers.gui; + +import at.hannibal2.skyhanni.events.render.gui.ReplaceItemEvent; +import net.minecraft.inventory.InventoryBasic; +import net.minecraft.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(InventoryBasic.class) +public class MixinInventoryBasic { + + @Shadow + private ItemStack[] inventoryContents; + + @Inject(method = "getStackInSlot", at = @At("HEAD"), cancellable = true) + public void getStackInSlot(int index, CallbackInfoReturnable cir) { + ReplaceItemEvent.postEvent((InventoryBasic) (Object) this, this.inventoryContents, index, cir); + } +} From 6b0e324c96073d824c12dff1629a782352155e99 Mon Sep 17 00:00:00 2001 From: Thunderblade73 <85900443+Thunderblade73@users.noreply.github.com> Date: Thu, 30 May 2024 11:21:50 +0200 Subject: [PATCH 27/34] Feature: Hotm Features + Hotm API/Data (#1059) Co-authored-by: J10a1n15 <45315647+j10a1n15@users.noreply.github.com> Co-authored-by: Empa <42304516+ItsEmpa@users.noreply.github.com> Co-authored-by: martimavocado <39881008+martimavocado@users.noreply.github.com> Co-authored-by: martimavocado Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com> --- .../java/at/hannibal2/skyhanni/SkyHanniMod.kt | 4 + .../java/at/hannibal2/skyhanni/api/HotmAPI.kt | 117 ++++ .../config/features/mining/HotmConfig.java | 27 + .../config/features/mining/MiningConfig.java | 4 + .../storage/ProfileSpecificStorage.java | 23 + .../at/hannibal2/skyhanni/data/HotmData.kt | 612 ++++++++++++++++++ .../data/jsonobjects/local/HotmTree.kt | 29 + .../skyhanni/events/DebugDataCollectEvent.kt | 2 +- .../gui/customscoreboard/ScoreboardPattern.kt | 11 +- .../skyhanni/features/mining/HotmFeatures.kt | 53 ++ .../hannibal2/skyhanni/utils/LorenzColor.kt | 11 + .../at/hannibal2/skyhanni/utils/RegexUtils.kt | 7 + 12 files changed, 898 insertions(+), 2 deletions(-) create mode 100644 src/main/java/at/hannibal2/skyhanni/api/HotmAPI.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/config/features/mining/HotmConfig.java create mode 100644 src/main/java/at/hannibal2/skyhanni/data/HotmData.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/data/jsonobjects/local/HotmTree.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/mining/HotmFeatures.kt diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt index 794a7a568803..79728810c93f 100644 --- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt +++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt @@ -30,6 +30,7 @@ import at.hannibal2.skyhanni.data.GuiData import at.hannibal2.skyhanni.data.GuiEditManager import at.hannibal2.skyhanni.data.GuildAPI import at.hannibal2.skyhanni.data.HighlightOnHoverSlot +import at.hannibal2.skyhanni.data.HotmData import at.hannibal2.skyhanni.data.HypixelData import at.hannibal2.skyhanni.data.ItemAddManager import at.hannibal2.skyhanni.data.ItemClickData @@ -308,6 +309,7 @@ import at.hannibal2.skyhanni.features.mining.ColdOverlay import at.hannibal2.skyhanni.features.mining.DeepCavernsGuide import at.hannibal2.skyhanni.features.mining.GoldenGoblinHighlight import at.hannibal2.skyhanni.features.mining.HighlightMiningCommissionMobs +import at.hannibal2.skyhanni.features.mining.HotmFeatures import at.hannibal2.skyhanni.features.mining.KingTalismanHelper import at.hannibal2.skyhanni.features.mining.MiningCommissionsBlocksColor import at.hannibal2.skyhanni.features.mining.MiningNotifications @@ -571,6 +573,7 @@ class SkyHanniMod { loadModule(ChatUtils) loadModule(FixedRateTimerManager()) loadModule(ChromaManager) + loadModule(HotmData) loadModule(ContributorManager) loadModule(TabComplete) loadModule(HypixelBazaarFetcher) @@ -715,6 +718,7 @@ class SkyHanniMod { loadModule(StatsTuning()) loadModule(NonGodPotEffectDisplay()) loadModule(SoopyGuessBurrow()) + loadModule(HotmFeatures()) loadModule(DianaProfitTracker) loadModule(DianaFixChat()) loadModule(MythologicalCreatureTracker) diff --git a/src/main/java/at/hannibal2/skyhanni/api/HotmAPI.kt b/src/main/java/at/hannibal2/skyhanni/api/HotmAPI.kt new file mode 100644 index 000000000000..a9940670dab2 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/api/HotmAPI.kt @@ -0,0 +1,117 @@ +package at.hannibal2.skyhanni.api + +import at.hannibal2.skyhanni.data.HotmData +import at.hannibal2.skyhanni.data.ProfileStorageData +import at.hannibal2.skyhanni.utils.InventoryUtils +import at.hannibal2.skyhanni.utils.ItemCategory +import at.hannibal2.skyhanni.utils.ItemUtils.getItemCategoryOrNull +import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName +import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getDrillUpgrades +import at.hannibal2.skyhanni.utils.StringUtils.firstLetterUppercase +import at.hannibal2.skyhanni.utils.TimeLimitedCache +import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern +import net.minecraft.item.ItemStack +import kotlin.time.Duration.Companion.seconds + +object HotmAPI { + + fun copyCurrentTree() = HotmData.storage?.deepCopy() + + val activeMiningAbility get() = HotmData.abilities.firstOrNull { it.enabled } + + private val blueGoblinEgg = "GOBLIN_OMELETTE_BLUE_CHEESE".asInternalName() + + private val blueEggCache = TimeLimitedCache(10.0.seconds) + val isBlueEggActive + get() = InventoryUtils.getItemInHand()?.let { + blueEggCache.getOrPut(it) { + it.getItemCategoryOrNull() == ItemCategory.DRILL && it.getDrillUpgrades() + ?.contains(blueGoblinEgg) == true + } + } == true + + enum class Powder() { + MITHRIL, + GEMSTONE, + GLACITE, + + ; + + val lowName = name.lowercase().firstLetterUppercase() + + val heartPattern by RepoPattern.pattern( + "inventory.${name.lowercase()}.heart", + "§7$lowName Powder: §a§.(?[\\d,]+)" + ) + val resetPattern by RepoPattern.pattern( + "inventory.${name.lowercase()}.reset", + "\\s+§8- §.(?[\\d,]+) $lowName Powder" + ) + + fun pattern(isHeart: Boolean) = if (isHeart) heartPattern else resetPattern + + fun getStorage() = ProfileStorageData.profileSpecific?.mining?.powder?.get(this) + + fun getCurrent() = getStorage()?.available ?: 0L + + fun setCurrent(value: Long) { + getStorage()?.available = value + } + + fun addCurrent(value: Long) { + setCurrent(getCurrent() + value) + } + + fun getTotal() = getStorage()?.total ?: 0L + + fun setTotal(value: Long) { + getStorage()?.total = value + } + + fun addTotal(value: Long) { + setTotal(getTotal() + value) + } + + /** Use when new powder gets collected*/ + fun gain(value: Long) { + addTotal(value) + addCurrent(value) + } + + fun reset() { + setCurrent(0) + setTotal(0) + } + } + + var skymall: SkymallPerk? = null + + var mineshaftMayhem: MayhemPerk? = null + + enum class SkymallPerk(chat: String, itemString: String) { + MINING_SPEED("Gain §r§a+100 §r§6⸕ Mining Speed§r§f.", "Gain §a+100 §6⸕ Mining Speed§7."), + MINING_FORTUNE("Gain §r§a+50 §r§6☘ Mining Fortune§r§f.", "Gain §a+50 §6☘ Mining Fortune§7."), + EXTRA_POWDER("Gain §r§a+15% §r§fmore Powder while mining.", "Gain §a+15% §7more Powder while mining."), + ABILITY_COOLDOWN("Reduce Pickaxe Ability cooldown by §r§a20%§r§f.", "Reduce Pickaxe Ability cooldown by"), + GOBLIN_CHANCE("§r§a10x §r§fchance to find Golden and Diamond Goblins.", "§a10x §7chance to find Golden and"), + TITANIUM("Gain §r§a5x §r§9Titanium §r§fdrops", "Gain §a+15% §7more Powder while mining.") + ; + + private val patternName = name.lowercase().replace("_", ".") + + val chatPattern by RepoPattern.pattern("mining.hotm.skymall.chat.$patternName", chat) + val itemPattern by RepoPattern.pattern("mining.hotm.skymall.item.$patternName", itemString) + } + + enum class MayhemPerk(chat: String) { + SCRAP_CHANCE("Your §r§9Suspicious Scrap §r§7chance was buffed by your §r§aMineshaft Mayhem §r§7perk!"), + MINING_FORTUNE("You received a §r§a§r§6☘ Mining Fortune §r§7buff from your §r§aMineshaft Mayhem §r§7perk!"), + MINING_SPEED("You received a §r§a§r§6⸕ Mining Speed §r§7buff from your §r§aMineshaft Mayhem §r§7perk!"), + COLD_RESISTANCE("You received a §r§a§r§b❄ Cold Resistance §r§7buff from your §r§aMineshaft Mayhem §r§7perk!"), + ABILITY_COOLDOWN("Your Pickaxe Ability cooldown was reduced §r§7from your §r§aMineshaft Mayhem §r§7perk!"); + + private val patternName = name.lowercase().replace("_", ".") + + val chatPattern by RepoPattern.pattern("mining.hotm.mayhem.chat.$patternName", chat) + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/mining/HotmConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/mining/HotmConfig.java new file mode 100644 index 000000000000..cbe7d0be07ce --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/config/features/mining/HotmConfig.java @@ -0,0 +1,27 @@ +package at.hannibal2.skyhanni.config.features.mining; + +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 HotmConfig { + + @Expose + @ConfigOption(name = "Enabled Highlight", desc = "Highlights enabled perks in the hotm tree green and disabled red. Not unlocked perks are highlighted gray.") + @ConfigEditorBoolean + @FeatureToggle + public boolean highlightEnabledPerks = true; + + @Expose + @ConfigOption(name = "Level Stack", desc = "Shows the level of a perk as item stacks.") + @ConfigEditorBoolean + @FeatureToggle + public boolean levelStackSize = true; + + @Expose + @ConfigOption(name = "Token Stack", desc = "Shows unused tokens on the heart.") + @ConfigEditorBoolean + @FeatureToggle + public boolean tokenStackSize = true; +} diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/mining/MiningConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/mining/MiningConfig.java index 9c4af3882f17..05ad3fb2784e 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/mining/MiningConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/mining/MiningConfig.java @@ -13,6 +13,10 @@ public class MiningConfig { @Category(name = "Mining Event Tracker", desc = "Settings for the Mining Event Tracker") public MiningEventConfig miningEvent = new MiningEventConfig(); + @Expose + @Category(name = "HotM", desc = "Settings for Heart of the Mountain") + public HotmConfig hotm = new HotmConfig(); + @Expose @ConfigOption(name = "Powder Tracker", desc = "") @Accordion diff --git a/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java b/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java index 747d5c116e6d..d73e707ab69c 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java +++ b/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java @@ -1,8 +1,10 @@ package at.hannibal2.skyhanni.config.storage; +import at.hannibal2.skyhanni.api.HotmAPI; import at.hannibal2.skyhanni.api.SkillAPI; import at.hannibal2.skyhanni.data.IslandType; import at.hannibal2.skyhanni.data.MaxwellAPI; +import at.hannibal2.skyhanni.data.jsonobjects.local.HotmTree; import at.hannibal2.skyhanni.data.model.ComposterUpgrade; import at.hannibal2.skyhanni.features.combat.endernodetracker.EnderNodeTracker; import at.hannibal2.skyhanni.features.combat.ghostcounter.GhostData; @@ -490,6 +492,27 @@ public static class MiningConfig { @Expose public ExcavatorProfitTracker.Data fossilExcavatorProfitTracker = new ExcavatorProfitTracker.Data(); + + @Expose + public HotmTree hotmTree = new HotmTree(); + + @Expose + public Map powder = new HashMap<>(); + + public static class PowderStorage { + + @Expose + public Long available; + + @Expose + public Long total; + } + + @Expose + public int tokens; + + @Expose + public int availableTokens; } @Expose diff --git a/src/main/java/at/hannibal2/skyhanni/data/HotmData.kt b/src/main/java/at/hannibal2/skyhanni/data/HotmData.kt new file mode 100644 index 000000000000..f23795acdfaf --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/data/HotmData.kt @@ -0,0 +1,612 @@ +package at.hannibal2.skyhanni.data + +import at.hannibal2.skyhanni.api.HotmAPI +import at.hannibal2.skyhanni.api.HotmAPI.MayhemPerk +import at.hannibal2.skyhanni.api.HotmAPI.SkymallPerk +import at.hannibal2.skyhanni.config.storage.ProfileSpecificStorage +import at.hannibal2.skyhanni.data.jsonobjects.local.HotmTree +import at.hannibal2.skyhanni.events.DebugDataCollectEvent +import at.hannibal2.skyhanni.events.InventoryCloseEvent +import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent +import at.hannibal2.skyhanni.events.IslandChangeEvent +import at.hannibal2.skyhanni.events.LorenzChatEvent +import at.hannibal2.skyhanni.events.ProfileJoinEvent +import at.hannibal2.skyhanni.events.ScoreboardChangeEvent +import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardPattern +import at.hannibal2.skyhanni.test.command.ErrorManager +import at.hannibal2.skyhanni.utils.ChatUtils +import at.hannibal2.skyhanni.utils.ConditionalUtils.transformIf +import at.hannibal2.skyhanni.utils.DelayedRun +import at.hannibal2.skyhanni.utils.InventoryUtils +import at.hannibal2.skyhanni.utils.ItemUtils.getLore +import at.hannibal2.skyhanni.utils.ItemUtils.name +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators +import at.hannibal2.skyhanni.utils.NumberUtil.formatLong +import at.hannibal2.skyhanni.utils.RegexUtils.indexOfFirstMatch +import at.hannibal2.skyhanni.utils.RegexUtils.matchFirst +import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher +import at.hannibal2.skyhanni.utils.RegexUtils.matches +import at.hannibal2.skyhanni.utils.StringUtils.allLettersFirstUppercase +import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern +import net.minecraft.inventory.Slot +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import kotlin.math.ceil +import kotlin.math.floor +import kotlin.math.pow + +enum class HotmData( + guiName: String, + val maxLevel: Int, + val costFun: ((Int) -> (Double?)), + val rewardFun: ((Int) -> (Map)), +) { + + MINING_SPEED("Mining Speed", + 50, + { currentLevel -> (currentLevel + 2.0).pow(3) }, + { level -> mapOf(HotmReward.MINING_SPEED to level * 20.0) }), + MINING_FORTUNE("Mining Fortune", + 50, + { currentLevel -> (currentLevel + 2.0).pow(3.05) }, + { level -> mapOf(HotmReward.MINING_FORTUNE to level * 5.0) }), + QUICK_FORGE("Quick Forge", + 20, + { currentLevel -> (currentLevel + 2.0).pow(4) }, + { level -> mapOf(HotmReward.FORGE_TIME_DECREASE to 10.0 + (level * 0.5)) }), + TITANIUM_INSANIUM("Titanium Insanium", + 50, + { currentLevel -> (currentLevel + 2.0).pow(3.1) }, + { level -> mapOf(HotmReward.TITANIUM_CHANCE to 2.0 + (level * 0.1)) }), + DAILY_POWDER("Daily Powder", + 100, + { currentLevel -> 200.0 + (currentLevel * 18.0) }, + { level -> mapOf(HotmReward.DAILY_POWDER to (200.0 + ((level - 1.0) * 18.0)) * 2.0) }), + LUCK_OF_THE_CAVE("Luck of the Cave", + 45, + { currentLevel -> (currentLevel + 2.0).pow(3.07) }, + { level -> mapOf(HotmReward.EXTRA_CHANCE_TRIGGER_RARE_OCCURRENCES to 5.0 + level) }), + CRYSTALLIZED("Crystallized", 30, { currentLevel -> (currentLevel + 2.0).pow(3.4) }, { level -> + mapOf( + HotmReward.MINING_SPEED to 20.0 + ((level - 1.0) * 6.0), + HotmReward.MINING_FORTUNE to 20.0 + ((level - 1.0) * 5.0) + ) + }), + EFFICIENT_MINER("Efficient Miner", + 100, + { currentLevel -> (currentLevel + 2.0).pow(2.6) }, + { level -> mapOf(HotmReward.AVERAGE_BLOCK_BREAKS to (10.0 + (level * 0.4)) * (1.0 + (level * 0.05))) }), + ORBITER("Orbiter", + 80, + { currentLevel -> (currentLevel + 1.0) * 70.0 }, + { level -> mapOf(HotmReward.CHANCE_EXTRA_XP_ORBS to 0.2 + (level * 0.01)) }), + SEASONED_MINEMAN("Seasoned Mineman", + 100, + { currentLevel -> (currentLevel + 2.0).pow(2.3) }, + { level -> mapOf(HotmReward.MINING_WISDOM to 5.0 + (level * 0.1)) }), + MOLE("Mole", + 190, + { currentLevel -> (currentLevel + 2.0).pow(2.2) }, + { level -> mapOf(HotmReward.AVERAGE_BLOCK_BREAKS to 1.0 + ((level + 9.0) * 0.05 * ((level + 8) % 20))) }), + PROFESSIONAL("Professional", + 140, + { currentLevel -> (currentLevel + 2.0).pow(2.3) }, + { level -> mapOf(HotmReward.MINING_SPEED to 50.0 + (level * 5.0)) }), + LONESOME_MINER("Lonesome Miner", + 45, + { currentLevel -> (currentLevel + 2.0).pow(3.07) }, + { level -> mapOf(HotmReward.COMBAT_STAT_BOOST to 5.0 + ((level - 1.0) * 0.5)) }), + GREAT_EXPLORER("Great Explorer", 20, { currentLevel -> (currentLevel + 2.0).pow(4.0) }, { level -> + mapOf( + HotmReward.CHANCE_OF_TREASURE_CHEST to (0.2 * (0.2 + 0.04 * (level - 1.0))), + HotmReward.LOCKS_OF_TREASURE_CHEST to 1 + level * 0.2 + ) + }), + FORTUNATE("Fortunate", + 20, + { currentLevel -> (currentLevel + 1.0).pow(3.05) }, + { level -> mapOf(HotmReward.MINING_FORTUNE to 20.0 + (level * 4.0)) }), + POWDER_BUFF("Powder Buff", 50, { currentLevel -> (currentLevel + 1.0).pow(3.2) }, { level -> + mapOf( + HotmReward.MORE_MITHRIL_POWER to level.toDouble(), HotmReward.MORE_GEMSTONE_POWER to level.toDouble() + ) + }), + MINING_SPEED_II("Mining Speed II", + 50, + { currentLevel -> (currentLevel + 2.0).pow(3.2) }, + { level -> mapOf(HotmReward.MINING_SPEED to level * 40.0) }), + MINING_FORTUNE_II("Mining Fortune II", + 50, + { currentLevel -> (currentLevel + 2.0).pow(3.2) }, + { level -> mapOf(HotmReward.MINING_FORTUNE to level * 5.0) }), + + // Static + + MINING_MADNESS("Mining Madness", 1, { null }, { + mapOf( + HotmReward.MINING_SPEED to 50.0, HotmReward.MINING_FORTUNE to 50.0 + ) + }), + SKY_MALL("Sky Mall", 1, { null }, { emptyMap() }), + PRECISION_MINING("Precision Mining", 1, { null }, { mapOf(HotmReward.MINING_SPEED_BOOST to 30.0) }), + FRONT_LOADED("Front Loaded", 1, { null }, { + mapOf( + HotmReward.MINING_SPEED to 100.0, + HotmReward.MINING_FORTUNE to 100.0, + HotmReward.MORE_BASE_MITHRIL_POWER to 2.0, + HotmReward.MORE_BASE_GEMSTONE_POWER to 2.0 + ) + }), + STAR_POWDER("Star Powder", 1, { null }, { mapOf(HotmReward.MORE_MITHRIL_POWER to 300.0) }), + GOBLIN_KILLER("Goblin Killer", 1, { null }, { emptyMap() }), + + // Abilities + + PICKOBULUS("Pickobulus", 3, { null }, { level -> + mapOf( + HotmReward.ABILITY_RADIUS to ceil(level * 0.5) + 1.0, + HotmReward.ABILITY_COOLDOWN to 130.0 - 10.0 * level + ) + }), + MINING_SPEED_BOOST("Mining Speed Boost", 3, { null }, { level -> + mapOf( + HotmReward.ABILITY_DURATION to level + 1.0, HotmReward.ABILITY_COOLDOWN to 10.0 + 5.0 * level + ) + }), + VEIN_SEEKER("Vein Seeker", 3, { null }, { level -> + mapOf( + HotmReward.ABILITY_RADIUS to level + 1.0, + HotmReward.ABILITY_DURATION to 10.0 + 2.0 * level, + HotmReward.ABILITY_COOLDOWN to 60.0 + ) + }), + MANIAC_MINER("Maniac Miner", 3, { null }, { level -> + mapOf( + HotmReward.ABILITY_DURATION to 5.0 + level * 5.0, HotmReward.ABILITY_COOLDOWN to 60.0 - level + ) + }), + + PEAK_OF_THE_MOUNTAIN("Peak of the Mountain", 10, { null }, { emptyMap() }), + + // Mining V3 + DAILY_GRIND("Daily Grind", + 100, + { currentLevel -> 218.0 + (18.0 * (currentLevel - 2.0)) }, + { level -> mapOf(HotmReward.DAILY_POWDER to 50.0 * level) }), + DUST_COLLECTOR( + "Dust Collector", + 20, + { currentLevel -> (currentLevel + 1.0).pow(4) }, + { level -> mapOf(HotmReward.FOSSIL_DUST to 1.0 * level) }), + WARM_HEARTED("Warm Hearted", + 50, + { currentLevel -> floor((currentLevel + 1.0).pow(3.1)) }, + { level -> mapOf(HotmReward.COLD_RESISTANCE to 0.2 * level) }), + + STRONG_ARM("Strong Arm", + 100, + { currentLevel -> floor((currentLevel + 1.0).pow(2.3)) }, + { level -> mapOf(HotmReward.MINING_SPEED to 5.0 * level) }), + NO_STONE_UNTURNED("No Stone Unturned", + 50, + { currentLevel -> floor((currentLevel + 1.0).pow(3.05)) }, + { level -> mapOf(HotmReward.UNKNOWN to 0.5 * level) }), + + SUB_ZERO_MINING("SubZero Mining", + 100, + { currentLevel -> floor((currentLevel + 1.0).pow(2.3)) }, + { level -> mapOf(HotmReward.MINING_FORTUNE to 1.0 * level) }), + SURVEYOR("Surveyor", + 20, + { currentLevel -> (currentLevel + 1.0).pow(4) }, + { level -> mapOf(HotmReward.UNKNOWN to 0.75 * level) }), + EAGER_ADVENTURER("Eager Adventurer", + 100, + { currentLevel -> floor((currentLevel + 1.0).pow(2.3)) }, + { level -> mapOf(HotmReward.MINING_SPEED to 2.0 * level) }), + + DEAD_MANS_CHEST("Dead Man's Chest", + 50, + { currentLevel -> floor((currentLevel + 1.0).pow(3.2)) }, + { level -> mapOf(HotmReward.UNKNOWN to 1.0 * level) }), + + GIFTS_FROM_THE_DEPARTED("Gifts from the Departed", + 100, + { currentLevel -> floor((currentLevel + 1.0).pow(2.45)) }, + { level -> mapOf(HotmReward.UNKNOWN to 0.2 * level) }), + + EXCAVATOR( + "Excavator", + 50, + { currentLevel -> (currentLevel + 1.0).pow(3) }, + { level -> mapOf(HotmReward.UNKNOWN to 0.5 * level) }), + RAGS_TO_RICHES("Rags to Riches", + 50, + { currentLevel -> floor((currentLevel + 1.0).pow(3.05)) }, + { level -> mapOf(HotmReward.MINING_FORTUNE to 2.0 * level) }), + + KEEN_EYE("Keen Eye", 1, { null }, { emptyMap() }), + MINESHAFT_MAYHEM("Mineshaft Mayhem", 1, { null }, { emptyMap() }), + FROZEN_SOLID("Frozen Solid", 1, { null }, { emptyMap() }), + GEMSTONE_INFUSION("Gemstone Infusion", 1, { null }, { emptyMap() }), + HAZARDOUS_MINER("Hazardous Miner", 1, { null }, { emptyMap() }), + + ; + + private val guiNamePattern by patternGroup.pattern("perk.name.${name.lowercase().replace("_", "")}", "§.$guiName") + + val printName = name.allLettersFirstUppercase() + + val rawLevel: Int + get() = storage?.perks?.get(this.name)?.level ?: 0 + + var activeLevel: Int + get() = storage?.perks?.get(this.name)?.level?.plus(blueEgg()) ?: 0 + private set(value) { + storage?.perks?.computeIfAbsent(this.name) { HotmTree.HotmPerk() }?.level = value + } + + private fun blueEgg() = if (this != PEAK_OF_THE_MOUNTAIN && maxLevel != 1 && HotmAPI.isBlueEggActive) 1 else 0 + + var enabled: Boolean + get() = storage?.perks?.get(this.name)?.enabled ?: false + private set(value) { + storage?.perks?.computeIfAbsent(this.name) { HotmTree.HotmPerk() }?.enabled = value + } + + var isUnlocked: Boolean + get() = storage?.perks?.get(this.name)?.isUnlocked ?: false + private set(value) { + storage?.perks?.computeIfAbsent(this.name) { HotmTree.HotmPerk() }?.isUnlocked = value + } + + var slot: Slot? = null + private set + + fun getLevelUpCost() = costFun(rawLevel) + + fun getReward() = rewardFun(activeLevel) + + companion object { + + val storage get() = ProfileStorageData.profileSpecific?.mining?.hotmTree + + val abilities = + listOf(PICKOBULUS, MINING_SPEED_BOOST, VEIN_SEEKER, MANIAC_MINER, HAZARDOUS_MINER, GEMSTONE_INFUSION) + + private val inventoryPattern by patternGroup.pattern( + "inventory", "Heart of the Mountain" + ) + + private val levelPattern by patternGroup.pattern( + "perk.level", "§(?.)Level (?\\d+).*" + ) + + private val notUnlockedPattern by patternGroup.pattern( + "perk.notunlocked", "(§.)*Requires.*|.*Mountain!|(§.)*Click to unlock!|" + ) + + private val enabledPattern by patternGroup.pattern( + "perk.enable", "§a§lENABLED|(§.)*SELECTED" + ) + private val disabledPattern by patternGroup.pattern( + "perk.disabled", "§c§lDISABLED|§7§eClick to select!" + ) // unused for now since the assumption is when enabled isn't found it is disabled, but the value might be useful in the future or for debugging + + private val resetChatPattern by patternGroup.pattern( + "reset.chat", "§aReset your §r§5Heart of the Mountain§r§a! Your Perks and Abilities have been reset." + ) + + private val heartItemPattern by patternGroup.pattern( + "inventory.heart", "§5Heart of the Mountain" + ) + private val resetItemPattern by patternGroup.pattern( + "inventory.reset", "§cReset Heart of the Mountain" + ) + + private val heartTokensPattern by patternGroup.pattern( + "inventory.heart.token", "§7Token of the Mountain: §5(?\\d+)" + ) + + private val resetTokensPattern by patternGroup.pattern( + "inventory.reset.token", "\\s+§8- §5(?\\d+) Token of the Mountain" + ) + + private val skymallPattern by patternGroup.pattern( + "skymall", "(?:§eNew buff§r§r§r: §r§f|§8 ■ §7)(?.*)" + ) + + private val mayhemChatPattern by patternGroup.pattern( + "mayhem", "§b§lMAYHEM! §r§7(?.*)" + ) + + var inInventory = false + + var tokens: Int + get() = ProfileStorageData.profileSpecific?.mining?.tokens ?: 0 + private set(value) { + ProfileStorageData.profileSpecific?.mining?.tokens = value + } + + var availableTokens: Int + get() = ProfileStorageData.profileSpecific?.mining?.availableTokens ?: 0 + private set(value) { + ProfileStorageData.profileSpecific?.mining?.availableTokens = value + } + + var heartItem: Slot? = null + + init { + entries.forEach { it.guiNamePattern } + HotmAPI.Powder.entries.forEach { + it.heartPattern + it.resetPattern + } + HotmAPI.SkymallPerk.entries.forEach { + it.chatPattern + it.itemPattern + } + HotmAPI.MayhemPerk.entries.forEach { + it.chatPattern + } + } + + private fun resetTree() = entries.forEach { + it.activeLevel = 0 + it.enabled = false + it.isUnlocked = false + HotmAPI.Powder.entries.forEach { it.setCurrent(it.getTotal()) } + availableTokens = tokens + } + + private fun Slot.parse() { + val item = this.stack ?: return + + if (this.handlePowder()) return + + val entry = entries.firstOrNull { it.guiNamePattern.matches(item.name) } ?: return + entry.slot = this + + val lore = item.getLore().takeIf { it.isNotEmpty() } ?: return + + if (entry != PEAK_OF_THE_MOUNTAIN && notUnlockedPattern.matches(lore.last())) { + entry.activeLevel = 0 + entry.enabled = false + entry.isUnlocked = false + return + } + + entry.isUnlocked = true + + entry.activeLevel = levelPattern.matchMatcher(lore.first()) { + group("level").toInt().transformIf({ group("color") == "b" }, { this.minus(1) }) + } ?: entry.maxLevel + + if (entry.activeLevel > entry.maxLevel) { + throw IllegalStateException("Hotm Perk '${entry.name}' over max level") + } + + if (entry == PEAK_OF_THE_MOUNTAIN) { + entry.enabled = entry.activeLevel != 0 + return + } + entry.enabled = lore.any { enabledPattern.matches(it) } + + if (entry == SKY_MALL) handelSkyMall(lore) + } + + private fun Slot.handlePowder(): Boolean { + val item = this.stack ?: return false + + val isHeartItem = when { + heartItemPattern.matches(item.name) -> true + resetItemPattern.matches(item.name) -> false + else -> return false + } + + if (isHeartItem) { // Reset on the heart Item to remove duplication + tokens = 0 + availableTokens = 0 + HotmAPI.Powder.entries.forEach { it.reset() } + heartItem = this + } + + val lore = item.getLore() + + val tokenPattern = if (isHeartItem) heartTokensPattern else resetTokensPattern + + lore@ for (line in lore) { + + HotmAPI.Powder.entries.forEach { + it.pattern(isHeartItem).matchMatcher(line) { + val powder = group("powder").replace(",", "").toLong() + if (isHeartItem) { + it.setCurrent(powder) + } + it.addTotal(powder) + continue@lore + } + } + + tokenPattern.matchMatcher(line) { + val token = group("token").toInt() + if (isHeartItem) { + availableTokens = token + } + tokens += token + continue@lore + } + } + return true + } + + private val skyMallCurrentEffect by patternGroup.pattern( + "skymall.current", "§aYour Current Effect" + ) + + private fun handelSkyMall(lore: List) { + if (!SKY_MALL.enabled || !SKY_MALL.isUnlocked) HotmAPI.skymall = null + else { + val index = (lore.indexOfFirstMatch(skyMallCurrentEffect) ?: run { + ErrorManager.logErrorStateWithData( + "Could not read the skymall effect from the hotm tree", + "skyMallCurrentEffect didn't match", + "lore" to lore + ) + return + }) + 1 + skymallPattern.matchMatcher(lore[index]) { + val perk = group("perk") + HotmAPI.skymall = SkymallPerk.entries.firstOrNull { it.itemPattern.matches(perk) } ?: run { + ErrorManager.logErrorStateWithData( + "Could not read the skymall effect from the hotm tree", + "no itemPattern matched", + "lore" to lore, + "perk" to perk + ) + null + } + } + } + } + + @SubscribeEvent + fun onScoreboardUpdate(event: ScoreboardChangeEvent) { + if (!LorenzUtils.inSkyBlock) return + + event.newList.matchFirst(ScoreboardPattern.powderPattern) { + val type = HotmAPI.Powder.entries.firstOrNull { it.lowName == group("type") } ?: return + val amount = group("amount").formatLong() + val difference = amount - type.getCurrent() + + if (difference > 0) { + type.gain(difference) + ChatUtils.debug("Gained §a${difference.addSeparators()} §e${type.lowName} Powder") + } + } + } + + @SubscribeEvent + fun onInventoryClose(event: InventoryCloseEvent) { + if (!inInventory) return + inInventory = false + entries.forEach { it.slot = null } + heartItem = null + } + + @SubscribeEvent + fun onInventoryFullyOpen(event: InventoryFullyOpenedEvent) { + if (!LorenzUtils.inSkyBlock) return + inInventory = inventoryPattern.matches(event.inventoryName) + DelayedRun.runNextTick { + InventoryUtils.getItemsInOpenChest().forEach { it.parse() } + abilities.filter { it.isUnlocked }.forEach { + it.activeLevel = if (PEAK_OF_THE_MOUNTAIN.rawLevel >= 1) 2 else 1 + } + } + } + + @SubscribeEvent + fun onChat(event: LorenzChatEvent) { + if (!LorenzUtils.inSkyBlock) return + if (resetChatPattern.matches(event.message)) { + resetTree() + return + } + skymallPattern.matchMatcher(event.message) { + val perk = group("perk") + HotmAPI.skymall = SkymallPerk.entries.firstOrNull { it.chatPattern.matches(perk) } ?: run { + ErrorManager.logErrorStateWithData( + "Could not read the skymall effect from chat", + "no chatPattern matched", + "chat" to event.message, + "perk" to perk + ) + null + } + ChatUtils.debug("setting skymall to ${HotmAPI.skymall}") + return + } + DelayedRun.runNextTick { + mayhemChatPattern.matchMatcher(event.message) { + val perk = group("perk") + HotmAPI.mineshaftMayhem = MayhemPerk.entries.firstOrNull { it.chatPattern.matches(perk) } ?: run { + ErrorManager.logErrorStateWithData( + "Could not read the mayhem effect from chat", + "no chatPattern matched", + "chat" to event.message, + "perk" to perk + ) + null + } + ChatUtils.debug("setting mineshaftMayhem to ${HotmAPI.mineshaftMayhem}") + } + } + } + + @SubscribeEvent + fun onWorldSwitch(event: IslandChangeEvent) { + if (HotmAPI.mineshaftMayhem == null) return + HotmAPI.mineshaftMayhem = null + ChatUtils.debug("resetting mineshaftMayhem") + } + + @SubscribeEvent + fun onProfileSwitch(event: ProfileJoinEvent) { + HotmAPI.Powder.entries.forEach { + if (it.getStorage() == null) { + ProfileStorageData.profileSpecific?.mining?.powder?.put( + it, ProfileSpecificStorage.MiningConfig.PowderStorage() + ) + } + } + } + + @SubscribeEvent + fun onDebug(event: DebugDataCollectEvent) { + event.title("HotM") + event.addIrrelevant { + add("Tokens : $availableTokens/$tokens") + HotmAPI.Powder.entries.forEach { + add("${it.lowName} Powder: ${it.getCurrent()}/${it.getTotal()}") + } + add("Ability: ${HotmAPI.activeMiningAbility?.printName}") + add("Blue Egg: ${HotmAPI.isBlueEggActive}") + add("SkyMall: ${HotmAPI.skymall}") + add("Mineshaft Mayhem: ${HotmAPI.mineshaftMayhem}") + } + event.title("HotM - Tree") + event.addIrrelevant(entries.filter { it.isUnlocked }.map { + "${if (it.enabled) "✔" else "✖"} ${it.printName}: ${it.activeLevel}" + }) + } + } +} + +private val patternGroup = RepoPattern.group("mining.hotm") + +enum class HotmReward { + MINING_SPEED, + MINING_FORTUNE, + MINING_WISDOM, + FORGE_TIME_DECREASE, + TITANIUM_CHANCE, + DAILY_POWDER, + MORE_BASE_MITHRIL_POWER, + MORE_BASE_GEMSTONE_POWER, + MORE_MITHRIL_POWER, + MORE_GEMSTONE_POWER, + COMBAT_STAT_BOOST, + CHANCE_OF_TREASURE_CHEST, + LOCKS_OF_TREASURE_CHEST, + EXTRA_CHANCE_TRIGGER_RARE_OCCURRENCES, + AVERAGE_BLOCK_BREAKS, + CHANCE_EXTRA_XP_ORBS, + MINING_SPEED_BOOST, + ABILITY_DURATION, + ABILITY_RADIUS, + ABILITY_COOLDOWN, + FOSSIL_DUST, + UNKNOWN, + COLD_RESISTANCE +} diff --git a/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/local/HotmTree.kt b/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/local/HotmTree.kt new file mode 100644 index 000000000000..b9fba9ca0f83 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/local/HotmTree.kt @@ -0,0 +1,29 @@ +package at.hannibal2.skyhanni.data.jsonobjects.local; + +import at.hannibal2.skyhanni.utils.fromJson +import com.google.gson.Gson +import com.google.gson.annotations.Expose + +class HotmTree { + + @Expose + val perks = mutableMapOf(); + + fun deepCopy(): HotmTree { + val gson = Gson(); + val json = gson.toJson(this); + return gson.fromJson(json) + } + + class HotmPerk { + + @Expose + var level: Int = 0 + + @Expose + var enabled: Boolean = false + + @Expose + var isUnlocked: Boolean = false + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/events/DebugDataCollectEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/DebugDataCollectEvent.kt index 0162e72e4b2d..3b8a884a9e8f 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/DebugDataCollectEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/DebugDataCollectEvent.kt @@ -18,7 +18,7 @@ class DebugDataCollectEvent(private val list: MutableList, private val s fun addIrrelevant(text: String) = addIrrelevant(listOf(text)) - private fun addIrrelevant(text: List) { + fun addIrrelevant(text: List) { irrelevant = true addData(text) } 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 ec4cf0c6f4f3..2db0c37f7be2 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 @@ -173,9 +173,18 @@ object ScoreboardPattern { // mining private val miningSb = scoreboardGroup.group("mining") + + /** + * REGEX-TEST: §2᠅ §fMithril§f: §235,448 + * REGEX-TEST: §d᠅ §fGemstone§f: §d36,758 + * REGEX-TEST: §b᠅ §fGlacite§f: §b29,537 + * REGEX-TEST: §2᠅ §fMithril Powder§f: §235,448 + * REGEX-TEST: §d᠅ §fGemstone Powder§f: §d36,758 + * REGEX-TEST: §b᠅ §fGlacite Powder§f: §b29,537 + */ val powderPattern by miningSb.pattern( "powder", - "(§.)*᠅ §.(Gemstone|Mithril|Glacite)( Powder)?(§.)*:?.*$" + "(?:§.)*᠅ (?:§.)(?Gemstone|Mithril|Glacite)(?: Powder)?(?:§.)*:? (?:§.)*(?[\\d,.]*)" ) val windCompassPattern by miningSb.pattern( "windcompass", diff --git a/src/main/java/at/hannibal2/skyhanni/features/mining/HotmFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/mining/HotmFeatures.kt new file mode 100644 index 000000000000..c594312a32d3 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/mining/HotmFeatures.kt @@ -0,0 +1,53 @@ +package at.hannibal2.skyhanni.features.mining + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.data.HotmData +import at.hannibal2.skyhanni.events.GuiContainerEvent +import at.hannibal2.skyhanni.events.RenderItemTipEvent +import at.hannibal2.skyhanni.utils.LorenzColor +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.RenderUtils.highlight +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +class HotmFeatures { + + val config get() = SkyHanniMod.feature.mining.hotm + + fun isEnabled() = LorenzUtils.inSkyBlock && HotmData.inInventory + + @SubscribeEvent + fun onRender(event: GuiContainerEvent.BackgroundDrawnEvent) { + if (!isEnabled()) return + if (!config.highlightEnabledPerks) return + HotmData.entries.forEach { entry -> + val color = if (!entry.isUnlocked) LorenzColor.DARK_GRAY + else if (entry.enabled) LorenzColor.GREEN else LorenzColor.RED + entry.slot?.highlight(color) + } + } + + @SubscribeEvent + fun onRenderTip(event: RenderItemTipEvent) { + if (!isEnabled()) return + handleLevelStackSize(event) + handleTokenStackSize(event) + } + + private fun handleLevelStackSize(event: RenderItemTipEvent) { + if (!config.levelStackSize) return + HotmData.entries.firstOrNull() { + event.stack == it.slot?.stack + }?.let { + event.stackTip = if (it.activeLevel == 0 || it.activeLevel == it.maxLevel) "" else + "§e${it.activeLevel}" + it.activeLevel.toString() + } + } + + private fun handleTokenStackSize(event: RenderItemTipEvent) { + if (!config.tokenStackSize) return + if (event.stack != HotmData.heartItem?.stack) return + event.stackTip = HotmData.availableTokens.takeIf { it != 0 }?.let { "§b$it" } ?: "" + } + +} diff --git a/src/main/java/at/hannibal2/skyhanni/utils/LorenzColor.kt b/src/main/java/at/hannibal2/skyhanni/utils/LorenzColor.kt index 8309a8f86466..d1a9922cbcad 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/LorenzColor.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/LorenzColor.kt @@ -25,6 +25,17 @@ enum class LorenzColor(val chatColorCode: Char, private val color: Color, privat CHROMA('Z', Color(0, 0, 0, 0), "§ZChroma") // If chroma, go transparent instead of color code. ; + val next by lazy { + when (this) { + WHITE -> BLACK + CHROMA -> BLACK + else -> { + val index = entries.indexOf(this) + entries[index + 1] + } + } + } + fun getChatColor(): String = "§$chatColorCode" fun toColor(): Color = color diff --git a/src/main/java/at/hannibal2/skyhanni/utils/RegexUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/RegexUtils.kt index f12ecdef6f27..927b08d54cb7 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/RegexUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/RegexUtils.kt @@ -49,4 +49,11 @@ object RegexUtils { fun Matcher.groupOrNull(groupName: String): String? = runCatching { this.group(groupName) }.getOrNull() fun Matcher.hasGroup(groupName: String): Boolean = groupOrNull(groupName) != null + + fun List.indexOfFirstMatch(pattern: Pattern): Int? { + for ((index, line) in this.withIndex()) { + pattern.matcher(line).let { if (it.matches()) return index } + } + return null + } } From fca0126e4bbc63f8f8218d25be12f9795b70fadc Mon Sep 17 00:00:00 2001 From: Obsidian <108832807+Obsidianninja11@users.noreply.github.com> Date: Thu, 30 May 2024 01:32:56 -0800 Subject: [PATCH 28/34] Feature: Jyrre Bottle and Cacao Truffle held time in lore (#1916) Co-authored-by: CalMWolfs <94038482+CalMWolfs@users.noreply.github.com> Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com> --- .../java/at/hannibal2/skyhanni/SkyHanniMod.kt | 2 + .../features/inventory/InventoryConfig.java | 7 ++++ .../features/inventory/HeldTimeInLore.kt | 37 +++++++++++++++++++ .../inventory/ItemDisplayOverlayFeatures.kt | 7 ++++ .../utils/SkyBlockItemModifierUtils.kt | 12 ++++-- 5 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 src/main/java/at/hannibal2/skyhanni/features/inventory/HeldTimeInLore.kt diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt index 79728810c93f..fed79b9c3346 100644 --- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt +++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt @@ -262,6 +262,7 @@ import at.hannibal2.skyhanni.features.inventory.AuctionsHighlighter import at.hannibal2.skyhanni.features.inventory.ChestValue import at.hannibal2.skyhanni.features.inventory.DojoRankDisplay import at.hannibal2.skyhanni.features.inventory.HarpFeatures +import at.hannibal2.skyhanni.features.inventory.HeldTimeInLore import at.hannibal2.skyhanni.features.inventory.HideNotClickableItems import at.hannibal2.skyhanni.features.inventory.HighlightBonzoMasks import at.hannibal2.skyhanni.features.inventory.ItemDisplayOverlayFeatures @@ -947,6 +948,7 @@ class SkyHanniMod { loadModule(SkillTooltip()) loadModule(MaxPurseItems()) loadModule(SuperCraftFeatures) + loadModule(HeldTimeInLore) loadModule(InfernoMinionFeatures()) loadModule(LimboPlaytime) loadModule(CopyPlaytime) diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/InventoryConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/InventoryConfig.java index 86403f24afe3..872fb8ad6ba1 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/InventoryConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/InventoryConfig.java @@ -127,6 +127,7 @@ public enum ItemNumberEntry implements HasLegacyId { DUNGEON_POTION_LEVEL("§bDungeon Potion Level", 13), VACUUM_GARDEN("§bVacuum (Garden)", 14), BOTTLE_OF_JYRRE("§bBottle Of Jyrre", 15), + DARK_CACAO_TRUFFLE("§bDark Cacao Truffle"), EDITION_NUMBER("§bEdition Number", 16), BINGO_GOAL_RANK("§bBingo Goal Rank"), ; @@ -228,4 +229,10 @@ public String toString() { @ConfigEditorBoolean @FeatureToggle public boolean shiftClickBrewing = false; + + @Expose + @ConfigOption(name = "Time Held in Lore", desc = "Shows time held for Bottle of Jyrre and Dark Cacao Truffle in the lore.") + @ConfigEditorBoolean + @FeatureToggle + public boolean timeHeldInLore = false; } diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/HeldTimeInLore.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/HeldTimeInLore.kt new file mode 100644 index 000000000000..99801a3224c1 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/HeldTimeInLore.kt @@ -0,0 +1,37 @@ +package at.hannibal2.skyhanni.features.inventory + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.events.LorenzToolTipEvent +import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName +import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getBottleOfJyrreSeconds +import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getSecondsHeld +import at.hannibal2.skyhanni.utils.TimeUtils.format +import net.minecraft.item.ItemStack +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import kotlin.time.Duration.Companion.seconds + +object HeldTimeInLore { + private val config get() = SkyHanniMod.feature.inventory + + private val jyrreBottle by lazy { "NEW_BOTTLE_OF_JYRRE".asInternalName() } + private val cacaoTruffle by lazy { "DARK_CACAO_TRUFFLE".asInternalName() } + + @SubscribeEvent + fun onTooltip(event: LorenzToolTipEvent) { + if (!LorenzUtils.inSkyBlock) return + if (!config.timeHeldInLore) return + + val seconds = event.itemStack.getSeconds() ?: return + val formatted = seconds.seconds.format() + + event.toolTip.add(10, "§7Time Held: §b$formatted") + } + + private fun ItemStack.getSeconds(): Int? = when (getInternalName()) { + jyrreBottle -> getBottleOfJyrreSeconds() + cacaoTruffle -> getSecondsHeld() + else -> null + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/ItemDisplayOverlayFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/ItemDisplayOverlayFeatures.kt index 08dec7a4aa85..9d1df7abdd6a 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/ItemDisplayOverlayFeatures.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/ItemDisplayOverlayFeatures.kt @@ -8,6 +8,7 @@ import at.hannibal2.skyhanni.config.features.inventory.InventoryConfig.ItemNumbe import at.hannibal2.skyhanni.config.features.inventory.InventoryConfig.ItemNumberEntry.BINGO_GOAL_RANK import at.hannibal2.skyhanni.config.features.inventory.InventoryConfig.ItemNumberEntry.BOTTLE_OF_JYRRE import at.hannibal2.skyhanni.config.features.inventory.InventoryConfig.ItemNumberEntry.COLLECTION_LEVEL +import at.hannibal2.skyhanni.config.features.inventory.InventoryConfig.ItemNumberEntry.DARK_CACAO_TRUFFLE import at.hannibal2.skyhanni.config.features.inventory.InventoryConfig.ItemNumberEntry.DUNGEON_HEAD_FLOOR_NUMBER import at.hannibal2.skyhanni.config.features.inventory.InventoryConfig.ItemNumberEntry.DUNGEON_POTION_LEVEL import at.hannibal2.skyhanni.config.features.inventory.InventoryConfig.ItemNumberEntry.EDITION_NUMBER @@ -48,6 +49,7 @@ import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getEdition import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getNewYearCake import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getPetLevel import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getRanchersSpeed +import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getSecondsHeld import at.hannibal2.skyhanni.utils.StringUtils.removeColor import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern import com.google.gson.JsonArray @@ -243,6 +245,11 @@ object ItemDisplayOverlayFeatures { return "§a${(seconds / 3600)}" } + if (DARK_CACAO_TRUFFLE.isSelected() && internalName == "DARK_CACAO_TRUFFLE".asInternalName()) { + val seconds = item.getSecondsHeld() ?: 0 + return "§a${(seconds / 3600)}" + } + if (EDITION_NUMBER.isSelected()) { item.getEdition()?.let { edition -> if (edition < 1_000) { diff --git a/src/main/java/at/hannibal2/skyhanni/utils/SkyBlockItemModifierUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/SkyBlockItemModifierUtils.kt index b6cb3a3302af..1780764cdfcc 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/SkyBlockItemModifierUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/SkyBlockItemModifierUtils.kt @@ -179,16 +179,20 @@ object SkyBlockItemModifierUtils { fun ItemStack.getLivingMetalProgress() = getAttributeInt("lm_evo") + fun ItemStack.getSecondsHeld() = getAttributeInt("seconds_held") + fun ItemStack.getBottleOfJyrreSeconds() = getAttributeInt("bottle_of_jyrre_seconds") fun ItemStack.getEdition() = getAttributeInt("edition") fun ItemStack.getNewYearCake() = getAttributeInt("new_years_cake") - fun ItemStack.getEnchantments(): Map? = getExtraAttributes()?.takeIf { it.hasKey("enchantments") }?.run { - val enchantments = this.getCompoundTag("enchantments") - enchantments.keySet.associateWith { enchantments.getInteger(it) } - } + fun ItemStack.getEnchantments(): Map? = getExtraAttributes() + ?.takeIf { it.hasKey("enchantments") } + ?.run { + val enchantments = this.getCompoundTag("enchantments") + enchantments.keySet.associateWith { enchantments.getInteger(it) } + } fun ItemStack.getAppliedPocketSackInASack(): Int? { val data = cachedData From 6140a0c4a50c3508bbf8fcc278296557765f8fc5 Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 30 May 2024 03:28:47 -0700 Subject: [PATCH 29/34] Improvement: Hoppity eggs timer outside sb (#1926) Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com> --- .../features/event/HoppityEggsConfig.java | 6 ++++ .../features/event/hoppity/HoppityEggType.kt | 12 ++++--- .../event/hoppity/HoppityEggsManager.kt | 35 ++++++++++++------- .../skyhanni/utils/HypixelCommands.kt | 3 ++ 4 files changed, 39 insertions(+), 17 deletions(-) diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/event/HoppityEggsConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/event/HoppityEggsConfig.java index 5361991e1ebc..59f2d7516aaf 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/event/HoppityEggsConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/event/HoppityEggsConfig.java @@ -84,6 +84,12 @@ public class HoppityEggsConfig { @FeatureToggle public boolean showDuringContest = false; + @Expose + @ConfigOption(name = "Show outside Skyblock", desc = "Show on Hypixel even when not playing Skyblock.") + @ConfigEditorBoolean + @FeatureToggle + public boolean showOutsideSkyblock = false; + @Expose @ConfigOption(name = "Shared Hoppity Waypoints", desc = "Enable being able to share and receive egg waypoints in your lobby.") @ConfigEditorBoolean diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggType.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggType.kt index d67e9550abbc..87df6c3cbaee 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggType.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggType.kt @@ -6,14 +6,14 @@ import kotlin.time.Duration enum class HoppityEggType( val mealName: String, - val resetsAt: Int, private val mealColour: String, + val resetsAt: Int, var lastResetDay: Int = -1, private var claimed: Boolean = false, ) { - BREAKFAST("Breakfast", 7, "§6"), - LUNCH("Lunch", 14, "§9"), - DINNER("Dinner", 21, "§a"), + BREAKFAST("Breakfast", "§6", 7), + LUNCH("Lunch", "§9", 14), + DINNER("Dinner", "§a", 21), ; fun timeUntil(): Duration { @@ -62,5 +62,9 @@ enum class HoppityEggType( fun eggsRemaining(): Boolean { return entries.any { !it.claimed } } + + fun allEggsRemaining(): Boolean { + return entries.all { !it.claimed } + } } } 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 f6332219e1b6..771e55c59708 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 @@ -180,19 +180,19 @@ object HoppityEggsManager { } } + // TODO move logic into second passed event and cache @SubscribeEvent fun onRenderOverlay(event: GuiRenderEvent.GuiOverlayRenderEvent) { if (!isActive()) return if (!config.showClaimedEggs) return - if (isBuzy()) return - if (!ChocolateFactoryAPI.isHoppityEvent()) return + if (isBusy()) return val displayList = HoppityEggType.entries .map { "§7 - ${it.formattedName} ${it.timeUntil().format()}" } .toMutableList() displayList.add(0, "§bUnclaimed Eggs:") - if (config.showCollectedLocationCount) { + if (config.showCollectedLocationCount && LorenzUtils.inSkyBlock) { val totalEggs = HoppityEggLocator.getCurrentIslandEggLocations()?.size if (totalEggs != null) { val collectedEggs = HoppityUniqueEggLocations.collectedEggsThisIsland() @@ -222,11 +222,11 @@ object HoppityEggsManager { private fun checkWarn() { if (!warningActive) { - warningActive = HoppityEggType.entries.all { it.isClaimed() } + warningActive = !HoppityEggType.allEggsRemaining() } if (warningActive) { - if (HoppityEggType.entries.all { !it.isClaimed() }) { + if (HoppityEggType.allEggsRemaining()) { warn() } } @@ -234,24 +234,32 @@ object HoppityEggsManager { private fun warn() { if (!config.warnUnclaimedEggs) return - if (isBuzy()) return + if (isBusy()) return if (lastWarnTime.passedSince() < 30.seconds) return lastWarnTime = now() val amount = HoppityEggType.entries.size val message = "All $amount Hoppity Eggs are ready to be found!" if (config.warpUnclaimedEggs) { - ChatUtils.clickableChat( - message, - onClick = { HypixelCommands.warp(config.warpDestination) }, - "§eClick to /warp ${config.warpDestination}!" - ) + if (LorenzUtils.inSkyBlock) { + ChatUtils.clickableChat( + message, + onClick = { HypixelCommands.warp(config.warpDestination) }, + "§eClick to /warp ${config.warpDestination}!" + ) + } else { + ChatUtils.clickableChat( + message, + onClick = { HypixelCommands.skyblock() }, + "§eClick to join /skyblock!" + ) + } } else ChatUtils.chat(message) LorenzUtils.sendTitle("§e$amount Hoppity Eggs!", 5.seconds) SoundUtils.repeatSound(100, 10, SoundUtils.plingSound) } - private fun isBuzy() = ReminderUtils.isBusy(config.showDuringContest) + private fun isBusy() = ReminderUtils.isBusy(config.showDuringContest) @SubscribeEvent fun onConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) { @@ -263,5 +271,6 @@ object HoppityEggsManager { event.move(44, "event.chocolateFactory.hoppityEggs", "event.hoppityEggs") } - fun isActive() = LorenzUtils.inSkyBlock && ChocolateFactoryAPI.isHoppityEvent() + fun isActive() = (LorenzUtils.inSkyBlock || (LorenzUtils.onHypixel && config.showOutsideSkyblock)) && + ChocolateFactoryAPI.isHoppityEvent() } diff --git a/src/main/java/at/hannibal2/skyhanni/utils/HypixelCommands.kt b/src/main/java/at/hannibal2/skyhanni/utils/HypixelCommands.kt index a515262a868b..3ae6548e9897 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/HypixelCommands.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/HypixelCommands.kt @@ -1,6 +1,9 @@ package at.hannibal2.skyhanni.utils object HypixelCommands { + fun skyblock() { + send("skyblock") + } fun bazaar(searchTerm: String) { send("bz $searchTerm") From 0495dd85006dba5959c34a9089248a3b81b93156 Mon Sep 17 00:00:00 2001 From: hannibal2 <24389977+hannibal00212@users.noreply.github.com> Date: Thu, 30 May 2024 12:35:36 +0200 Subject: [PATCH 30/34] added more debug info --- .../at/hannibal2/skyhanni/data/ProfileStorageData.kt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/at/hannibal2/skyhanni/data/ProfileStorageData.kt b/src/main/java/at/hannibal2/skyhanni/data/ProfileStorageData.kt index e44c1089e582..21f3d5b8c3ca 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/ProfileStorageData.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/ProfileStorageData.kt @@ -57,11 +57,13 @@ object ProfileStorageData { val sackPlayers = sackPlayers if (playerSpecific == null) { - ErrorManager.logErrorStateWithData( - "failed to load your profile data a second time", - "workaround in 10 seconds did not work" + ErrorManager.skyHanniError( + "failed to load your profile data delayed ", + "onHypixel" to LorenzUtils.onHypixel, + "HypixelData.hypixelLive" to HypixelData.hypixelLive, + "HypixelData.hypixelAlpha" to HypixelData.hypixelAlpha, + "sidebarLinesFormatted" to ScoreboardData.sidebarLinesFormatted, ) - ErrorManager.skyHanniError("playerSpecific is still null in ProfileJoinEvent!") } if (sackPlayers == null) { ErrorManager.skyHanniError("sackPlayers is null in ProfileJoinEvent!") From e058044eca6f0b6330de6e14eaa9b11a9ef060ae Mon Sep 17 00:00:00 2001 From: Thunderblade73 <85900443+Thunderblade73@users.noreply.github.com> Date: Thu, 30 May 2024 12:49:21 +0200 Subject: [PATCH 31/34] Fix: Skymall patterns (#1938) --- src/main/java/at/hannibal2/skyhanni/api/HotmAPI.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/at/hannibal2/skyhanni/api/HotmAPI.kt b/src/main/java/at/hannibal2/skyhanni/api/HotmAPI.kt index a9940670dab2..9bc9c3c1db5f 100644 --- a/src/main/java/at/hannibal2/skyhanni/api/HotmAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/api/HotmAPI.kt @@ -89,12 +89,12 @@ object HotmAPI { var mineshaftMayhem: MayhemPerk? = null enum class SkymallPerk(chat: String, itemString: String) { - MINING_SPEED("Gain §r§a+100 §r§6⸕ Mining Speed§r§f.", "Gain §a+100 §6⸕ Mining Speed§7."), - MINING_FORTUNE("Gain §r§a+50 §r§6☘ Mining Fortune§r§f.", "Gain §a+50 §6☘ Mining Fortune§7."), - EXTRA_POWDER("Gain §r§a+15% §r§fmore Powder while mining.", "Gain §a+15% §7more Powder while mining."), - ABILITY_COOLDOWN("Reduce Pickaxe Ability cooldown by §r§a20%§r§f.", "Reduce Pickaxe Ability cooldown by"), - GOBLIN_CHANCE("§r§a10x §r§fchance to find Golden and Diamond Goblins.", "§a10x §7chance to find Golden and"), - TITANIUM("Gain §r§a5x §r§9Titanium §r§fdrops", "Gain §a+15% §7more Powder while mining.") + MINING_SPEED("Gain §r§a\\+100 §r§6⸕ Mining Speed§r§f\\.", "Gain §a\\+100 §6⸕ Mining Speed§7\\."), + MINING_FORTUNE("Gain §r§a\\+50 §r§6☘ Mining Fortune§r§f\\.", "Gain §a\\+50 §6☘ Mining Fortune§7\\."), + EXTRA_POWDER("Gain §r§a\\+15% §r§fmore Powder while mining\\.", "Gain §a\\+15% §7more Powder while mining\\."), + ABILITY_COOLDOWN("Reduce Pickaxe Ability cooldown by §r§a20%§r§f\\.", "Reduce Pickaxe Ability cooldown by"), + GOBLIN_CHANCE("§r§a10x §r§fchance to find Golden and Diamond Goblins\\.", "§a10x §7chance to find Golden and"), + TITANIUM("Gain §r§a5x §r§9Titanium §r§fdrops", "Gain §a\\+15% §7more Powder while mining\\.") ; private val patternName = name.lowercase().replace("_", ".") From 5d89d56e1a480ae26f325c995a66a4b40a436638 Mon Sep 17 00:00:00 2001 From: hannibal2 <24389977+hannibal002@users.noreply.github.com> Date: Thu, 30 May 2024 12:59:00 +0200 Subject: [PATCH 32/34] Fix: /viewrecipe (#1939) Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com> --- .../features/commands/ViewRecipeCommand.kt | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/main/java/at/hannibal2/skyhanni/features/commands/ViewRecipeCommand.kt b/src/main/java/at/hannibal2/skyhanni/features/commands/ViewRecipeCommand.kt index fbfb1a64086f..cbdc626acd0b 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/commands/ViewRecipeCommand.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/commands/ViewRecipeCommand.kt @@ -2,23 +2,36 @@ package at.hannibal2.skyhanni.features.commands import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.events.MessageSendToServerEvent +import at.hannibal2.skyhanni.utils.ChatUtils.senderIsSkyhanni import at.hannibal2.skyhanni.utils.HypixelCommands import at.hannibal2.skyhanni.utils.NEUItems +import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher +import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern import net.minecraftforge.fml.common.eventhandler.SubscribeEvent object ViewRecipeCommand { private val config get() = SkyHanniMod.feature.misc.commands + /** + * REGEX-TEST: /viewrecipe aspect of the end + * REGEX-TEST: /viewrecipe aspect_of_the_end + * REGEX-TEST: /viewrecipe ASPECT_OF_THE_END + */ + private val pattern by RepoPattern.pattern( + "commands.viewrecipe", + "\\/viewrecipe (?.*)" + ) + @SubscribeEvent fun onMessageSendToServer(event: MessageSendToServerEvent) { if (!config.viewRecipeLowerCase) return - val message = event.message - if (!message.startsWith("/viewrecipe ", ignoreCase = true)) return + if (event.senderIsSkyhanni()) return + + val item = pattern.matchMatcher(event.message.lowercase()) { + group("item").uppercase().replace(" ", "_") + } ?: return - if (message == message.uppercase()) return - val item = message.uppercase().substringAfter("viewrecipe").trim() - if (item.isEmpty()) return event.isCanceled = true HypixelCommands.viewRecipe(item) } From a6133f8ff76b2e8ed00ff707c2e4bd7f75112c8f Mon Sep 17 00:00:00 2001 From: HiZe Date: Thu, 30 May 2024 13:18:05 +0200 Subject: [PATCH 33/34] Feature: Highlight rabbits with requirement (#1874) Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com> --- .../ChocolateFactoryConfig.java | 14 ++++++++ .../event/hoppity/HoppityCollectionStats.kt | 36 +++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/chocolatefactory/ChocolateFactoryConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/chocolatefactory/ChocolateFactoryConfig.java index db49702d9c04..f954015ac8bf 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/chocolatefactory/ChocolateFactoryConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/chocolatefactory/ChocolateFactoryConfig.java @@ -171,6 +171,20 @@ public class ChocolateFactoryConfig { @FeatureToggle public boolean hoppityMenuShortcut = true; + @Expose + @ConfigOption(name = "Highlight Requirement Rabbits", desc = "Highlight rabbits that have requirements.\n" + + "§cRed: Requirement not met.\n" + + "§aGreen: Requirement met.") + @ConfigEditorBoolean + @FeatureToggle + public boolean highlightRabbitsWithRequirement = false; + + @Expose + @ConfigOption(name = "Only Requirement Not Met", desc = "Only highlight the rabbits you don't have the requirement for.") + @ConfigEditorBoolean + @FeatureToggle + public boolean onlyHighlightRequirementNotMet = true; + @Expose @ConfigOption(name = "Chocolate Shop Price", desc = "") @Accordion diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCollectionStats.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCollectionStats.kt index f8ef5ac62061..b570ae37338d 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCollectionStats.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCollectionStats.kt @@ -1,13 +1,16 @@ package at.hannibal2.skyhanni.features.event.hoppity import at.hannibal2.skyhanni.data.ProfileStorageData +import at.hannibal2.skyhanni.events.GuiContainerEvent import at.hannibal2.skyhanni.events.GuiRenderEvent import at.hannibal2.skyhanni.events.InventoryCloseEvent import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryAPI import at.hannibal2.skyhanni.utils.ChatUtils import at.hannibal2.skyhanni.utils.DisplayTableEntry +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.LorenzUtils.round import at.hannibal2.skyhanni.utils.NEUInternalName @@ -15,8 +18,10 @@ import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators import at.hannibal2.skyhanni.utils.NumberUtil.formatInt import at.hannibal2.skyhanni.utils.RegexUtils.anyMatches +import at.hannibal2.skyhanni.utils.RegexUtils.find import at.hannibal2.skyhanni.utils.RegexUtils.matchFirst import at.hannibal2.skyhanni.utils.RegexUtils.matches +import at.hannibal2.skyhanni.utils.RenderUtils.highlight import at.hannibal2.skyhanni.utils.RenderUtils.renderRenderables import at.hannibal2.skyhanni.utils.StringUtils.removeColor import at.hannibal2.skyhanni.utils.renderables.Renderable @@ -49,6 +54,22 @@ object HoppityCollectionStats { "rabbits.found", "§.§l§m[ §a-z]+§r §.(?[0-9]+)§./§.(?[0-9]+)" ) + /** + * REGEX-TEST: §a✔ §7Requirement + */ + private val requirementMet by patternGroup.pattern( + "rabbit.requirement.met", + "§a✔ §7Requirement" + ) + /** + * REGEX-TEST: §c✖ §7Requirement §e0§7/§a15 + * REGEX-TEST: §c✖ §7Requirement §e6§7/§a20 + * REGEX-TEST: §c✖ §7Requirement §e651§7/§a1,000 + */ + private val requirementNotMet by patternGroup.pattern( + "rabbit.requirement.notmet", + "§c✖ §7Requirement.*", + ) private var display = emptyList() private val loggedRabbits @@ -82,6 +103,21 @@ object HoppityCollectionStats { ) } + // TODO cache with inventory update event + @SubscribeEvent + fun onBackgroundDrawn(event: GuiContainerEvent.BackgroundDrawnEvent) { + if (!config.highlightRabbitsWithRequirement) return + if (!inInventory) return + + for (slot in InventoryUtils.getItemsInOpenChest()) { + val lore = slot.stack.getLore() + if (lore.any { requirementMet.find(it) } && !config.onlyHighlightRequirementNotMet) + slot highlight LorenzColor.GREEN + if (lore.any { requirementNotMet.find(it) }) + slot highlight LorenzColor.RED + } + } + private fun buildDisplay(event: InventoryFullyOpenedEvent): MutableList { logRabbits(event) From 469e6187ee15d3559f91ce21be7a37d13d16f809 Mon Sep 17 00:00:00 2001 From: hannibal2 <24389977+hannibal00212@users.noreply.github.com> Date: Thu, 30 May 2024 14:38:04 +0200 Subject: [PATCH 34/34] Version 0.26 Beta 4 --- build.gradle.kts | 2 +- docs/CHANGELOG.md | 33 ++++++++++++++++++- docs/FEATURES.md | 16 ++++++++- .../java/at/hannibal2/skyhanni/SkyHanniMod.kt | 2 +- 4 files changed, 49 insertions(+), 4 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 8e769413e13d..9fc6afae8193 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,7 +15,7 @@ plugins { } group = "at.hannibal2.skyhanni" -version = "0.26.Beta.3" +version = "0.26.Beta.4" val gitHash by lazy { val baos = ByteArrayOutputStream() diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index aec372972b9c..962d47db264f 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -37,14 +37,26 @@ #### Event Features + Chat reminder to check Hoppity Shop each year. - appable (https://github.com/hannibal002/SkyHanni/pull/1843) ++ Highlight rabbits that have requirements in the Hoppity's Collection menu. - HiZe (https://github.com/hannibal002/SkyHanni/pull/1874) + + Green: Requirement met. + + Red: Requirement not met. ++ Mark duplicate egg locations in red for unlocking some of the new rabbits. - appable (https://github.com/hannibal002/SkyHanni/pull/1929) + + Option to always mark nearby duplicate egg locations. ++ Added "Collected Locations" line to the Unclaimed Eggs Display. - appable (https://github.com/hannibal002/SkyHanni/pull/1929) + + This may be inaccurate if you've already collected eggs on an island. ++ Show total amount of chocolate spent in the Chocolate Shop. - sayomaki (https://github.com/hannibal002/SkyHanni/pull/1921) #### Mining Features + Configurable cold amount for the ascension rope message in Glacite Mines. - nopo (https://github.com/hannibal002/SkyHanni/pull/1905) ++ Added HOTM perks level and Enable Display. - Thunderblade73 (https://github.com/hannibal002/SkyHanni/pull/1059) #### Inventory Features + Warning when outbid on an auction. - seraid (https://github.com/hannibal002/SkyHanni/pull/1818) ++ Added option to show time held in lore for Jyrre Bottles and Cacao Truffles. - Obsidian (https://github.com/hannibal002/SkyHanni/pull/1916) ++ Added Dark Cacao Truffle hours held as stack size. - Obsidian (https://github.com/hannibal002/SkyHanni/pull/1916) ++ Added ULTRA RARE Book Notification when doing the Experiment Table. - raven (https://github.com/hannibal002/SkyHanni/pull/1738) #### Fishing Features @@ -62,6 +74,8 @@ #### Misc Features + Click on breakdown display in /playtimedetailed to copy the stats into the clipboard. - seraid (https://github.com/hannibal002/SkyHanni/pull/1807) ++ Added Editable Hotbar. - Thunderblade73 (https://github.com/hannibal002/SkyHanni/pull/1903) + + Allows for moving and scaling in the SkyHanni GUI editor. ### Improvements @@ -82,10 +96,12 @@ + Hoppity Collection Stats are now persistent. - appable (https://github.com/hannibal002/SkyHanni/pull/1836) + No longer reset on profile swap or game restart. + Merged duplicate times in compacted Hoppity's messages. - DavidArthurCole (https://github.com/hannibal002/SkyHanni/pull/1887) ++ Option to show Hoppity Eggs timer outside of SkyBlock. - maxime-bodifee (https://github.com/hannibal002/SkyHanni/pull/1926) #### Mining Improvements + Highlight Treasure Hoarders during Treasure Hoarder Puncher commissions. - Luna (https://github.com/hannibal002/SkyHanni/pull/1852) ++ Added Mining Event Icons. - Thunderblade73 (https://github.com/hannibal002/SkyHanni/pull/1305) #### Commands Improvements @@ -106,6 +122,10 @@ + Adjusted and added Rabbit Uncle & Dog Keybinds. - raven (https://github.com/hannibal002/SkyHanni/pull/1907) +#### Fishing Improvements + ++ Added option to show the name of the sea creature in the title notification. - Empa (https://github.com/hannibal002/SkyHanni/pull/1858) + #### Misc Improvements + Added a toggle for 24-hour time. - seraid (https://github.com/hannibal002/SkyHanni/pull/1804) @@ -128,10 +148,12 @@ + Fixed farming contests showing in the election GUI. - CalMWolfs (https://github.com/hannibal002/SkyHanni/pull/1871) + Fixed wrong icon for the rat crop type in Stereo Harmony display. - raven (https://github.com/hannibal002/SkyHanni/pull/1849) -#### Chocolate Factory Fixes +#### Chocolate Factory & Hoppity Hunt Fixes + Fixed some Chocolate Factory issues caused by a Hypixel update. - CalMWolfs (https://github.com/hannibal002/SkyHanni/pull/1860) + Fixed a bug where the chocolate factory leaderboard position was not showing when the position had many digits. - sayomaki (https://github.com/hannibal002/SkyHanni/pull/1918) ++ Fixed compact chat sometimes breaking when obtaining legendary or higher tier rabbits. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/1923) ++ Fixed Sigma Rabbit bonuses not counting in collection stats display. - appable (https://github.com/hannibal002/SkyHanni/pull/1925) #### Custom Scoreboard Fixes @@ -149,11 +171,20 @@ #### Commands Fixes + Fixed typo in /shclearkismet command. - fahr-plan (https://github.com/hannibal002/SkyHanni/pull/1912) ++ Fixed 'viewrecipe' lowercase not working. - Obsidian + hannibal2 (https://github.com/hannibal002/SkyHanni/pull/1939) + +#### Fishing Fixes + ++ Fixed Thunder and Jawbus not being highlighted by Highlight Rare Sea Creatures. - Empa (https://github.com/hannibal002/SkyHanni/pull/1858) #### Performance Fixes + Fixed small memory leaks when staying in one island for extended periods. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/1890) +#### Misc Fixes + ++ Fixed LorenzToolTipEvent triggering when not actually hovering over an item. - CalMWolfs (https://github.com/hannibal002/SkyHanni/pull/1920) + ### Technical Details + Use more simple time mark. - CalMWolfs (https://github.com/hannibal002/SkyHanni/pull/1777) diff --git a/docs/FEATURES.md b/docs/FEATURES.md index 2c73b9eed830..ca95424b7521 100644 --- a/docs/FEATURES.md +++ b/docs/FEATURES.md @@ -54,7 +54,7 @@ Use `/sh` or `/skyhanni` to open the SkyHanni config in game. - Powder Mining messages hider - Winter gift messages hider - Many other messages (Not separated into own categories yet) -+ Added new chat filters. - Mikecraft1224 (https://github.com/hannibal002/SkyHanni/pull/1750) ++ More chat filters. - Mikecraft1224 (https://github.com/hannibal002/SkyHanni/pull/1750) + Filters for rare dungeon chest rewards and sacrifice messages from other players.
@@ -841,6 +841,7 @@ Use `/sh` or `/skyhanni` to open the SkyHanni config in game. + Profit Per Corpse. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/1734) + Displays profit/loss in chat after looting a corpse in the Mineshaft. + Includes a breakdown of information on hover. ++ HOTM perks level and Enable Display. - Thunderblade73 (https://github.com/hannibal002/SkyHanni/pull/1059)
@@ -871,6 +872,7 @@ Use `/sh` or `/skyhanni` to open the SkyHanni config in game. + Jyrre Timer for Bottle of Jyrre. - walker + A timer showing the remaining duration of your intelligence boost. + Option to show the timer when inactive rather than removing it. ++ Option to show time held in lore for Jyrre Bottles and Cacao Truffles. - Obsidian (https://github.com/hannibal002/SkyHanni/pull/1916) + New Year Cake Reminder. - hannibal2 + Easter Egg Hunt 2024 waypoints. - Erymanthus + walker (https://github.com/hannibal002/SkyHanni/pull/1193) @@ -906,6 +908,14 @@ Use `/sh` or `/skyhanni` to open the SkyHanni config in game. + Time until the next Hoppity event in chat message for egg locator. - seraid (https://github.com/hannibal002/SkyHanni/pull/1625) + Warning before the Time Tower in the Chocolate Factory ends. - seraid (https://github.com/hannibal002/SkyHanni/pull/1816) + Chat reminder to check Hoppity Shop each year. - appable (https://github.com/hannibal002/SkyHanni/pull/1843) ++ Highlight rabbits that have requirements in the Hoppity's Collection menu. - HiZe (https://github.com/hannibal002/SkyHanni/pull/1874) + + Green: Requirement met. + + Red: Requirement not met. ++ Mark duplicate egg locations in red for unlocking some of the new rabbits. - appable (https://github.com/hannibal002/SkyHanni/pull/1929) + + Option to always mark nearby duplicate egg locations. ++ Mark duplicate egg locations in red for unlocking some of the new rabbits. - appable (https://github.com/hannibal002/SkyHanni/pull/1929) + + Option to always mark nearby duplicate egg locations. ++ Show total amount of chocolate spent in the Chocolate Shop. - sayomaki (https://github.com/hannibal002/SkyHanni/pull/1921)
@@ -1053,6 +1063,7 @@ Use `/sh` or `/skyhanni` to open the SkyHanni config in game. + **/sendcoords** - dragon99z + Sending, detecting and rendering. + Dungeon Potion level as item stack size - HiZe ++ Dark Cacao Truffle hours held as stack size. - Obsidian (https://github.com/hannibal002/SkyHanni/pull/1916) + **Ender Node Tracker** - pretz + Tracks items and profit obtained from collecting ender nodes and killing normal endermen. + **Harp Keybinds** - NetheriteMiner @@ -1193,6 +1204,9 @@ Use `/sh` or `/skyhanni` to open the SkyHanni config in game. + Simple Ferocity Display. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/1765) + Shows the Ferocity stat as a single GUI element. + Requires the Tab List widget to be enabled and Ferocity to be selected to work. ++ Editable Hotbar. - Thunderblade73 (https://github.com/hannibal002/SkyHanni/pull/1903) + + Allows for moving and scaling in the SkyHanni GUI editor. ++ ULTRA RARE Book Notification when doing the Experiment Table. - raven (https://github.com/hannibal002/SkyHanni/pull/1738)
diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt index fed79b9c3346..d068150fa2b0 100644 --- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt +++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt @@ -498,7 +498,7 @@ import org.apache.logging.log4j.Logger clientSideOnly = true, useMetadata = true, guiFactory = "at.hannibal2.skyhanni.config.ConfigGuiForgeInterop", - version = "0.26.Beta.3", + version = "0.26.Beta.4", ) class SkyHanniMod {