diff options
8 files changed, 191 insertions, 87 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt index ff905b3b0..44aa8dd7f 100644 --- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt +++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt @@ -143,6 +143,7 @@ import at.hannibal2.skyhanni.features.event.diana.HighlightInquisitors import at.hannibal2.skyhanni.features.event.diana.InquisitorWaypointShare import at.hannibal2.skyhanni.features.event.diana.MythologicalCreatureTracker import at.hannibal2.skyhanni.features.event.diana.SoopyGuessBurrow +import at.hannibal2.skyhanni.features.event.hoppity.HoppityCollectionData import at.hannibal2.skyhanni.features.event.hoppity.HoppityCollectionStats import at.hannibal2.skyhanni.features.event.hoppity.HoppityEggDisplayManager import at.hannibal2.skyhanni.features.event.hoppity.HoppityEggLocator @@ -680,6 +681,7 @@ class SkyHanniMod { loadModule(HoppityEggLocator) loadModule(HoppityEggsShared) loadModule(HoppityEggDisplayManager) + loadModule(HoppityCollectionData) loadModule(HoppityCollectionStats) loadModule(SpawnTimers()) loadModule(MarkedPlayerManager()) diff --git a/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt b/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt index 881861ad3..884a2c140 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt +++ b/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt @@ -28,6 +28,7 @@ import at.hannibal2.skyhanni.features.event.diana.DianaProfitTracker import at.hannibal2.skyhanni.features.event.diana.GriffinBurrowHelper import at.hannibal2.skyhanni.features.event.diana.InquisitorWaypointShare import at.hannibal2.skyhanni.features.event.diana.MythologicalCreatureTracker +import at.hannibal2.skyhanni.features.event.hoppity.HoppityCollectionStats import at.hannibal2.skyhanni.features.event.jerry.frozentreasure.FrozenTreasureTracker import at.hannibal2.skyhanni.features.fishing.tracker.FishingProfitTracker import at.hannibal2.skyhanni.features.fishing.tracker.SeaCreatureTracker @@ -402,6 +403,10 @@ object Commands { "shUpdateBazaarPrices", "Forcefully updating the bazaar prices right now." ) { HypixelBazaarFetcher.fetchNow() } + registerCommand( + "shclearsavedrabbits", + "Clears the saved rabbits on this profile." + ) { HoppityCollectionStats.clearSavedRabbits() } } private fun developersDebugFeatures() { 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 e5127faf5..d2a38831a 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java +++ b/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java @@ -9,6 +9,7 @@ import at.hannibal2.skyhanni.features.dungeon.CroesusChestTracker; import at.hannibal2.skyhanni.features.dungeon.DungeonFloor; import at.hannibal2.skyhanni.features.event.diana.DianaProfitTracker; import at.hannibal2.skyhanni.features.event.diana.MythologicalCreatureTracker; +import at.hannibal2.skyhanni.features.event.hoppity.HoppityCollectionStats; import at.hannibal2.skyhanni.features.event.jerry.frozentreasure.FrozenTreasureTracker; import at.hannibal2.skyhanni.features.fishing.tracker.FishingProfitTracker; import at.hannibal2.skyhanni.features.fishing.tracker.SeaCreatureTracker; @@ -123,6 +124,9 @@ public class ProfileSpecificStorage { @Expose public String targetName = null; + + @Expose + public Map<String, Integer> rabbitCounts = new HashMap(); } @Expose diff --git a/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/neu/NeuHoppityJson.kt b/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/neu/NeuHoppityJson.kt new file mode 100644 index 000000000..1c80f6ad3 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/neu/NeuHoppityJson.kt @@ -0,0 +1,23 @@ +package at.hannibal2.skyhanni.data.jsonobjects.repo.neu + +import com.google.gson.annotations.Expose + +data class NeuHoppityJson( + @Expose val hoppity: HoppityInfo +) + +data class HoppityInfo( + @Expose val rarities: Map<String, HoppityRarityInfo>, + @Expose val special: Map<String, MythicRabbitInfo>, +) + +data class HoppityRarityInfo( + @Expose val rabbits: List<String>, + @Expose val chocolate: Int, + @Expose val multiplier: Double, +) + +data class MythicRabbitInfo( + @Expose val chocolate: Int, + @Expose val multiplier: Double, +) diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCollectionData.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCollectionData.kt new file mode 100644 index 000000000..4d44b9ca8 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCollectionData.kt @@ -0,0 +1,60 @@ +package at.hannibal2.skyhanni.features.event.hoppity + +import at.hannibal2.skyhanni.data.jsonobjects.repo.neu.NeuHoppityJson +import at.hannibal2.skyhanni.events.NeuRepositoryReloadEvent +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import at.hannibal2.skyhanni.features.event.hoppity.HoppityCollectionStats.RabbitCollectionRarity + +object HoppityCollectionData { + private val rabbitRarities = mutableMapOf<String, RabbitCollectionRarity>() + private val rarityBonuses = mutableMapOf<RabbitCollectionRarity, ChocolateBonuses>() + private val specialBonuses = mutableMapOf<String, ChocolateBonuses>() + + val knownRabbitCount + get() = rabbitRarities.size + + fun getRarity(rabbit: String): RabbitCollectionRarity? { + val apiName = rabbit.toApiName() + return rabbitRarities[apiName] + } + + fun knownRabbitsOfRarity(rarity: RabbitCollectionRarity): Int = + rabbitRarities.filterValues { it == rarity }.count() + + fun isKnownRabbit(rabbit: String) = rabbitRarities.contains(rabbit.toApiName()) + + fun getChocolateBonuses(rabbit: String): ChocolateBonuses { + val apiName = rabbit.toApiName() + val rarity = rabbitRarities[apiName] + return specialBonuses[apiName] + ?: rarityBonuses[rarity] + ?: ChocolateBonuses(0, 0.0) + } + + private fun String.toApiName(): String = + lowercase().replace("[- ]".toRegex(), "_") + + @SubscribeEvent + fun onNeuRepoReload(event: NeuRepositoryReloadEvent) { + rabbitRarities.clear() + rarityBonuses.clear() + specialBonuses.clear() + + val data = event.readConstant<NeuHoppityJson>("hoppity").hoppity + for ((rarityString, rarityData) in data.rarities.entries) { + val rarity = RabbitCollectionRarity.valueOf(rarityString.uppercase()) + + for (rabbit in rarityData.rabbits) { + rabbitRarities[rabbit] = rarity + } + + rarityBonuses[rarity] = ChocolateBonuses(rarityData.chocolate, rarityData.multiplier) + } + + data.special.forEach { (rabbit, data) -> + specialBonuses[rabbit] = ChocolateBonuses(data.chocolate, data.multiplier) + } + } + + data class ChocolateBonuses(val chocolate: Int, val multiplier: Double) +} 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 ef4504239..6807a712f 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,10 +1,11 @@ package at.hannibal2.skyhanni.features.event.hoppity +import at.hannibal2.skyhanni.data.ProfileStorageData import at.hannibal2.skyhanni.events.GuiRenderEvent import at.hannibal2.skyhanni.events.InventoryCloseEvent import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent -import at.hannibal2.skyhanni.events.ProfileJoinEvent 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.ItemUtils.getLore import at.hannibal2.skyhanni.utils.LorenzUtils @@ -13,9 +14,11 @@ import at.hannibal2.skyhanni.utils.NEUInternalName 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.matchMatcher +import at.hannibal2.skyhanni.utils.RegexUtils.anyMatches +import at.hannibal2.skyhanni.utils.RegexUtils.matchFirst import at.hannibal2.skyhanni.utils.RegexUtils.matches import at.hannibal2.skyhanni.utils.RenderUtils.renderRenderables +import at.hannibal2.skyhanni.utils.StringUtils.removeColor import at.hannibal2.skyhanni.utils.renderables.Renderable import net.minecraftforge.fml.common.eventhandler.SubscribeEvent @@ -28,10 +31,6 @@ object HoppityCollectionStats { "page.current", "\\((?<page>\\d+)/(?<maxPage>\\d+)\\) Hoppity's Collection" ) - private val rabbitRarityPattern by patternGroup.pattern( - "rabbit.rarity", - "§.§L(?<rarity>\\w+) RABBIT" - ) private val duplicatesFoundPattern by patternGroup.pattern( "duplicates.found", "§7Duplicates Found: §a(?<duplicates>[\\d,]+)" @@ -45,16 +44,17 @@ object HoppityCollectionStats { "rabbit.notfound", "(?:§.)+You (?:have not found this rabbit yet!|cannot find this rabbit until you)" ) + private val rabbitsFoundPattern by patternGroup.pattern( "rabbits.found", "§.§l§m[ §a-z]+§r §.(?<current>[0-9]+)§./§.(?<total>[0-9]+)" ) private var display = emptyList<Renderable>() - private val loggedRabbits = mutableMapOf<String, RabbitCollectionInfo>() - private var totalRabbits = 0 + private val loggedRabbits + get() = ProfileStorageData.profileSpecific?.chocolateFactory?.rabbitCounts ?: mutableMapOf() + var inInventory = false - private var currentPage = 0 @SubscribeEvent fun onInventoryOpen(event: InventoryFullyOpenedEvent) { @@ -63,19 +63,13 @@ object HoppityCollectionStats { inInventory = true display = buildDisplay(event) + checkSpecialRabbits() } @SubscribeEvent fun onInventoryClose(event: InventoryCloseEvent) { inInventory = false - } - - @SubscribeEvent - fun onProfileChange(event: ProfileJoinEvent) { display = emptyList() - loggedRabbits.clear() - currentPage = 0 - inInventory = false } @SubscribeEvent @@ -90,13 +84,16 @@ object HoppityCollectionStats { } private fun buildDisplay(event: InventoryFullyOpenedEvent): MutableList<Renderable> { - val totalAmount = logRabbits(event) + logRabbits(event) val newList = mutableListOf<Renderable>() newList.add(Renderable.string("§eHoppity Rabbit Collection§f:")) newList.add(LorenzUtils.fillTable(getRabbitStats(), padding = 5)) - if (totalAmount != totalRabbits) { + val loggedRabbitCount = loggedRabbits.size + val foundRabbitCount = getFoundRabbitsFromHypixel(event) + + if (loggedRabbitCount < foundRabbitCount) { newList.add(Renderable.string("")) newList.add( Renderable.wrappedString( @@ -114,32 +111,39 @@ object HoppityCollectionStats { var totalDuplicates = 0 var totalChocolatePerSecond = 0 var totalChocolateMultiplier = 0.0 - totalRabbits = 0 val table = mutableListOf<DisplayTableEntry>() for (rarity in RabbitCollectionRarity.entries) { - val filtered = loggedRabbits.filter { it.value.rarity == rarity } - val isTotal = rarity == RabbitCollectionRarity.TOTAL - if (filtered.isEmpty() && !isTotal) continue + + val foundOfRarity = loggedRabbits.filterKeys { + HoppityCollectionData.getRarity(it) == rarity + } val title = "${rarity.displayName} Rabbits" - val amountFound = filtered.filter { it.value.found }.size - val totalOfRarity = filtered.size - val duplicates = filtered.values.sumOf { it.duplicates } - val chocolatePerSecond = rarity.chocolatePerSecond * amountFound - val chocolateMultiplier = (rarity.chocolateMultiplier * amountFound) + val amountFound = foundOfRarity.size + val duplicates = foundOfRarity.values.sum() - amountFound + + val chocolateBonuses = foundOfRarity.keys.map { + HoppityCollectionData.getChocolateBonuses(it) + } + + val chocolatePerSecond = chocolateBonuses.sumOf { it.chocolate } + val chocolateMultiplier = chocolateBonuses.sumOf { it.multiplier } if (!isTotal) { totalAmountFound += amountFound - totalRabbits += totalOfRarity totalDuplicates += duplicates totalChocolatePerSecond += chocolatePerSecond totalChocolateMultiplier += chocolateMultiplier } val displayFound = if (isTotal) totalAmountFound else amountFound - val displayTotal = if (isTotal) totalRabbits else totalOfRarity + val displayTotal = if (isTotal) { + HoppityCollectionData.knownRabbitCount + } else { + HoppityCollectionData.knownRabbitsOfRarity(rarity) + } val displayDuplicates = if (isTotal) totalDuplicates else duplicates val displayChocolatePerSecond = if (isTotal) totalChocolatePerSecond else chocolatePerSecond val displayChocolateMultiplier = if (isTotal) totalChocolateMultiplier else chocolateMultiplier @@ -158,7 +162,7 @@ object HoppityCollectionStats { DisplayTableEntry( title, "§a$displayFound§7/§a$displayTotal", - displayFound.toDouble(), + displayTotal.toDouble(), rarity.item, hover ) @@ -167,77 +171,79 @@ object HoppityCollectionStats { return table } - private fun logRabbits(event: InventoryFullyOpenedEvent): Int { - var totalAmount = 0 + fun incrementRabbit(name: String) { + 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 + // 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) { + group("current").formatInt() + } + } + } + + private fun logRabbits(event: InventoryFullyOpenedEvent) { for ((_, item) in event.inventoryItems) { - val itemName = item.displayName ?: continue + val itemName = item.displayName?.removeColor() ?: continue + val isRabbit = HoppityCollectionData.isKnownRabbit(itemName) + + if (!isRabbit) continue + val itemLore = item.getLore() + val found = !rabbitNotFoundPattern.anyMatches(itemLore) - var duplicatesFound = 0 - var rabbitRarity: RabbitCollectionRarity? = null - var found = true - - for (line in itemLore) { - rabbitRarityPattern.matchMatcher(line) { - rabbitRarity = RabbitCollectionRarity.fromDisplayName(group("rarity")) - } - duplicatesFoundPattern.matchMatcher(line) { - duplicatesFound = group("duplicates").formatInt() - } - if (rabbitNotFoundPattern.matches(line)) found = false - - rabbitsFoundPattern.matchMatcher(line) { - totalAmount = group("total").formatInt() - } - } + if (!found) continue - val rarity = rabbitRarity ?: continue + val duplicates = itemLore.matchFirst(duplicatesFoundPattern) { + group("duplicates").formatInt() + } ?: 0 - if (itemName == "§dEinstein" && found) { - ChocolateFactoryAPI.profileStorage?.timeTowerCooldown = 7 - } + loggedRabbits[itemName] = duplicates + 1 + } + } - if (itemName == "§dMu" && found) { - ChocolateFactoryAPI.profileStorage?.hasMuRabbit = true - } - val duplicates = duplicatesFound.coerceAtLeast(0) - loggedRabbits[itemName] = RabbitCollectionInfo(rarity, found, duplicates) + // bugfix for some weird potential user errors (e.g. if users play on alpha and get rabbits) + fun clearSavedRabbits() { + loggedRabbits.clear() + 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 } - // For getting data for neu pv -// val rarityToRabbit = mutableMapOf<RabbitCollectionRarity, MutableList<String>>() -// loggedRabbits.forEach { (name, info) -> -// val formattedName = name.removeColor().lowercase().replace(" ", "_").replace("-", "_") -// rarityToRabbit.getOrPut(info.rarity) { mutableListOf() }.add("\"$formattedName\"") -// } -// println(rarityToRabbit) - return totalAmount } - private fun isEnabled() = LorenzUtils.inSkyBlock && config.hoppityCollectionStats + private fun hasFoundRabbit(rabbit: String): Boolean = loggedRabbits.containsKey(rabbit) - private data class RabbitCollectionInfo( - val rarity: RabbitCollectionRarity, - val found: Boolean, - val duplicates: Int, - ) + private fun isEnabled() = LorenzUtils.inSkyBlock && config.hoppityCollectionStats - // todo in future make the amount and multiplier work with mythic rabbits (can't until I have some) - private enum class RabbitCollectionRarity( + enum class RabbitCollectionRarity( val displayName: String, - val chocolatePerSecond: Int, - val chocolateMultiplier: Double, val item: NEUInternalName, ) { - COMMON("§fCommon", 1, 0.002, "STAINED_GLASS".asInternalName()), - UNCOMMON("§aUncommon", 2, 0.003, "STAINED_GLASS-5".asInternalName()), - RARE("§9Rare", 4, 0.004, "STAINED_GLASS-11".asInternalName()), - EPIC("§5Epic", 10, 0.005, "STAINED_GLASS-10".asInternalName()), - LEGENDARY("§6Legendary", 0, 0.02, "STAINED_GLASS-1".asInternalName()), - MYTHIC("§dMythic", 0, 0.0, "STAINED_GLASS-6".asInternalName()), - DIVINE("§bDivine", 0, 0.025, "STAINED_GLASS-3".asInternalName()), - TOTAL("§cTotal", 0, 0.0, "STAINED_GLASS-14".asInternalName()), + COMMON("§fCommon", "STAINED_GLASS".asInternalName()), + UNCOMMON("§aUncommon", "STAINED_GLASS-5".asInternalName()), + RARE("§9Rare", "STAINED_GLASS-11".asInternalName()), + EPIC("§5Epic", "STAINED_GLASS-10".asInternalName()), + LEGENDARY("§6Legendary", "STAINED_GLASS-1".asInternalName()), + MYTHIC("§dMythic", "STAINED_GLASS-6".asInternalName()), + DIVINE("§bDivine", "STAINED_GLASS-3".asInternalName()), + TOTAL("§cTotal", "STAINED_GLASS-14".asInternalName()), ; companion object { 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 fdb029fa6..cfe229871 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 @@ -78,7 +78,7 @@ object HoppityEggsCompactChat { compactChat(event) } - HoppityEggsManager.rabbitFoundPatttern.matchMatcher(event.message) { + HoppityEggsManager.rabbitFoundPattern.matchMatcher(event.message) { lastName = group("name") lastRarity = group("rarity") 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 05377116a..c085fcf16 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 @@ -46,7 +46,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)! */ - val rabbitFoundPatttern by ChocolateFactoryAPI.patternGroup.pattern( + val rabbitFoundPattern by ChocolateFactoryAPI.patternGroup.pattern( "rabbit.found", "§D§LHOPPITY'S HUNT §7You found (?<name>.*) §7\\((?<rarity>.*)§7\\)!" ) @@ -142,6 +142,10 @@ object HoppityEggsManager { getEggType(event).markSpawned() return } + + rabbitFoundPattern.matchMatcher(event.message) { + HoppityCollectionStats.incrementRabbit(group("name")) + } } internal fun Matcher.getEggType(event: LorenzChatEvent): HoppityEggType = |