From 37127d5c7936377483d7bae4a9296a44b0279263 Mon Sep 17 00:00:00 2001 From: hannibal2 <24389977+hannibal00212@users.noreply.github.com> Date: Tue, 30 Apr 2024 14:05:35 +0200 Subject: moving few classes --- src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt | 22 +- .../features/event/ChocolateFactoryConfig.java | 2 +- .../event/chocolatefactory/ChocolateAmount.kt | 61 ----- .../event/chocolatefactory/ChocolateFactoryAPI.kt | 5 + .../ChocolateFactoryBarnManager.kt | 1 + .../chocolatefactory/ChocolateFactoryInventory.kt | 131 ----------- .../chocolatefactory/ChocolateFactoryStats.kt | 136 ------------ .../ChocolateFactoryTimeTowerManager.kt | 113 ---------- .../chocolatefactory/ChocolateFactoryTooltip.kt | 92 -------- .../chocolatefactory/HoppityCollectionStats.kt | 216 ------------------ .../event/chocolatefactory/HoppityEggLocator.kt | 245 -------------------- .../event/chocolatefactory/HoppityEggType.kt | 53 ----- .../event/chocolatefactory/HoppityEggsManager.kt | 117 ---------- .../event/chocolatefactory/HoppityEggsShared.kt | 57 ----- .../features/event/chocolatefactory/HoppityNpc.kt | 66 ------ .../clicks/FactoryItemTooltipFeatures.kt | 77 ------- .../hoppity/HoppityCollectionStats.kt | 217 ++++++++++++++++++ .../chocolatefactory/hoppity/HoppityEggLocator.kt | 246 +++++++++++++++++++++ .../chocolatefactory/hoppity/HoppityEggType.kt | 53 +++++ .../chocolatefactory/hoppity/HoppityEggsManager.kt | 118 ++++++++++ .../chocolatefactory/hoppity/HoppityEggsShared.kt | 58 +++++ .../event/chocolatefactory/hoppity/HoppityNpc.kt | 67 ++++++ .../event/chocolatefactory/menu/ChocolateAmount.kt | 62 ++++++ .../menu/ChocolateFactoryInventory.kt | 133 +++++++++++ .../chocolatefactory/menu/ChocolateFactoryStats.kt | 138 ++++++++++++ .../menu/ChocolateFactoryTimeTowerManager.kt | 114 ++++++++++ .../menu/ChocolateFactoryTooltip.kt | 93 ++++++++ .../menu/ChocolateFactoryTooltipCompact.kt | 77 +++++++ 28 files changed, 1394 insertions(+), 1376 deletions(-) delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateAmount.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryInventory.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryStats.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryTimeTowerManager.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryTooltip.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/HoppityCollectionStats.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/HoppityEggLocator.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/HoppityEggType.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/HoppityEggsManager.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/HoppityEggsShared.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/HoppityNpc.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/clicks/FactoryItemTooltipFeatures.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/hoppity/HoppityCollectionStats.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/hoppity/HoppityEggLocator.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/hoppity/HoppityEggType.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/hoppity/HoppityEggsManager.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/hoppity/HoppityEggsShared.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/hoppity/HoppityNpc.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/menu/ChocolateAmount.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/menu/ChocolateFactoryInventory.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/menu/ChocolateFactoryStats.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/menu/ChocolateFactoryTimeTowerManager.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/menu/ChocolateFactoryTooltip.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/menu/ChocolateFactoryTooltipCompact.kt diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt index 74ebfb1de..5c96ecde0 100644 --- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt +++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt @@ -127,17 +127,17 @@ import at.hannibal2.skyhanni.features.dungeon.TerracottaPhase import at.hannibal2.skyhanni.features.event.UniqueGiftingOpportunitiesFeatures import at.hannibal2.skyhanni.features.event.chocolatefactory.ChocolateFactoryAPI import at.hannibal2.skyhanni.features.event.chocolatefactory.ChocolateFactoryBarnManager -import at.hannibal2.skyhanni.features.event.chocolatefactory.ChocolateFactoryInventory import at.hannibal2.skyhanni.features.event.chocolatefactory.ChocolateFactoryShortcut -import at.hannibal2.skyhanni.features.event.chocolatefactory.ChocolateFactoryStats -import at.hannibal2.skyhanni.features.event.chocolatefactory.ChocolateFactoryTimeTowerManager -import at.hannibal2.skyhanni.features.event.chocolatefactory.ChocolateFactoryTooltip -import at.hannibal2.skyhanni.features.event.chocolatefactory.HoppityCollectionStats -import at.hannibal2.skyhanni.features.event.chocolatefactory.HoppityEggLocator -import at.hannibal2.skyhanni.features.event.chocolatefactory.HoppityEggsManager -import at.hannibal2.skyhanni.features.event.chocolatefactory.HoppityEggsShared -import at.hannibal2.skyhanni.features.event.chocolatefactory.HoppityNpc -import at.hannibal2.skyhanni.features.event.chocolatefactory.clicks.FactoryItemTooltipFeatures +import at.hannibal2.skyhanni.features.event.chocolatefactory.hoppity.HoppityCollectionStats +import at.hannibal2.skyhanni.features.event.chocolatefactory.hoppity.HoppityEggLocator +import at.hannibal2.skyhanni.features.event.chocolatefactory.hoppity.HoppityEggsManager +import at.hannibal2.skyhanni.features.event.chocolatefactory.hoppity.HoppityEggsShared +import at.hannibal2.skyhanni.features.event.chocolatefactory.hoppity.HoppityNpc +import at.hannibal2.skyhanni.features.event.chocolatefactory.menu.ChocolateFactoryInventory +import at.hannibal2.skyhanni.features.event.chocolatefactory.menu.ChocolateFactoryStats +import at.hannibal2.skyhanni.features.event.chocolatefactory.menu.ChocolateFactoryTimeTowerManager +import at.hannibal2.skyhanni.features.event.chocolatefactory.menu.ChocolateFactoryTooltip +import at.hannibal2.skyhanni.features.event.chocolatefactory.menu.ChocolateFactoryTooltipCompact import at.hannibal2.skyhanni.features.event.diana.AllBurrowsList import at.hannibal2.skyhanni.features.event.diana.BurrowWarpHelper import at.hannibal2.skyhanni.features.event.diana.DianaProfitTracker @@ -632,7 +632,7 @@ class SkyHanniMod { loadModule(ChocolateFactoryShortcut()) loadModule(ChocolateFactoryInventory) loadModule(ChocolateFactoryStats) - loadModule(FactoryItemTooltipFeatures) + loadModule(ChocolateFactoryTooltipCompact) loadModule(ChocolateFactoryTimeTowerManager) loadModule(ChocolateFactoryTooltip) loadModule(HoppityNpc) diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/event/ChocolateFactoryConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/event/ChocolateFactoryConfig.java index affb69381..ec89c9754 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/event/ChocolateFactoryConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/event/ChocolateFactoryConfig.java @@ -2,7 +2,7 @@ package at.hannibal2.skyhanni.config.features.event; import at.hannibal2.skyhanni.config.FeatureToggle; import at.hannibal2.skyhanni.config.core.config.Position; -import at.hannibal2.skyhanni.features.event.chocolatefactory.ChocolateFactoryStats.ChocolateFactoryStat; +import at.hannibal2.skyhanni.features.event.chocolatefactory.menu.ChocolateFactoryStats.ChocolateFactoryStat; import com.google.gson.annotations.Expose; import io.github.notenoughupdates.moulconfig.annotations.Accordion; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean; diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateAmount.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateAmount.kt deleted file mode 100644 index bbaf0dc25..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateAmount.kt +++ /dev/null @@ -1,61 +0,0 @@ -package at.hannibal2.skyhanni.features.event.chocolatefactory - -import at.hannibal2.skyhanni.features.event.chocolatefactory.ChocolateFactoryAPI.profileStorage -import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators -import at.hannibal2.skyhanni.utils.SimpleTimeMark -import at.hannibal2.skyhanni.utils.TimeUtils.format -import kotlin.time.Duration -import kotlin.time.Duration.Companion.seconds - -enum class ChocolateAmount(val chocolate: () -> Long) { - CURRENT({ profileStorage?.currentChocolate ?: 0 }), - PRESTIGE({ profileStorage?.chocolateThisPrestige ?: 0 }), - ALL_TIME({ profileStorage?.chocolateAllTime ?: 0 }), - ; - - val formatted get(): String = (chocolate() + chocolateSinceUpdate()).addSeparators() - - fun formattedTimeUntilGoal(goal: Long): String { - val time = timeUntilGoal(goal) - return when { - time.isInfinite() -> "§cNever" - time.isNegative() -> "§aNow" - else -> "§6${time.format()}" - } - } - - private fun timeUntilGoal(goal: Long): Duration { - val profileStorage = ChocolateFactoryAPI.profileStorage ?: return Duration.ZERO - - val updatedAgo = SimpleTimeMark(profileStorage.lastDataSave).passedSince().inWholeSeconds - - val baseMultiplier = profileStorage.rawChocolateMultiplier - val rawChocolatePerSecond = profileStorage.rawChocPerSecond - val timeTowerMultiplier = baseMultiplier + profileStorage.timeTowerLevel * 0.1 - - var needed = goal - chocolate() - val secondsUntilTowerExpires = ChocolateFactoryTimeTowerManager.timeTowerActiveDuration().inWholeSeconds - - val timeTowerChocPerSecond = rawChocolatePerSecond * timeTowerMultiplier - - val secondsAtRate = needed / timeTowerChocPerSecond - if (secondsAtRate < secondsUntilTowerExpires) { - return secondsAtRate.seconds - updatedAgo.seconds - } - - needed -= (secondsUntilTowerExpires * timeTowerChocPerSecond).toLong() - val basePerSecond = rawChocolatePerSecond * baseMultiplier - return (needed / basePerSecond + secondsUntilTowerExpires).seconds - updatedAgo.seconds - } - - companion object { - fun chocolateSinceUpdate(): Long { - val lastUpdate = SimpleTimeMark(profileStorage?.lastDataSave ?: return 0) - val currentTime = SimpleTimeMark.now() - val secondsSinceUpdate = (currentTime - lastUpdate).inWholeSeconds - - val perSecond = ChocolateFactoryAPI.chocolatePerSecond - return (perSecond * secondsSinceUpdate).toLong() - } - } -} diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryAPI.kt index 3ecbaf47e..377e79072 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryAPI.kt @@ -10,6 +10,11 @@ import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent import at.hannibal2.skyhanni.events.InventoryUpdatedEvent import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent import at.hannibal2.skyhanni.events.RepositoryReloadEvent +import at.hannibal2.skyhanni.features.event.chocolatefactory.hoppity.HoppityEggLocator +import at.hannibal2.skyhanni.features.event.chocolatefactory.menu.ChocolateAmount +import at.hannibal2.skyhanni.features.event.chocolatefactory.menu.ChocolateFactoryStats +import at.hannibal2.skyhanni.features.event.chocolatefactory.menu.ChocolateFactoryTimeTowerManager +import at.hannibal2.skyhanni.features.event.chocolatefactory.menu.ChocolateFactoryTooltip import at.hannibal2.skyhanni.utils.CollectionUtils.nextAfter import at.hannibal2.skyhanni.utils.DelayedRun import at.hannibal2.skyhanni.utils.InventoryUtils diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryBarnManager.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryBarnManager.kt index 8f387a6b0..7b1be9152 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryBarnManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryBarnManager.kt @@ -1,6 +1,7 @@ package at.hannibal2.skyhanni.features.event.chocolatefactory import at.hannibal2.skyhanni.events.LorenzChatEvent +import at.hannibal2.skyhanni.features.event.chocolatefactory.hoppity.HoppityEggsManager import at.hannibal2.skyhanni.utils.ChatUtils import at.hannibal2.skyhanni.utils.HypixelCommands import at.hannibal2.skyhanni.utils.LorenzUtils diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryInventory.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryInventory.kt deleted file mode 100644 index 46d8e966d..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryInventory.kt +++ /dev/null @@ -1,131 +0,0 @@ -package at.hannibal2.skyhanni.features.event.chocolatefactory - -import at.hannibal2.skyhanni.events.GuiContainerEvent -import at.hannibal2.skyhanni.events.GuiRenderItemEvent -import at.hannibal2.skyhanni.events.RenderInventoryItemTipEvent -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.LorenzColor -import at.hannibal2.skyhanni.utils.NumberUtil.formatInt -import at.hannibal2.skyhanni.utils.NumberUtil.romanToDecimal -import at.hannibal2.skyhanni.utils.RenderUtils.drawSlotText -import at.hannibal2.skyhanni.utils.RenderUtils.highlight -import at.hannibal2.skyhanni.utils.StringUtils.matchFirst -import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher -import at.hannibal2.skyhanni.utils.StringUtils.removeColor -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent - -object ChocolateFactoryInventory { - - private val config get() = ChocolateFactoryAPI.config - private val profileStorage get() = ChocolateFactoryAPI.profileStorage - - private val rabbitAmountPattern by ChocolateFactoryAPI.patternGroup.pattern( - "rabbit.amount", - "Rabbit \\S+ - \\[(?\\d+)].*" - ) - private val upgradeTierPattern by ChocolateFactoryAPI.patternGroup.pattern( - "upgradetier", - ".*\\s(?[IVXLC]+)" - ) - private val unclaimedRewardsPattern by ChocolateFactoryAPI.patternGroup.pattern( - "unclaimedrewards", - "§7§aYou have \\d+ unclaimed rewards?!" - ) - - @SubscribeEvent - fun onRenderItemOverlayPost(event: GuiRenderItemEvent.RenderOverlayEvent.GuiRenderItemPost) { - if (!ChocolateFactoryAPI.inChocolateFactory) return - if (!config.highlightUpgrades) return - - val item = event.stack ?: return - val itemName = item.name - if (itemName != ChocolateFactoryAPI.bestRabbitUpgrade) return - - event.drawSlotText(event.x + 18, event.y, "§6✦", .8f) - } - - @SubscribeEvent - fun onBackgroundDrawn(event: GuiContainerEvent.BackgroundDrawnEvent) { - if (!ChocolateFactoryAPI.inChocolateFactory) return - if (!config.highlightUpgrades) return - - for (slot in InventoryUtils.getItemsInOpenChest()) { - if (slot.slotIndex in ChocolateFactoryAPI.upgradeableSlots) { - if (slot.slotIndex == ChocolateFactoryAPI.bestUpgrade) { - slot highlight LorenzColor.GREEN.addOpacity(200) - } else { - slot highlight LorenzColor.GREEN.addOpacity(75) - } - } - if (slot.slotIndex == ChocolateFactoryAPI.barnIndex && ChocolateFactoryBarnManager.barnFull) { - slot highlight LorenzColor.RED - } - if (slot.slotIndex == ChocolateFactoryAPI.clickRabbitSlot) { - slot highlight LorenzColor.RED - } - if (slot.slotIndex == ChocolateFactoryAPI.milestoneIndex) { - slot.stack?.getLore()?.matchFirst(unclaimedRewardsPattern) { - slot highlight LorenzColor.RED - } - } - if (slot.slotIndex == ChocolateFactoryAPI.timeTowerIndex) { - if (ChocolateFactoryTimeTowerManager.timeTowerActive()) { - slot highlight LorenzColor.LIGHT_PURPLE - } - if (ChocolateFactoryTimeTowerManager.timeTowerFull()) { - slot highlight LorenzColor.RED - } - } - } - } - - @SubscribeEvent - fun onRenderItemTip(event: RenderInventoryItemTipEvent) { - if (!ChocolateFactoryAPI.inChocolateFactory) return - if (!config.showStackSizes) return - val profileStorage = profileStorage ?: return - - val item = event.stack - val itemName = item.name.removeColor() - val slotNumber = event.slot.slotNumber - - if (slotNumber in ChocolateFactoryAPI.rabbitSlots) { - rabbitAmountPattern.matchMatcher(itemName) { - val rabbitTip = when (val rabbitAmount = group("amount").formatInt()) { - in (0..9) -> "$rabbitAmount" - in (10..74) -> "§a$rabbitAmount" - in (75..124) -> "§9$rabbitAmount" - in (125..174) -> "§5$rabbitAmount" - in (175..199) -> "§6$rabbitAmount" - 200 -> "§d$rabbitAmount" - else -> "§c$rabbitAmount" - } - - event.stackTip = rabbitTip - } - } - if (slotNumber in ChocolateFactoryAPI.otherUpgradeSlots) { - upgradeTierPattern.matchMatcher(itemName) { - val level = group("tier").romanToDecimal() - - if (slotNumber == ChocolateFactoryAPI.timeTowerIndex) profileStorage.timeTowerLevel = level - - event.stackTip = level.toString() - } - } - } - - @SubscribeEvent - fun onSlotClick(event: GuiContainerEvent.SlotClickEvent) { - if (!ChocolateFactoryAPI.inChocolateFactory) return - val slot = event.slot ?: return - val slotNumber = slot.slotNumber - if (!config.useMiddleClick) return - if (slotNumber in ChocolateFactoryAPI.noPickblockSlots && - (slotNumber != ChocolateFactoryAPI.timeTowerIndex || event.clickedButton == 1)) return - - event.makePickblock() - } -} diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryStats.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryStats.kt deleted file mode 100644 index e1129a82d..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryStats.kt +++ /dev/null @@ -1,136 +0,0 @@ -package at.hannibal2.skyhanni.features.event.chocolatefactory - -import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator -import at.hannibal2.skyhanni.events.GuiRenderEvent -import at.hannibal2.skyhanni.events.SecondPassedEvent -import at.hannibal2.skyhanni.utils.ClipboardUtils -import at.hannibal2.skyhanni.utils.LorenzUtils -import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators -import at.hannibal2.skyhanni.utils.RenderUtils.renderRenderables -import at.hannibal2.skyhanni.utils.StringUtils.removeColor -import at.hannibal2.skyhanni.utils.renderables.Renderable -import com.google.gson.JsonPrimitive -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent - -object ChocolateFactoryStats { - - private val config get() = ChocolateFactoryAPI.config - private val profileStorage get() = ChocolateFactoryAPI.profileStorage - - private var display = listOf() - - @SubscribeEvent - fun onSecondPassed(event: SecondPassedEvent) { - if (!LorenzUtils.inSkyBlock) return - if (!ChocolateFactoryAPI.chocolateFactoryPaused) return - updateDisplay() - } - - @SubscribeEvent - fun onBackgroundDraw(event: GuiRenderEvent.ChestGuiOverlayRenderEvent) { - if (!ChocolateFactoryAPI.inChocolateFactory && !ChocolateFactoryAPI.chocolateFactoryPaused) return - if (!config.statsDisplay) return - - config.position.renderRenderables(display, posLabel = "Chocolate Factory Stats") - } - - fun updateDisplay() { - val profileStorage = profileStorage ?: return - - val perSecond = ChocolateFactoryAPI.chocolatePerSecond - val perMinute = perSecond * 60 - val perHour = perMinute * 60 - val perDay = perHour * 24 - val position = ChocolateFactoryAPI.leaderboardPosition?.addSeparators() ?: "???" - val percentile = ChocolateFactoryAPI.leaderboardPercentile?.let { "§7Top §a$it%" } ?: "" - val timeTowerInfo = if (ChocolateFactoryTimeTowerManager.timeTowerActive()) { - "§d§lActive" - } else { - "§6${ChocolateFactoryTimeTowerManager.timeTowerCharges()}" - } - - val prestigeEstimate = ChocolateAmount.PRESTIGE.formattedTimeUntilGoal(ChocolateFactoryAPI.chocolateForPrestige) - - val map = buildMap { - put(ChocolateFactoryStat.HEADER, "§6§lChocolate Factory Stats") - - put(ChocolateFactoryStat.CURRENT, "§eCurrent Chocolate: §6${ChocolateAmount.CURRENT.formatted}") - put(ChocolateFactoryStat.THIS_PRESTIGE, "§eThis Prestige: §6${ChocolateAmount.PRESTIGE.formatted}") - put(ChocolateFactoryStat.ALL_TIME, "§eAll-time: §6${ChocolateAmount.ALL_TIME.formatted}") - - put(ChocolateFactoryStat.PER_SECOND, "§ePer Second: §6${perSecond.addSeparators()}") - put(ChocolateFactoryStat.PER_MINUTE, "§ePer Minute: §6${perMinute.addSeparators()}") - put(ChocolateFactoryStat.PER_HOUR, "§ePer Hour: §6${perHour.addSeparators()}") - put(ChocolateFactoryStat.PER_DAY, "§ePer Day: §6${perDay.addSeparators()}") - - put(ChocolateFactoryStat.MULTIPLIER, "§eChocolate Multiplier: §6${profileStorage.chocolateMultiplier}") - put(ChocolateFactoryStat.BARN, "§eBarn: §6${ChocolateFactoryBarnManager.barnStatus()}") - - put(ChocolateFactoryStat.LEADERBOARD_POS, "§ePosition: §7#§b$position $percentile") - - put(ChocolateFactoryStat.EMPTY, "") - put(ChocolateFactoryStat.EMPTY_2, "") - put(ChocolateFactoryStat.EMPTY_3, "") - - put(ChocolateFactoryStat.TIME_TOWER, "§eTime Tower: §6$timeTowerInfo") - put(ChocolateFactoryStat.TIME_TO_PRESTIGE, "§eTime To Prestige: $prestigeEstimate") - put( - ChocolateFactoryStat.RAW_PER_SECOND, - "§eRaw Per Second: §6${profileStorage.rawChocPerSecond.addSeparators()}" - ) - } - val text = config.statsDisplayList.mapNotNull { map[it] } - - display = listOf(Renderable.clickAndHover( - Renderable.verticalContainer(text.map(Renderable::string)), - tips = listOf("§bCopy to Clipboard!"), - onClick = { - val list = text.toMutableList() - val titleHeader = list.indexOf("§6§lChocolate Factory Stats") - if (titleHeader != -1) { - list[titleHeader] = "${LorenzUtils.getPlayerName()}'s Chocolate Factory Stats" - } else { - list.add(0, "${LorenzUtils.getPlayerName()}'s Chocolate Factory Stats") - } - ClipboardUtils.copyToClipboard(list.joinToString("\n") { it.removeColor() }) - } - )) - } - - @SubscribeEvent - fun onConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) { - event.transform(42, "event.chocolateFactory.statsDisplayList") { element -> - val jsonArray = element.asJsonArray - - jsonArray.add(JsonPrimitive("TIME_TOWER")) - jsonArray.add(JsonPrimitive("TIME_TO_PRESTIGE")) - - jsonArray - } - } - - enum class ChocolateFactoryStat(private val display: String, val shouldDisplay: () -> Boolean = { true }) { - HEADER("§6§lChocolate Factory Stats"), - CURRENT("§eCurrent Chocolate: §65,272,230"), - THIS_PRESTIGE("§eThis Prestige: §6483,023,853", { ChocolateFactoryAPI.currentPrestige != 1 }), - ALL_TIME("§eAll-time: §6641,119,115"), - PER_SECOND("§ePer Second: §63,780.72"), - PER_MINUTE("§ePer Minute: §6226,843.2"), - PER_HOUR("§ePer Hour: §613,610,592"), - PER_DAY("§ePer Day: §6326,654,208"), - MULTIPLIER("§eChocolate Multiplier: §61.77"), - BARN("§eBarn: §6171/190 Rabbits"), - LEADERBOARD_POS("§ePosition: §7#§b103 §7Top §a0.87%"), - EMPTY(""), - EMPTY_2(""), - EMPTY_3(""), - TIME_TOWER("§eTime Tower: §62/3 Charges", { ChocolateFactoryTimeTowerManager.currentCharges() != -1 }), - TIME_TO_PRESTIGE("§eTime To Prestige: §61d 13h 59m 4s", { ChocolateFactoryAPI.currentPrestige != 5 }), - RAW_PER_SECOND("§eRaw Per Second: §62,136"), - ; - - override fun toString(): String { - return display - } - } -} diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryTimeTowerManager.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryTimeTowerManager.kt deleted file mode 100644 index 2fe1af812..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryTimeTowerManager.kt +++ /dev/null @@ -1,113 +0,0 @@ -package at.hannibal2.skyhanni.features.event.chocolatefactory - -import at.hannibal2.skyhanni.events.ProfileJoinEvent -import at.hannibal2.skyhanni.events.SecondPassedEvent -import at.hannibal2.skyhanni.features.fame.ReminderUtils -import at.hannibal2.skyhanni.utils.ChatUtils -import at.hannibal2.skyhanni.utils.HypixelCommands -import at.hannibal2.skyhanni.utils.LorenzUtils -import at.hannibal2.skyhanni.utils.SimpleTimeMark -import at.hannibal2.skyhanni.utils.SoundUtils -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent -import kotlin.time.Duration -import kotlin.time.Duration.Companion.hours -import kotlin.time.Duration.Companion.milliseconds -import kotlin.time.Duration.Companion.minutes -import kotlin.time.Duration.Companion.seconds - -object ChocolateFactoryTimeTowerManager { - - private val config get() = ChocolateFactoryAPI.config - private val profileStorage get() = ChocolateFactoryAPI.profileStorage - - private var lastTimeTowerWarning = SimpleTimeMark.farPast() - - @SubscribeEvent - fun onSecondPassed(event: SecondPassedEvent) { - if (!LorenzUtils.inSkyBlock) return - val profileStorage = profileStorage ?: return - - if (SimpleTimeMark(profileStorage.currentTimeTowerEnds).isInPast()) { - profileStorage.currentTimeTowerEnds = SimpleTimeMark.farPast().toMillis() - } - - if (ChocolateFactoryAPI.inChocolateFactory) return - - val nextCharge = SimpleTimeMark(profileStorage.nextTimeTower) - - if (nextCharge.isInPast() && !nextCharge.isFarPast() && currentCharges() < maxCharges()) { - profileStorage.currentTimeTowerUses++ - - val nextTimeTower = SimpleTimeMark(profileStorage.nextTimeTower) + (profileStorage.timeTowerCooldown).hours - profileStorage.nextTimeTower = nextTimeTower.toMillis() - - if (!config.timeTowerWarning) return - ChatUtils.clickableChat( - "Your Time Tower has another charge available §7(${timeTowerCharges()})§e, " + - "Click here to use one", - onClick = { - HypixelCommands.chocolateFactory() - } - ) - SoundUtils.playBeepSound() - lastTimeTowerWarning = SimpleTimeMark.now() - return - } - checkTimeTowerWarning(false) - } - - fun checkTimeTowerWarning(inInventory: Boolean) { - if (!ChocolateFactoryAPI.isEnabled()) return - if (!config.timeTowerWarning) return - if (!timeTowerFull()) return - if (ReminderUtils.isBusy()) return - - val warningSeparation = if (inInventory) 30.seconds else 5.minutes - if (lastTimeTowerWarning.passedSince() < warningSeparation) return - - ChatUtils.clickableChat( - "§cYour Time Tower is full §7(${timeTowerCharges()})§c, " + - "Use one to avoid wasting time tower usages!", - onClick = { - HypixelCommands.chocolateFactory() - } - ) - SoundUtils.playBeepSound() - lastTimeTowerWarning = SimpleTimeMark.now() - } - - fun timeTowerCharges(): String { - return "${currentCharges()}/${maxCharges()} Charges" - } - - fun currentCharges(): Int { - return profileStorage?.currentTimeTowerUses ?: -1 - } - - private fun maxCharges(): Int { - return profileStorage?.maxTimeTowerUses ?: 3 - } - - fun timeTowerFull() = currentCharges() >= maxCharges() - - fun timeTowerActive(): Boolean { - val currentTime = profileStorage?.lastDataSave ?: 0 - val endTime = profileStorage?.currentTimeTowerEnds ?: 0 - - return endTime > currentTime - } - - fun timeTowerActiveDuration(): Duration { - if (!timeTowerActive()) return Duration.ZERO - val currentTime = profileStorage?.lastDataSave ?: 0 - val endTime = profileStorage?.currentTimeTowerEnds ?: 0 - - val duration = endTime - currentTime - return duration.milliseconds - } - - @SubscribeEvent - fun onProfileChange(event: ProfileJoinEvent) { - lastTimeTowerWarning = SimpleTimeMark.farPast() - } -} diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryTooltip.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryTooltip.kt deleted file mode 100644 index 3861fe76d..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryTooltip.kt +++ /dev/null @@ -1,92 +0,0 @@ -package at.hannibal2.skyhanni.features.event.chocolatefactory - -import at.hannibal2.skyhanni.events.LorenzToolTipEvent -import at.hannibal2.skyhanni.features.event.chocolatefactory.ChocolateFactoryAPI.profileStorage -import at.hannibal2.skyhanni.utils.LorenzUtils.round -import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators -import net.minecraftforge.fml.common.eventhandler.EventPriority -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent - -object ChocolateFactoryTooltip { - - private val config get() = ChocolateFactoryAPI.config - - private var ignoredSlotIndexes = listOf() - - fun updateIgnoredSlots() { - ignoredSlotIndexes = listOf( - ChocolateFactoryAPI.prestigeIndex, - ChocolateFactoryAPI.handCookieIndex, - ChocolateFactoryAPI.shrineIndex, - ChocolateFactoryAPI.barnIndex, - ) - } - - @SubscribeEvent(priority = EventPriority.HIGH) - fun onTooltip(event: LorenzToolTipEvent) { - if (!ChocolateFactoryAPI.inChocolateFactory) return - if (!config.extraTooltipStats) return - - val slotIndex = event.slot.slotNumber - if (slotIndex == ChocolateFactoryAPI.prestigeIndex) return - if (slotIndex !in ChocolateFactoryAPI.otherUpgradeSlots && slotIndex !in ChocolateFactoryAPI.rabbitSlots) return - - val upgradeCost = ChocolateFactoryAPI.getChocolateUpgradeCost(event.toolTip) ?: return - - event.toolTip.add("§8§m-----------------") - val timeToUpgrade = ChocolateAmount.CURRENT.formattedTimeUntilGoal(upgradeCost) - - event.toolTip.add("§7Time until upgrade: §e$timeToUpgrade") - - if (slotIndex in ignoredSlotIndexes) return - - val averageChocolate = averageChocPerSecond().round(2) - - val newAverageChocolate = when (slotIndex) { - in ChocolateFactoryAPI.rabbitSlots -> { - val chocolateIncrease = ChocolateFactoryAPI.rabbitSlots[slotIndex] ?: 0 - averageChocPerSecond(rawPerSecondIncrease = chocolateIncrease) - } - - ChocolateFactoryAPI.timeTowerIndex -> averageChocPerSecond(timeTowerLevelIncrease = 1) - ChocolateFactoryAPI.coachRabbitIndex -> averageChocPerSecond(baseMultiplierIncrease = 0.01) - else -> averageChocolate - }.round(2) - - val extra = (newAverageChocolate - averageChocolate).round(2) - val ratioForUpgrade = (upgradeCost / extra).round(2) - - event.toolTip.add("§7Extra: §6$extra §7choc/s") - event.toolTip.add("§7Effective Cost: §6${ratioForUpgrade.addSeparators()}") - - if (slotIndex == ChocolateFactoryAPI.timeTowerIndex) { - event.toolTip.add("§7One charge will give: §6${chocPerTimeTower().addSeparators()}") - } - } - - private fun averageChocPerSecond( - baseMultiplierIncrease: Double = 0.0, - rawPerSecondIncrease: Int = 0, - timeTowerLevelIncrease: Int = 0, - ): Double { - val profileStorage = profileStorage ?: return 0.0 - - val baseMultiplier = profileStorage.chocolateMultiplier + baseMultiplierIncrease - val rawPerSecond = profileStorage.rawChocPerSecond + rawPerSecondIncrease - val timeTowerLevel = profileStorage.timeTowerLevel + timeTowerLevelIncrease - - val timeTowerCooldown = profileStorage.timeTowerCooldown - - val basePerSecond = rawPerSecond * baseMultiplier - val towerCalc = (rawPerSecond * timeTowerLevel * .1) / timeTowerCooldown - - return basePerSecond + towerCalc - } - - private fun chocPerTimeTower(): Int { - val profileStorage = profileStorage ?: return 0 - val amountPerSecond = profileStorage.rawChocPerSecond * profileStorage.timeTowerLevel * .1 - val amountPerHour = amountPerSecond * 60 * 60 - return amountPerHour.toInt() - } -} diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/HoppityCollectionStats.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/HoppityCollectionStats.kt deleted file mode 100644 index ee3b3d2eb..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/HoppityCollectionStats.kt +++ /dev/null @@ -1,216 +0,0 @@ -package at.hannibal2.skyhanni.features.event.chocolatefactory - -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.utils.DisplayTableEntry -import at.hannibal2.skyhanni.utils.ItemUtils.getLore -import at.hannibal2.skyhanni.utils.LorenzUtils -import at.hannibal2.skyhanni.utils.LorenzUtils.round -import at.hannibal2.skyhanni.utils.NEUInternalName -import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName -import at.hannibal2.skyhanni.utils.NumberUtil.formatInt -import at.hannibal2.skyhanni.utils.RenderUtils.renderRenderables -import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher -import at.hannibal2.skyhanni.utils.StringUtils.matches -import at.hannibal2.skyhanni.utils.renderables.Renderable -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent - -class HoppityCollectionStats { - - private val config get() = ChocolateFactoryAPI.config - - private val patternGroup = ChocolateFactoryAPI.patternGroup.group("collection") - private val pagePattern by patternGroup.pattern( - "page.current", - "\\((?\\d+)/(?\\d+)\\) Hoppity's Collection" - ) - private val rabbitRarityPattern by patternGroup.pattern( - "rabbit.rarity", - "§.§L(?\\w+) RABBIT" - ) - private val duplicatesFoundPattern by patternGroup.pattern( - "duplicates.found", - "§7Duplicates Found: §a(?[\\d,]+)" - ) - private val rabbitNotFoundPattern by patternGroup.pattern( - "rabbit.notfound", - "(?:§.)+You have not found this rabbit yet!" - ) - private val rabbitsFoundPattern by patternGroup.pattern( - "rabbits.found", - "§.§l§m[ §a-z]+§r §.(?[0-9]+)§./§.(?[0-9]+)" - ) - - private var display = emptyList() - private val loggedRabbits = mutableMapOf() - private var inInventory = false - private var currentPage = 0 - - @SubscribeEvent - fun onInventoryOpen(event: InventoryFullyOpenedEvent) { - if (!isEnabled()) return - if (!pagePattern.matches(event.inventoryName)) return - - inInventory = true - - var totalAmount = 0 - - for ((_, item) in event.inventoryItems) { - val itemName = item.displayName ?: continue - val itemLore = item.getLore() - - 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() - } - } - - val rarity = rabbitRarity ?: continue - - if (itemName == "§dEinstein" && found) { - ChocolateFactoryAPI.profileStorage?.timeTowerCooldown = 7 - } - - val duplicates = duplicatesFound.coerceAtLeast(0) - loggedRabbits[itemName] = RabbitCollectionInfo(rarity, found, duplicates) - } - - var totalAmountFound = 0 - var totalRabbits = 0 - var totalDuplicates = 0 - var totalChocolatePerSecond = 0 - var totalChocolateMultiplier = 0.0 - - val table = mutableListOf() - for (rarity in RabbitCollectionRarity.entries) { - val filtered = loggedRabbits.filter { it.value.rarity == rarity } - - val isTotal = rarity == RabbitCollectionRarity.TOTAL - - 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) - - 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 displayDuplicates = if (isTotal) totalDuplicates else duplicates - val displayChocolatePerSecond = if (isTotal) totalChocolatePerSecond else chocolatePerSecond - val displayChocolateMultiplier = if (isTotal) totalChocolateMultiplier else chocolateMultiplier - - val hover = buildList { - add(title) - add("") - add("§7Unique Rabbits: §a$displayFound§7/§a$displayTotal") - add("§7Duplicate Rabbits: §a$displayDuplicates") - add("§7Total Rabbits Found: §a${displayFound + displayDuplicates}") - add("") - add("§7Chocolate Per Second: §a$displayChocolatePerSecond") - add("§7Chocolate Multiplier: §a${displayChocolateMultiplier.round(3)}") - } - table.add( - DisplayTableEntry( - title, - "§a$displayFound§7/§a$displayTotal", - displayFound.toDouble(), - rarity.item, - hover - ) - ) - } - - val newList = mutableListOf() - newList.add(Renderable.string("§eHoppity Rabbit Collection§f:")) - newList.add(LorenzUtils.fillTable(table, padding = 5)) - - if (totalAmount != totalRabbits) { - newList.add(Renderable.string("")) - newList.add( - Renderable.wrappedString( - "§cPlease Scroll through \n" + - "§call pages!", - width = 200, - ) - ) - } - - display = newList - } - - @SubscribeEvent - fun onInventoryClose(event: InventoryCloseEvent) { - inInventory = false - } - - @SubscribeEvent - fun onProfileChange(event: ProfileJoinEvent) { - display = emptyList() - loggedRabbits.clear() - currentPage = 0 - inInventory = false - } - - @SubscribeEvent - fun onBackgroundDraw(event: GuiRenderEvent.ChestGuiOverlayRenderEvent) { - if (!inInventory) return - - config.hoppityStatsPosition.renderRenderables( - display, - extraSpace = 5, - posLabel = "Hoppity's Collection Stats" - ) - } - - private fun isEnabled() = LorenzUtils.inSkyBlock && config.hoppityCollectionStats - - private data class RabbitCollectionInfo( - val rarity: RabbitCollectionRarity, - val found: Boolean, - val duplicates: Int, - ) - - // todo in future make the amount and multiplier work with mythic rabbits (can't until I have some) - private 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()), - TOTAL("§cTotal", 0, 0.0, "STAINED_GLASS-14".asInternalName()), - ; - - companion object { - fun fromDisplayName(displayName: String) = entries.firstOrNull { it.name == displayName } - } - } -} diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/HoppityEggLocator.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/HoppityEggLocator.kt deleted file mode 100644 index f375dd4bb..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/HoppityEggLocator.kt +++ /dev/null @@ -1,245 +0,0 @@ -package at.hannibal2.skyhanni.features.event.chocolatefactory - -import at.hannibal2.skyhanni.data.IslandType -import at.hannibal2.skyhanni.events.DebugDataCollectEvent -import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent -import at.hannibal2.skyhanni.events.LorenzTickEvent -import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent -import at.hannibal2.skyhanni.events.ReceiveParticleEvent -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.LorenzColor -import at.hannibal2.skyhanni.utils.LorenzUtils -import at.hannibal2.skyhanni.utils.LorenzUtils.round -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.drawDynamicText -import at.hannibal2.skyhanni.utils.SimpleTimeMark -import net.minecraft.item.ItemStack -import net.minecraft.util.EnumParticleTypes -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent -import kotlin.time.Duration.Companion.seconds - -object HoppityEggLocator { - - private val config get() = ChocolateFactoryAPI.config.hoppityEggs - - private val locatorItem = "EGGLOCATOR".asInternalName() - - private var lastParticlePosition: LorenzVec? = null - private val validParticleLocations = mutableListOf() - - private var drawLocations = false - private var firstPos = LorenzVec() - private var secondPos = LorenzVec() - private var possibleEggLocations = listOf() - - private var ticksSinceLastParticleFound = -1 - private var lastGuessMade = SimpleTimeMark.farPast() - private var eggLocationWeights = listOf() - - var sharedEggLocation: LorenzVec? = null - var currentEggType: HoppityEggType? = null - - var eggLocations: Map> = mapOf() - - @SubscribeEvent - fun onWorldChange(event: LorenzWorldChangeEvent) { - resetData() - } - - private fun resetData() { - validParticleLocations.clear() - ticksSinceLastParticleFound = -1 - possibleEggLocations = emptyList() - firstPos = LorenzVec() - secondPos = LorenzVec() - drawLocations = false - sharedEggLocation = null - currentEggType = null - } - - @SubscribeEvent - fun onRenderWorld(event: LorenzRenderWorldEvent) { - if (!isEnabled()) return - - event.draw3DLine(firstPos, secondPos, LorenzColor.RED.toColor(), 2, false) - - 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) - } - return - } - - val sharedEggLocation = sharedEggLocation - if (sharedEggLocation != null && config.sharedWaypoints) { - event.drawWaypointFilled( - sharedEggLocation, - LorenzColor.GREEN.toColor(), - seeThroughBlocks = true, - ) - event.drawDynamicText(sharedEggLocation.add(y = 1), "§aShared Egg", 1.5) - return - } - - if (!config.showAllWaypoints) return - if (hasLocatorInInventory()) 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) - } - } - - fun eggFound() { - resetData() - } - - @SubscribeEvent - fun onReceiveParticle(event: ReceiveParticleEvent) { - if (!isEnabled()) return - if (!hasLocatorInInventory()) return - if (!event.isVillagerParticle() && !event.isEnchantmentParticle()) return - - val lastParticlePosition = lastParticlePosition ?: run { - lastParticlePosition = event.location - return - } - if (lastParticlePosition == event.location) { - validParticleLocations.add(event.location) - ticksSinceLastParticleFound = 0 - } - HoppityEggLocator.lastParticlePosition = null - } - - @SubscribeEvent - fun onTick(event: LorenzTickEvent) { - if (!isEnabled()) return - if (validParticleLocations.isEmpty()) return - ticksSinceLastParticleFound++ - - if (ticksSinceLastParticleFound < 6) return - - calculateEggPosition() - - ticksSinceLastParticleFound = 0 - validParticleLocations.clear() - lastParticlePosition = null - } - - private fun calculateEggPosition() { - if (lastGuessMade.passedSince() < 1.seconds) return - lastGuessMade = SimpleTimeMark.now() - possibleEggLocations = emptyList() - - val islandEggsLocations = getCurrentIslandEggLocations() ?: return - val listSize = validParticleLocations.size - - if (listSize < 5) return - - val secondPoint = validParticleLocations.removeLast() - firstPos = validParticleLocations.removeLast() - - val xDiff = secondPoint.x - firstPos.x - val yDiff = secondPoint.y - firstPos.y - val zDiff = secondPoint.z - firstPos.z - - secondPos = LorenzVec( - secondPoint.x + xDiff * 1000, - secondPoint.y + yDiff * 1000, - secondPoint.z + zDiff * 1000 - ) - - val sortedEggs = islandEggsLocations.map { - it to it.getEggLocationWeight(firstPos, secondPos) - }.sortedBy { it.second } - - eggLocationWeights = sortedEggs.map { - it.second.round(3) - }.take(5) - - val filteredEggs = sortedEggs.filter { - it.second < 1 - }.map { it.first } - - val maxLineDistance = filteredEggs.sortedByDescending { - it.nearestPointOnLine(firstPos, secondPos).distance(firstPos) - } - - if (maxLineDistance.isEmpty()) { - LorenzUtils.sendTitle("§cNo eggs found, try getting closer", 2.seconds) - return - } - secondPos = maxLineDistance.first().nearestPointOnLine(firstPos, secondPos) - - possibleEggLocations = filteredEggs - - drawLocations = true - } - - fun getCurrentIslandEggLocations(): List? = - eggLocations[LorenzUtils.skyBlockIsland] - - fun isValidEggLocation(location: LorenzVec): Boolean = - getCurrentIslandEggLocations()?.any { it.distance(location) < 5.0 } ?: false - - private fun ReceiveParticleEvent.isVillagerParticle() = - type == EnumParticleTypes.VILLAGER_HAPPY && speed == 0.0f && count == 1 - - private fun ReceiveParticleEvent.isEnchantmentParticle() = - type == EnumParticleTypes.ENCHANTMENT_TABLE && speed == -2.0f && count == 10 - - private fun isEnabled() = LorenzUtils.inSkyBlock && config.waypoints - && ChocolateFactoryAPI.isHoppityEvent() - - private val ItemStack.isLocatorItem get() = getInternalName() == locatorItem - - fun hasLocatorInInventory() = RecalculatingValue(1.seconds) { - LorenzUtils.inSkyBlock && InventoryUtils.getItemsInOwnInventory().any { it.isLocatorItem } - }.getValue() - - private fun LorenzVec.getEggLocationWeight(firstPoint: LorenzVec, secondPoint: LorenzVec): Double { - val distToLine = this.distanceToLine(firstPoint, secondPoint) - val distToStart = this.distance(firstPoint) - val distMultiplier = distToStart * 2 / 100 + 5 - val disMultiplierSquared = distMultiplier * distMultiplier - return distToLine / disMultiplierSquared - } - - @SubscribeEvent - fun onDebugDataCollect(event: DebugDataCollectEvent) { - event.title("Hoppity Eggs Locations") - - if (!isEnabled()) { - event.addIrrelevant("not in skyblock or waypoints are disabled") - return - } - - event.addData { - add("First Pos: $firstPos") - add("Second Pos: $secondPos") - add("Possible Egg Locations: ${possibleEggLocations.size}") - add("Egg Location Weights: $eggLocationWeights") - add("Last Time Checked: ${lastGuessMade.passedSince().inWholeSeconds}s ago") - add("Draw Locations: $drawLocations") - add("Shared Egg Location: ${sharedEggLocation ?: "None"}") - add("Current Egg Type: ${currentEggType ?: "None"}") - } - } -} diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/HoppityEggType.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/HoppityEggType.kt deleted file mode 100644 index 80a03c050..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/HoppityEggType.kt +++ /dev/null @@ -1,53 +0,0 @@ -package at.hannibal2.skyhanni.features.event.chocolatefactory - -import io.github.moulberry.notenoughupdates.util.SkyBlockTime - -enum class HoppityEggType( - val mealName: String, - val resetsAt: Int, - private val mealColour: String, - var lastResetDay: Int = -1, - private var claimed: Boolean = false, -) { - BREAKFAST("Breakfast", 7, "§a"), - LUNCH("Lunch", 14, "§9"), - DINNER("Dinner", 21, "§6"), - ; - - fun markClaimed() { - claimed = true - } - - fun markSpawned() { - claimed = false - } - - fun isClaimed() = claimed - val formattedName by lazy { "$mealColour$mealName" } - - companion object { - fun allFound() = entries.forEach { it.markClaimed() } - - fun getMealByName(mealName: String) = entries.find { it.mealName == mealName } - - fun checkClaimed() { - val currentSbTime = SkyBlockTime.now() - val currentSbDay = currentSbTime.day - val currentSbHour = currentSbTime.hour - - for (eggType in entries) { - if (currentSbHour < eggType.resetsAt || eggType.lastResetDay == currentSbDay) continue - eggType.markSpawned() - eggType.lastResetDay = currentSbDay - if (HoppityEggLocator.currentEggType == eggType) { - HoppityEggLocator.currentEggType = null - HoppityEggLocator.sharedEggLocation = null - } - } - } - - fun eggsRemaining(): Boolean { - return entries.any { !it.claimed } - } - } -} diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/HoppityEggsManager.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/HoppityEggsManager.kt deleted file mode 100644 index 168afe3aa..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/HoppityEggsManager.kt +++ /dev/null @@ -1,117 +0,0 @@ -package at.hannibal2.skyhanni.features.event.chocolatefactory - -import at.hannibal2.skyhanni.events.GuiRenderEvent -import at.hannibal2.skyhanni.events.LorenzChatEvent -import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent -import at.hannibal2.skyhanni.events.SecondPassedEvent -import at.hannibal2.skyhanni.features.fame.ReminderUtils -import at.hannibal2.skyhanni.test.command.ErrorManager -import at.hannibal2.skyhanni.utils.ChatUtils -import at.hannibal2.skyhanni.utils.DelayedRun -import at.hannibal2.skyhanni.utils.LocationUtils -import at.hannibal2.skyhanni.utils.LorenzUtils -import at.hannibal2.skyhanni.utils.RenderUtils.renderStrings -import at.hannibal2.skyhanni.utils.SimpleTimeMark.Companion.fromNow -import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent -import java.util.regex.Matcher -import kotlin.time.Duration.Companion.seconds - -object HoppityEggsManager { - - private val config get() = ChocolateFactoryAPI.config.hoppityEggs - - private val eggFoundPattern by ChocolateFactoryAPI.patternGroup.pattern( - "egg.found", - "§d§lHOPPITY'S HUNT §r§dYou found a §r§.Chocolate (?\\w+) Egg.*" - ) - private val noEggsLeftPattern by ChocolateFactoryAPI.patternGroup.pattern( - "egg.noneleft", - "§cThere are no hidden Chocolate Rabbit Eggs nearby! Try again later!" - ) - private val eggSpawnedPattern by ChocolateFactoryAPI.patternGroup.pattern( - "egg.spawned", - "§d§lHOPPITY'S HUNT §r§dA §r§.Chocolate (?\\w+) Egg §r§dhas appeared!" - ) - private val eggAlreadyCollectedPattern by ChocolateFactoryAPI.patternGroup.pattern( - "egg.alreadycollected", - "§cYou have already collected this Chocolate (?\\w+) Egg§r§c! Try again when it respawns!" - ) - - private var lastMeal: HoppityEggType? = null - - @SubscribeEvent - fun onWorldChange(event: LorenzWorldChangeEvent) { - lastMeal = null - } - - @SubscribeEvent - fun onChat(event: LorenzChatEvent) { - if (!LorenzUtils.inSkyBlock) return - - eggFoundPattern.matchMatcher(event.message) { - HoppityEggLocator.eggFound() - val meal = getEggType(event) - meal.markClaimed() - lastMeal = meal - } - - noEggsLeftPattern.matchMatcher(event.message) { - HoppityEggType.allFound() - return - } - - eggAlreadyCollectedPattern.matchMatcher(event.message) { - getEggType(event).markClaimed() - } - - eggSpawnedPattern.matchMatcher(event.message) { - getEggType(event).markSpawned() - } - } - - internal fun Matcher.getEggType(event: LorenzChatEvent): HoppityEggType = - HoppityEggType.getMealByName(group("meal")) ?: run { - ErrorManager.skyHanniError( - "Unknown meal: ${group("meal")}", - "message" to event.message - ) - } - - fun shareWaypointPrompt() { - if (!config.sharedWaypoints) return - val meal = lastMeal ?: return - lastMeal = null - - val currentLocation = LocationUtils.playerLocation() - DelayedRun.runNextTick { - ChatUtils.clickableChat( - "Click here to share the location of this chocolate egg with the server!", - onClick = { HoppityEggsShared.shareNearbyEggLocation(currentLocation, meal) }, - expireAt = 30.seconds.fromNow() - ) - } - } - - @SubscribeEvent - fun onRenderOverlay(event: GuiRenderEvent.GuiOverlayRenderEvent) { - if (!LorenzUtils.inSkyBlock) return - if (!config.showClaimedEggs) return - if (ReminderUtils.isBusy()) return - if (!ChocolateFactoryAPI.isHoppityEvent()) return - - val displayList = HoppityEggType.entries - .filter { !it.isClaimed() } - .map { "§7 - ${it.formattedName}" } - .toMutableList() - displayList.add(0, "§bUnfound Eggs:") - if (displayList.size == 1) return - - config.position.renderStrings(displayList, posLabel = "Hoppity Eggs") - } - - @SubscribeEvent - fun onSecondPassed(event: SecondPassedEvent) { - HoppityEggType.checkClaimed() - } -} diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/HoppityEggsShared.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/HoppityEggsShared.kt deleted file mode 100644 index 3dac4b856..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/HoppityEggsShared.kt +++ /dev/null @@ -1,57 +0,0 @@ -package at.hannibal2.skyhanni.features.event.chocolatefactory - -import at.hannibal2.skyhanni.events.LorenzChatEvent -import at.hannibal2.skyhanni.features.event.chocolatefactory.HoppityEggsManager.getEggType -import at.hannibal2.skyhanni.utils.ChatUtils -import at.hannibal2.skyhanni.utils.LorenzUtils -import at.hannibal2.skyhanni.utils.LorenzVec -import at.hannibal2.skyhanni.utils.NumberUtil.formatInt -import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher -import at.hannibal2.skyhanni.utils.StringUtils.removeColor -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent - -object HoppityEggsShared { - - private val config get() = ChocolateFactoryAPI.config.hoppityEggs - - /** - * REGEX-TEST: CalMWolfs: [SkyHanni] Breakfast Chocolate Egg located at x: 142, y: 71, z: -453 - */ - private val sharedEggPattern by ChocolateFactoryAPI.patternGroup.pattern( - "egg.shared", - ".*\\[SkyHanni] (?\\w+) Chocolate Egg located at x: (?-?\\d+), y: (?-?\\d+), z: (?-?\\d+)" - ) - - @SubscribeEvent - fun onChat(event: LorenzChatEvent) { - if (!isEnabled()) return - - sharedEggPattern.matchMatcher(event.message.removeColor()) { - val (x, y, z) = listOf(group("x"), group("y"), group("z")).map { it.formatInt() } - val eggLocation = LorenzVec(x, y, z) - - val meal = getEggType(event) - - if (meal.isClaimed()) return - if (!HoppityEggLocator.isValidEggLocation(eggLocation)) return - - HoppityEggLocator.sharedEggLocation = eggLocation - HoppityEggLocator.currentEggType = meal - } - } - - fun shareNearbyEggLocation(playerLocation: LorenzVec, meal: HoppityEggType) { - if (!isEnabled()) return - val islandEggsLocations = HoppityEggLocator.getCurrentIslandEggLocations() ?: return - val closestEgg = islandEggsLocations.minByOrNull { it.distance(playerLocation) } ?: return - - val x = closestEgg.x.toInt() - val y = closestEgg.y.toInt() - val z = closestEgg.z.toInt() - - val message = "[SkyHanni] ${meal.mealName} Chocolate Egg located at x: $x, y: $y, z: $z" - ChatUtils.sendCommandToServer("ac $message") - } - - fun isEnabled() = LorenzUtils.inSkyBlock && config.waypoints && config.sharedWaypoints -} diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/HoppityNpc.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/HoppityNpc.kt deleted file mode 100644 index 527b3ea40..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/HoppityNpc.kt +++ /dev/null @@ -1,66 +0,0 @@ -package at.hannibal2.skyhanni.features.event.chocolatefactory - -import at.hannibal2.skyhanni.events.GuiContainerEvent -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.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 net.minecraftforge.fml.common.eventhandler.SubscribeEvent - -object HoppityNpc { - - private val config get() = ChocolateFactoryAPI.config - - private var slotsToHighlight = mutableSetOf() - private var inShop = false - - @SubscribeEvent - fun onInventoryOpen(event: InventoryFullyOpenedEvent) { - if (!isEnabled()) return - if (event.inventoryName != "Hoppity") return - inShop = true - } - - private fun clear() { - inShop = false - slotsToHighlight.clear() - } - - @SubscribeEvent - fun onInventoryClose(event: InventoryCloseEvent) { - clear() - } - - @SubscribeEvent - fun onWorldChange(event: LorenzWorldChangeEvent) { - clear() - } - - @SubscribeEvent - fun onInventoryUpdated(event: InventoryUpdatedEvent) { - if (!inShop) return - slotsToHighlight.clear() - for ((slot, item) in event.inventoryItems) { - if (item.getLore().contains("§eClick to trade!")) { - slotsToHighlight.add(slot) - } - } - } - - @SubscribeEvent - fun onBackgroundDrawn(event: GuiContainerEvent.BackgroundDrawnEvent) { - if (!inShop) return - for (slot in InventoryUtils.getItemsInOpenChest()) { - if (slot.slotIndex in slotsToHighlight) { - slot highlight LorenzColor.GREEN.addOpacity(200) - } - } - } - - fun isEnabled() = LorenzUtils.inSkyBlock && config.highlightHoppityShop -} diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/clicks/FactoryItemTooltipFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/clicks/FactoryItemTooltipFeatures.kt deleted file mode 100644 index a7d2a3c79..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/clicks/FactoryItemTooltipFeatures.kt +++ /dev/null @@ -1,77 +0,0 @@ -package at.hannibal2.skyhanni.features.event.chocolatefactory.clicks - -import at.hannibal2.skyhanni.events.GuiContainerEvent -import at.hannibal2.skyhanni.events.GuiRenderEvent -import at.hannibal2.skyhanni.events.LorenzToolTipEvent -import at.hannibal2.skyhanni.features.event.chocolatefactory.ChocolateFactoryAPI -import at.hannibal2.skyhanni.utils.CollectionUtils.getOrNull -import at.hannibal2.skyhanni.utils.ItemUtils.getLore -import at.hannibal2.skyhanni.utils.ItemUtils.name -import at.hannibal2.skyhanni.utils.RenderUtils.renderStrings -import at.hannibal2.skyhanni.utils.SimpleTimeMark -import net.minecraftforge.fml.common.eventhandler.EventPriority -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent -import kotlin.time.Duration.Companion.milliseconds -import kotlin.time.Duration.Companion.seconds - -object FactoryItemTooltipFeatures { - private val config get() = ChocolateFactoryAPI.config - - private var lastClick = SimpleTimeMark.farPast() - private var lastHover = SimpleTimeMark.farPast() - private var tooltipToHover = listOf() - - @SubscribeEvent - fun onTooltip(event: LorenzToolTipEvent) { - if (!ChocolateFactoryAPI.inChocolateFactory) return - - if (config.tooltipMove) { - if (event.slot.slotNumber <= 44) { - lastHover = SimpleTimeMark.now() - tooltipToHover = event.toolTip.toList() - event.cancel() - } else { - lastHover = SimpleTimeMark.farPast() - } - return - } - - onCompactClick(event) - } - - @SubscribeEvent - fun onBackgroundDraw(event: GuiRenderEvent.ChestGuiOverlayRenderEvent) { - if (!ChocolateFactoryAPI.inChocolateFactory) return - if (config.tooltipMove) { - if (lastHover.passedSince() < 300.milliseconds) { - config.tooltipMovePosition.renderStrings(tooltipToHover, posLabel = "Tooltip Move") - } - } - } - - private fun onCompactClick(event: LorenzToolTipEvent) { - if (!config.compactOnClick) return - - val itemStack = event.itemStack - val lore = itemStack.getLore() - if (!lore.any { it == "§7§eClick to uncover the meaning of life!" }) return - if (lastClick.passedSince() >= 1.seconds && !config.compactOnClickAlways) return - val list = mutableListOf() - list.add(itemStack.name) - lore.getOrNull(5)?.let { - list.add(it) - } - event.toolTip = list - return - } - - @SubscribeEvent(priority = EventPriority.HIGH) - fun onSlotClick(event: GuiContainerEvent.SlotClickEvent) { - - if (ChocolateFactoryAPI.inChocolateFactory) { - if (event.slotId == 13) { - lastClick = SimpleTimeMark.now() - } - } - } -} diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/hoppity/HoppityCollectionStats.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/hoppity/HoppityCollectionStats.kt new file mode 100644 index 000000000..09091532a --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/hoppity/HoppityCollectionStats.kt @@ -0,0 +1,217 @@ +package at.hannibal2.skyhanni.features.event.chocolatefactory.hoppity + +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.event.chocolatefactory.ChocolateFactoryAPI +import at.hannibal2.skyhanni.utils.DisplayTableEntry +import at.hannibal2.skyhanni.utils.ItemUtils.getLore +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.LorenzUtils.round +import at.hannibal2.skyhanni.utils.NEUInternalName +import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName +import at.hannibal2.skyhanni.utils.NumberUtil.formatInt +import at.hannibal2.skyhanni.utils.RenderUtils.renderRenderables +import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher +import at.hannibal2.skyhanni.utils.StringUtils.matches +import at.hannibal2.skyhanni.utils.renderables.Renderable +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +class HoppityCollectionStats { + + private val config get() = ChocolateFactoryAPI.config + + private val patternGroup = ChocolateFactoryAPI.patternGroup.group("collection") + private val pagePattern by patternGroup.pattern( + "page.current", + "\\((?\\d+)/(?\\d+)\\) Hoppity's Collection" + ) + private val rabbitRarityPattern by patternGroup.pattern( + "rabbit.rarity", + "§.§L(?\\w+) RABBIT" + ) + private val duplicatesFoundPattern by patternGroup.pattern( + "duplicates.found", + "§7Duplicates Found: §a(?[\\d,]+)" + ) + private val rabbitNotFoundPattern by patternGroup.pattern( + "rabbit.notfound", + "(?:§.)+You have not found this rabbit yet!" + ) + private val rabbitsFoundPattern by patternGroup.pattern( + "rabbits.found", + "§.§l§m[ §a-z]+§r §.(?[0-9]+)§./§.(?[0-9]+)" + ) + + private var display = emptyList() + private val loggedRabbits = mutableMapOf() + private var inInventory = false + private var currentPage = 0 + + @SubscribeEvent + fun onInventoryOpen(event: InventoryFullyOpenedEvent) { + if (!isEnabled()) return + if (!pagePattern.matches(event.inventoryName)) return + + inInventory = true + + var totalAmount = 0 + + for ((_, item) in event.inventoryItems) { + val itemName = item.displayName ?: continue + val itemLore = item.getLore() + + 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() + } + } + + val rarity = rabbitRarity ?: continue + + if (itemName == "§dEinstein" && found) { + ChocolateFactoryAPI.profileStorage?.timeTowerCooldown = 7 + } + + val duplicates = duplicatesFound.coerceAtLeast(0) + loggedRabbits[itemName] = RabbitCollectionInfo(rarity, found, duplicates) + } + + var totalAmountFound = 0 + var totalRabbits = 0 + var totalDuplicates = 0 + var totalChocolatePerSecond = 0 + var totalChocolateMultiplier = 0.0 + + val table = mutableListOf() + for (rarity in RabbitCollectionRarity.entries) { + val filtered = loggedRabbits.filter { it.value.rarity == rarity } + + val isTotal = rarity == RabbitCollectionRarity.TOTAL + + 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) + + 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 displayDuplicates = if (isTotal) totalDuplicates else duplicates + val displayChocolatePerSecond = if (isTotal) totalChocolatePerSecond else chocolatePerSecond + val displayChocolateMultiplier = if (isTotal) totalChocolateMultiplier else chocolateMultiplier + + val hover = buildList { + add(title) + add("") + add("§7Unique Rabbits: §a$displayFound§7/§a$displayTotal") + add("§7Duplicate Rabbits: §a$displayDuplicates") + add("§7Total Rabbits Found: §a${displayFound + displayDuplicates}") + add("") + add("§7Chocolate Per Second: §a$displayChocolatePerSecond") + add("§7Chocolate Multiplier: §a${displayChocolateMultiplier.round(3)}") + } + table.add( + DisplayTableEntry( + title, + "§a$displayFound§7/§a$displayTotal", + displayFound.toDouble(), + rarity.item, + hover + ) + ) + } + + val newList = mutableListOf() + newList.add(Renderable.string("§eHoppity Rabbit Collection§f:")) + newList.add(LorenzUtils.fillTable(table, padding = 5)) + + if (totalAmount != totalRabbits) { + newList.add(Renderable.string("")) + newList.add( + Renderable.wrappedString( + "§cPlease Scroll through \n" + + "§call pages!", + width = 200, + ) + ) + } + + display = newList + } + + @SubscribeEvent + fun onInventoryClose(event: InventoryCloseEvent) { + inInventory = false + } + + @SubscribeEvent + fun onProfileChange(event: ProfileJoinEvent) { + display = emptyList() + loggedRabbits.clear() + currentPage = 0 + inInventory = false + } + + @SubscribeEvent + fun onBackgroundDraw(event: GuiRenderEvent.ChestGuiOverlayRenderEvent) { + if (!inInventory) return + + config.hoppityStatsPosition.renderRenderables( + display, + extraSpace = 5, + posLabel = "Hoppity's Collection Stats" + ) + } + + private fun isEnabled() = LorenzUtils.inSkyBlock && config.hoppityCollectionStats + + private data class RabbitCollectionInfo( + val rarity: RabbitCollectionRarity, + val found: Boolean, + val duplicates: Int, + ) + + // todo in future make the amount and multiplier work with mythic rabbits (can't until I have some) + private 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()), + TOTAL("§cTotal", 0, 0.0, "STAINED_GLASS-14".asInternalName()), + ; + + companion object { + fun fromDisplayName(displayName: String) = entries.firstOrNull { it.name == displayName } + } + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/hoppity/HoppityEggLocator.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/hoppity/HoppityEggLocator.kt new file mode 100644 index 000000000..b6767f7b8 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/hoppity/HoppityEggLocator.kt @@ -0,0 +1,246 @@ +package at.hannibal2.skyhanni.features.event.chocolatefactory.hoppity + +import at.hannibal2.skyhanni.data.IslandType +import at.hannibal2.skyhanni.events.DebugDataCollectEvent +import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent +import at.hannibal2.skyhanni.events.LorenzTickEvent +import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent +import at.hannibal2.skyhanni.events.ReceiveParticleEvent +import at.hannibal2.skyhanni.features.event.chocolatefactory.ChocolateFactoryAPI +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.LorenzColor +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.LorenzUtils.round +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.drawDynamicText +import at.hannibal2.skyhanni.utils.SimpleTimeMark +import net.minecraft.item.ItemStack +import net.minecraft.util.EnumParticleTypes +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import kotlin.time.Duration.Companion.seconds + +object HoppityEggLocator { + + private val config get() = ChocolateFactoryAPI.config.hoppityEggs + + private val locatorItem = "EGGLOCATOR".asInternalName() + + private var lastParticlePosition: LorenzVec? = null + private val validParticleLocations = mutableListOf() + + private var drawLocations = false + private var firstPos = LorenzVec() + private var secondPos = LorenzVec() + private var possibleEggLocations = listOf() + + private var ticksSinceLastParticleFound = -1 + private var lastGuessMade = SimpleTimeMark.farPast() + private var eggLocationWeights = listOf() + + var sharedEggLocation: LorenzVec? = null + var currentEggType: HoppityEggType? = null + + var eggLocations: Map> = mapOf() + + @SubscribeEvent + fun onWorldChange(event: LorenzWorldChangeEvent) { + resetData() + } + + private fun resetData() { + validParticleLocations.clear() + ticksSinceLastParticleFound = -1 + possibleEggLocations = emptyList() + firstPos = LorenzVec() + secondPos = LorenzVec() + drawLocations = false + sharedEggLocation = null + currentEggType = null + } + + @SubscribeEvent + fun onRenderWorld(event: LorenzRenderWorldEvent) { + if (!isEnabled()) return + + event.draw3DLine(firstPos, secondPos, LorenzColor.RED.toColor(), 2, false) + + 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) + } + return + } + + val sharedEggLocation = sharedEggLocation + if (sharedEggLocation != null && config.sharedWaypoints) { + event.drawWaypointFilled( + sharedEggLocation, + LorenzColor.GREEN.toColor(), + seeThroughBlocks = true, + ) + event.drawDynamicText(sharedEggLocation.add(y = 1), "§aShared Egg", 1.5) + return + } + + if (!config.showAllWaypoints) return + if (hasLocatorInInventory()) 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) + } + } + + fun eggFound() { + resetData() + } + + @SubscribeEvent + fun onReceiveParticle(event: ReceiveParticleEvent) { + if (!isEnabled()) return + if (!hasLocatorInInventory()) return + if (!event.isVillagerParticle() && !event.isEnchantmentParticle()) return + + val lastParticlePosition = lastParticlePosition ?: run { + lastParticlePosition = event.location + return + } + if (lastParticlePosition == event.location) { + validParticleLocations.add(event.location) + ticksSinceLastParticleFound = 0 + } + HoppityEggLocator.lastParticlePosition = null + } + + @SubscribeEvent + fun onTick(event: LorenzTickEvent) { + if (!isEnabled()) return + if (validParticleLocations.isEmpty()) return + ticksSinceLastParticleFound++ + + if (ticksSinceLastParticleFound < 6) return + + calculateEggPosition() + + ticksSinceLastParticleFound = 0 + validParticleLocations.clear() + lastParticlePosition = null + } + + private fun calculateEggPosition() { + if (lastGuessMade.passedSince() < 1.seconds) return + lastGuessMade = SimpleTimeMark.now() + possibleEggLocations = emptyList() + + val islandEggsLocations = getCurrentIslandEggLocations() ?: return + val listSize = validParticleLocations.size + + if (listSize < 5) return + + val secondPoint = validParticleLocations.removeLast() + firstPos = validParticleLocations.removeLast() + + val xDiff = secondPoint.x - firstPos.x + val yDiff = secondPoint.y - firstPos.y + val zDiff = secondPoint.z - firstPos.z + + secondPos = LorenzVec( + secondPoint.x + xDiff * 1000, + secondPoint.y + yDiff * 1000, + secondPoint.z + zDiff * 1000 + ) + + val sortedEggs = islandEggsLocations.map { + it to it.getEggLocationWeight(firstPos, secondPos) + }.sortedBy { it.second } + + eggLocationWeights = sortedEggs.map { + it.second.round(3) + }.take(5) + + val filteredEggs = sortedEggs.filter { + it.second < 1 + }.map { it.first } + + val maxLineDistance = filteredEggs.sortedByDescending { + it.nearestPointOnLine(firstPos, secondPos).distance(firstPos) + } + + if (maxLineDistance.isEmpty()) { + LorenzUtils.sendTitle("§cNo eggs found, try getting closer", 2.seconds) + return + } + secondPos = maxLineDistance.first().nearestPointOnLine(firstPos, secondPos) + + possibleEggLocations = filteredEggs + + drawLocations = true + } + + fun getCurrentIslandEggLocations(): List? = + eggLocations[LorenzUtils.skyBlockIsland] + + fun isValidEggLocation(location: LorenzVec): Boolean = + getCurrentIslandEggLocations()?.any { it.distance(location) < 5.0 } ?: false + + private fun ReceiveParticleEvent.isVillagerParticle() = + type == EnumParticleTypes.VILLAGER_HAPPY && speed == 0.0f && count == 1 + + private fun ReceiveParticleEvent.isEnchantmentParticle() = + type == EnumParticleTypes.ENCHANTMENT_TABLE && speed == -2.0f && count == 10 + + private fun isEnabled() = LorenzUtils.inSkyBlock && config.waypoints + && ChocolateFactoryAPI.isHoppityEvent() + + private val ItemStack.isLocatorItem get() = getInternalName() == locatorItem + + fun hasLocatorInInventory() = RecalculatingValue(1.seconds) { + LorenzUtils.inSkyBlock && InventoryUtils.getItemsInOwnInventory().any { it.isLocatorItem } + }.getValue() + + private fun LorenzVec.getEggLocationWeight(firstPoint: LorenzVec, secondPoint: LorenzVec): Double { + val distToLine = this.distanceToLine(firstPoint, secondPoint) + val distToStart = this.distance(firstPoint) + val distMultiplier = distToStart * 2 / 100 + 5 + val disMultiplierSquared = distMultiplier * distMultiplier + return distToLine / disMultiplierSquared + } + + @SubscribeEvent + fun onDebugDataCollect(event: DebugDataCollectEvent) { + event.title("Hoppity Eggs Locations") + + if (!isEnabled()) { + event.addIrrelevant("not in skyblock or waypoints are disabled") + return + } + + event.addData { + add("First Pos: $firstPos") + add("Second Pos: $secondPos") + add("Possible Egg Locations: ${possibleEggLocations.size}") + add("Egg Location Weights: $eggLocationWeights") + add("Last Time Checked: ${lastGuessMade.passedSince().inWholeSeconds}s ago") + add("Draw Locations: $drawLocations") + add("Shared Egg Location: ${sharedEggLocation ?: "None"}") + add("Current Egg Type: ${currentEggType ?: "None"}") + } + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/hoppity/HoppityEggType.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/hoppity/HoppityEggType.kt new file mode 100644 index 000000000..295e95d9c --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/hoppity/HoppityEggType.kt @@ -0,0 +1,53 @@ +package at.hannibal2.skyhanni.features.event.chocolatefactory.hoppity + +import io.github.moulberry.notenoughupdates.util.SkyBlockTime + +enum class HoppityEggType( + val mealName: String, + val resetsAt: Int, + private val mealColour: String, + var lastResetDay: Int = -1, + private var claimed: Boolean = false, +) { + BREAKFAST("Breakfast", 7, "§a"), + LUNCH("Lunch", 14, "§9"), + DINNER("Dinner", 21, "§6"), + ; + + fun markClaimed() { + claimed = true + } + + fun markSpawned() { + claimed = false + } + + fun isClaimed() = claimed + val formattedName by lazy { "$mealColour$mealName" } + + companion object { + fun allFound() = entries.forEach { it.markClaimed() } + + fun getMealByName(mealName: String) = entries.find { it.mealName == mealName } + + fun checkClaimed() { + val currentSbTime = SkyBlockTime.now() + val currentSbDay = currentSbTime.day + val currentSbHour = currentSbTime.hour + + for (eggType in entries) { + if (currentSbHour < eggType.resetsAt || eggType.lastResetDay == currentSbDay) continue + eggType.markSpawned() + eggType.lastResetDay = currentSbDay + if (HoppityEggLocator.currentEggType == eggType) { + HoppityEggLocator.currentEggType = null + HoppityEggLocator.sharedEggLocation = null + } + } + } + + fun eggsRemaining(): Boolean { + return entries.any { !it.claimed } + } + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/hoppity/HoppityEggsManager.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/hoppity/HoppityEggsManager.kt new file mode 100644 index 000000000..f7dfaf99e --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/hoppity/HoppityEggsManager.kt @@ -0,0 +1,118 @@ +package at.hannibal2.skyhanni.features.event.chocolatefactory.hoppity + +import at.hannibal2.skyhanni.events.GuiRenderEvent +import at.hannibal2.skyhanni.events.LorenzChatEvent +import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent +import at.hannibal2.skyhanni.events.SecondPassedEvent +import at.hannibal2.skyhanni.features.event.chocolatefactory.ChocolateFactoryAPI +import at.hannibal2.skyhanni.features.fame.ReminderUtils +import at.hannibal2.skyhanni.test.command.ErrorManager +import at.hannibal2.skyhanni.utils.ChatUtils +import at.hannibal2.skyhanni.utils.DelayedRun +import at.hannibal2.skyhanni.utils.LocationUtils +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.RenderUtils.renderStrings +import at.hannibal2.skyhanni.utils.SimpleTimeMark.Companion.fromNow +import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import java.util.regex.Matcher +import kotlin.time.Duration.Companion.seconds + +object HoppityEggsManager { + + private val config get() = ChocolateFactoryAPI.config.hoppityEggs + + private val eggFoundPattern by ChocolateFactoryAPI.patternGroup.pattern( + "egg.found", + "§d§lHOPPITY'S HUNT §r§dYou found a §r§.Chocolate (?\\w+) Egg.*" + ) + private val noEggsLeftPattern by ChocolateFactoryAPI.patternGroup.pattern( + "egg.noneleft", + "§cThere are no hidden Chocolate Rabbit Eggs nearby! Try again later!" + ) + private val eggSpawnedPattern by ChocolateFactoryAPI.patternGroup.pattern( + "egg.spawned", + "§d§lHOPPITY'S HUNT §r§dA §r§.Chocolate (?\\w+) Egg §r§dhas appeared!" + ) + private val eggAlreadyCollectedPattern by ChocolateFactoryAPI.patternGroup.pattern( + "egg.alreadycollected", + "§cYou have already collected this Chocolate (?\\w+) Egg§r§c! Try again when it respawns!" + ) + + private var lastMeal: HoppityEggType? = null + + @SubscribeEvent + fun onWorldChange(event: LorenzWorldChangeEvent) { + lastMeal = null + } + + @SubscribeEvent + fun onChat(event: LorenzChatEvent) { + if (!LorenzUtils.inSkyBlock) return + + eggFoundPattern.matchMatcher(event.message) { + HoppityEggLocator.eggFound() + val meal = getEggType(event) + meal.markClaimed() + lastMeal = meal + } + + noEggsLeftPattern.matchMatcher(event.message) { + HoppityEggType.allFound() + return + } + + eggAlreadyCollectedPattern.matchMatcher(event.message) { + getEggType(event).markClaimed() + } + + eggSpawnedPattern.matchMatcher(event.message) { + getEggType(event).markSpawned() + } + } + + internal fun Matcher.getEggType(event: LorenzChatEvent): HoppityEggType = + HoppityEggType.getMealByName(group("meal")) ?: run { + ErrorManager.skyHanniError( + "Unknown meal: ${group("meal")}", + "message" to event.message + ) + } + + fun shareWaypointPrompt() { + if (!config.sharedWaypoints) return + val meal = lastMeal ?: return + lastMeal = null + + val currentLocation = LocationUtils.playerLocation() + DelayedRun.runNextTick { + ChatUtils.clickableChat( + "Click here to share the location of this chocolate egg with the server!", + onClick = { HoppityEggsShared.shareNearbyEggLocation(currentLocation, meal) }, + expireAt = 30.seconds.fromNow() + ) + } + } + + @SubscribeEvent + fun onRenderOverlay(event: GuiRenderEvent.GuiOverlayRenderEvent) { + if (!LorenzUtils.inSkyBlock) return + if (!config.showClaimedEggs) return + if (ReminderUtils.isBusy()) return + if (!ChocolateFactoryAPI.isHoppityEvent()) return + + val displayList = HoppityEggType.entries + .filter { !it.isClaimed() } + .map { "§7 - ${it.formattedName}" } + .toMutableList() + displayList.add(0, "§bUnfound Eggs:") + if (displayList.size == 1) return + + config.position.renderStrings(displayList, posLabel = "Hoppity Eggs") + } + + @SubscribeEvent + fun onSecondPassed(event: SecondPassedEvent) { + HoppityEggType.checkClaimed() + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/hoppity/HoppityEggsShared.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/hoppity/HoppityEggsShared.kt new file mode 100644 index 000000000..effd33500 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/hoppity/HoppityEggsShared.kt @@ -0,0 +1,58 @@ +package at.hannibal2.skyhanni.features.event.chocolatefactory.hoppity + +import at.hannibal2.skyhanni.events.LorenzChatEvent +import at.hannibal2.skyhanni.features.event.chocolatefactory.ChocolateFactoryAPI +import at.hannibal2.skyhanni.features.event.chocolatefactory.hoppity.HoppityEggsManager.getEggType +import at.hannibal2.skyhanni.utils.ChatUtils +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.LorenzVec +import at.hannibal2.skyhanni.utils.NumberUtil.formatInt +import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher +import at.hannibal2.skyhanni.utils.StringUtils.removeColor +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +object HoppityEggsShared { + + private val config get() = ChocolateFactoryAPI.config.hoppityEggs + + /** + * REGEX-TEST: CalMWolfs: [SkyHanni] Breakfast Chocolate Egg located at x: 142, y: 71, z: -453 + */ + private val sharedEggPattern by ChocolateFactoryAPI.patternGroup.pattern( + "egg.shared", + ".*\\[SkyHanni] (?\\w+) Chocolate Egg located at x: (?-?\\d+), y: (?-?\\d+), z: (?-?\\d+)" + ) + + @SubscribeEvent + fun onChat(event: LorenzChatEvent) { + if (!isEnabled()) return + + sharedEggPattern.matchMatcher(event.message.removeColor()) { + val (x, y, z) = listOf(group("x"), group("y"), group("z")).map { it.formatInt() } + val eggLocation = LorenzVec(x, y, z) + + val meal = getEggType(event) + + if (meal.isClaimed()) return + if (!HoppityEggLocator.isValidEggLocation(eggLocation)) return + + HoppityEggLocator.sharedEggLocation = eggLocation + HoppityEggLocator.currentEggType = meal + } + } + + fun shareNearbyEggLocation(playerLocation: LorenzVec, meal: HoppityEggType) { + if (!isEnabled()) return + val islandEggsLocations = HoppityEggLocator.getCurrentIslandEggLocations() ?: return + val closestEgg = islandEggsLocations.minByOrNull { it.distance(playerLocation) } ?: return + + val x = closestEgg.x.toInt() + val y = closestEgg.y.toInt() + val z = closestEgg.z.toInt() + + val message = "[SkyHanni] ${meal.mealName} Chocolate Egg located at x: $x, y: $y, z: $z" + ChatUtils.sendCommandToServer("ac $message") + } + + fun isEnabled() = LorenzUtils.inSkyBlock && config.waypoints && config.sharedWaypoints +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/hoppity/HoppityNpc.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/hoppity/HoppityNpc.kt new file mode 100644 index 000000000..8e8e137ae --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/hoppity/HoppityNpc.kt @@ -0,0 +1,67 @@ +package at.hannibal2.skyhanni.features.event.chocolatefactory.hoppity + +import at.hannibal2.skyhanni.events.GuiContainerEvent +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.features.event.chocolatefactory.ChocolateFactoryAPI +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 net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +object HoppityNpc { + + private val config get() = ChocolateFactoryAPI.config + + private var slotsToHighlight = mutableSetOf() + private var inShop = false + + @SubscribeEvent + fun onInventoryOpen(event: InventoryFullyOpenedEvent) { + if (!isEnabled()) return + if (event.inventoryName != "Hoppity") return + inShop = true + } + + private fun clear() { + inShop = false + slotsToHighlight.clear() + } + + @SubscribeEvent + fun onInventoryClose(event: InventoryCloseEvent) { + clear() + } + + @SubscribeEvent + fun onWorldChange(event: LorenzWorldChangeEvent) { + clear() + } + + @SubscribeEvent + fun onInventoryUpdated(event: InventoryUpdatedEvent) { + if (!inShop) return + slotsToHighlight.clear() + for ((slot, item) in event.inventoryItems) { + if (item.getLore().contains("§eClick to trade!")) { + slotsToHighlight.add(slot) + } + } + } + + @SubscribeEvent + fun onBackgroundDrawn(event: GuiContainerEvent.BackgroundDrawnEvent) { + if (!inShop) return + for (slot in InventoryUtils.getItemsInOpenChest()) { + if (slot.slotIndex in slotsToHighlight) { + slot highlight LorenzColor.GREEN.addOpacity(200) + } + } + } + + fun isEnabled() = LorenzUtils.inSkyBlock && config.highlightHoppityShop +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/menu/ChocolateAmount.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/menu/ChocolateAmount.kt new file mode 100644 index 000000000..160023629 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/menu/ChocolateAmount.kt @@ -0,0 +1,62 @@ +package at.hannibal2.skyhanni.features.event.chocolatefactory.menu + +import at.hannibal2.skyhanni.features.event.chocolatefactory.ChocolateFactoryAPI +import at.hannibal2.skyhanni.features.event.chocolatefactory.ChocolateFactoryAPI.profileStorage +import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators +import at.hannibal2.skyhanni.utils.SimpleTimeMark +import at.hannibal2.skyhanni.utils.TimeUtils.format +import kotlin.time.Duration +import kotlin.time.Duration.Companion.seconds + +enum class ChocolateAmount(val chocolate: () -> Long) { + CURRENT({ profileStorage?.currentChocolate ?: 0 }), + PRESTIGE({ profileStorage?.chocolateThisPrestige ?: 0 }), + ALL_TIME({ profileStorage?.chocolateAllTime ?: 0 }), + ; + + val formatted get(): String = (chocolate() + chocolateSinceUpdate()).addSeparators() + + fun formattedTimeUntilGoal(goal: Long): String { + val time = timeUntilGoal(goal) + return when { + time.isInfinite() -> "§cNever" + time.isNegative() -> "§aNow" + else -> "§6${time.format()}" + } + } + + private fun timeUntilGoal(goal: Long): Duration { + val profileStorage = ChocolateFactoryAPI.profileStorage ?: return Duration.ZERO + + val updatedAgo = SimpleTimeMark(profileStorage.lastDataSave).passedSince().inWholeSeconds + + val baseMultiplier = profileStorage.rawChocolateMultiplier + val rawChocolatePerSecond = profileStorage.rawChocPerSecond + val timeTowerMultiplier = baseMultiplier + profileStorage.timeTowerLevel * 0.1 + + var needed = goal - chocolate() + val secondsUntilTowerExpires = ChocolateFactoryTimeTowerManager.timeTowerActiveDuration().inWholeSeconds + + val timeTowerChocPerSecond = rawChocolatePerSecond * timeTowerMultiplier + + val secondsAtRate = needed / timeTowerChocPerSecond + if (secondsAtRate < secondsUntilTowerExpires) { + return secondsAtRate.seconds - updatedAgo.seconds + } + + needed -= (secondsUntilTowerExpires * timeTowerChocPerSecond).toLong() + val basePerSecond = rawChocolatePerSecond * baseMultiplier + return (needed / basePerSecond + secondsUntilTowerExpires).seconds - updatedAgo.seconds + } + + companion object { + fun chocolateSinceUpdate(): Long { + val lastUpdate = SimpleTimeMark(profileStorage?.lastDataSave ?: return 0) + val currentTime = SimpleTimeMark.now() + val secondsSinceUpdate = (currentTime - lastUpdate).inWholeSeconds + + val perSecond = ChocolateFactoryAPI.chocolatePerSecond + return (perSecond * secondsSinceUpdate).toLong() + } + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/menu/ChocolateFactoryInventory.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/menu/ChocolateFactoryInventory.kt new file mode 100644 index 000000000..add477bb9 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/menu/ChocolateFactoryInventory.kt @@ -0,0 +1,133 @@ +package at.hannibal2.skyhanni.features.event.chocolatefactory.menu + +import at.hannibal2.skyhanni.events.GuiContainerEvent +import at.hannibal2.skyhanni.events.GuiRenderItemEvent +import at.hannibal2.skyhanni.events.RenderInventoryItemTipEvent +import at.hannibal2.skyhanni.features.event.chocolatefactory.ChocolateFactoryAPI +import at.hannibal2.skyhanni.features.event.chocolatefactory.ChocolateFactoryBarnManager +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.LorenzColor +import at.hannibal2.skyhanni.utils.NumberUtil.formatInt +import at.hannibal2.skyhanni.utils.NumberUtil.romanToDecimal +import at.hannibal2.skyhanni.utils.RenderUtils.drawSlotText +import at.hannibal2.skyhanni.utils.RenderUtils.highlight +import at.hannibal2.skyhanni.utils.StringUtils.matchFirst +import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher +import at.hannibal2.skyhanni.utils.StringUtils.removeColor +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +object ChocolateFactoryInventory { + + private val config get() = ChocolateFactoryAPI.config + private val profileStorage get() = ChocolateFactoryAPI.profileStorage + + private val rabbitAmountPattern by ChocolateFactoryAPI.patternGroup.pattern( + "rabbit.amount", + "Rabbit \\S+ - \\[(?\\d+)].*" + ) + private val upgradeTierPattern by ChocolateFactoryAPI.patternGroup.pattern( + "upgradetier", + ".*\\s(?[IVXLC]+)" + ) + private val unclaimedRewardsPattern by ChocolateFactoryAPI.patternGroup.pattern( + "unclaimedrewards", + "§7§aYou have \\d+ unclaimed rewards?!" + ) + + @SubscribeEvent + fun onRenderItemOverlayPost(event: GuiRenderItemEvent.RenderOverlayEvent.GuiRenderItemPost) { + if (!ChocolateFactoryAPI.inChocolateFactory) return + if (!config.highlightUpgrades) return + + val item = event.stack ?: return + val itemName = item.name + if (itemName != ChocolateFactoryAPI.bestRabbitUpgrade) return + + event.drawSlotText(event.x + 18, event.y, "§6✦", .8f) + } + + @SubscribeEvent + fun onBackgroundDrawn(event: GuiContainerEvent.BackgroundDrawnEvent) { + if (!ChocolateFactoryAPI.inChocolateFactory) return + if (!config.highlightUpgrades) return + + for (slot in InventoryUtils.getItemsInOpenChest()) { + if (slot.slotIndex in ChocolateFactoryAPI.upgradeableSlots) { + if (slot.slotIndex == ChocolateFactoryAPI.bestUpgrade) { + slot highlight LorenzColor.GREEN.addOpacity(200) + } else { + slot highlight LorenzColor.GREEN.addOpacity(75) + } + } + if (slot.slotIndex == ChocolateFactoryAPI.barnIndex && ChocolateFactoryBarnManager.barnFull) { + slot highlight LorenzColor.RED + } + if (slot.slotIndex == ChocolateFactoryAPI.clickRabbitSlot) { + slot highlight LorenzColor.RED + } + if (slot.slotIndex == ChocolateFactoryAPI.milestoneIndex) { + slot.stack?.getLore()?.matchFirst(unclaimedRewardsPattern) { + slot highlight LorenzColor.RED + } + } + if (slot.slotIndex == ChocolateFactoryAPI.timeTowerIndex) { + if (ChocolateFactoryTimeTowerManager.timeTowerActive()) { + slot highlight LorenzColor.LIGHT_PURPLE + } + if (ChocolateFactoryTimeTowerManager.timeTowerFull()) { + slot highlight LorenzColor.RED + } + } + } + } + + @SubscribeEvent + fun onRenderItemTip(event: RenderInventoryItemTipEvent) { + if (!ChocolateFactoryAPI.inChocolateFactory) return + if (!config.showStackSizes) return + val profileStorage = profileStorage ?: return + + val item = event.stack + val itemName = item.name.removeColor() + val slotNumber = event.slot.slotNumber + + if (slotNumber in ChocolateFactoryAPI.rabbitSlots) { + rabbitAmountPattern.matchMatcher(itemName) { + val rabbitTip = when (val rabbitAmount = group("amount").formatInt()) { + in (0..9) -> "$rabbitAmount" + in (10..74) -> "§a$rabbitAmount" + in (75..124) -> "§9$rabbitAmount" + in (125..174) -> "§5$rabbitAmount" + in (175..199) -> "§6$rabbitAmount" + 200 -> "§d$rabbitAmount" + else -> "§c$rabbitAmount" + } + + event.stackTip = rabbitTip + } + } + if (slotNumber in ChocolateFactoryAPI.otherUpgradeSlots) { + upgradeTierPattern.matchMatcher(itemName) { + val level = group("tier").romanToDecimal() + + if (slotNumber == ChocolateFactoryAPI.timeTowerIndex) profileStorage.timeTowerLevel = level + + event.stackTip = level.toString() + } + } + } + + @SubscribeEvent + fun onSlotClick(event: GuiContainerEvent.SlotClickEvent) { + if (!ChocolateFactoryAPI.inChocolateFactory) return + val slot = event.slot ?: return + val slotNumber = slot.slotNumber + if (!config.useMiddleClick) return + if (slotNumber in ChocolateFactoryAPI.noPickblockSlots && + (slotNumber != ChocolateFactoryAPI.timeTowerIndex || event.clickedButton == 1)) return + + event.makePickblock() + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/menu/ChocolateFactoryStats.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/menu/ChocolateFactoryStats.kt new file mode 100644 index 000000000..e1b26fed8 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/menu/ChocolateFactoryStats.kt @@ -0,0 +1,138 @@ +package at.hannibal2.skyhanni.features.event.chocolatefactory.menu + +import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator +import at.hannibal2.skyhanni.events.GuiRenderEvent +import at.hannibal2.skyhanni.events.SecondPassedEvent +import at.hannibal2.skyhanni.features.event.chocolatefactory.ChocolateFactoryAPI +import at.hannibal2.skyhanni.features.event.chocolatefactory.ChocolateFactoryBarnManager +import at.hannibal2.skyhanni.utils.ClipboardUtils +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators +import at.hannibal2.skyhanni.utils.RenderUtils.renderRenderables +import at.hannibal2.skyhanni.utils.StringUtils.removeColor +import at.hannibal2.skyhanni.utils.renderables.Renderable +import com.google.gson.JsonPrimitive +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +object ChocolateFactoryStats { + + private val config get() = ChocolateFactoryAPI.config + private val profileStorage get() = ChocolateFactoryAPI.profileStorage + + private var display = listOf() + + @SubscribeEvent + fun onSecondPassed(event: SecondPassedEvent) { + if (!LorenzUtils.inSkyBlock) return + if (!ChocolateFactoryAPI.chocolateFactoryPaused) return + updateDisplay() + } + + @SubscribeEvent + fun onBackgroundDraw(event: GuiRenderEvent.ChestGuiOverlayRenderEvent) { + if (!ChocolateFactoryAPI.inChocolateFactory && !ChocolateFactoryAPI.chocolateFactoryPaused) return + if (!config.statsDisplay) return + + config.position.renderRenderables(display, posLabel = "Chocolate Factory Stats") + } + + fun updateDisplay() { + val profileStorage = profileStorage ?: return + + val perSecond = ChocolateFactoryAPI.chocolatePerSecond + val perMinute = perSecond * 60 + val perHour = perMinute * 60 + val perDay = perHour * 24 + val position = ChocolateFactoryAPI.leaderboardPosition?.addSeparators() ?: "???" + val percentile = ChocolateFactoryAPI.leaderboardPercentile?.let { "§7Top §a$it%" } ?: "" + val timeTowerInfo = if (ChocolateFactoryTimeTowerManager.timeTowerActive()) { + "§d§lActive" + } else { + "§6${ChocolateFactoryTimeTowerManager.timeTowerCharges()}" + } + + val prestigeEstimate = ChocolateAmount.PRESTIGE.formattedTimeUntilGoal(ChocolateFactoryAPI.chocolateForPrestige) + + val map = buildMap { + put(ChocolateFactoryStat.HEADER, "§6§lChocolate Factory Stats") + + put(ChocolateFactoryStat.CURRENT, "§eCurrent Chocolate: §6${ChocolateAmount.CURRENT.formatted}") + put(ChocolateFactoryStat.THIS_PRESTIGE, "§eThis Prestige: §6${ChocolateAmount.PRESTIGE.formatted}") + put(ChocolateFactoryStat.ALL_TIME, "§eAll-time: §6${ChocolateAmount.ALL_TIME.formatted}") + + put(ChocolateFactoryStat.PER_SECOND, "§ePer Second: §6${perSecond.addSeparators()}") + put(ChocolateFactoryStat.PER_MINUTE, "§ePer Minute: §6${perMinute.addSeparators()}") + put(ChocolateFactoryStat.PER_HOUR, "§ePer Hour: §6${perHour.addSeparators()}") + put(ChocolateFactoryStat.PER_DAY, "§ePer Day: §6${perDay.addSeparators()}") + + put(ChocolateFactoryStat.MULTIPLIER, "§eChocolate Multiplier: §6${profileStorage.chocolateMultiplier}") + put(ChocolateFactoryStat.BARN, "§eBarn: §6${ChocolateFactoryBarnManager.barnStatus()}") + + put(ChocolateFactoryStat.LEADERBOARD_POS, "§ePosition: §7#§b$position $percentile") + + put(ChocolateFactoryStat.EMPTY, "") + put(ChocolateFactoryStat.EMPTY_2, "") + put(ChocolateFactoryStat.EMPTY_3, "") + + put(ChocolateFactoryStat.TIME_TOWER, "§eTime Tower: §6$timeTowerInfo") + put(ChocolateFactoryStat.TIME_TO_PRESTIGE, "§eTime To Prestige: $prestigeEstimate") + put( + ChocolateFactoryStat.RAW_PER_SECOND, + "§eRaw Per Second: §6${profileStorage.rawChocPerSecond.addSeparators()}" + ) + } + val text = config.statsDisplayList.mapNotNull { map[it] } + + display = listOf(Renderable.clickAndHover( + Renderable.verticalContainer(text.map(Renderable::string)), + tips = listOf("§bCopy to Clipboard!"), + onClick = { + val list = text.toMutableList() + val titleHeader = list.indexOf("§6§lChocolate Factory Stats") + if (titleHeader != -1) { + list[titleHeader] = "${LorenzUtils.getPlayerName()}'s Chocolate Factory Stats" + } else { + list.add(0, "${LorenzUtils.getPlayerName()}'s Chocolate Factory Stats") + } + ClipboardUtils.copyToClipboard(list.joinToString("\n") { it.removeColor() }) + } + )) + } + + @SubscribeEvent + fun onConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) { + event.transform(42, "event.chocolateFactory.statsDisplayList") { element -> + val jsonArray = element.asJsonArray + + jsonArray.add(JsonPrimitive("TIME_TOWER")) + jsonArray.add(JsonPrimitive("TIME_TO_PRESTIGE")) + + jsonArray + } + } + + enum class ChocolateFactoryStat(private val display: String, val shouldDisplay: () -> Boolean = { true }) { + HEADER("§6§lChocolate Factory Stats"), + CURRENT("§eCurrent Chocolate: §65,272,230"), + THIS_PRESTIGE("§eThis Prestige: §6483,023,853", { ChocolateFactoryAPI.currentPrestige != 1 }), + ALL_TIME("§eAll-time: §6641,119,115"), + PER_SECOND("§ePer Second: §63,780.72"), + PER_MINUTE("§ePer Minute: §6226,843.2"), + PER_HOUR("§ePer Hour: §613,610,592"), + PER_DAY("§ePer Day: §6326,654,208"), + MULTIPLIER("§eChocolate Multiplier: §61.77"), + BARN("§eBarn: §6171/190 Rabbits"), + LEADERBOARD_POS("§ePosition: §7#§b103 §7Top §a0.87%"), + EMPTY(""), + EMPTY_2(""), + EMPTY_3(""), + TIME_TOWER("§eTime Tower: §62/3 Charges", { ChocolateFactoryTimeTowerManager.currentCharges() != -1 }), + TIME_TO_PRESTIGE("§eTime To Prestige: §61d 13h 59m 4s", { ChocolateFactoryAPI.currentPrestige != 5 }), + RAW_PER_SECOND("§eRaw Per Second: §62,136"), + ; + + override fun toString(): String { + return display + } + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/menu/ChocolateFactoryTimeTowerManager.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/menu/ChocolateFactoryTimeTowerManager.kt new file mode 100644 index 000000000..a1b34a1a4 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/menu/ChocolateFactoryTimeTowerManager.kt @@ -0,0 +1,114 @@ +package at.hannibal2.skyhanni.features.event.chocolatefactory.menu + +import at.hannibal2.skyhanni.events.ProfileJoinEvent +import at.hannibal2.skyhanni.events.SecondPassedEvent +import at.hannibal2.skyhanni.features.event.chocolatefactory.ChocolateFactoryAPI +import at.hannibal2.skyhanni.features.fame.ReminderUtils +import at.hannibal2.skyhanni.utils.ChatUtils +import at.hannibal2.skyhanni.utils.HypixelCommands +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.SimpleTimeMark +import at.hannibal2.skyhanni.utils.SoundUtils +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import kotlin.time.Duration +import kotlin.time.Duration.Companion.hours +import kotlin.time.Duration.Companion.milliseconds +import kotlin.time.Duration.Companion.minutes +import kotlin.time.Duration.Companion.seconds + +object ChocolateFactoryTimeTowerManager { + + private val config get() = ChocolateFactoryAPI.config + private val profileStorage get() = ChocolateFactoryAPI.profileStorage + + private var lastTimeTowerWarning = SimpleTimeMark.farPast() + + @SubscribeEvent + fun onSecondPassed(event: SecondPassedEvent) { + if (!LorenzUtils.inSkyBlock) return + val profileStorage = profileStorage ?: return + + if (SimpleTimeMark(profileStorage.currentTimeTowerEnds).isInPast()) { + profileStorage.currentTimeTowerEnds = SimpleTimeMark.farPast().toMillis() + } + + if (ChocolateFactoryAPI.inChocolateFactory) return + + val nextCharge = SimpleTimeMark(profileStorage.nextTimeTower) + + if (nextCharge.isInPast() && !nextCharge.isFarPast() && currentCharges() < maxCharges()) { + profileStorage.currentTimeTowerUses++ + + val nextTimeTower = SimpleTimeMark(profileStorage.nextTimeTower) + (profileStorage.timeTowerCooldown).hours + profileStorage.nextTimeTower = nextTimeTower.toMillis() + + if (!config.timeTowerWarning) return + ChatUtils.clickableChat( + "Your Time Tower has another charge available §7(${timeTowerCharges()})§e, " + + "Click here to use one", + onClick = { + HypixelCommands.chocolateFactory() + } + ) + SoundUtils.playBeepSound() + lastTimeTowerWarning = SimpleTimeMark.now() + return + } + checkTimeTowerWarning(false) + } + + fun checkTimeTowerWarning(inInventory: Boolean) { + if (!ChocolateFactoryAPI.isEnabled()) return + if (!config.timeTowerWarning) return + if (!timeTowerFull()) return + if (ReminderUtils.isBusy()) return + + val warningSeparation = if (inInventory) 30.seconds else 5.minutes + if (lastTimeTowerWarning.passedSince() < warningSeparation) return + + ChatUtils.clickableChat( + "§cYour Time Tower is full §7(${timeTowerCharges()})§c, " + + "Use one to avoid wasting time tower usages!", + onClick = { + HypixelCommands.chocolateFactory() + } + ) + SoundUtils.playBeepSound() + lastTimeTowerWarning = SimpleTimeMark.now() + } + + fun timeTowerCharges(): String { + return "${currentCharges()}/${maxCharges()} Charges" + } + + fun currentCharges(): Int { + return profileStorage?.currentTimeTowerUses ?: -1 + } + + private fun maxCharges(): Int { + return profileStorage?.maxTimeTowerUses ?: 3 + } + + fun timeTowerFull() = currentCharges() >= maxCharges() + + fun timeTowerActive(): Boolean { + val currentTime = profileStorage?.lastDataSave ?: 0 + val endTime = profileStorage?.currentTimeTowerEnds ?: 0 + + return endTime > currentTime + } + + fun timeTowerActiveDuration(): Duration { + if (!timeTowerActive()) return Duration.ZERO + val currentTime = profileStorage?.lastDataSave ?: 0 + val endTime = profileStorage?.currentTimeTowerEnds ?: 0 + + val duration = endTime - currentTime + return duration.milliseconds + } + + @SubscribeEvent + fun onProfileChange(event: ProfileJoinEvent) { + lastTimeTowerWarning = SimpleTimeMark.farPast() + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/menu/ChocolateFactoryTooltip.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/menu/ChocolateFactoryTooltip.kt new file mode 100644 index 000000000..dd09a2402 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/menu/ChocolateFactoryTooltip.kt @@ -0,0 +1,93 @@ +package at.hannibal2.skyhanni.features.event.chocolatefactory.menu + +import at.hannibal2.skyhanni.events.LorenzToolTipEvent +import at.hannibal2.skyhanni.features.event.chocolatefactory.ChocolateFactoryAPI +import at.hannibal2.skyhanni.features.event.chocolatefactory.ChocolateFactoryAPI.profileStorage +import at.hannibal2.skyhanni.utils.LorenzUtils.round +import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators +import net.minecraftforge.fml.common.eventhandler.EventPriority +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +object ChocolateFactoryTooltip { + + private val config get() = ChocolateFactoryAPI.config + + private var ignoredSlotIndexes = listOf() + + fun updateIgnoredSlots() { + ignoredSlotIndexes = listOf( + ChocolateFactoryAPI.prestigeIndex, + ChocolateFactoryAPI.handCookieIndex, + ChocolateFactoryAPI.shrineIndex, + ChocolateFactoryAPI.barnIndex, + ) + } + + @SubscribeEvent(priority = EventPriority.HIGH) + fun onTooltip(event: LorenzToolTipEvent) { + if (!ChocolateFactoryAPI.inChocolateFactory) return + if (!config.extraTooltipStats) return + + val slotIndex = event.slot.slotNumber + if (slotIndex == ChocolateFactoryAPI.prestigeIndex) return + if (slotIndex !in ChocolateFactoryAPI.otherUpgradeSlots && slotIndex !in ChocolateFactoryAPI.rabbitSlots) return + + val upgradeCost = ChocolateFactoryAPI.getChocolateUpgradeCost(event.toolTip) ?: return + + event.toolTip.add("§8§m-----------------") + val timeToUpgrade = ChocolateAmount.CURRENT.formattedTimeUntilGoal(upgradeCost) + + event.toolTip.add("§7Time until upgrade: §e$timeToUpgrade") + + if (slotIndex in ignoredSlotIndexes) return + + val averageChocolate = averageChocPerSecond().round(2) + + val newAverageChocolate = when (slotIndex) { + in ChocolateFactoryAPI.rabbitSlots -> { + val chocolateIncrease = ChocolateFactoryAPI.rabbitSlots[slotIndex] ?: 0 + averageChocPerSecond(rawPerSecondIncrease = chocolateIncrease) + } + + ChocolateFactoryAPI.timeTowerIndex -> averageChocPerSecond(timeTowerLevelIncrease = 1) + ChocolateFactoryAPI.coachRabbitIndex -> averageChocPerSecond(baseMultiplierIncrease = 0.01) + else -> averageChocolate + }.round(2) + + val extra = (newAverageChocolate - averageChocolate).round(2) + val ratioForUpgrade = (upgradeCost / extra).round(2) + + event.toolTip.add("§7Extra: §6$extra §7choc/s") + event.toolTip.add("§7Effective Cost: §6${ratioForUpgrade.addSeparators()}") + + if (slotIndex == ChocolateFactoryAPI.timeTowerIndex) { + event.toolTip.add("§7One charge will give: §6${chocPerTimeTower().addSeparators()}") + } + } + + private fun averageChocPerSecond( + baseMultiplierIncrease: Double = 0.0, + rawPerSecondIncrease: Int = 0, + timeTowerLevelIncrease: Int = 0, + ): Double { + val profileStorage = profileStorage ?: return 0.0 + + val baseMultiplier = profileStorage.chocolateMultiplier + baseMultiplierIncrease + val rawPerSecond = profileStorage.rawChocPerSecond + rawPerSecondIncrease + val timeTowerLevel = profileStorage.timeTowerLevel + timeTowerLevelIncrease + + val timeTowerCooldown = profileStorage.timeTowerCooldown + + val basePerSecond = rawPerSecond * baseMultiplier + val towerCalc = (rawPerSecond * timeTowerLevel * .1) / timeTowerCooldown + + return basePerSecond + towerCalc + } + + private fun chocPerTimeTower(): Int { + val profileStorage = profileStorage ?: return 0 + val amountPerSecond = profileStorage.rawChocPerSecond * profileStorage.timeTowerLevel * .1 + val amountPerHour = amountPerSecond * 60 * 60 + return amountPerHour.toInt() + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/menu/ChocolateFactoryTooltipCompact.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/menu/ChocolateFactoryTooltipCompact.kt new file mode 100644 index 000000000..00d6783ba --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/menu/ChocolateFactoryTooltipCompact.kt @@ -0,0 +1,77 @@ +package at.hannibal2.skyhanni.features.event.chocolatefactory.menu + +import at.hannibal2.skyhanni.events.GuiContainerEvent +import at.hannibal2.skyhanni.events.GuiRenderEvent +import at.hannibal2.skyhanni.events.LorenzToolTipEvent +import at.hannibal2.skyhanni.features.event.chocolatefactory.ChocolateFactoryAPI +import at.hannibal2.skyhanni.utils.CollectionUtils.getOrNull +import at.hannibal2.skyhanni.utils.ItemUtils.getLore +import at.hannibal2.skyhanni.utils.ItemUtils.name +import at.hannibal2.skyhanni.utils.RenderUtils.renderStrings +import at.hannibal2.skyhanni.utils.SimpleTimeMark +import net.minecraftforge.fml.common.eventhandler.EventPriority +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import kotlin.time.Duration.Companion.milliseconds +import kotlin.time.Duration.Companion.seconds + +object ChocolateFactoryTooltipCompact { + private val config get() = ChocolateFactoryAPI.config + + private var lastClick = SimpleTimeMark.farPast() + private var lastHover = SimpleTimeMark.farPast() + private var tooltipToHover = listOf() + + @SubscribeEvent + fun onTooltip(event: LorenzToolTipEvent) { + if (!ChocolateFactoryAPI.inChocolateFactory) return + + if (config.tooltipMove) { + if (event.slot.slotNumber <= 44) { + lastHover = SimpleTimeMark.now() + tooltipToHover = event.toolTip.toList() + event.cancel() + } else { + lastHover = SimpleTimeMark.farPast() + } + return + } + + onCompactClick(event) + } + + @SubscribeEvent + fun onBackgroundDraw(event: GuiRenderEvent.ChestGuiOverlayRenderEvent) { + if (!ChocolateFactoryAPI.inChocolateFactory) return + if (config.tooltipMove) { + if (lastHover.passedSince() < 300.milliseconds) { + config.tooltipMovePosition.renderStrings(tooltipToHover, posLabel = "Tooltip Move") + } + } + } + + private fun onCompactClick(event: LorenzToolTipEvent) { + if (!config.compactOnClick) return + + val itemStack = event.itemStack + val lore = itemStack.getLore() + if (!lore.any { it == "§7§eClick to uncover the meaning of life!" }) return + if (lastClick.passedSince() >= 1.seconds && !config.compactOnClickAlways) return + val list = mutableListOf() + list.add(itemStack.name) + lore.getOrNull(5)?.let { + list.add(it) + } + event.toolTip = list + return + } + + @SubscribeEvent(priority = EventPriority.HIGH) + fun onSlotClick(event: GuiContainerEvent.SlotClickEvent) { + + if (ChocolateFactoryAPI.inChocolateFactory) { + if (event.slotId == 13) { + lastClick = SimpleTimeMark.now() + } + } + } +} -- cgit