From b8f4b63f6efdef2cb189d6094b5f5bad17b8a80a Mon Sep 17 00:00:00 2001 From: The1Divider <65572114+The1Divider@users.noreply.github.com> Date: Sun, 15 Sep 2024 04:25:29 -0600 Subject: Feature: Highlight More Hoppity's Collection Rabbits (#2438) Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com> --- .../chocolatefactory/ChocolateFactoryConfig.java | 21 ++-- .../event/hoppity/HoppityCollectionStats.kt | 116 +++++++++++++++++---- 2 files changed, 109 insertions(+), 28 deletions(-) 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 e35bc4d7e..fa817ede0 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 @@ -2,6 +2,7 @@ package at.hannibal2.skyhanni.config.features.inventory.chocolatefactory; import at.hannibal2.skyhanni.config.FeatureToggle; import at.hannibal2.skyhanni.config.core.config.Position; +import at.hannibal2.skyhanni.features.event.hoppity.HoppityCollectionStats.HighlightRabbitTypes; import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryStats.ChocolateFactoryStat; import com.google.gson.annotations.Expose; import io.github.notenoughupdates.moulconfig.annotations.Accordion; @@ -174,18 +175,22 @@ public class ChocolateFactoryConfig { 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.") + @ConfigOption(name = "Highlight Found Rabbits", desc = "Highlight rabbits that have already been found.") @ConfigEditorBoolean @FeatureToggle - public boolean highlightRabbitsWithRequirement = false; + public boolean highlightFoundRabbits = 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; + @ConfigOption(name = "Highlight Rabbits", desc = "Highlight specific rabbit types in Hoppity's Collection.") + @ConfigEditorDraggableList + public List highlightRabbits = new ArrayList<>(Arrays.asList( + HighlightRabbitTypes.ABI, + HighlightRabbitTypes.FACTORY, + HighlightRabbitTypes.MET, + HighlightRabbitTypes.NOT_MET, + HighlightRabbitTypes.SHOP, + HighlightRabbitTypes.STRAYS + )); @Expose @ConfigOption( 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 a06b3dcbc..800ac5729 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 @@ -24,15 +24,17 @@ 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.findMatcher -import at.hannibal2.skyhanni.utils.RegexUtils.matchFirst +import at.hannibal2.skyhanni.utils.RegexUtils.firstMatcher 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 +import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern +import net.minecraft.item.ItemStack import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import java.util.regex.Pattern @SkyHanniModule object HoppityCollectionStats { @@ -97,6 +99,30 @@ object HoppityCollectionStats { "§c✖ §7Requirement §e(?[\\d,]+)§7/§a(?[\\d,]+)", ) + /** + * REGEX-TEST: §6Factory Milestones§7. + */ + private val factoryMilestone by RepoPattern.pattern( + "rabbit.requirement.factory", + "§6Factory Milestones§7.", + ) + + /** + * REGEX-TEST: §6Shop Milestones§7. + */ + private val shopMilestone by RepoPattern.pattern( + "rabbit.requirement.shop", + "§6Shop Milestones§7.", + ) + + /** + * REGEX-TEST: §7§7Obtained by finding the §aStray Rabbit + */ + private val strayRabbit by RepoPattern.pattern( + "rabbit.requirement.stray", + "§7§7Obtained by finding the §aStray Rabbit", + ) + /** * REGEX-TEST: Find 15 unique egg locations in the Deep Caverns. */ @@ -109,6 +135,21 @@ object HoppityCollectionStats { private val loggedRabbits get() = ProfileStorageData.profileSpecific?.chocolateFactory?.rabbitCounts ?: mutableMapOf() + enum class HighlightRabbitTypes( + private val displayName: String, + val color: LorenzColor, + ) { + ABI("§2Abi", LorenzColor.DARK_GREEN), + FACTORY("§eFactory Milestones", LorenzColor.YELLOW), + MET("§aRequirement Met", LorenzColor.GREEN), + NOT_MET("§cRequirement Not Met.", LorenzColor.RED), + SHOP("§6Shop Milestones", LorenzColor.GOLD), + STRAYS("§3Stray Rabbits", LorenzColor.DARK_AQUA), + ; + + override fun toString(): String = displayName + } + @KSerializable data class LocationRabbit( val locationName: String, @@ -133,17 +174,57 @@ object HoppityCollectionStats { var inInventory = false + private val highlightConfigMap: Map = mapOf( + factoryMilestone to HighlightRabbitTypes.FACTORY, + requirementMet to HighlightRabbitTypes.MET, + requirementNotMet to HighlightRabbitTypes.NOT_MET, + shopMilestone to HighlightRabbitTypes.SHOP, + strayRabbit to HighlightRabbitTypes.STRAYS, + ) + @SubscribeEvent fun onInventoryOpen(event: InventoryFullyOpenedEvent) { if (!(LorenzUtils.inSkyBlock)) return - if (!pagePattern.matches(event.inventoryName)) return + if (!pagePattern.matches(event.inventoryName)) { + // Clear highlight cache in case options are toggled + highlightMap.clear() + return + } inInventory = true if (config.hoppityCollectionStats) { display = buildDisplay(event) } + + if (config.highlightRabbits.isNotEmpty()) { + for ((_, stack) in event.inventoryItems) filterRabbitToHighlight(stack) + } } + private fun filterRabbitToHighlight(stack: ItemStack) { + val lore = stack.getLore() + + if (lore.isEmpty()) return + if (!rabbitNotFoundPattern.anyMatches(lore) && !config.highlightFoundRabbits) return + + if (highlightMap.containsKey(stack.displayName)) return + + if (stack.displayName == "§aAbi" && config.highlightRabbits.contains(HighlightRabbitTypes.ABI)) { + highlightMap[stack.displayName] = HighlightRabbitTypes.ABI.color + return + } + + // cache rabbits until collection is closed + for ((pattern, rabbitType) in highlightConfigMap) { + if (pattern.anyMatches(lore) && config.highlightRabbits.contains(rabbitType)) { + highlightMap[stack.displayName] = rabbitType.color + break + } + } + } + + private var highlightMap = mutableMapOf() + @SubscribeEvent fun onInventoryClose(event: InventoryCloseEvent) { inInventory = false @@ -162,22 +243,17 @@ object HoppityCollectionStats { ) } - // TODO cache with inventory update event @SubscribeEvent fun onBackgroundDrawn(event: GuiContainerEvent.BackgroundDrawnEvent) { - if (!config.highlightRabbitsWithRequirement) return if (!inInventory) return + if (config.highlightRabbits.isEmpty()) 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) }) { - val found = !rabbitNotFoundPattern.anyMatches(lore) - // Hypixel allows purchasing Rabbits from Hoppity NPC even when the requirement is not yet met. - if (!found) { - slot highlight LorenzColor.RED - } + val name = slot.stack.displayName + + if (name.isEmpty()) continue + highlightMap[name]?.let { + slot highlight it } } } @@ -186,9 +262,10 @@ object HoppityCollectionStats { if (!config.showLocationRequirementsRabbitsInHoppityStats) return val missingLocationRabbits = locationRabbitRequirements.values.filter { !it.hasMetRequirements() } - val tips = locationRabbitRequirements.map { - it.key + " §7(§e" + it.value.locationName + "§7): " + (if (it.value.hasMetRequirements()) "§a" else "§c") + - it.value.foundCount + "§7/§a" + it.value.requiredCount + val tips = locationRabbitRequirements.map { (name, rabbit) -> + "$name §7(§e${rabbit.locationName}§7): ${ + if (rabbit.hasMetRequirements()) "§a" else "§c" + }${rabbit.foundCount}§7/§a${rabbit.requiredCount}" } newList.add( @@ -311,7 +388,7 @@ object HoppityCollectionStats { // used to make sure that mod data is synchronized with Hypixel private fun getFoundRabbitsFromHypixel(event: InventoryFullyOpenedEvent): Int { return event.inventoryItems.firstNotNullOf { - it.value.getLore().matchFirst(rabbitsFoundPattern) { + rabbitsFoundPattern.firstMatcher(it.value.getLore()) { group("current").formatInt() } } @@ -354,7 +431,7 @@ object HoppityCollectionStats { if (!found) continue - val duplicates = itemLore.matchFirst(duplicatesFoundPattern) { + val duplicates = duplicatesFoundPattern.firstMatcher(itemLore) { group("duplicates").formatInt() } ?: 0 @@ -362,7 +439,6 @@ object HoppityCollectionStats { } } - // bugfix for some weird potential user errors (e.g. if users play on alpha and get rabbits) fun clearSavedRabbits() { loggedRabbits.clear() -- cgit