From 19f23335cc4852e8f9c7d56036e7e89c52d230fe Mon Sep 17 00:00:00 2001 From: ILike2WatchMemes Date: Fri, 20 Sep 2024 23:32:10 +0200 Subject: Feature: Inventory - Experiments rework (#2171) Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com> Co-authored-by: CalMWolfs <94038482+CalMWolfs@users.noreply.github.com> --- .../skyhanni/config/ConfigUpdaterMigrator.kt | 2 +- .../hannibal2/skyhanni/config/commands/Commands.kt | 5 + .../config/features/inventory/InventoryConfig.java | 5 + .../ExperimentationTableConfig.java | 50 ++++ .../ExperimentsDryStreakConfig.java | 31 +++ .../ExperimentsProfitTrackerConfig.java | 37 +++ .../features/inventory/helper/HelperConfig.java | 26 -- .../config/storage/ProfileSpecificStorage.java | 24 ++ .../features/inventory/SuperpairsClicksAlert.kt | 70 ------ .../ExperimentationTableAPI.kt | 157 ++++++++++++ .../ExperimentationTableEnums.kt | 28 +++ .../ExperimentsDryStreakDisplay.kt | 113 +++++++++ .../ExperimentsProfitTracker.kt | 258 +++++++++++++++++++ .../experimentationtable/GuardianReminder.kt | 89 +++++++ .../SuperpairExperimentInformationDisplay.kt | 272 +++++++++++++++++++++ .../experimentationtable/SuperpairsClicksAlert.kt | 72 ++++++ .../experimentationtable/UltraRareBookAlert.kt | 95 +++++++ .../inventory/experiments/GuardianReminder.kt | 99 -------- .../inventory/experiments/UltraRareBookAlert.kt | 104 -------- 19 files changed, 1237 insertions(+), 300 deletions(-) create mode 100644 src/main/java/at/hannibal2/skyhanni/config/features/inventory/experimentationtable/ExperimentationTableConfig.java create mode 100644 src/main/java/at/hannibal2/skyhanni/config/features/inventory/experimentationtable/ExperimentsDryStreakConfig.java create mode 100644 src/main/java/at/hannibal2/skyhanni/config/features/inventory/experimentationtable/ExperimentsProfitTrackerConfig.java delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/inventory/SuperpairsClicksAlert.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/ExperimentationTableAPI.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/ExperimentationTableEnums.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/ExperimentsDryStreakDisplay.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/ExperimentsProfitTracker.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/GuardianReminder.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/SuperpairExperimentInformationDisplay.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/SuperpairsClicksAlert.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/UltraRareBookAlert.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/inventory/experiments/GuardianReminder.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/inventory/experiments/UltraRareBookAlert.kt (limited to 'src/main') diff --git a/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt b/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt index 8eb47d394..b9f21ca22 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 = 58 + const val CONFIG_VERSION = 59 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/commands/Commands.kt b/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt index 3f2ddace6..9b85c2cf9 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt +++ b/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt @@ -57,6 +57,7 @@ import at.hannibal2.skyhanni.features.garden.pests.PestFinder import at.hannibal2.skyhanni.features.garden.pests.PestProfitTracker import at.hannibal2.skyhanni.features.garden.visitor.GardenVisitorDropStatistics import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryStrayTracker +import at.hannibal2.skyhanni.features.inventory.experimentationtable.ExperimentsProfitTracker import at.hannibal2.skyhanni.features.mining.KingTalismanHelper import at.hannibal2.skyhanni.features.mining.MineshaftPityDisplay import at.hannibal2.skyhanni.features.mining.fossilexcavator.ExcavatorProfitTracker @@ -276,6 +277,10 @@ object Commands { "shresetpestprofittracker", "Resets the Pest Profit Tracker", ) { PestProfitTracker.resetCommand() } + registerCommand( + "shresetexperimentsprofittracker", + "Resets the Experiments Profit Tracker", + ) { ExperimentsProfitTracker.resetCommand() } registerCommand( "shresetmythologicalcreaturetracker", "Resets the Mythological Creature Tracker", 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 5c3bf3170..062f29b30 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 @@ -4,6 +4,7 @@ import at.hannibal2.skyhanni.config.FeatureToggle; import at.hannibal2.skyhanni.config.HasLegacyId; import at.hannibal2.skyhanni.config.features.inventory.chocolatefactory.ChocolateFactoryConfig; import at.hannibal2.skyhanni.config.features.inventory.customwardrobe.CustomWardrobeConfig; +import at.hannibal2.skyhanni.config.features.inventory.experimentationtable.ExperimentationTableConfig; import at.hannibal2.skyhanni.config.features.inventory.helper.HelperConfig; import at.hannibal2.skyhanni.config.features.itemability.ItemAbilityConfig; import at.hannibal2.skyhanni.config.features.misc.EstimatedItemValueConfig; @@ -38,6 +39,10 @@ public class InventoryConfig { @Category(name = "Bazaar", desc = "Be smart when buying or selling many items in the Bazaar.") public BazaarConfig bazaar = new BazaarConfig(); + @Expose + @Category(name = "Experimentation Table", desc = "QOL features for the Experimentation Table.") + public ExperimentationTableConfig experimentationTable = new ExperimentationTableConfig(); + @Expose @Category(name = "Enchant Parsing", desc = "Settings for SkyHanni's Enchant Parsing") public EnchantParsingConfig enchantParsing = new EnchantParsingConfig(); diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/experimentationtable/ExperimentationTableConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/experimentationtable/ExperimentationTableConfig.java new file mode 100644 index 000000000..dfdad2482 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/experimentationtable/ExperimentationTableConfig.java @@ -0,0 +1,50 @@ +package at.hannibal2.skyhanni.config.features.inventory.experimentationtable; + +import at.hannibal2.skyhanni.config.FeatureToggle; +import at.hannibal2.skyhanni.config.core.config.Position; +import com.google.gson.annotations.Expose; +import io.github.notenoughupdates.moulconfig.annotations.Accordion; +import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean; +import io.github.notenoughupdates.moulconfig.annotations.ConfigLink; +import io.github.notenoughupdates.moulconfig.annotations.ConfigOption; + +public class ExperimentationTableConfig { + + @Expose + @ConfigOption(name = "Profit Tracker", desc = "") + @Accordion + public ExperimentsProfitTrackerConfig experimentsProfitTracker = new ExperimentsProfitTrackerConfig(); + + @Expose + @ConfigOption(name = "Dry-Streak Display", desc = "") + @Accordion + public ExperimentsDryStreakConfig dryStreak = new ExperimentsDryStreakConfig(); + + @Expose + @ConfigOption(name = "Superpair Data", desc = "Shows a display with useful information while doing the Superpair experiment.") + @ConfigEditorBoolean + @FeatureToggle + public boolean superpairDisplay = false; + + @Expose + @ConfigLink(owner = ExperimentationTableConfig.class, field = "superpairDisplay") + public Position superpairDisplayPosition = new Position(-372, 161, false, true); + + @Expose + @ConfigOption(name = "Superpairs Clicks Alert", desc = "Display an alert when you reach the maximum clicks gained from Chronomatron or Ultrasequencer.") + @ConfigEditorBoolean + @FeatureToggle + public boolean superpairsClicksAlert = false; + + @Expose + @ConfigOption(name = "ULTRA-RARE Book Alert", desc = "Send a chat message, title and sound when you find an ULTRA-RARE book.") + @ConfigEditorBoolean + @FeatureToggle + public boolean ultraRareBookAlert = false; + + @Expose + @ConfigOption(name = "Guardian Reminder", desc = "Sends a warning when opening the Experimentation Table without a §9§lGuardian Pet §7equipped.") + @ConfigEditorBoolean + @FeatureToggle + public boolean guardianReminder = false; +} diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/experimentationtable/ExperimentsDryStreakConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/experimentationtable/ExperimentsDryStreakConfig.java new file mode 100644 index 000000000..dfba626a7 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/experimentationtable/ExperimentsDryStreakConfig.java @@ -0,0 +1,31 @@ +package at.hannibal2.skyhanni.config.features.inventory.experimentationtable; + +import at.hannibal2.skyhanni.config.FeatureToggle; +import at.hannibal2.skyhanni.config.core.config.Position; +import com.google.gson.annotations.Expose; +import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean; +import io.github.notenoughupdates.moulconfig.annotations.ConfigLink; +import io.github.notenoughupdates.moulconfig.annotations.ConfigOption; + +public class ExperimentsDryStreakConfig { + + @Expose + @ConfigOption(name = "Enabled", desc = "Display attempts and or XP since your last ULTRA-RARE.") + @ConfigEditorBoolean + @FeatureToggle + public boolean enabled = false; + + @Expose + @ConfigOption(name = "Attempts", desc = "Display Attempts since.") + @ConfigEditorBoolean + public boolean attemptsSince = true; + + @Expose + @ConfigOption(name = "XP", desc = "Display XP since.") + @ConfigEditorBoolean + public boolean xpSince = true; + + @Expose + @ConfigLink(owner = ExperimentsDryStreakConfig.class, field = "enabled") + public Position position = new Position(200, -187, false, true); +} diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/experimentationtable/ExperimentsProfitTrackerConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/experimentationtable/ExperimentsProfitTrackerConfig.java new file mode 100644 index 000000000..62ee4f540 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/experimentationtable/ExperimentsProfitTrackerConfig.java @@ -0,0 +1,37 @@ +package at.hannibal2.skyhanni.config.features.inventory.experimentationtable; + +import at.hannibal2.skyhanni.config.FeatureToggle; +import at.hannibal2.skyhanni.config.core.config.Position; +import at.hannibal2.skyhanni.features.inventory.experimentationtable.ExperimentMessages; +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.List; + +public class ExperimentsProfitTrackerConfig { + + @Expose + @ConfigOption(name = "Enabled", desc = "Tracker for drops/XP you get from experiments.") + @ConfigEditorBoolean + @FeatureToggle + public boolean enabled = false; + + @Expose + @ConfigOption(name = "Hide Messages", desc = "Change the messages to be hidden after completing Add-on/Main experiments.") + @ConfigEditorDraggableList + public List hideMessages = new ArrayList<>(); + + @Expose + @ConfigOption(name = "Time displayed", desc = "Time displayed after completing an experiment.") + @ConfigEditorSlider(minValue = 5, maxValue = 60, minStep = 1) + public int timeDisplayed = 30; + + @Expose + @ConfigLink(owner = ExperimentsProfitTrackerConfig.class, field = "enabled") + public Position position = new Position(20, 20, false, true); +} diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/helper/HelperConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/helper/HelperConfig.java index 5f54e707d..717dd7659 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/helper/HelperConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/helper/HelperConfig.java @@ -56,30 +56,4 @@ public class HelperConfig { @ConfigOption(name = "Reforge Helper", desc = "") @Accordion public ReforgeHelperConfig reforge = new ReforgeHelperConfig(); - - @Expose - @ConfigOption(name = "Enchanting", desc = "") - @Accordion - public EnchantingConfig enchanting = new EnchantingConfig(); - - public static class EnchantingConfig { - @Expose - @ConfigOption(name = "Superpairs Clicks Alert", desc = "Display an alert when you reach the maximum clicks gained from Chronomatron or Ultrasequencer.") - @ConfigEditorBoolean - @FeatureToggle - public boolean superpairsClicksAlert = false; - - @Expose - @ConfigOption(name = "ULTRA-RARE Book Alert", desc = "Send a chat message, title and sound when you find an ULTRA-RARE book.") - @ConfigEditorBoolean - @FeatureToggle - public boolean ultraRareBookAlert = false; - - @Expose - @ConfigOption(name = "Guardian Reminder", desc = "Sends a warning when opening the Experimentation Table without a §9§lGuardian Pet §7equipped.") - @ConfigEditorBoolean - @FeatureToggle - public boolean guardianReminder = false; - } - } diff --git a/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java b/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java index 83e7ea47c..754eea3bb 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java +++ b/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java @@ -31,6 +31,7 @@ import at.hannibal2.skyhanni.features.garden.pests.PestProfitTracker; import at.hannibal2.skyhanni.features.garden.pests.VinylType; import at.hannibal2.skyhanni.features.garden.visitor.VisitorReward; import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryStrayTracker; +import at.hannibal2.skyhanni.features.inventory.experimentationtable.ExperimentsProfitTracker; import at.hannibal2.skyhanni.features.inventory.wardrobe.WardrobeAPI; import at.hannibal2.skyhanni.features.mining.MineshaftPityDisplay; import at.hannibal2.skyhanni.features.mining.fossilexcavator.ExcavatorProfitTracker; @@ -65,6 +66,29 @@ public class ProfileSpecificStorage { @Expose public String currentPet = ""; + @Expose + public ExperimentationStorage experimentation = new ExperimentationStorage(); + + public static class ExperimentationStorage { + + @Expose + public LorenzVec tablePos = new LorenzVec(); + + @Expose + public ExperimentsDryStreakStorage dryStreak = new ExperimentsDryStreakStorage(); + + public static class ExperimentsDryStreakStorage { + @Expose + public int attemptsSince = 0; + + @Expose + public int xpSince = 0; + } + + @Expose + public ExperimentsProfitTracker.Data experimentsProfitTracker = new ExperimentsProfitTracker.Data(); + } + @Expose public ChocolateFactoryStorage chocolateFactory = new ChocolateFactoryStorage(); diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/SuperpairsClicksAlert.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/SuperpairsClicksAlert.kt deleted file mode 100644 index 5c5011c85..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/SuperpairsClicksAlert.kt +++ /dev/null @@ -1,70 +0,0 @@ -package at.hannibal2.skyhanni.features.inventory - -import at.hannibal2.skyhanni.SkyHanniMod -import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator -import at.hannibal2.skyhanni.events.InventoryOpenEvent -import at.hannibal2.skyhanni.events.InventoryUpdatedEvent -import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule -import at.hannibal2.skyhanni.utils.ChatUtils -import at.hannibal2.skyhanni.utils.ItemUtils.getLore -import at.hannibal2.skyhanni.utils.SoundUtils -import at.hannibal2.skyhanni.utils.StringUtils.removeColor -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent - -@SkyHanniModule -object SuperpairsClicksAlert { - - private val config get() = SkyHanniMod.feature.inventory.helper.enchanting - - private var roundsNeeded = -1 - private val roundsNeededRegex = Regex("""(?:Chain|Series) of (\d+):""") - private val currentRoundRegex = Regex("""Round: (\d+)""") - private val targetInventoryNames = arrayOf("Chronomatron", "Ultrasequencer") - - @SubscribeEvent - fun onInventoryOpen(event: InventoryOpenEvent) { - if (!config.superpairsClicksAlert) return - if (!targetInventoryNames.any { event.inventoryName.contains(it) }) return - - // player may have drank Metaphysical Serum which reduces clicks needed by up to 3, so need to parse it - for (i in 24 downTo 20) { - val lore = event.inventoryItems[i]?.getLore() ?: continue - if (lore.any { it.contains("Practice mode has no rewards") }) { - roundsNeeded = -1 - break - } - if (lore.any { it.contains("Enchanting level too low!") || it.contains("Not enough experience!") }) continue - val match = lore.asReversed().firstNotNullOfOrNull { roundsNeededRegex.find(it.removeColor()) } ?: continue - roundsNeeded = match.groups[1]!!.value.toInt() - break - } - } - - @SubscribeEvent - fun onInventoryUpdated(event: InventoryUpdatedEvent) { - if (!config.superpairsClicksAlert) return - if (roundsNeeded == -1) return - if (!targetInventoryNames.any { event.inventoryName.contains(it) }) return - - if ( // checks if we have succeeded in either minigame - (event.inventoryName.contains("Chronomatron") - && ((event.inventoryItems[4]?.displayName?.removeColor() - ?.let { currentRoundRegex.find(it) } - ?.groups?.get(1)?.value?.toInt() ?: -1) > roundsNeeded)) - - || (event.inventoryName.contains("Ultrasequencer") - && event.inventoryItems.entries - .filter { it.key < 45 } - .any { it.value.stackSize > roundsNeeded }) - ) { - SoundUtils.playBeepSound() - ChatUtils.chat("You have reached the maximum extra Superpairs clicks from this add-on!") - roundsNeeded = -1 - } - } - - @SubscribeEvent - fun onConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) { - event.move(46, "misc.superpairsClicksAlert", "inventory.helper.enchanting.superpairsClicksAlert") - } -} diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/ExperimentationTableAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/ExperimentationTableAPI.kt new file mode 100644 index 000000000..80433b68e --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/ExperimentationTableAPI.kt @@ -0,0 +1,157 @@ +package at.hannibal2.skyhanni.features.inventory.experimentationtable + +import at.hannibal2.skyhanni.data.IslandType +import at.hannibal2.skyhanni.data.ProfileStorageData +import at.hannibal2.skyhanni.events.InventoryUpdatedEvent +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.utils.EntityUtils +import at.hannibal2.skyhanni.utils.EntityUtils.hasSkullTexture +import at.hannibal2.skyhanni.utils.InventoryUtils.openInventoryName +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.LorenzVec +import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher +import at.hannibal2.skyhanni.utils.RegexUtils.matches +import at.hannibal2.skyhanni.utils.getLorenzVec +import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern +import net.minecraft.entity.item.EntityArmorStand +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +@SkyHanniModule +object ExperimentationTableAPI { + + private val storage get() = ProfileStorageData.profileSpecific?.experimentation + + val inTable get() = inventoriesPattern.matches(openInventoryName()) + + fun inDistanceToTable(vec: LorenzVec, max: Double): Boolean = + storage?.tablePos?.let { it.distance(vec) <= max } ?: false + + fun getCurrentExperiment(): Experiment? = + superpairsPattern.matchMatcher(openInventoryName()) { + Experiment.entries.find { it.nameString == group("experiment") } + } + + @SubscribeEvent + fun onInventoryUpdated(event: InventoryUpdatedEvent) { + if (LorenzUtils.skyBlockIsland != IslandType.PRIVATE_ISLAND || !inTable) return + + val entity = EntityUtils.getEntities().find { it.hasSkullTexture(experimentationTableSkull) } ?: return + val vec = entity.getLorenzVec() + if (storage?.tablePos != vec) storage?.tablePos = vec + } + + private val experimentationTableSkull = + "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTUyOWF" + + "iYzg4MzA5NTNmNGQ5MWVkZmZmMjQ2OTVhOWY2Mjc1OGZhNGM1MWIyOWFjMjQ2YzM3NDllYWFlODliMyJ9fX0=" + + private val patternGroup = RepoPattern.group("enchanting.experiments") + + /** + * REGEX-TEST: Superpairs (Metaphysical) + */ + private val superpairsPattern by patternGroup.pattern( + "superpairs", + "Superpairs \\((?\\w+)\\)", + ) + + /** + * REGEX-TEST: Gained +3 Clicks + */ + val powerUpPattern by patternGroup.pattern( + "powerups", + "Gained \\+\\d Clicks?|Instant Find|\\+\\S* XP", + ) + + /** + * REGEX-TEST: 123k Enchanting Exp + * REGEX-TEST: Titanic Experience Bottle + */ + val rewardPattern by patternGroup.pattern( + "rewards", + "\\d{1,3}k Enchanting Exp|Enchanted Book|(?:Titanic |Grand |\\b)Experience Bottle|Metaphysical Serum|Experiment The Fish", + ) + + /** + * REGEX-TEST: Superpairs (Metaphysical) + * REGEX-TEST: Chronomatron (Metaphysical) + */ + val inventoriesPattern by patternGroup.pattern( + "inventories", + "(?:Superpairs|Chronomatron|Ultrasequencer) (?:\\(.+\\)|➜ Stakes|Rewards)|Experimentation Table", + ) + + /** + * REGEX-TEST: +42,000 Enchanting Exp + */ + val enchantingExpChatPattern by patternGroup.pattern( + "chatexp", + "^ \\+(?\\d+|\\d+,\\d+)k? Enchanting Exp$", + ) + + /** + * REGEX-TEST: +Smite VII + * REGEX-TEST: +42,000 Enchanting Exp + */ + val experimentsDropPattern by patternGroup.pattern( + "drop", + "^ \\+(?.*)\$", + ) + + /** + * REGEX-TEST: You claimed the Superpairs rewards! + */ + val claimMessagePattern by patternGroup.pattern( + "claim", + "You claimed the \\S+ rewards!", + ) + + /** + * REGEX-TEST: 131k Enchanting Exp + * REGEX-TEST: 42,000 Enchanting Exp + */ + val enchantingExpPattern by patternGroup.pattern( + "exp", + "(?\\d+|\\d+,\\d+)k? Enchanting Exp", + ) + + /** + * REGEX-TEST: Titanic Experience Bottle + */ + val experienceBottlePattern by patternGroup.pattern( + "xpbottle", + "(?:Titanic |Grand |\\b)Experience Bottle", + ) + + /** + * REGEX-TEST: ☕ You renewed the experiment table! (1/3) + */ + val experimentRenewPattern by patternGroup.pattern( + "renew", + "^☕ You renewed the experiment table! \\((?\\d)/3\\)$", + ) + + /** + * REGEX-TEST: §d§kXX§5 ULTRA-RARE BOOK! §d§kXX + */ + val ultraRarePattern by patternGroup.pattern( + "ultrarare", + "§d§kXX§5 ULTRA-RARE BOOK! §d§kXX", + ) + + /** + * REGEX-TEST: §9Smite VII + */ + val bookPattern by patternGroup.pattern( + "book", + "§9(?.*)", + ) + + /** + * REGEX-TEST: §dGuardian + * REGEX-TEST: §9Guardian§e + */ + val petNamePattern by patternGroup.pattern( + "guardianpet", + "§[956d]Guardian.*", + ) +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/ExperimentationTableEnums.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/ExperimentationTableEnums.kt new file mode 100644 index 000000000..0071d3af3 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/ExperimentationTableEnums.kt @@ -0,0 +1,28 @@ +package at.hannibal2.skyhanni.features.inventory.experimentationtable + +enum class ExperimentMessages(private val str: String) { + DONE("§eYou claimed the §dSuperpairs §erewards! §8(§7Claim§8)"), + EXPERIENCE("§8 +§3141k Experience §8(§7Experience Drops§8)"), + ENCHANTMENTS("§8 +§9Smite VII §8(§7Enchantment Drops§8)"), + BOTTLES("§8 +§9Titanic Experience Bottle §8(§7Bottle Drops§8)"), + MISC("§8 +§5Metaphysical Serum §8(§7Misc Drops§8)"); + + override fun toString(): String { + return str + } +} + +enum class Experiment(val nameString: String, val gridSize: Int, val startSlot: Int, val endSlot: Int, val sideSpace: Int) { + NONE("", 0, 0, 0, 0), + BEGINNER("Beginner", 14, 18, 35, 1), + HIGH("High", 20, 10, 43, 2), + GRAND("Grand", 20, 10, 43, 2), + SUPREME("Supreme", 28, 9, 44, 1), + TRANSCENDENT("Transcendent", 28, 9, 44, 1), + METAPHYSICAL("Metaphysical", 28, 9, 44, 1), + ; + + override fun toString(): String { + return nameString + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/ExperimentsDryStreakDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/ExperimentsDryStreakDisplay.kt new file mode 100644 index 000000000..50d033842 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/ExperimentsDryStreakDisplay.kt @@ -0,0 +1,113 @@ +package at.hannibal2.skyhanni.features.inventory.experimentationtable + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.data.ProfileStorageData +import at.hannibal2.skyhanni.events.GuiRenderEvent +import at.hannibal2.skyhanni.events.InventoryCloseEvent +import at.hannibal2.skyhanni.events.InventoryOpenEvent +import at.hannibal2.skyhanni.events.InventoryUpdatedEvent +import at.hannibal2.skyhanni.events.LorenzChatEvent +import at.hannibal2.skyhanni.features.inventory.experimentationtable.ExperimentationTableAPI.bookPattern +import at.hannibal2.skyhanni.features.inventory.experimentationtable.ExperimentationTableAPI.ultraRarePattern +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.utils.ChatUtils +import at.hannibal2.skyhanni.utils.InventoryUtils +import at.hannibal2.skyhanni.utils.ItemUtils.getLore +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.NumberUtil.shortFormat +import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher +import at.hannibal2.skyhanni.utils.RegexUtils.matches +import at.hannibal2.skyhanni.utils.RenderUtils.renderStrings +import at.hannibal2.skyhanni.utils.StringUtils.removeColor +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +@SkyHanniModule +object ExperimentsDryStreakDisplay { + + private val config get() = SkyHanniMod.feature.inventory.experimentationTable.dryStreak + private val storage get() = ProfileStorageData.profileSpecific?.experimentation?.dryStreak + + private var display = emptyList() + + private var didJustFind = false + + @SubscribeEvent + fun onChestGuiOverlayRendered(event: GuiRenderEvent.ChestGuiOverlayRenderEvent) { + if (!isEnabled()) return + if (!ExperimentationTableAPI.inventoriesPattern.matches(InventoryUtils.openInventoryName())) return + + display = drawDisplay() + config.position.renderStrings( + display, + posLabel = "Experimentation Table Dry Streak", + ) + } + + @SubscribeEvent + fun onInventoryOpen(event: InventoryOpenEvent) { + if (event.inventoryName == "Experimentation Table" && didJustFind) didJustFind = false + } + + @SubscribeEvent + fun onInventoryUpdated(event: InventoryUpdatedEvent) { + if (!isEnabled() || didJustFind || ExperimentationTableAPI.getCurrentExperiment() == null) return + + for (lore in event.inventoryItems.map { it.value.getLore() }) { + val firstLine = lore.firstOrNull() ?: continue + if (!ultraRarePattern.matches(firstLine)) continue + val bookNameLine = lore.getOrNull(2) ?: continue + bookPattern.matchMatcher(bookNameLine) { + val storage = storage ?: return + ChatUtils.chat( + "§a§lDRY-STREAK ENDED! §eYou have (finally) " + + "found a §5ULTRA-RARE §eafter §3${storage.xpSince.shortFormat()} Enchanting Exp " + + "§e and §2${storage.attemptsSince} attempts§e!", + ) + storage.attemptsSince = 0 + storage.xpSince = 0 + didJustFind = true + } + } + } + + @SubscribeEvent + fun onInventoryClose(event: InventoryCloseEvent) { + if (didJustFind || ExperimentationTableAPI.getCurrentExperiment() == null) return + + val storage = storage ?: return + storage.attemptsSince += 1 + } + + @SubscribeEvent + fun onChat(event: LorenzChatEvent) { + if (!isEnabled() || didJustFind) return + + ExperimentationTableAPI.enchantingExpChatPattern.matchMatcher(event.message.removeColor()) { + val storage = storage ?: return + storage.xpSince += group("amount").substringBefore(",").toInt() * 1000 + } + } + + private fun drawDisplay() = buildList { + val storage = storage ?: return@buildList + + add("§cDry-Streak since last §5ULTRA-RARE") + + val colorPrefix = "§e" + val attemptsSince = storage.attemptsSince + val xpSince = storage.xpSince.shortFormat() + val attemptsSuffix = if (attemptsSince == 1) "" else "s" + + if (config.attemptsSince && config.xpSince) { + add("$colorPrefix ├ $attemptsSince Attempt$attemptsSuffix") + add("$colorPrefix └ $xpSince XP") + } else if (config.attemptsSince) { + add("$colorPrefix └ $attemptsSince Attempt$attemptsSuffix") + } else { + add("$colorPrefix └ $xpSince XP") + } + } + + private fun isEnabled() = + LorenzUtils.inSkyBlock && config.enabled && (config.xpSince || config.attemptsSince) +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/ExperimentsProfitTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/ExperimentsProfitTracker.kt new file mode 100644 index 000000000..16c0305cb --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/ExperimentsProfitTracker.kt @@ -0,0 +1,258 @@ +package at.hannibal2.skyhanni.features.inventory.experimentationtable + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.data.ClickType +import at.hannibal2.skyhanni.data.IslandType +import at.hannibal2.skyhanni.events.GuiRenderEvent +import at.hannibal2.skyhanni.events.InventoryCloseEvent +import at.hannibal2.skyhanni.events.InventoryUpdatedEvent +import at.hannibal2.skyhanni.events.IslandChangeEvent +import at.hannibal2.skyhanni.events.ItemClickEvent +import at.hannibal2.skyhanni.events.LorenzChatEvent +import at.hannibal2.skyhanni.features.inventory.experimentationtable.ExperimentationTableAPI.claimMessagePattern +import at.hannibal2.skyhanni.features.inventory.experimentationtable.ExperimentationTableAPI.enchantingExpPattern +import at.hannibal2.skyhanni.features.inventory.experimentationtable.ExperimentationTableAPI.experienceBottlePattern +import at.hannibal2.skyhanni.features.inventory.experimentationtable.ExperimentationTableAPI.experimentRenewPattern +import at.hannibal2.skyhanni.features.inventory.experimentationtable.ExperimentationTableAPI.experimentsDropPattern +import at.hannibal2.skyhanni.features.inventory.experimentationtable.ExperimentationTableAPI.inventoriesPattern +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.utils.CollectionUtils.addOrPut +import at.hannibal2.skyhanni.utils.CollectionUtils.addSearchString +import at.hannibal2.skyhanni.utils.InventoryUtils +import at.hannibal2.skyhanni.utils.ItemPriceUtils.getNpcPriceOrNull +import at.hannibal2.skyhanni.utils.ItemPriceUtils.getPrice +import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName +import at.hannibal2.skyhanni.utils.ItemUtils.getInternalNameOrNull +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 +import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators +import at.hannibal2.skyhanni.utils.NumberUtil.shortFormat +import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher +import at.hannibal2.skyhanni.utils.RegexUtils.matches +import at.hannibal2.skyhanni.utils.SimpleTimeMark +import at.hannibal2.skyhanni.utils.StringUtils.removeColor +import at.hannibal2.skyhanni.utils.renderables.Renderable +import at.hannibal2.skyhanni.utils.renderables.Searchable +import at.hannibal2.skyhanni.utils.renderables.toSearchable +import at.hannibal2.skyhanni.utils.tracker.ItemTrackerData +import at.hannibal2.skyhanni.utils.tracker.SkyHanniItemTracker +import com.google.gson.annotations.Expose +import net.minecraft.item.ItemStack +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import kotlin.math.absoluteValue + +@SkyHanniModule +object ExperimentsProfitTracker { + + private val config get() = SkyHanniMod.feature.inventory.experimentationTable.experimentsProfitTracker + + private val tracker = SkyHanniItemTracker( + "Experiments Profit Tracker", + { Data() }, + { it.experimentation.experimentsProfitTracker }, + ) { drawDisplay(it) } + + private var lastSplashes = mutableListOf() + private var lastSplashTime = SimpleTimeMark.farPast() + private var lastBottlesInInventory = mutableMapOf() + private var currentBottlesInInventory = mutableMapOf() + + class Data : ItemTrackerData() { + override fun resetItems() { + experimentsDone = 0L + xpGained = 0L + bitCost = 0L + startCost = 0L + } + + override fun getDescription(timesGained: Long): List { + val percentage = timesGained.toDouble() / experimentsDone + val dropRate = LorenzUtils.formatPercentage(percentage.coerceAtMost(1.0)) + return listOf( + "§7Dropped §e${timesGained.addSeparators()} §7times.", + "§7Your drop rate: §c$dropRate.", + ) + } + + override fun getCoinName(item: TrackedItem) = "" + + override fun getCoinDescription(item: TrackedItem) = listOf() + + @Expose + var experimentsDone = 0L + + @Expose + var xpGained = 0L + + @Expose + var bitCost = 0L + + @Expose + var startCost = 0L + } + + @SubscribeEvent + fun onChat(event: LorenzChatEvent) { + if (!isEnabled()) return + + val message = event.message.removeColor() + if (claimMessagePattern.matches(message) && ExperimentMessages.DONE.isSelected()) + event.blockedReason = "CLAIM_MESSAGE" + + experimentsDropPattern.matchMatcher(message) { + val reward = group("reward") + + event.blockedReason = when { + enchantingExpPattern.matches(reward) && ExperimentMessages.EXPERIENCE.isSelected() -> "EXPERIENCE_DROP" + experienceBottlePattern.matches(reward) && ExperimentMessages.BOTTLES.isSelected() -> "BOTTLE_DROP" + listOf("Metaphysical Serum", "Experiment The Fish").contains(reward) && ExperimentMessages.MISC.isSelected() -> "MISC_DROP" + ExperimentMessages.ENCHANTMENTS.isSelected() -> "ENCHANT_DROP" + else -> "" + } + + enchantingExpPattern.matchMatcher(reward) { + tracker.modify { + it.xpGained += group("amount").substringBefore(",").toInt() * 1000 + } + return + } + + val internalName = NEUInternalName.fromItemNameOrNull(reward) ?: return + if (!experienceBottlePattern.matches(group("reward"))) tracker.addItem(internalName, 1, false) + return + } + + experimentRenewPattern.matchMatcher(message) { + val increments = mapOf(1 to 150, 2 to 300, 3 to 500) + tracker.modify { + it.bitCost += increments.getValue(group("current").toInt()) + } + } + } + + @SubscribeEvent + fun onItemClick(event: ItemClickEvent) { + if (event.clickType == ClickType.RIGHT_CLICK) { + val item = event.itemInHand ?: return + if (experienceBottlePattern.matches(item.displayName.removeColor())) { + lastSplashTime = SimpleTimeMark.now() + lastSplashes.add(item) + } + } + } + + @SubscribeEvent + fun onInventoryUpdated(event: InventoryUpdatedEvent) { + if (!isEnabled()) return + + if (inventoriesPattern.matches(event.inventoryName)) { + var startCostTemp = 0 + val iterator = lastSplashes.iterator() + while (iterator.hasNext()) { + val item = iterator.next() + val internalName = item.getInternalName() + val price = internalName.getPrice() + val npcPrice = internalName.getNpcPriceOrNull() ?: 0.0 + val maxPrice = npcPrice.coerceAtLeast(price) + startCostTemp += maxPrice.round(0).toInt() + iterator.remove() + } + tracker.modify { + it.startCost -= startCostTemp + } + lastSplashTime = SimpleTimeMark.farPast() + } + + handleExpBottles(false) + } + + @SubscribeEvent + fun onInventoryClose(event: InventoryCloseEvent) { + if (!isEnabled()) return + + if (ExperimentationTableAPI.getCurrentExperiment() != null) { + tracker.modify { + it.experimentsDone++ + } + } + if (ExperimentationTableAPI.inTable && InventoryUtils.openInventoryName() == "Superpairs Rewards") { + handleExpBottles(true) + } + } + + private fun drawDisplay(data: Data): List = buildList { + addSearchString("§e§lExperiments Profit Tracker") + val profit = tracker.drawItems(data, { true }, this) + data.startCost + + val experimentsDone = data.experimentsDone + addSearchString("") + addSearchString("§eExperiments Done: §a${experimentsDone.addSeparators()}") + val startCostFormat = data.startCost.absoluteValue.shortFormat() + val bitCostFormat = data.bitCost.shortFormat() + add( + Renderable.hoverTips( + "§eTotal Cost: §c-$startCostFormat§e/§b-$bitCostFormat", + listOf( + "§7You paid §c$startCostFormat §7coins and", "§b$bitCostFormat §7bits for starting", + "§7experiments.", + ), + ).toSearchable(), + ) + add(tracker.addTotalProfit(profit, data.experimentsDone, "experiment")) + addSearchString("§eTotal Enchanting Exp: §b${data.xpGained.shortFormat()}") + + tracker.addPriceFromButton(this) + } + + @SubscribeEvent + fun onRenderOverlay(event: GuiRenderEvent) { + if (!isEnabled()) return + + tracker.renderDisplay(config.position) + } + + @SubscribeEvent + fun onIslandChange(event: IslandChangeEvent) { + if (event.newIsland == IslandType.PRIVATE_ISLAND) { + tracker.firstUpdate() + } + } + + fun resetCommand() { + tracker.resetCommand() + } + + private fun handleExpBottles(addToTracker: Boolean) { + for (item in InventoryUtils.getItemsInOwnInventory()) { + val internalName = item.getInternalNameOrNull() ?: continue + if (internalName.asString() !in listOf("EXP_BOTTLE", "GRAND_EXP_BOTTLE", "TITANIC_EXP_BOTTLE")) continue + currentBottlesInInventory.addOrPut(internalName, item.stackSize) + } + for ((internalName, amount) in currentBottlesInInventory) { + val lastInInv = lastBottlesInInventory.getOrDefault(internalName, 0) + if (lastInInv >= amount) { + currentBottlesInInventory[internalName] = 0 + lastBottlesInInventory[internalName] = amount + continue + } + if (lastInInv == 0) { + currentBottlesInInventory[internalName] = 0 + lastBottlesInInventory[internalName] = amount + if (addToTracker) tracker.addItem(internalName, amount, false) + continue + } + + currentBottlesInInventory[internalName] = 0 + lastBottlesInInventory[internalName] = amount + if (addToTracker) tracker.addItem(internalName, amount - lastInInv, false) + } + } + + private fun ExperimentMessages.isSelected() = config.hideMessages.contains(this) + + private fun isEnabled() = + LorenzUtils.inSkyBlock && config.enabled + && ExperimentationTableAPI.inDistanceToTable(LorenzVec.getBlockBelowPlayer(), 5.0) +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/GuardianReminder.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/GuardianReminder.kt new file mode 100644 index 000000000..216cbf7c6 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/GuardianReminder.kt @@ -0,0 +1,89 @@ +package at.hannibal2.skyhanni.features.inventory.experimentationtable + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator +import at.hannibal2.skyhanni.data.PetAPI +import at.hannibal2.skyhanni.events.GuiRenderEvent +import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.utils.ChatUtils +import at.hannibal2.skyhanni.utils.ColorUtils.withAlpha +import at.hannibal2.skyhanni.utils.HypixelCommands +import at.hannibal2.skyhanni.utils.InventoryUtils +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.RegexUtils.matches +import at.hannibal2.skyhanni.utils.RenderUtils +import at.hannibal2.skyhanni.utils.SimpleTimeMark +import at.hannibal2.skyhanni.utils.SoundUtils +import at.hannibal2.skyhanni.utils.renderables.Renderable +import at.hannibal2.skyhanni.utils.renderables.RenderableUtils.renderXYAligned +import net.minecraft.client.Minecraft +import net.minecraft.client.gui.inventory.GuiContainer +import net.minecraft.client.renderer.GlStateManager +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import java.awt.Color +import kotlin.time.Duration.Companion.milliseconds +import kotlin.time.Duration.Companion.seconds + +@SkyHanniModule +object GuardianReminder { + + private val config get() = SkyHanniMod.feature.inventory.experimentationTable + private var lastInventoryOpen = SimpleTimeMark.farPast() + private var lastWarn = SimpleTimeMark.farPast() + private var lastErrorSound = SimpleTimeMark.farPast() + + @SubscribeEvent + fun onInventory(event: InventoryFullyOpenedEvent) { + if (!isEnabled()) return + if (event.inventoryName != "Experimentation Table") return + if (ExperimentationTableAPI.petNamePattern.matches(PetAPI.currentPet)) return + + lastInventoryOpen = SimpleTimeMark.now() + + if (lastWarn.passedSince() < 5.seconds) return + lastWarn = SimpleTimeMark.now() + ChatUtils.clickToActionOrDisable( + "Use a §9§lGuardian Pet §efor more Exp in the Experimentation Table.", + config::guardianReminder, + actionName = "open pets menu", + action = { HypixelCommands.pet() }, + ) + } + + @SubscribeEvent + fun onRenderOverlay(event: GuiRenderEvent.ChestGuiOverlayRenderEvent) { + if (!isEnabled()) return + if (InventoryUtils.openInventoryName() != "Experimentation Table") return + if (lastInventoryOpen.passedSince() > 2.seconds) return + val gui = Minecraft.getMinecraft().currentScreen as? GuiContainer ?: return + + sendTitle(gui.width, gui.height) + if (lastErrorSound.passedSince() > 200.milliseconds) { + lastErrorSound = SimpleTimeMark.now() + SoundUtils.playPlingSound() + } + } + + // TODO rename to "send title in inventory", move to utils + private fun sendTitle(width: Int, height: Int) { + GlStateManager.pushMatrix() + GlStateManager.translate(0f, -150f, 500f) + Renderable.drawInsideRoundedRect( + Renderable.string("§cWrong Pet equipped!", 1.5), + Color(Color.DARK_GRAY.withAlpha(0), true), + horizontalAlign = RenderUtils.HorizontalAlignment.CENTER, + verticalAlign = RenderUtils.VerticalAlignment.CENTER, + ).renderXYAligned(0, 125, width, height) + + GlStateManager.translate(0f, 150f, -500f) + GlStateManager.popMatrix() + } + + @SubscribeEvent + fun onConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) { + event.move(59, "inventory.helper.enchanting.guardianReminder", "inventory.experimentationTable.guardianReminder") + } + + private fun isEnabled() = LorenzUtils.inSkyBlock && config.guardianReminder +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/SuperpairExperimentInformationDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/SuperpairExperimentInformationDisplay.kt new file mode 100644 index 000000000..21bc6052e --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/SuperpairExperimentInformationDisplay.kt @@ -0,0 +1,272 @@ +package at.hannibal2.skyhanni.features.inventory.experimentationtable + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.events.GuiContainerEvent.SlotClickEvent +import at.hannibal2.skyhanni.events.GuiRenderEvent +import at.hannibal2.skyhanni.events.InventoryCloseEvent +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.utils.InventoryUtils +import at.hannibal2.skyhanni.utils.ItemUtils.getLore +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.RegexUtils.matches +import at.hannibal2.skyhanni.utils.RenderUtils.renderStrings +import at.hannibal2.skyhanni.utils.SimpleTimeMark +import at.hannibal2.skyhanni.utils.StringUtils.removeColor +import net.minecraft.item.ItemStack +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import kotlin.time.Duration.Companion.milliseconds + +@SkyHanniModule +object SuperpairExperimentInformationDisplay { + + private val config get() = SkyHanniMod.feature.inventory.experimentationTable + + private var display = emptyList() + + private var uncoveredAt = 0 + private var uncoveredItems = mutableListOf>() + private var possiblePairs = 0 + + data class Item(val index: Int, val name: String) + data class ItemPair(val first: Item, val second: Item) + + private var found = mutableMapOf, String>() + + private var toCheck = mutableListOf>() + private var lastClicked = mutableListOf>() + private var lastClick = SimpleTimeMark.farPast() + private var currentExperiment = Experiment.NONE + private var instantFind = 0 + + private val sideSpaces1 = listOf(17, 18, 26, 27, 35, 36) + private val sideSpaces2 = listOf(16, 17, 18, 19, 25, 26, 27, 28, 34, 35, 36, 37) + + @SubscribeEvent + fun onInventoryClose(event: InventoryCloseEvent) { + display = emptyList() + + uncoveredAt = 0 + uncoveredItems.clear() + possiblePairs = 0 + + found.clear() + toCheck.clear() + lastClicked.clear() + lastClick = SimpleTimeMark.farPast() + currentExperiment = Experiment.NONE + instantFind = 0 + } + + @SubscribeEvent + fun onChestGuiOverlayRendered(event: GuiRenderEvent.ChestGuiOverlayRenderEvent) { + if (!isEnabled()) return + config.superpairDisplayPosition.renderStrings(display, posLabel = "Sperpair Experiment Information") + display = checkItems(toCheck) + } + + @SubscribeEvent + fun onSlotClick(event: SlotClickEvent) { + if (!isEnabled()) return + currentExperiment = ExperimentationTableAPI.getCurrentExperiment() ?: return + + if (isOutOfBounds(event.slotId, currentExperiment)) return + val item = event.item ?: return + if (item.displayName.removeColor() == "?") return + val clicksItem = InventoryUtils.getItemAtSlotIndex(4) + + if (lastClicked.none { it.first == event.slotId && it.second == uncoveredAt } && lastClick.passedSince() > 100.milliseconds) { + if (clicksItem != null && clicksItem.displayName.removeColor().split(" ")[1] == "0") return + lastClicked.add(Pair(event.slotId, uncoveredAt)) + lastClick = SimpleTimeMark.now() + toCheck.add(event.slotId to uncoveredAt) + uncoveredAt += 1 + } + } + + private fun checkItems(check: MutableList>): List { + currentExperiment = ExperimentationTableAPI.getCurrentExperiment() ?: return listOf() + if (check.isEmpty()) return drawDisplay() + + for ((slot, uncovered) in check) { + val itemNow = InventoryUtils.getItemAtSlotIndex(slot) ?: return drawDisplay() + val itemName = itemNow.displayName.removeColor() + + if (isWaiting(itemName) || isOutOfBounds(slot, currentExperiment)) return drawDisplay() + + val reward = convertToReward(itemNow) + if (uncoveredItems.none { it.first == slot }) uncoveredItems.add(Pair(slot, reward)) + + when { + isPowerUp(reward) -> handlePowerUp(slot, reward) + isReward(itemName) -> handleReward(slot, uncovered, reward) + } + + possiblePairs = calculatePossiblePairs() + + val since = clicksSinceSeparator(lastClicked) + + if ((since >= 2 || (since == -1 && lastClicked.size >= 2)) && instantFind == 0) { + lastClicked.add(-1 to uncoveredAt) + uncoveredAt += 1 + } + toCheck.removeIf { it.first == slot } + + return drawDisplay() + } + possiblePairs = calculatePossiblePairs() + return drawDisplay() + } + + private fun handlePowerUp(slot: Int, reward: String) { + val item = toEither(Item(slot, reward)) + + found[item] = "Powerup" + possiblePairs-- + lastClicked.removeIf { it.first == slot } + uncoveredAt -= 1 + if (reward == "Instant Find") instantFind += 1 + } + + private fun handleReward(slot: Int, uncovered: Int, reward: String) { + val lastSlotClicked = + if (instantFind == 0 && lastClicked.none { it.first == -1 && it.second == uncovered - 1 } && lastClicked.size != 1) lastClicked.find { it.second == uncovered - 1 } + ?: return else lastClicked.find { it.second == uncovered } ?: return + + val lastItem = InventoryUtils.getItemAtSlotIndex(lastSlotClicked.first) ?: return + val lastItemName = convertToReward(lastItem) + + if (isWaiting(lastItemName)) return + + when { + instantFind >= 1 -> { + handleFoundPair(slot, reward, lastSlotClicked.first) + instantFind -= 1 + lastClicked.add(-1 to uncoveredAt) + uncoveredAt += 1 + } + + hasFoundPair(slot, lastSlotClicked.first, reward, lastItemName) -> handleFoundPair( + slot, + reward, + lastSlotClicked.first, + ) + + hasFoundMatch(slot, reward) -> handleFoundMatch(slot, reward) + else -> handleNormalReward(slot, reward) + } + + } + + private fun handleFoundPair( + slot: Int, + reward: String, + lastSlotClicked: Int, + ) { + val pair = toEither(ItemPair(Item(slot, reward), Item(lastSlotClicked, reward))) + + found[pair] = "Pair" + found.entries.removeIf { + it.value == "Match" && right(it.key).first.name == reward + } + found.entries.removeIf { + it.value == "Normal" && (left(it.key).index == slot || left(it.key).index == lastSlotClicked) + } + } + + private fun handleFoundMatch(slot: Int, reward: String) { + val match = uncoveredItems.find { it.second == reward }?.first ?: return + val pair = toEither(ItemPair(Item(slot, reward), Item(match, reward))) + + found[pair] = "Match" + found.entries.removeIf { + it.value == "Normal" && (left(it.key).index == slot || left(it.key).index == match) + } + } + + private fun handleNormalReward(slot: Int, reward: String) { + val item = toEither(Item(slot, reward)) + + if (found.none { + listOf("Match", "Pair").contains(it.value) && (right(it.key).first.index == slot || right(it.key).second.index == slot) + } && found.none { it.value == "Normal" && left(it.key).index == slot }) found[item] = "Normal" + } + + private fun calculatePossiblePairs() = + ((currentExperiment.gridSize - 2) / 2) - found.filter { listOf("Pair", "Match", "Normal").contains(it.value) }.size + + private fun drawDisplay() = buildList { + add("§6Superpair Experimentation Data") + add("") + + val pairs = found.entries.filter { it.value == "Pair" } + val matches = found.entries.filter { it.value == "Match" } + val powerups = found.entries.filter { it.value == "Powerup" } + val normals = found.entries.filter { it.value == "Normal" } + + if (pairs.isNotEmpty()) add("§2Found") + for (pair in pairs) { + val prefix = determinePrefix(pairs.indexOf(pair), pairs.lastIndex) + add(" $prefix §a${right(pair.key).first.name}") + } + if (matches.isNotEmpty()) add("§eMatched") + for (match in matches) { + val prefix = determinePrefix(matches.indexOf(match), matches.lastIndex) + add(" $prefix §e${right(match.key).first.name}") + } + if (powerups.isNotEmpty()) add("§bPowerUp") + for (powerup in powerups) { + val prefix = determinePrefix(powerups.indexOf(powerup), powerups.size - 1) + add(" $prefix §b${left(powerup.key).name}") + } + val toAdd = mutableListOf() + if (possiblePairs >= 1) toAdd.add("§ePairs - $possiblePairs") + if (2 - powerups.size >= 1) toAdd.add("§bPowerUps - ${2 - powerups.size}") + if (normals.isNotEmpty()) toAdd.add("§7Normals - ${normals.size}") + + if (toAdd.isNotEmpty()) { + add("") + add("§4Not found") + } + for (string in toAdd) if (string != toAdd.last()) add(" ├ $string") else add(" └ $string") + } + + private fun convertToReward(item: ItemStack) = if (item.displayName.removeColor() == "Enchanted Book") item.getLore()[2].removeColor() + else item.displayName.removeColor() + + private fun determinePrefix(index: Int, lastIndex: Int) = if (index == lastIndex) "└" else "├" + + private fun hasFoundPair( + firstSlot: Int, + secondSlot: Int, + firstName: String, + secondName: String, + ) = firstSlot != secondSlot && firstName == secondName + + private fun hasFoundMatch(itemSlot: Int, reward: String) = + uncoveredItems.any { (slot, name) -> slot != itemSlot && name == reward } && found.none { + listOf("Pair", "Match").contains(it.value) && (right(it.key).first.index == itemSlot || right(it.key).second.index == itemSlot) + } + + private fun isPowerUp(reward: String) = ExperimentationTableAPI.powerUpPattern.matches(reward) + + private fun isReward(reward: String) = ExperimentationTableAPI.rewardPattern.matches(reward) + + private fun isWaiting(itemName: String) = + listOf("Click any button!", "Click a second button!", "Next button is instantly rewarded!").contains(itemName) + + private fun clicksSinceSeparator(list: MutableList>): Int { + val lastIndex = list.indexOfLast { it.first == -1 } + return if (lastIndex != -1) list.size - 1 - lastIndex else -1 + } + + private fun isOutOfBounds(slot: Int, experiment: Experiment): Boolean = + slot <= experiment.startSlot || slot >= experiment.endSlot || (if (experiment.sideSpace == 1) slot in sideSpaces1 else slot in sideSpaces2) + + private fun left(it: Pair): Item = it.first ?: Item(-1, "") + + private fun right(it: Pair): ItemPair = it.second ?: ItemPair(Item(-1, ""), Item(-1, "")) + + private fun toEither(it: Any): Pair = if (it is Item) it to null else null to it as ItemPair + + private fun isEnabled() = LorenzUtils.inSkyBlock && config.superpairDisplay && ExperimentationTableAPI.getCurrentExperiment() != null +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/SuperpairsClicksAlert.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/SuperpairsClicksAlert.kt new file mode 100644 index 000000000..ef99c40ba --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/SuperpairsClicksAlert.kt @@ -0,0 +1,72 @@ +package at.hannibal2.skyhanni.features.inventory.experimentationtable + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator +import at.hannibal2.skyhanni.events.InventoryOpenEvent +import at.hannibal2.skyhanni.events.InventoryUpdatedEvent +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.utils.ChatUtils +import at.hannibal2.skyhanni.utils.ItemUtils.getLore +import at.hannibal2.skyhanni.utils.SoundUtils +import at.hannibal2.skyhanni.utils.StringUtils.removeColor +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +@SkyHanniModule +object SuperpairsClicksAlert { + + private val config get() = SkyHanniMod.feature.inventory.experimentationTable + + private var roundsNeeded = -1 + private val roundsNeededRegex = Regex("""(?:Chain|Series) of (\d+):""") + private val currentRoundRegex = Regex("""Round: (\d+)""") + private val targetInventoryNames = arrayOf("Chronomatron", "Ultrasequencer") + + @SubscribeEvent + fun onInventoryOpen(event: InventoryOpenEvent) { + if (!config.superpairsClicksAlert) return + if (!targetInventoryNames.any { event.inventoryName.contains(it) }) return + + // player may have drank Metaphysical Serum which reduces clicks needed by up to 3, so need to parse it + for (i in 24 downTo 20) { + val lore = event.inventoryItems[i]?.getLore() ?: continue + if (lore.any { it.contains("Practice mode has no rewards") }) { + roundsNeeded = -1 + break + } + if (lore.any { it.contains("Enchanting level too low!") || it.contains("Not enough experience!") }) continue + val match = lore.asReversed().firstNotNullOfOrNull { roundsNeededRegex.find(it.removeColor()) } ?: continue + roundsNeeded = match.groups[1]!!.value.toInt() + break + } + } + + @SubscribeEvent + fun onInventoryUpdated(event: InventoryUpdatedEvent) { + if (!config.superpairsClicksAlert) return + if (roundsNeeded == -1) return + if (!targetInventoryNames.any { event.inventoryName.contains(it) }) return + + if ( // checks if we have succeeded in either minigame + (event.inventoryName.contains("Chronomatron") + && ((event.inventoryItems[4]?.displayName?.removeColor() + ?.let { currentRoundRegex.find(it) } + ?.groups?.get(1)?.value?.toInt() ?: -1) > roundsNeeded)) + + || (event.inventoryName.contains("Ultrasequencer") + && event.inventoryItems.entries + .filter { it.key < 45 } + .any { it.value.stackSize > roundsNeeded }) + ) { + SoundUtils.playBeepSound() + ChatUtils.chat("You have reached the maximum extra Superpairs clicks from this add-on!") + roundsNeeded = -1 + } + } + + @SubscribeEvent + fun onConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) { + event.move(46, "misc.superpairsClicksAlert", "inventory.helper.enchanting.superpairsClicksAlert") + + event.move(59, "inventory.helper.enchanting.superpairsClicksAlert", "inventory.experimentationTable.superpairsClicksAlert") + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/UltraRareBookAlert.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/UltraRareBookAlert.kt new file mode 100644 index 000000000..e6a9dda42 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/UltraRareBookAlert.kt @@ -0,0 +1,95 @@ +package at.hannibal2.skyhanni.features.inventory.experimentationtable + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator +import at.hannibal2.skyhanni.events.GuiRenderEvent +import at.hannibal2.skyhanni.events.InventoryCloseEvent +import at.hannibal2.skyhanni.events.InventoryUpdatedEvent +import at.hannibal2.skyhanni.features.inventory.experimentationtable.ExperimentationTableAPI.bookPattern +import at.hannibal2.skyhanni.features.inventory.experimentationtable.ExperimentationTableAPI.ultraRarePattern +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.utils.ChatUtils +import at.hannibal2.skyhanni.utils.ColorUtils.withAlpha +import at.hannibal2.skyhanni.utils.ItemUtils.getLore +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher +import at.hannibal2.skyhanni.utils.RegexUtils.matches +import at.hannibal2.skyhanni.utils.RenderUtils +import at.hannibal2.skyhanni.utils.SimpleTimeMark +import at.hannibal2.skyhanni.utils.SoundUtils.createSound +import at.hannibal2.skyhanni.utils.SoundUtils.playSound +import at.hannibal2.skyhanni.utils.renderables.Renderable +import at.hannibal2.skyhanni.utils.renderables.RenderableUtils.renderXYAligned +import net.minecraft.client.Minecraft +import net.minecraft.client.gui.inventory.GuiContainer +import net.minecraft.client.renderer.GlStateManager +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import java.awt.Color +import kotlin.time.Duration.Companion.seconds + +@SkyHanniModule +object UltraRareBookAlert { + + private val config get() = SkyHanniMod.feature.inventory.experimentationTable + private val dragonSound by lazy { createSound("mob.enderdragon.growl", 1f) } + + private var enchantsFound = false + + private var lastNotificationTime = SimpleTimeMark.farPast() + + private fun notification(enchantsName: String) { + lastNotificationTime = SimpleTimeMark.now() + dragonSound.playSound() + ChatUtils.chat("You have uncovered a §d§kXX§5 ULTRA-RARE BOOK! §d§kXX§e! You found: §9$enchantsName") + } + + @SubscribeEvent + fun onRenderOverlay(event: GuiRenderEvent.ChestGuiOverlayRenderEvent) { + if (!isEnabled()) return + if (lastNotificationTime.passedSince() > 5.seconds) return + val gui = Minecraft.getMinecraft().currentScreen as? GuiContainer ?: return + + GlStateManager.pushMatrix() + GlStateManager.translate(0f, -150f, 500f) + + Renderable.drawInsideRoundedRect( + Renderable.string("§d§kXX§5 ULTRA-RARE BOOK! §d§kXX", 1.5), + Color(Color.DARK_GRAY.withAlpha(0), true), + horizontalAlign = RenderUtils.HorizontalAlignment.CENTER, + verticalAlign = RenderUtils.VerticalAlignment.CENTER, + ).renderXYAligned(0, 125, gui.width, gui.height) + + GlStateManager.translate(0f, 150f, -500f) + GlStateManager.popMatrix() + } + + @SubscribeEvent + fun onInventoryUpdated(event: InventoryUpdatedEvent) { + if (!isEnabled()) return + if (enchantsFound) return + + for (lore in event.inventoryItems.map { it.value.getLore() }) { + val firstLine = lore.firstOrNull() ?: continue + if (!ultraRarePattern.matches(firstLine)) continue + val bookNameLine = lore.getOrNull(2) ?: continue + bookPattern.matchMatcher(bookNameLine) { + val enchantsName = group("enchant") + notification(enchantsName) + enchantsFound = true + } + } + } + + @SubscribeEvent + fun onInventoryClose(event: InventoryCloseEvent) { + enchantsFound = false + } + + @SubscribeEvent + fun onConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) { + event.move(59, "inventory.helper.enchanting.ultraRareBookAlert", "inventory.experimentationTable.ultraRareBookAlert") + } + + private fun isEnabled() = + LorenzUtils.inSkyBlock && config.ultraRareBookAlert && ExperimentationTableAPI.getCurrentExperiment() != null +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/experiments/GuardianReminder.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/experiments/GuardianReminder.kt deleted file mode 100644 index 9ae93f227..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/experiments/GuardianReminder.kt +++ /dev/null @@ -1,99 +0,0 @@ -package at.hannibal2.skyhanni.features.inventory.experiments - -import at.hannibal2.skyhanni.SkyHanniMod -import at.hannibal2.skyhanni.data.PetAPI -import at.hannibal2.skyhanni.events.GuiRenderEvent -import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent -import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule -import at.hannibal2.skyhanni.utils.ChatUtils -import at.hannibal2.skyhanni.utils.ColorUtils.withAlpha -import at.hannibal2.skyhanni.utils.HypixelCommands -import at.hannibal2.skyhanni.utils.InventoryUtils -import at.hannibal2.skyhanni.utils.LorenzUtils -import at.hannibal2.skyhanni.utils.RegexUtils.matches -import at.hannibal2.skyhanni.utils.RenderUtils -import at.hannibal2.skyhanni.utils.SimpleTimeMark -import at.hannibal2.skyhanni.utils.SoundUtils -import at.hannibal2.skyhanni.utils.renderables.Renderable -import at.hannibal2.skyhanni.utils.renderables.RenderableUtils.renderXYAligned -import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern -import net.minecraft.client.Minecraft -import net.minecraft.client.gui.inventory.GuiContainer -import net.minecraft.client.renderer.GlStateManager -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent -import java.awt.Color -import kotlin.time.Duration.Companion.milliseconds -import kotlin.time.Duration.Companion.seconds - -@SkyHanniModule -object GuardianReminder { - - private val config get() = SkyHanniMod.feature.inventory.helper.enchanting - private var lastInventoryOpen = SimpleTimeMark.farPast() - private var lastWarn = SimpleTimeMark.farPast() - private var lastErrorSound = SimpleTimeMark.farPast() - - private val patternGroup = RepoPattern.group("data.enchanting.inventory.experimentstable") - private val inventoryNamePattern by patternGroup.pattern( - "mainmenu", - "Experimentation Table", - ) - - /** - * REGEX-TEST: §dGuardian - * REGEX-TEST: §9Guardian§e - */ - private val petNamePattern by patternGroup.pattern( - "guardianpet", - "§[956d]Guardian.*", - ) - - @SubscribeEvent - fun onInventory(event: InventoryFullyOpenedEvent) { - if (!isEnabled()) return - if (!inventoryNamePattern.matches(event.inventoryName)) return - if (petNamePattern.matches(PetAPI.currentPet)) return - - lastInventoryOpen = SimpleTimeMark.now() - - if (lastWarn.passedSince() < 5.seconds) return - lastWarn = SimpleTimeMark.now() - ChatUtils.clickToActionOrDisable( - "Use a §9§lGuardian Pet §efor more Exp in the Experimentation Table.", - config::guardianReminder, - actionName = "open pets menu", - action = { HypixelCommands.pet() }, - ) - } - - @SubscribeEvent - fun onRenderOverlay(event: GuiRenderEvent.ChestGuiOverlayRenderEvent) { - if (!isEnabled()) return - if (!inventoryNamePattern.matches(InventoryUtils.openInventoryName())) return - if (lastInventoryOpen.passedSince() > 2.seconds) return - val gui = Minecraft.getMinecraft().currentScreen as? GuiContainer ?: return - - sendTitle(gui.width, gui.height) - if (lastErrorSound.passedSince() > 200.milliseconds) { - lastErrorSound = SimpleTimeMark.now() - SoundUtils.playPlingSound() - } - } - - // TODO rename to "send title in inventory", move to utils - private fun sendTitle(width: Int, height: Int) { - GlStateManager.pushMatrix() - GlStateManager.translate(0f, -150f, 500f) - Renderable.drawInsideRoundedRect( - Renderable.string("§cWrong Pet equipped!", 1.5), - Color(Color.DARK_GRAY.withAlpha(0), true), - horizontalAlign = RenderUtils.HorizontalAlignment.CENTER, - verticalAlign = RenderUtils.VerticalAlignment.CENTER, - ).renderXYAligned(0, 125, width, height) - - GlStateManager.translate(0f, 150f, -500f) - GlStateManager.popMatrix() - } - - private fun isEnabled() = LorenzUtils.inSkyBlock && config.guardianReminder -} diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/experiments/UltraRareBookAlert.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/experiments/UltraRareBookAlert.kt deleted file mode 100644 index 1cc849cad..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/experiments/UltraRareBookAlert.kt +++ /dev/null @@ -1,104 +0,0 @@ -package at.hannibal2.skyhanni.features.inventory.experiments - -import at.hannibal2.skyhanni.SkyHanniMod -import at.hannibal2.skyhanni.events.GuiRenderEvent -import at.hannibal2.skyhanni.events.InventoryCloseEvent -import at.hannibal2.skyhanni.events.InventoryUpdatedEvent -import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule -import at.hannibal2.skyhanni.utils.ChatUtils -import at.hannibal2.skyhanni.utils.ColorUtils.withAlpha -import at.hannibal2.skyhanni.utils.InventoryUtils -import at.hannibal2.skyhanni.utils.ItemUtils.getLore -import at.hannibal2.skyhanni.utils.LorenzUtils -import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher -import at.hannibal2.skyhanni.utils.RegexUtils.matches -import at.hannibal2.skyhanni.utils.RenderUtils -import at.hannibal2.skyhanni.utils.SimpleTimeMark -import at.hannibal2.skyhanni.utils.SoundUtils.createSound -import at.hannibal2.skyhanni.utils.SoundUtils.playSound -import at.hannibal2.skyhanni.utils.renderables.Renderable -import at.hannibal2.skyhanni.utils.renderables.RenderableUtils.renderXYAligned -import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern -import net.minecraft.client.Minecraft -import net.minecraft.client.gui.inventory.GuiContainer -import net.minecraft.client.renderer.GlStateManager -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent -import java.awt.Color -import kotlin.time.Duration.Companion.seconds - -@SkyHanniModule -object UltraRareBookAlert { - - private val config get() = SkyHanniMod.feature.inventory.helper.enchanting - private val dragonSound by lazy { createSound("mob.enderdragon.growl", 1f) } - - private val patternGroup = RepoPattern.group("data.enchanting") - private val superpairsGui by patternGroup.pattern( - "inventory.experimentstable.gui", - "Superpairs.*" - ) - private val ultraRarePattern by patternGroup.pattern( - "inventory.experimentstable.ultrarare", - "§d§kXX§5 ULTRA-RARE BOOK! §d§kXX" - ) - private val bookPattern by patternGroup.pattern( - "inventory.experimentstable.book", - "§9(?.*)" - ) - - private var enchantsFound = false - - private var lastNotificationTime = SimpleTimeMark.farPast() - - private fun notification(enchantsName: String) { - lastNotificationTime = SimpleTimeMark.now() - dragonSound.playSound() - ChatUtils.chat("You have uncovered a §d§kXX§5 ULTRA-RARE BOOK! §d§kXX§e! You found: §9$enchantsName") - } - - @SubscribeEvent - fun onRenderOverlay(event: GuiRenderEvent.ChestGuiOverlayRenderEvent) { - if (!LorenzUtils.inSkyBlock) return - if (!config.ultraRareBookAlert) return - if (!superpairsGui.matches(InventoryUtils.openInventoryName())) return - if (lastNotificationTime.passedSince() > 5.seconds) return - val gui = Minecraft.getMinecraft().currentScreen as? GuiContainer ?: return - - GlStateManager.pushMatrix() - GlStateManager.translate(0f, -150f, 500f) - - Renderable.drawInsideRoundedRect( - Renderable.string("§d§kXX§5 ULTRA-RARE BOOK! §d§kXX", 1.5), - Color(Color.DARK_GRAY.withAlpha(0), true), - horizontalAlign = RenderUtils.HorizontalAlignment.CENTER, - verticalAlign = RenderUtils.VerticalAlignment.CENTER, - ).renderXYAligned(0, 125, gui.width, gui.height) - - GlStateManager.translate(0f, 150f, -500f) - GlStateManager.popMatrix() - } - - @SubscribeEvent - fun onInventoryUpdated(event: InventoryUpdatedEvent) { - if (!LorenzUtils.inSkyBlock) return - if (!config.ultraRareBookAlert) return - if (enchantsFound) return - if (!superpairsGui.matches(event.inventoryName)) return - - for (lore in event.inventoryItems.map { it.value.getLore() }) { - val firstLine = lore.firstOrNull() ?: continue - if (!ultraRarePattern.matches(firstLine)) continue - val bookNameLine = lore.getOrNull(2) ?: continue - bookPattern.matchMatcher(bookNameLine) { - val enchantsName = group("enchant") - notification(enchantsName) - enchantsFound = true - } - } - } - - @SubscribeEvent - fun onInventoryClose(event: InventoryCloseEvent) { - enchantsFound = false - } -} -- cgit