From 1259d8a657829a9343e3024c031f7bf94f6897b9 Mon Sep 17 00:00:00 2001 From: hannibal2 <24389977+hannibal002@users.noreply.github.com> Date: Wed, 1 May 2024 05:26:08 +0200 Subject: Merge pull request #1599 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * doing big moves * Merge branch 'refs/heads/beta' into splitting-factory-and-hoppity-in-… * 43 -> 44 --- src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt | 26 +- .../skyhanni/config/ConfigUpdaterMigrator.kt | 2 +- .../features/event/ChocolateFactoryConfig.java | 148 --------- .../config/features/event/EventConfig.java | 4 +- .../config/features/event/HoppityEggsConfig.java | 6 + .../features/inventory/ChocolateFactoryConfig.java | 136 ++++++++ .../config/features/inventory/InventoryConfig.java | 4 + .../event/chocolatefactory/ChocolateFactoryAPI.kt | 345 ------------------- .../ChocolateFactoryBarnManager.kt | 92 ------ .../chocolatefactory/ChocolateFactoryShortcut.kt | 72 ---- .../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 ----- .../event/hoppity/HoppityCollectionStats.kt | 217 ++++++++++++ .../features/event/hoppity/HoppityEggLocator.kt | 246 ++++++++++++++ .../features/event/hoppity/HoppityEggType.kt | 53 +++ .../features/event/hoppity/HoppityEggsManager.kt | 130 ++++++++ .../features/event/hoppity/HoppityEggsShared.kt | 58 ++++ .../skyhanni/features/event/hoppity/HoppityNpc.kt | 66 ++++ .../inventory/chocolatefactory/ChocolateAmount.kt | 61 ++++ .../chocolatefactory/ChocolateFactoryAPI.kt | 364 +++++++++++++++++++++ .../ChocolateFactoryBarnManager.kt | 92 ++++++ .../chocolatefactory/ChocolateFactoryInventory.kt | 131 ++++++++ .../chocolatefactory/ChocolateFactoryShortcut.kt | 72 ++++ .../chocolatefactory/ChocolateFactoryStats.kt | 136 ++++++++ .../ChocolateFactoryTimeTowerManager.kt | 113 +++++++ .../chocolatefactory/ChocolateFactoryTooltip.kt | 92 ++++++ .../ChocolateFactoryTooltipCompact.kt | 76 +++++ 37 files changed, 2069 insertions(+), 2049 deletions(-) delete mode 100644 src/main/java/at/hannibal2/skyhanni/config/features/event/ChocolateFactoryConfig.java create mode 100644 src/main/java/at/hannibal2/skyhanni/config/features/inventory/ChocolateFactoryConfig.java delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryAPI.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryBarnManager.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryShortcut.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/hoppity/HoppityCollectionStats.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/hoppity/HoppityEggLocator.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/hoppity/HoppityEggType.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/hoppity/HoppityEggsManager.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/hoppity/HoppityEggsShared.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/hoppity/HoppityNpc.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/menu/ChocolateAmount.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/menu/ChocolateFactoryInventory.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/menu/ChocolateFactoryStats.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/menu/ChocolateFactoryTimeTowerManager.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/menu/ChocolateFactoryTooltip.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/menu/ChocolateFactoryTooltipCompact.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCollectionStats.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggLocator.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggType.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggsManager.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggsShared.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityNpc.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateAmount.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryAPI.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryBarnManager.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryInventory.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryShortcut.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryStats.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryTimeTowerManager.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryTooltip.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryTooltipCompact.kt (limited to 'src/main/java') diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt index 143ac7dd9..b59e6bd9f 100644 --- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt +++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt @@ -125,19 +125,6 @@ import at.hannibal2.skyhanni.features.dungeon.DungeonTeammateOutlines import at.hannibal2.skyhanni.features.dungeon.HighlightDungeonDeathmite 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.ChocolateFactoryShortcut -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 @@ -148,6 +135,11 @@ import at.hannibal2.skyhanni.features.event.diana.HighlightInquisitors import at.hannibal2.skyhanni.features.event.diana.InquisitorWaypointShare import at.hannibal2.skyhanni.features.event.diana.MythologicalCreatureTracker import at.hannibal2.skyhanni.features.event.diana.SoopyGuessBurrow +import at.hannibal2.skyhanni.features.event.hoppity.HoppityCollectionStats +import at.hannibal2.skyhanni.features.event.hoppity.HoppityEggLocator +import at.hannibal2.skyhanni.features.event.hoppity.HoppityEggsManager +import at.hannibal2.skyhanni.features.event.hoppity.HoppityEggsShared +import at.hannibal2.skyhanni.features.event.hoppity.HoppityNpc import at.hannibal2.skyhanni.features.event.jerry.HighlightJerries import at.hannibal2.skyhanni.features.event.jerry.frozentreasure.FrozenTreasureTracker import at.hannibal2.skyhanni.features.event.lobby.waypoints.christmas.PresentWaypoints @@ -276,6 +268,14 @@ import at.hannibal2.skyhanni.features.inventory.bazaar.BazaarCancelledBuyOrderCl import at.hannibal2.skyhanni.features.inventory.bazaar.BazaarOpenPriceWebsite import at.hannibal2.skyhanni.features.inventory.bazaar.BazaarOrderHelper import at.hannibal2.skyhanni.features.inventory.bazaar.CraftMaterialsFromBazaar +import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryAPI +import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryBarnManager +import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryInventory +import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryShortcut +import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryStats +import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryTimeTowerManager +import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryTooltip +import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryTooltipCompact import at.hannibal2.skyhanni.features.inventory.tiarelay.TiaRelayHelper import at.hannibal2.skyhanni.features.inventory.tiarelay.TiaRelayWaypoints import at.hannibal2.skyhanni.features.itemabilities.ChickenHeadTimer diff --git a/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt b/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt index faeab5a00..6fa027640 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt +++ b/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt @@ -12,7 +12,7 @@ import com.google.gson.JsonPrimitive object ConfigUpdaterMigrator { val logger = LorenzLogger("ConfigMigration") - const val CONFIG_VERSION = 43 + const val CONFIG_VERSION = 44 fun JsonElement.at(chain: List, init: Boolean): JsonElement? { if (chain.isEmpty()) return this if (this !is JsonObject) return null diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/event/ChocolateFactoryConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/event/ChocolateFactoryConfig.java deleted file mode 100644 index d725c2974..000000000 --- a/src/main/java/at/hannibal2/skyhanni/config/features/event/ChocolateFactoryConfig.java +++ /dev/null @@ -1,148 +0,0 @@ -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.menu.ChocolateFactoryStats.ChocolateFactoryStat; -import com.google.gson.annotations.Expose; -import io.github.notenoughupdates.moulconfig.annotations.Accordion; -import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean; -import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorDraggableList; -import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorSlider; -import io.github.notenoughupdates.moulconfig.annotations.ConfigLink; -import io.github.notenoughupdates.moulconfig.annotations.ConfigOption; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -public class ChocolateFactoryConfig { - - @Expose - @ConfigOption(name = "Hoppity Eggs", desc = "") - @Accordion - public HoppityEggsConfig hoppityEggs = new HoppityEggsConfig(); - - @Expose - @ConfigOption(name = "Chocolate Factory Features", desc = "Global toggle for all chocolate factory features.") - @ConfigEditorBoolean - @FeatureToggle - public boolean enabled = true; - - @Expose - @ConfigOption(name = "Chocolate Factory Stats", desc = "Show general info about your chocolate factory.") - @ConfigEditorBoolean - @FeatureToggle - public boolean statsDisplay = true; - - @Expose - @ConfigOption( - name = "Stats List", - desc = "Drag text to change what displays in the chocolate factory stats list and what order the text appears in." - ) - @ConfigEditorDraggableList - public List statsDisplayList = new ArrayList<>(Arrays.asList( - ChocolateFactoryStat.HEADER, - ChocolateFactoryStat.CURRENT, - ChocolateFactoryStat.THIS_PRESTIGE, - ChocolateFactoryStat.ALL_TIME, - ChocolateFactoryStat.TIME_TO_PRESTIGE, - ChocolateFactoryStat.EMPTY, - ChocolateFactoryStat.PER_SECOND, - ChocolateFactoryStat.PER_MINUTE, - ChocolateFactoryStat.PER_HOUR, - ChocolateFactoryStat.PER_DAY, - ChocolateFactoryStat.EMPTY_2, - ChocolateFactoryStat.MULTIPLIER, - ChocolateFactoryStat.BARN, - ChocolateFactoryStat.TIME_TOWER, - ChocolateFactoryStat.LEADERBOARD_POS - )); - - @Expose - @ConfigOption(name = "Show Stack Sizes", desc = "Shows additional info as many items in the chocolate menu as the stack size.") - @ConfigEditorBoolean - public boolean showStackSizes = true; - - @Expose - @ConfigOption(name = "Highlight Upgrades", desc = "Highlight any upgrades that you can afford. The upgrade with a star is the most optimal and the lightest colour of green is the most optimal you can afford.") - @ConfigEditorBoolean - public boolean highlightUpgrades = true; - - @Expose - @ConfigOption(name = "Use Middle Click", desc = "Click on slots with middle click to speed up interactions.") - @ConfigEditorBoolean - public boolean useMiddleClick = true; - - @Expose - @ConfigOption(name = "Rabbit Warning", desc = "Warn when the rabbit that needs to be clicked appears.") - @ConfigEditorBoolean - public boolean rabbitWarning = true; - - @Expose - @ConfigOption( - name = "Rabbit Crush Threshold", - desc = "How close should you be to your barn capacity before being warned about needing to upgrade it." - ) - @ConfigEditorSlider(minValue = 0, maxValue = 20, minStep = 1) - public int barnCapacityThreshold = 6; - - @Expose - @ConfigOption(name = "Extra Tooltip Stats", desc = "Shows extra information about upgrades in the tooltip.") - @ConfigEditorBoolean - @FeatureToggle - public boolean extraTooltipStats = true; - - @Expose - @ConfigOption(name = "Hoppity Collection Stats", desc = "Shows info about your hoppity rabbit collection.") - @ConfigEditorBoolean - @FeatureToggle - public boolean hoppityCollectionStats = true; - - @Expose - @ConfigOption(name = "Time Tower Warning", desc = "Notification when you have a new time tower usage available and " + - "continuously warn when your time tower is full.") - @ConfigEditorBoolean - @FeatureToggle - public boolean timeTowerWarning = false; - - @Expose - @ConfigOption(name = "Hoppity Menu Shortcut", desc = "Add a Chocolate Factory button in the SkyBlock Menu that runs /chocolatefactory on click.") - @ConfigEditorBoolean - @FeatureToggle - public boolean hoppityMenuShortcut = true; - - @Expose - @ConfigLink(owner = ChocolateFactoryConfig.class, field = "statsDisplay") - public Position position = new Position(163, 160, false, true); - - @Expose - @ConfigLink(owner = ChocolateFactoryConfig.class, field = "hoppityCollectionStats") - public Position hoppityStatsPosition = new Position(163, 160, false, true); - - @Expose - @ConfigOption(name = "Compact On Click", desc = "Compact the item toolip when clicking on the chocolate.") - @ConfigEditorBoolean - @FeatureToggle - public boolean compactOnClick = true; - - @Expose - @ConfigOption(name = "Always Compact", desc = "Always Compact the item toolip on the chocolate. Requires the above option to be enabled.") - @ConfigEditorBoolean - public boolean compactOnClickAlways = false; - - @Expose - @ConfigOption(name = "Tooltip Move", desc = "Move Tooltip away from the item you hover over while inside the Chocolate Factory.") - @ConfigEditorBoolean - @FeatureToggle - public boolean tooltipMove = false; - - @Expose - @ConfigLink(owner = ChocolateFactoryConfig.class, field = "tooltipMove") - public Position tooltipMovePosition = new Position(-380, 150, false, true); - - @Expose - @ConfigOption(name = "Highlight Hoppity Shop", desc = "Highlight items that haven't been bought from the Hoppity shop yet.") - @ConfigEditorBoolean - @FeatureToggle - public boolean highlightHoppityShop = true; -} diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/event/EventConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/event/EventConfig.java index b68664d79..b50c67ea6 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/event/EventConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/event/EventConfig.java @@ -24,8 +24,8 @@ public class EventConfig { public WinterConfig winter = new WinterConfig(); @Expose - @Category(name = "Hoppity", desc = "Features for the Hoppity event and the chocolate factory.") - public ChocolateFactoryConfig chocolateFactory = new ChocolateFactoryConfig(); + @Category(name = "Hoppity Eggs", desc = "Features for the Hoppity event.") + public HoppityEggsConfig hoppityEggs = new HoppityEggsConfig(); @ConfigOption(name = "City Project", desc = "") @Accordion diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/event/HoppityEggsConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/event/HoppityEggsConfig.java index 133323926..5306cf967 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/event/HoppityEggsConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/event/HoppityEggsConfig.java @@ -36,4 +36,10 @@ public class HoppityEggsConfig { @Expose @ConfigLink(owner = HoppityEggsConfig.class, field = "showClaimedEggs") public Position position = new Position(33, 72, false, true); + + @Expose + @ConfigOption(name = "Highlight Hoppity Shop", desc = "Highlight items that haven't been bought from the Hoppity shop yet.") + @ConfigEditorBoolean + @FeatureToggle + public boolean highlightHoppityShop = true; } diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/ChocolateFactoryConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/ChocolateFactoryConfig.java new file mode 100644 index 000000000..7692d28c6 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/ChocolateFactoryConfig.java @@ -0,0 +1,136 @@ +package at.hannibal2.skyhanni.config.features.inventory; + +import at.hannibal2.skyhanni.config.FeatureToggle; +import at.hannibal2.skyhanni.config.core.config.Position; +import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryStats.ChocolateFactoryStat; +import com.google.gson.annotations.Expose; +import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean; +import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorDraggableList; +import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorSlider; +import io.github.notenoughupdates.moulconfig.annotations.ConfigLink; +import io.github.notenoughupdates.moulconfig.annotations.ConfigOption; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class ChocolateFactoryConfig { + + @Expose + @ConfigOption(name = "Chocolate Factory Features", desc = "Global toggle for all chocolate factory features.") + @ConfigEditorBoolean + @FeatureToggle + public boolean enabled = true; + + @Expose + @ConfigOption(name = "Chocolate Factory Stats", desc = "Show general info about your chocolate factory.") + @ConfigEditorBoolean + @FeatureToggle + public boolean statsDisplay = true; + + @Expose + @ConfigOption( + name = "Stats List", + desc = "Drag text to change what displays in the chocolate factory stats list and what order the text appears in." + ) + @ConfigEditorDraggableList + public List statsDisplayList = new ArrayList<>(Arrays.asList( + ChocolateFactoryStat.HEADER, + ChocolateFactoryStat.CURRENT, + ChocolateFactoryStat.THIS_PRESTIGE, + ChocolateFactoryStat.ALL_TIME, + ChocolateFactoryStat.TIME_TO_PRESTIGE, + ChocolateFactoryStat.EMPTY, + ChocolateFactoryStat.PER_SECOND, + ChocolateFactoryStat.PER_MINUTE, + ChocolateFactoryStat.PER_HOUR, + ChocolateFactoryStat.PER_DAY, + ChocolateFactoryStat.EMPTY_2, + ChocolateFactoryStat.MULTIPLIER, + ChocolateFactoryStat.BARN, + ChocolateFactoryStat.TIME_TOWER, + ChocolateFactoryStat.LEADERBOARD_POS + )); + + @Expose + @ConfigOption(name = "Show Stack Sizes", desc = "Shows additional info as many items in the chocolate menu as the stack size.") + @ConfigEditorBoolean + public boolean showStackSizes = true; + + @Expose + @ConfigOption(name = "Highlight Upgrades", desc = "Highlight any upgrades that you can afford. The upgrade with a star is the most optimal and the lightest colour of green is the most optimal you can afford.") + @ConfigEditorBoolean + public boolean highlightUpgrades = true; + + @Expose + @ConfigOption(name = "Use Middle Click", desc = "Click on slots with middle click to speed up interactions.") + @ConfigEditorBoolean + public boolean useMiddleClick = true; + + @Expose + @ConfigOption(name = "Rabbit Warning", desc = "Warn when the rabbit that needs to be clicked appears.") + @ConfigEditorBoolean + public boolean rabbitWarning = true; + + @Expose + @ConfigOption( + name = "Rabbit Crush Threshold", + desc = "How close should you be to your barn capacity before being warned about needing to upgrade it." + ) + @ConfigEditorSlider(minValue = 0, maxValue = 20, minStep = 1) + public int barnCapacityThreshold = 6; + + @Expose + @ConfigOption(name = "Extra Tooltip Stats", desc = "Shows extra information about upgrades in the tooltip.") + @ConfigEditorBoolean + @FeatureToggle + public boolean extraTooltipStats = true; + + @Expose + @ConfigOption(name = "Time Tower Warning", desc = "Notification when you have a new time tower usage available and " + + "continuously warn when your time tower is full.") + @ConfigEditorBoolean + @FeatureToggle + public boolean timeTowerWarning = false; + + @Expose + @ConfigLink(owner = ChocolateFactoryConfig.class, field = "statsDisplay") + public Position position = new Position(163, 160, false, true); + + @Expose + @ConfigOption(name = "Compact On Click", desc = "Compact the item toolip when clicking on the chocolate.") + @ConfigEditorBoolean + @FeatureToggle + public boolean compactOnClick = true; + + @Expose + @ConfigOption(name = "Always Compact", desc = "Always Compact the item toolip on the chocolate. Requires the above option to be enabled.") + @ConfigEditorBoolean + public boolean compactOnClickAlways = false; + + @Expose + @ConfigOption(name = "Tooltip Move", desc = "Move Tooltip away from the item you hover over while inside the Chocolate Factory.") + @ConfigEditorBoolean + @FeatureToggle + public boolean tooltipMove = false; + + @Expose + @ConfigLink(owner = ChocolateFactoryConfig.class, field = "tooltipMove") + public Position tooltipMovePosition = new Position(-380, 150, false, true); + + @Expose + @ConfigOption(name = "Hoppity Collection Stats", desc = "Shows info about your hoppity rabbit collection.") + @ConfigEditorBoolean + @FeatureToggle + public boolean hoppityCollectionStats = true; + + @Expose + @ConfigLink(owner = ChocolateFactoryConfig.class, field = "hoppityCollectionStats") + public Position hoppityStatsPosition = new Position(163, 160, false, true); + + @Expose + @ConfigOption(name = "Hoppity Menu Shortcut", desc = "Add a Chocolate Factory button in the SkyBlock Menu that runs /chocolatefactory on click.") + @ConfigEditorBoolean + @FeatureToggle + public boolean hoppityMenuShortcut = true; +} diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/InventoryConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/InventoryConfig.java index 518730117..f28aac82e 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/InventoryConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/InventoryConfig.java @@ -48,6 +48,10 @@ public class InventoryConfig { @Category(name = "Item Abilities", desc = "Stuff about item abilities.") public ItemAbilityConfig itemAbilities = new ItemAbilityConfig(); + @Expose + @Category(name = "Chocolate Factory", desc = "The chocolate factory") + public ChocolateFactoryConfig chocolateFactory = new ChocolateFactoryConfig(); + @Expose @ConfigOption(name = "Not Clickable Items", desc = "") @Accordion 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 deleted file mode 100644 index 377e79072..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryAPI.kt +++ /dev/null @@ -1,345 +0,0 @@ -package at.hannibal2.skyhanni.features.event.chocolatefactory - -import at.hannibal2.skyhanni.SkyHanniMod -import at.hannibal2.skyhanni.config.features.event.ChocolateFactoryConfig -import at.hannibal2.skyhanni.config.storage.ProfileSpecificStorage.ChocolateFactoryStorage -import at.hannibal2.skyhanni.data.ProfileStorageData -import at.hannibal2.skyhanni.data.jsonobjects.repo.HoppityEggLocationsJson -import at.hannibal2.skyhanni.events.InventoryCloseEvent -import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent -import at.hannibal2.skyhanni.events.InventoryUpdatedEvent -import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent -import at.hannibal2.skyhanni.events.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 -import at.hannibal2.skyhanni.utils.ItemUtils.getLore -import at.hannibal2.skyhanni.utils.ItemUtils.name -import at.hannibal2.skyhanni.utils.LorenzUtils -import at.hannibal2.skyhanni.utils.NumberUtil.formatDouble -import at.hannibal2.skyhanni.utils.NumberUtil.formatInt -import at.hannibal2.skyhanni.utils.NumberUtil.formatLong -import at.hannibal2.skyhanni.utils.NumberUtil.romanToDecimal -import at.hannibal2.skyhanni.utils.SimpleTimeMark -import at.hannibal2.skyhanni.utils.SkyblockSeason -import at.hannibal2.skyhanni.utils.SoundUtils -import at.hannibal2.skyhanni.utils.StringUtils.matchFirst -import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher -import at.hannibal2.skyhanni.utils.StringUtils.matches -import at.hannibal2.skyhanni.utils.StringUtils.removeColor -import at.hannibal2.skyhanni.utils.TimeUtils -import at.hannibal2.skyhanni.utils.UtilsPatterns -import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern -import net.minecraft.item.ItemStack -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent - -object ChocolateFactoryAPI { - - val config: ChocolateFactoryConfig get() = SkyHanniMod.feature.event.chocolateFactory - val profileStorage: ChocolateFactoryStorage? get() = ProfileStorageData.profileSpecific?.chocolateFactory - - val patternGroup = RepoPattern.group("misc.chocolatefactory") - private val chocolateAmountPattern by patternGroup.pattern( - "chocolate.amount", - "(?[\\d,]+) Chocolate" - ) - private val chocolatePerSecondPattern by patternGroup.pattern( - "chocolate.persecond", - "§6(?[\\d.,]+) §8per second" - ) - private val chocolateAllTimePattern by patternGroup.pattern( - "chocolate.alltime", - "§7All-time Chocolate: §6(?[\\d,]+)" - ) - private val chocolateThisPrestigePattern by patternGroup.pattern( - "chocolate.thisprestige", - "§7Chocolate this Prestige: §6(?[\\d,]+)" - ) - private val chocolateMultiplierPattern by patternGroup.pattern( - "chocolate.multiplier", - "§7Total Multiplier: §6(?[\\d.]+)x" - ) - private val barnAmountPattern by patternGroup.pattern( - "barn.amount", - "§7Your Barn: §.(?\\d+)§7/§.(?\\d+) Rabbits" - ) - private val prestigeLevelPattern by patternGroup.pattern( - "prestige.level", - "§6Chocolate Factory (?[IVX]+)" - ) - private val chocolateForPrestigePattern by patternGroup.pattern( - "chocolate.forprestige", - "§7§cRequires (?\\w+) Chocolate this.*" - ) - private val clickMeRabbitPattern by patternGroup.pattern( - "rabbit.clickme", - "§e§lCLICK ME!" - ) - private val leaderboardPlacePattern by patternGroup.pattern( - "leaderboard.place", - "§7You are §8#§b(?[\\d,]+)" - ) - private val leaderboardPercentilePattern by patternGroup.pattern( - "leaderboard.percentile", - "§7§8You are in the top §.(?[\\d.]+)%§8 of players!" - ) - private val timeTowerAmountPattern by patternGroup.pattern( - "timetower.amount", - "§7Charges: §.(?\\d+)§7/§a(?\\d+)" - ) - private val timeTowerStatusPattern by patternGroup.pattern( - "timetower.status", - "§7Status: §.§l(?INACTIVE|ACTIVE)(?: §f)?(?\\w*)" - ) - private val timeTowerRechargePattern by patternGroup.pattern( - "timetower.recharge", - "§7Next Charge: §a(?\\w+)" - ) - private val chocolateFactoryInventoryNamePattern by patternGroup.pattern( - "inventory.name", - "Hoppity|Chocolate Shop|Chocolate Factory Milestones" - ) - - var rabbitSlots = mapOf() - var otherUpgradeSlots = setOf() - var noPickblockSlots = setOf() - var barnIndex = 34 - private var infoIndex = 13 - private var productionInfoIndex = 45 - var prestigeIndex = 28 - var milestoneIndex = 53 - private var leaderboardIndex = 51 - var handCookieIndex = 38 - var timeTowerIndex = 39 - var shrineIndex = 41 - var coachRabbitIndex = 42 - var maxRabbits = 395 - - var inChocolateFactory = false - var chocolateFactoryPaused = false - - var currentPrestige = 1 - var chocolatePerSecond = 0.0 - var leaderboardPosition: Int? = null - var leaderboardPercentile: Double? = null - var chocolateForPrestige = 150_000_000L - - val upgradeableSlots: MutableSet = mutableSetOf() - var bestUpgrade: Int? = null - var bestRabbitUpgrade: String? = null - var clickRabbitSlot: Int? = null - - @SubscribeEvent - fun onInventoryOpen(event: InventoryFullyOpenedEvent) { - if (!isEnabled()) return - - if (chocolateFactoryInventoryNamePattern.matches(event.inventoryName)) { - chocolateFactoryPaused = true - ChocolateFactoryStats.updateDisplay() - return - } - if (event.inventoryName != "Chocolate Factory") return - inChocolateFactory = true - - DelayedRun.runNextTick { - updateInventoryItems(event.inventoryItems) - } - } - - @SubscribeEvent - fun onInventoryUpdated(event: InventoryUpdatedEvent) { - if (!inChocolateFactory) return - - updateInventoryItems(event.inventoryItems) - } - - private fun updateInventoryItems(inventory: Map) { - val infoItem = InventoryUtils.getItemAtSlotIndex(infoIndex) ?: return - val prestigeItem = InventoryUtils.getItemAtSlotIndex(prestigeIndex) ?: return - val productionInfoItem = InventoryUtils.getItemAtSlotIndex(productionInfoIndex) ?: return - val leaderboardItem = InventoryUtils.getItemAtSlotIndex(leaderboardIndex) ?: return - val barnItem = InventoryUtils.getItemAtSlotIndex(barnIndex) ?: return - val timeTowerItem = InventoryUtils.getItemAtSlotIndex(timeTowerIndex) ?: return - - processInfoItems(infoItem, prestigeItem, productionInfoItem, leaderboardItem, barnItem, timeTowerItem) - - bestUpgrade = null - upgradeableSlots.clear() - var bestAffordableUpgradeRatio = Double.MAX_VALUE - var bestPossibleUpgradeRatio = Double.MAX_VALUE - clickRabbitSlot = null - - for ((slotIndex, item) in inventory) { - if (config.rabbitWarning && clickMeRabbitPattern.matches(item.name)) { - SoundUtils.playBeepSound() - clickRabbitSlot = slotIndex - } - - val lore = item.getLore() - val upgradeCost = getChocolateUpgradeCost(lore) ?: continue - - val canAfford = upgradeCost <= ChocolateAmount.CURRENT.chocolate() - if (canAfford) upgradeableSlots.add(slotIndex) - - if (slotIndex in rabbitSlots) { - val chocolateIncrease = rabbitSlots[slotIndex] ?: 0 - val upgradeRatio = upgradeCost.toDouble() / chocolateIncrease - - if (canAfford && upgradeRatio < bestAffordableUpgradeRatio) { - bestUpgrade = slotIndex - bestAffordableUpgradeRatio = upgradeRatio - } - if (upgradeRatio < bestPossibleUpgradeRatio) { - bestPossibleUpgradeRatio = upgradeRatio - bestRabbitUpgrade = item.name - } - } - } - } - - private fun processInfoItems( - chocolateItem: ItemStack, - prestigeItem: ItemStack, - productionItem: ItemStack, - leaderboardItem: ItemStack, - barnItem: ItemStack, - timeTowerItem: ItemStack, - ) { - val profileStorage = profileStorage ?: return - - leaderboardPosition = null - leaderboardPercentile = null - - chocolateAmountPattern.matchMatcher(chocolateItem.name.removeColor()) { - profileStorage.currentChocolate = group("amount").formatLong() - } - for (line in chocolateItem.getLore()) { - chocolatePerSecondPattern.matchMatcher(line) { - chocolatePerSecond = group("amount").formatDouble() - } - chocolateAllTimePattern.matchMatcher(line) { - profileStorage.chocolateAllTime = group("amount").formatLong() - } - } - prestigeLevelPattern.matchMatcher(prestigeItem.name) { - currentPrestige = group("prestige").romanToDecimal() - } - for (line in prestigeItem.getLore()) { - chocolateThisPrestigePattern.matchMatcher(line) { - profileStorage.chocolateThisPrestige = group("amount").formatLong() - } - chocolateForPrestigePattern.matchMatcher(line) { - chocolateForPrestige = group("amount").formatLong() - } - } - productionItem.getLore().matchFirst(chocolateMultiplierPattern) { - val currentMultiplier = group("amount").formatDouble() - profileStorage.chocolateMultiplier = currentMultiplier - - if (ChocolateFactoryTimeTowerManager.timeTowerActive()) { - profileStorage.rawChocolateMultiplier = currentMultiplier - profileStorage.timeTowerLevel * 0.1 - } else { - profileStorage.rawChocolateMultiplier = currentMultiplier - } - } - for (line in leaderboardItem.getLore()) { - leaderboardPlacePattern.matchMatcher(line) { - leaderboardPosition = group("position").formatInt() - } - leaderboardPercentilePattern.matchMatcher(line) { - leaderboardPercentile = group("percent").formatDouble() - } - } - barnItem.getLore().matchFirst(barnAmountPattern) { - profileStorage.currentRabbits = group("rabbits").formatInt() - profileStorage.maxRabbits = group("max").formatInt() - ChocolateFactoryBarnManager.trySendBarnFullMessage() - } - for (line in timeTowerItem.getLore()) { - timeTowerAmountPattern.matchMatcher(line) { - profileStorage.currentTimeTowerUses = group("uses").formatInt() - profileStorage.maxTimeTowerUses = group("max").formatInt() - ChocolateFactoryTimeTowerManager.checkTimeTowerWarning(true) - } - timeTowerStatusPattern.matchMatcher(line) { - val activeTime = group("acitveTime") - if (activeTime.isNotEmpty()) { - // todo in future fix this issue with TimeUtils.getDuration - val formattedGroup = activeTime.replace("h", "h ").replace("m", "m ") - - val activeDuration = TimeUtils.getDuration(formattedGroup) - val activeUntil = SimpleTimeMark.now() + activeDuration - profileStorage.currentTimeTowerEnds = activeUntil.toMillis() - } - } - timeTowerRechargePattern.matchMatcher(line) { - // todo in future fix this issue with TimeUtils.getDuration - val formattedGroup = group("duration").replace("h", "h ").replace("m", "m ") - - val timeUntilTower = TimeUtils.getDuration(formattedGroup) - val nextTimeTower = SimpleTimeMark.now() + timeUntilTower - profileStorage.nextTimeTower = nextTimeTower.toMillis() - } - } - profileStorage.rawChocPerSecond = (chocolatePerSecond / profileStorage.chocolateMultiplier).toInt() - profileStorage.lastDataSave = SimpleTimeMark.now().toMillis() - - if (!config.statsDisplay) return - ChocolateFactoryStats.updateDisplay() - } - - @SubscribeEvent - fun onWorldChange(event: LorenzWorldChangeEvent) { - clearData() - } - - @SubscribeEvent - fun onInventoryClose(event: InventoryCloseEvent) { - clearData() - } - - private fun clearData() { - inChocolateFactory = false - chocolateFactoryPaused = false - } - - @SubscribeEvent - fun onRepoReload(event: RepositoryReloadEvent) { - val data = event.getConstant("HoppityEggLocations") - - HoppityEggLocator.eggLocations = data.eggLocations - - rabbitSlots = data.rabbitSlots - otherUpgradeSlots = data.otherUpgradeSlots - noPickblockSlots = data.noPickblockSlots - barnIndex = data.barnIndex - infoIndex = data.infoIndex - productionInfoIndex = data.productionInfoIndex - prestigeIndex = data.prestigeIndex - milestoneIndex = data.milestoneIndex - leaderboardIndex = data.leaderboardIndex - handCookieIndex = data.handCookieIndex - timeTowerIndex = data.timeTowerIndex - shrineIndex = data.shrineIndex - coachRabbitIndex = data.coachRabbitIndex - maxRabbits = data.maxRabbits - - ChocolateFactoryTooltip.updateIgnoredSlots() - } - - fun getChocolateUpgradeCost(lore: List): Long? { - val nextLine = lore.nextAfter({ UtilsPatterns.costLinePattern.matches(it) }) ?: return null - return chocolateAmountPattern.matchMatcher(nextLine.removeColor()) { - group("amount").formatLong() - } - } - - fun isEnabled() = LorenzUtils.inSkyBlock && config.enabled - - fun isHoppityEvent() = SkyblockSeason.getCurrentSeason() == SkyblockSeason.SPRING -} 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 deleted file mode 100644 index 7b1be9152..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryBarnManager.kt +++ /dev/null @@ -1,92 +0,0 @@ -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 -import at.hannibal2.skyhanni.utils.SimpleTimeMark -import at.hannibal2.skyhanni.utils.SoundUtils -import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent -import kotlin.time.Duration.Companion.seconds - -object ChocolateFactoryBarnManager { - - private val config get() = ChocolateFactoryAPI.config - private val profileStorage get() = ChocolateFactoryAPI.profileStorage - - private val newRabbitPattern by ChocolateFactoryAPI.patternGroup.pattern( - "rabbit.new", - "§d§lNEW RABBIT! §6\\+\\d Chocolate §7and §6\\+0.\\d+x Chocolate §7per second!" - ) - private val rabbitDuplicatePattern by ChocolateFactoryAPI.patternGroup.pattern( - "rabbit.duplicate", - "§7§lDUPLICATE RABBIT! §6\\+[\\d,]+ Chocolate" - ) - - var barnFull = false - private var lastBarnFullWarning = SimpleTimeMark.farPast() - - @SubscribeEvent - fun onChat(event: LorenzChatEvent) { - if (!LorenzUtils.inSkyBlock) return - - newRabbitPattern.matchMatcher(event.message) { - val profileStorage = profileStorage ?: return - profileStorage.currentRabbits += 1 - trySendBarnFullMessage() - HoppityEggsManager.shareWaypointPrompt() - } - - rabbitDuplicatePattern.matchMatcher(event.message) { - HoppityEggsManager.shareWaypointPrompt() - } - } - - fun trySendBarnFullMessage() { - if (!ChocolateFactoryAPI.isEnabled()) return - - if (config.barnCapacityThreshold <= 0) { - return - } - - val profileStorage = profileStorage ?: return - - if (profileStorage.maxRabbits >= ChocolateFactoryAPI.maxRabbits) return - - val remainingSpace = profileStorage.maxRabbits - profileStorage.currentRabbits - barnFull = remainingSpace <= config.barnCapacityThreshold - if (!barnFull) return - - if (lastBarnFullWarning.passedSince() < 30.seconds) return - - if (profileStorage.maxRabbits == -1) { - ChatUtils.clickableChat( - "Open your chocolate factory to see your barn's capacity status!", - onClick = { - HypixelCommands.chocolateFactory() - } - ) - return - } - - ChatUtils.clickableChat( - message = if (profileStorage.currentRabbits == profileStorage.maxRabbits) { - "§cYour barn is full! §7(${barnStatus()}). §cUpgrade it so they don't get crushed" - } else { - "§cYour barn is almost full! §7(${barnStatus()}). §cUpgrade it so they don't get crushed" - }, - onClick = { - HypixelCommands.chocolateFactory() - } - ) - SoundUtils.playBeepSound() - lastBarnFullWarning = SimpleTimeMark.now() - } - - fun barnStatus(): String { - val profileStorage = profileStorage ?: return "Unknown" - return "${profileStorage.currentRabbits}/${profileStorage.maxRabbits} Rabbits" - } -} diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryShortcut.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryShortcut.kt deleted file mode 100644 index 6b9fc671e..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryShortcut.kt +++ /dev/null @@ -1,72 +0,0 @@ -package at.hannibal2.skyhanni.features.event.chocolatefactory - -import at.hannibal2.skyhanni.data.IslandType -import at.hannibal2.skyhanni.events.GuiContainerEvent -import at.hannibal2.skyhanni.events.InventoryCloseEvent -import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent -import at.hannibal2.skyhanni.utils.HypixelCommands -import at.hannibal2.skyhanni.utils.LorenzUtils -import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName -import at.hannibal2.skyhanni.utils.NEUItems.getItemStack -import at.hannibal2.skyhanni.utils.SimpleTimeMark -import io.github.moulberry.notenoughupdates.events.ReplaceItemEvent -import io.github.moulberry.notenoughupdates.util.Utils -import net.minecraft.client.player.inventory.ContainerLocalMenu -import net.minecraftforge.fml.common.eventhandler.EventPriority -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent -import kotlin.time.Duration.Companion.seconds - -class ChocolateFactoryShortcut { - - private val config get() = ChocolateFactoryAPI.config - private var showItem = false - private var lastClick = SimpleTimeMark.farPast() - - private val item by lazy { - val neuItem = "COOKIE".asInternalName().getItemStack() - Utils.createItemStack( - neuItem.item, - "§6Open Chocolate Factory", - "§8(From SkyHanni)", - "", - "§7Click here to run", - "§e/chocolatefactory" - ) - } - - @SubscribeEvent - fun onInventoryOpen(event: InventoryFullyOpenedEvent) { - if (!LorenzUtils.inSkyBlock) return - if (LorenzUtils.inAnyIsland( - IslandType.THE_RIFT, - IslandType.KUUDRA_ARENA, - IslandType.CATACOMBS, - IslandType.MINESHAFT, - ) - ) return - showItem = config.hoppityMenuShortcut && event.inventoryName == "SkyBlock Menu" - } - - @SubscribeEvent - fun onInventoryClose(event: InventoryCloseEvent) { - showItem = false - } - - @SubscribeEvent - fun replaceItem(event: ReplaceItemEvent) { - if (event.inventory is ContainerLocalMenu && showItem && event.slotNumber == 15) { - event.replaceWith(item) - } - } - - @SubscribeEvent(priority = EventPriority.HIGH) - fun onStackClick(event: GuiContainerEvent.SlotClickEvent) { - if (showItem && event.slotId == 15) { - event.cancel() - if (lastClick.passedSince() > 2.seconds) { - HypixelCommands.chocolateFactory() - 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 deleted file mode 100644 index 09091532a..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/hoppity/HoppityCollectionStats.kt +++ /dev/null @@ -1,217 +0,0 @@ -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 deleted file mode 100644 index b6767f7b8..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/hoppity/HoppityEggLocator.kt +++ /dev/null @@ -1,246 +0,0 @@ -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 deleted file mode 100644 index 295e95d9c..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/hoppity/HoppityEggType.kt +++ /dev/null @@ -1,53 +0,0 @@ -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 deleted file mode 100644 index f7dfaf99e..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/hoppity/HoppityEggsManager.kt +++ /dev/null @@ -1,118 +0,0 @@ -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 deleted file mode 100644 index effd33500..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/hoppity/HoppityEggsShared.kt +++ /dev/null @@ -1,58 +0,0 @@ -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 deleted file mode 100644 index 8e8e137ae..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/hoppity/HoppityNpc.kt +++ /dev/null @@ -1,67 +0,0 @@ -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 deleted file mode 100644 index 160023629..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/menu/ChocolateAmount.kt +++ /dev/null @@ -1,62 +0,0 @@ -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 deleted file mode 100644 index add477bb9..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/menu/ChocolateFactoryInventory.kt +++ /dev/null @@ -1,133 +0,0 @@ -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 deleted file mode 100644 index e1b26fed8..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/menu/ChocolateFactoryStats.kt +++ /dev/null @@ -1,138 +0,0 @@ -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 deleted file mode 100644 index a1b34a1a4..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/menu/ChocolateFactoryTimeTowerManager.kt +++ /dev/null @@ -1,114 +0,0 @@ -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 deleted file mode 100644 index dd09a2402..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/menu/ChocolateFactoryTooltip.kt +++ /dev/null @@ -1,93 +0,0 @@ -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 deleted file mode 100644 index 00d6783ba..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/menu/ChocolateFactoryTooltipCompact.kt +++ /dev/null @@ -1,77 +0,0 @@ -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() - } - } - } -} diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCollectionStats.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCollectionStats.kt new file mode 100644 index 000000000..6f835b760 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCollectionStats.kt @@ -0,0 +1,217 @@ +package at.hannibal2.skyhanni.features.event.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.inventory.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/hoppity/HoppityEggLocator.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggLocator.kt new file mode 100644 index 000000000..9a6a8799d --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggLocator.kt @@ -0,0 +1,246 @@ +package at.hannibal2.skyhanni.features.event.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.inventory.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() = HoppityEggsManager.config + + 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/hoppity/HoppityEggType.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggType.kt new file mode 100644 index 000000000..15f463884 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggType.kt @@ -0,0 +1,53 @@ +package at.hannibal2.skyhanni.features.event.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/hoppity/HoppityEggsManager.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggsManager.kt new file mode 100644 index 000000000..8b3d81c44 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggsManager.kt @@ -0,0 +1,130 @@ +package at.hannibal2.skyhanni.features.event.hoppity + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator +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.features.inventory.chocolatefactory.ChocolateFactoryAPI +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 { + + val config get() = SkyHanniMod.feature.event.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() + } + + @SubscribeEvent + fun onConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) { + event.move( + 44, + "event.chocolateFactory.highlightHoppityShop", + "event.chocolateFactory.hoppityEggs.highlightHoppityShop" + ) + event.move(44, "event.chocolateFactory.hoppityEggs", "event.hoppityEggs") + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggsShared.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggsShared.kt new file mode 100644 index 000000000..5577db3fd --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggsShared.kt @@ -0,0 +1,58 @@ +package at.hannibal2.skyhanni.features.event.hoppity + +import at.hannibal2.skyhanni.events.LorenzChatEvent +import at.hannibal2.skyhanni.features.event.hoppity.HoppityEggsManager.getEggType +import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryAPI +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() = HoppityEggsManager.config + + /** + * 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/hoppity/HoppityNpc.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityNpc.kt new file mode 100644 index 000000000..199535279 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityNpc.kt @@ -0,0 +1,66 @@ +package at.hannibal2.skyhanni.features.event.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.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() = HoppityEggsManager.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/inventory/chocolatefactory/ChocolateAmount.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateAmount.kt new file mode 100644 index 000000000..cf22746ef --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateAmount.kt @@ -0,0 +1,61 @@ +package at.hannibal2.skyhanni.features.inventory.chocolatefactory + +import at.hannibal2.skyhanni.features.inventory.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/inventory/chocolatefactory/ChocolateFactoryAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryAPI.kt new file mode 100644 index 000000000..76fd47489 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryAPI.kt @@ -0,0 +1,364 @@ +package at.hannibal2.skyhanni.features.inventory.chocolatefactory + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator +import at.hannibal2.skyhanni.config.storage.ProfileSpecificStorage.ChocolateFactoryStorage +import at.hannibal2.skyhanni.data.ProfileStorageData +import at.hannibal2.skyhanni.data.jsonobjects.repo.HoppityEggLocationsJson +import at.hannibal2.skyhanni.events.InventoryCloseEvent +import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent +import at.hannibal2.skyhanni.events.InventoryUpdatedEvent +import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent +import at.hannibal2.skyhanni.events.RepositoryReloadEvent +import at.hannibal2.skyhanni.features.event.hoppity.HoppityEggLocator +import at.hannibal2.skyhanni.utils.CollectionUtils.nextAfter +import at.hannibal2.skyhanni.utils.DelayedRun +import at.hannibal2.skyhanni.utils.InventoryUtils +import at.hannibal2.skyhanni.utils.ItemUtils.getLore +import at.hannibal2.skyhanni.utils.ItemUtils.name +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.NumberUtil.formatDouble +import at.hannibal2.skyhanni.utils.NumberUtil.formatInt +import at.hannibal2.skyhanni.utils.NumberUtil.formatLong +import at.hannibal2.skyhanni.utils.NumberUtil.romanToDecimal +import at.hannibal2.skyhanni.utils.SimpleTimeMark +import at.hannibal2.skyhanni.utils.SkyblockSeason +import at.hannibal2.skyhanni.utils.SoundUtils +import at.hannibal2.skyhanni.utils.StringUtils.matchFirst +import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher +import at.hannibal2.skyhanni.utils.StringUtils.matches +import at.hannibal2.skyhanni.utils.StringUtils.removeColor +import at.hannibal2.skyhanni.utils.TimeUtils +import at.hannibal2.skyhanni.utils.UtilsPatterns +import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern +import net.minecraft.item.ItemStack +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +object ChocolateFactoryAPI { + val config get() = SkyHanniMod.feature.inventory.chocolateFactory + val profileStorage: ChocolateFactoryStorage? get() = ProfileStorageData.profileSpecific?.chocolateFactory + + val patternGroup = RepoPattern.group("misc.chocolatefactory") + private val chocolateAmountPattern by patternGroup.pattern( + "chocolate.amount", + "(?[\\d,]+) Chocolate" + ) + private val chocolatePerSecondPattern by patternGroup.pattern( + "chocolate.persecond", + "§6(?[\\d.,]+) §8per second" + ) + private val chocolateAllTimePattern by patternGroup.pattern( + "chocolate.alltime", + "§7All-time Chocolate: §6(?[\\d,]+)" + ) + private val chocolateThisPrestigePattern by patternGroup.pattern( + "chocolate.thisprestige", + "§7Chocolate this Prestige: §6(?[\\d,]+)" + ) + private val chocolateMultiplierPattern by patternGroup.pattern( + "chocolate.multiplier", + "§7Total Multiplier: §6(?[\\d.]+)x" + ) + private val barnAmountPattern by patternGroup.pattern( + "barn.amount", + "§7Your Barn: §.(?\\d+)§7/§.(?\\d+) Rabbits" + ) + private val prestigeLevelPattern by patternGroup.pattern( + "prestige.level", + "§6Chocolate Factory (?[IVX]+)" + ) + private val chocolateForPrestigePattern by patternGroup.pattern( + "chocolate.forprestige", + "§7§cRequires (?\\w+) Chocolate this.*" + ) + private val clickMeRabbitPattern by patternGroup.pattern( + "rabbit.clickme", + "§e§lCLICK ME!" + ) + private val leaderboardPlacePattern by patternGroup.pattern( + "leaderboard.place", + "§7You are §8#§b(?[\\d,]+)" + ) + private val leaderboardPercentilePattern by patternGroup.pattern( + "leaderboard.percentile", + "§7§8You are in the top §.(?[\\d.]+)%§8 of players!" + ) + private val timeTowerAmountPattern by patternGroup.pattern( + "timetower.amount", + "§7Charges: §.(?\\d+)§7/§a(?\\d+)" + ) + private val timeTowerStatusPattern by patternGroup.pattern( + "timetower.status", + "§7Status: §.§l(?INACTIVE|ACTIVE)(?: §f)?(?\\w*)" + ) + private val timeTowerRechargePattern by patternGroup.pattern( + "timetower.recharge", + "§7Next Charge: §a(?\\w+)" + ) + private val chocolateFactoryInventoryNamePattern by patternGroup.pattern( + "inventory.name", + "Hoppity|Chocolate Shop|Chocolate Factory Milestones" + ) + + var rabbitSlots = mapOf() + var otherUpgradeSlots = setOf() + var noPickblockSlots = setOf() + var barnIndex = 34 + private var infoIndex = 13 + private var productionInfoIndex = 45 + var prestigeIndex = 28 + var milestoneIndex = 53 + private var leaderboardIndex = 51 + var handCookieIndex = 38 + var timeTowerIndex = 39 + var shrineIndex = 41 + var coachRabbitIndex = 42 + var maxRabbits = 395 + + var inChocolateFactory = false + var chocolateFactoryPaused = false + + var currentPrestige = 1 + var chocolatePerSecond = 0.0 + var leaderboardPosition: Int? = null + var leaderboardPercentile: Double? = null + var chocolateForPrestige = 150_000_000L + + val upgradeableSlots: MutableSet = mutableSetOf() + var bestUpgrade: Int? = null + var bestRabbitUpgrade: String? = null + var clickRabbitSlot: Int? = null + + @SubscribeEvent + fun onInventoryOpen(event: InventoryFullyOpenedEvent) { + if (!isEnabled()) return + + if (chocolateFactoryInventoryNamePattern.matches(event.inventoryName)) { + chocolateFactoryPaused = true + ChocolateFactoryStats.updateDisplay() + return + } + if (event.inventoryName != "Chocolate Factory") return + inChocolateFactory = true + + DelayedRun.runNextTick { + updateInventoryItems(event.inventoryItems) + } + } + + @SubscribeEvent + fun onInventoryUpdated(event: InventoryUpdatedEvent) { + if (!inChocolateFactory) return + + updateInventoryItems(event.inventoryItems) + } + + private fun updateInventoryItems(inventory: Map) { + val infoItem = InventoryUtils.getItemAtSlotIndex(infoIndex) ?: return + val prestigeItem = InventoryUtils.getItemAtSlotIndex(prestigeIndex) ?: return + val productionInfoItem = InventoryUtils.getItemAtSlotIndex(productionInfoIndex) ?: return + val leaderboardItem = InventoryUtils.getItemAtSlotIndex(leaderboardIndex) ?: return + val barnItem = InventoryUtils.getItemAtSlotIndex(barnIndex) ?: return + val timeTowerItem = InventoryUtils.getItemAtSlotIndex(timeTowerIndex) ?: return + + processInfoItems(infoItem, prestigeItem, productionInfoItem, leaderboardItem, barnItem, timeTowerItem) + + bestUpgrade = null + upgradeableSlots.clear() + var bestAffordableUpgradeRatio = Double.MAX_VALUE + var bestPossibleUpgradeRatio = Double.MAX_VALUE + clickRabbitSlot = null + + for ((slotIndex, item) in inventory) { + if (config.rabbitWarning && clickMeRabbitPattern.matches(item.name)) { + SoundUtils.playBeepSound() + clickRabbitSlot = slotIndex + } + + val lore = item.getLore() + val upgradeCost = getChocolateUpgradeCost(lore) ?: continue + + val canAfford = upgradeCost <= ChocolateAmount.CURRENT.chocolate() + if (canAfford) upgradeableSlots.add(slotIndex) + + if (slotIndex in rabbitSlots) { + val chocolateIncrease = rabbitSlots[slotIndex] ?: 0 + val upgradeRatio = upgradeCost.toDouble() / chocolateIncrease + + if (canAfford && upgradeRatio < bestAffordableUpgradeRatio) { + bestUpgrade = slotIndex + bestAffordableUpgradeRatio = upgradeRatio + } + if (upgradeRatio < bestPossibleUpgradeRatio) { + bestPossibleUpgradeRatio = upgradeRatio + bestRabbitUpgrade = item.name + } + } + } + } + + private fun processInfoItems( + chocolateItem: ItemStack, + prestigeItem: ItemStack, + productionItem: ItemStack, + leaderboardItem: ItemStack, + barnItem: ItemStack, + timeTowerItem: ItemStack, + ) { + val profileStorage = profileStorage ?: return + + leaderboardPosition = null + leaderboardPercentile = null + + chocolateAmountPattern.matchMatcher(chocolateItem.name.removeColor()) { + profileStorage.currentChocolate = group("amount").formatLong() + } + for (line in chocolateItem.getLore()) { + chocolatePerSecondPattern.matchMatcher(line) { + chocolatePerSecond = group("amount").formatDouble() + } + chocolateAllTimePattern.matchMatcher(line) { + profileStorage.chocolateAllTime = group("amount").formatLong() + } + } + prestigeLevelPattern.matchMatcher(prestigeItem.name) { + currentPrestige = group("prestige").romanToDecimal() + } + for (line in prestigeItem.getLore()) { + chocolateThisPrestigePattern.matchMatcher(line) { + profileStorage.chocolateThisPrestige = group("amount").formatLong() + } + chocolateForPrestigePattern.matchMatcher(line) { + chocolateForPrestige = group("amount").formatLong() + } + } + productionItem.getLore().matchFirst(chocolateMultiplierPattern) { + val currentMultiplier = group("amount").formatDouble() + profileStorage.chocolateMultiplier = currentMultiplier + + if (ChocolateFactoryTimeTowerManager.timeTowerActive()) { + profileStorage.rawChocolateMultiplier = currentMultiplier - profileStorage.timeTowerLevel * 0.1 + } else { + profileStorage.rawChocolateMultiplier = currentMultiplier + } + } + for (line in leaderboardItem.getLore()) { + leaderboardPlacePattern.matchMatcher(line) { + leaderboardPosition = group("position").formatInt() + } + leaderboardPercentilePattern.matchMatcher(line) { + leaderboardPercentile = group("percent").formatDouble() + } + } + barnItem.getLore().matchFirst(barnAmountPattern) { + profileStorage.currentRabbits = group("rabbits").formatInt() + profileStorage.maxRabbits = group("max").formatInt() + ChocolateFactoryBarnManager.trySendBarnFullMessage() + } + for (line in timeTowerItem.getLore()) { + timeTowerAmountPattern.matchMatcher(line) { + profileStorage.currentTimeTowerUses = group("uses").formatInt() + profileStorage.maxTimeTowerUses = group("max").formatInt() + ChocolateFactoryTimeTowerManager.checkTimeTowerWarning(true) + } + timeTowerStatusPattern.matchMatcher(line) { + val activeTime = group("acitveTime") + if (activeTime.isNotEmpty()) { + // todo in future fix this issue with TimeUtils.getDuration + val formattedGroup = activeTime.replace("h", "h ").replace("m", "m ") + + val activeDuration = TimeUtils.getDuration(formattedGroup) + val activeUntil = SimpleTimeMark.now() + activeDuration + profileStorage.currentTimeTowerEnds = activeUntil.toMillis() + } + } + timeTowerRechargePattern.matchMatcher(line) { + // todo in future fix this issue with TimeUtils.getDuration + val formattedGroup = group("duration").replace("h", "h ").replace("m", "m ") + + val timeUntilTower = TimeUtils.getDuration(formattedGroup) + val nextTimeTower = SimpleTimeMark.now() + timeUntilTower + profileStorage.nextTimeTower = nextTimeTower.toMillis() + } + } + profileStorage.rawChocPerSecond = (chocolatePerSecond / profileStorage.chocolateMultiplier).toInt() + profileStorage.lastDataSave = SimpleTimeMark.now().toMillis() + + if (!config.statsDisplay) return + ChocolateFactoryStats.updateDisplay() + } + + @SubscribeEvent + fun onWorldChange(event: LorenzWorldChangeEvent) { + clearData() + } + + @SubscribeEvent + fun onInventoryClose(event: InventoryCloseEvent) { + clearData() + } + + private fun clearData() { + inChocolateFactory = false + chocolateFactoryPaused = false + } + + @SubscribeEvent + fun onRepoReload(event: RepositoryReloadEvent) { + val data = event.getConstant("HoppityEggLocations") + + HoppityEggLocator.eggLocations = data.eggLocations + + rabbitSlots = data.rabbitSlots + otherUpgradeSlots = data.otherUpgradeSlots + noPickblockSlots = data.noPickblockSlots + barnIndex = data.barnIndex + infoIndex = data.infoIndex + productionInfoIndex = data.productionInfoIndex + prestigeIndex = data.prestigeIndex + milestoneIndex = data.milestoneIndex + leaderboardIndex = data.leaderboardIndex + handCookieIndex = data.handCookieIndex + timeTowerIndex = data.timeTowerIndex + shrineIndex = data.shrineIndex + coachRabbitIndex = data.coachRabbitIndex + maxRabbits = data.maxRabbits + + ChocolateFactoryTooltip.updateIgnoredSlots() + } + + @SubscribeEvent + fun onConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) { + val old = "event.chocolateFactory" + val new = "inventory.chocolateFactory" + event.move(44, "$old.enabled", "$new.enabled") + event.move(44, "$old.statsDisplay", "$new.statsDisplay") + event.move(44, "$old.statsDisplayList", "$new.statsDisplayList") + event.move(44, "$old.showStackSizes", "$new.showStackSizes") + event.move(44, "$old.highlightUpgrades", "$new.highlightUpgrades") + event.move(44, "$old.useMiddleClick", "$new.useMiddleClick") + event.move(44, "$old.rabbitWarning", "$new.rabbitWarning") + event.move(44, "$old.barnCapacityThreshold", "$new.barnCapacityThreshold") + event.move(44, "$old.extraTooltipStats", "$new.extraTooltipStats") + event.move(44, "$old.timeTowerWarning", "$new.timeTowerWarning") + event.move(44, "$old.position", "$new.position") + event.move(44, "$old.compactOnClick", "$new.compactOnClick") + event.move(44, "$old.compactOnClickAlways", "$new.compactOnClickAlways") + event.move(44, "$old.tooltipMove", "$new.tooltipMove") + event.move(44, "$old.tooltipMovePosition", "$new.tooltipMovePosition") + event.move(44, "$old.hoppityMenuShortcut", "$new.hoppityMenuShortcut") + event.move(44, "$old.hoppityCollectionStats", "$new.hoppityCollectionStats") + event.move(44, "$old.hoppityStatsPosition", "$new.hoppityStatsPosition") + } + + fun getChocolateUpgradeCost(lore: List): Long? { + val nextLine = lore.nextAfter({ UtilsPatterns.costLinePattern.matches(it) }) ?: return null + return chocolateAmountPattern.matchMatcher(nextLine.removeColor()) { + group("amount").formatLong() + } + } + + fun isEnabled() = LorenzUtils.inSkyBlock && config.enabled + + fun isHoppityEvent() = SkyblockSeason.getCurrentSeason() == SkyblockSeason.SPRING +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryBarnManager.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryBarnManager.kt new file mode 100644 index 000000000..7154af4a1 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryBarnManager.kt @@ -0,0 +1,92 @@ +package at.hannibal2.skyhanni.features.inventory.chocolatefactory + +import at.hannibal2.skyhanni.events.LorenzChatEvent +import at.hannibal2.skyhanni.features.event.hoppity.HoppityEggsManager +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 at.hannibal2.skyhanni.utils.StringUtils.matchMatcher +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import kotlin.time.Duration.Companion.seconds + +object ChocolateFactoryBarnManager { + + private val config get() = ChocolateFactoryAPI.config + private val profileStorage get() = ChocolateFactoryAPI.profileStorage + + private val newRabbitPattern by ChocolateFactoryAPI.patternGroup.pattern( + "rabbit.new", + "§d§lNEW RABBIT! §6\\+\\d Chocolate §7and §6\\+0.\\d+x Chocolate §7per second!" + ) + private val rabbitDuplicatePattern by ChocolateFactoryAPI.patternGroup.pattern( + "rabbit.duplicate", + "§7§lDUPLICATE RABBIT! §6\\+[\\d,]+ Chocolate" + ) + + var barnFull = false + private var lastBarnFullWarning = SimpleTimeMark.farPast() + + @SubscribeEvent + fun onChat(event: LorenzChatEvent) { + if (!LorenzUtils.inSkyBlock) return + + newRabbitPattern.matchMatcher(event.message) { + val profileStorage = profileStorage ?: return + profileStorage.currentRabbits += 1 + trySendBarnFullMessage() + HoppityEggsManager.shareWaypointPrompt() + } + + rabbitDuplicatePattern.matchMatcher(event.message) { + HoppityEggsManager.shareWaypointPrompt() + } + } + + fun trySendBarnFullMessage() { + if (!ChocolateFactoryAPI.isEnabled()) return + + if (config.barnCapacityThreshold <= 0) { + return + } + + val profileStorage = profileStorage ?: return + + if (profileStorage.maxRabbits >= ChocolateFactoryAPI.maxRabbits) return + + val remainingSpace = profileStorage.maxRabbits - profileStorage.currentRabbits + barnFull = remainingSpace <= config.barnCapacityThreshold + if (!barnFull) return + + if (lastBarnFullWarning.passedSince() < 30.seconds) return + + if (profileStorage.maxRabbits == -1) { + ChatUtils.clickableChat( + "Open your chocolate factory to see your barn's capacity status!", + onClick = { + HypixelCommands.chocolateFactory() + } + ) + return + } + + ChatUtils.clickableChat( + message = if (profileStorage.currentRabbits == profileStorage.maxRabbits) { + "§cYour barn is full! §7(${barnStatus()}). §cUpgrade it so they don't get crushed" + } else { + "§cYour barn is almost full! §7(${barnStatus()}). §cUpgrade it so they don't get crushed" + }, + onClick = { + HypixelCommands.chocolateFactory() + } + ) + SoundUtils.playBeepSound() + lastBarnFullWarning = SimpleTimeMark.now() + } + + fun barnStatus(): String { + val profileStorage = profileStorage ?: return "Unknown" + return "${profileStorage.currentRabbits}/${profileStorage.maxRabbits} Rabbits" + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryInventory.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryInventory.kt new file mode 100644 index 000000000..0e5caca37 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryInventory.kt @@ -0,0 +1,131 @@ +package at.hannibal2.skyhanni.features.inventory.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/inventory/chocolatefactory/ChocolateFactoryShortcut.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryShortcut.kt new file mode 100644 index 000000000..7053f521d --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryShortcut.kt @@ -0,0 +1,72 @@ +package at.hannibal2.skyhanni.features.inventory.chocolatefactory + +import at.hannibal2.skyhanni.data.IslandType +import at.hannibal2.skyhanni.events.GuiContainerEvent +import at.hannibal2.skyhanni.events.InventoryCloseEvent +import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent +import at.hannibal2.skyhanni.utils.HypixelCommands +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName +import at.hannibal2.skyhanni.utils.NEUItems.getItemStack +import at.hannibal2.skyhanni.utils.SimpleTimeMark +import io.github.moulberry.notenoughupdates.events.ReplaceItemEvent +import io.github.moulberry.notenoughupdates.util.Utils +import net.minecraft.client.player.inventory.ContainerLocalMenu +import net.minecraftforge.fml.common.eventhandler.EventPriority +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import kotlin.time.Duration.Companion.seconds + +class ChocolateFactoryShortcut { + + private val config get() = ChocolateFactoryAPI.config + private var showItem = false + private var lastClick = SimpleTimeMark.farPast() + + private val item by lazy { + val neuItem = "COOKIE".asInternalName().getItemStack() + Utils.createItemStack( + neuItem.item, + "§6Open Chocolate Factory", + "§8(From SkyHanni)", + "", + "§7Click here to run", + "§e/chocolatefactory" + ) + } + + @SubscribeEvent + fun onInventoryOpen(event: InventoryFullyOpenedEvent) { + if (!LorenzUtils.inSkyBlock) return + if (LorenzUtils.inAnyIsland( + IslandType.THE_RIFT, + IslandType.KUUDRA_ARENA, + IslandType.CATACOMBS, + IslandType.MINESHAFT, + ) + ) return + showItem = config.hoppityMenuShortcut && event.inventoryName == "SkyBlock Menu" + } + + @SubscribeEvent + fun onInventoryClose(event: InventoryCloseEvent) { + showItem = false + } + + @SubscribeEvent + fun replaceItem(event: ReplaceItemEvent) { + if (event.inventory is ContainerLocalMenu && showItem && event.slotNumber == 15) { + event.replaceWith(item) + } + } + + @SubscribeEvent(priority = EventPriority.HIGH) + fun onStackClick(event: GuiContainerEvent.SlotClickEvent) { + if (showItem && event.slotId == 15) { + event.cancel() + if (lastClick.passedSince() > 2.seconds) { + HypixelCommands.chocolateFactory() + lastClick = SimpleTimeMark.now() + } + } + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryStats.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryStats.kt new file mode 100644 index 000000000..cbf38db46 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryStats.kt @@ -0,0 +1,136 @@ +package at.hannibal2.skyhanni.features.inventory.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/inventory/chocolatefactory/ChocolateFactoryTimeTowerManager.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryTimeTowerManager.kt new file mode 100644 index 000000000..e83e60e2b --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryTimeTowerManager.kt @@ -0,0 +1,113 @@ +package at.hannibal2.skyhanni.features.inventory.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/inventory/chocolatefactory/ChocolateFactoryTooltip.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryTooltip.kt new file mode 100644 index 000000000..227ece8d9 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryTooltip.kt @@ -0,0 +1,92 @@ +package at.hannibal2.skyhanni.features.inventory.chocolatefactory + +import at.hannibal2.skyhanni.events.LorenzToolTipEvent +import at.hannibal2.skyhanni.features.inventory.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/inventory/chocolatefactory/ChocolateFactoryTooltipCompact.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryTooltipCompact.kt new file mode 100644 index 000000000..212d9c130 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryTooltipCompact.kt @@ -0,0 +1,76 @@ +package at.hannibal2.skyhanni.features.inventory.chocolatefactory + +import at.hannibal2.skyhanni.events.GuiContainerEvent +import at.hannibal2.skyhanni.events.GuiRenderEvent +import at.hannibal2.skyhanni.events.LorenzToolTipEvent +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