From d3b2e23086bd9b974e34931eaafcd3e1596b9e6c Mon Sep 17 00:00:00 2001 From: Brandon Date: Sun, 22 Oct 2023 12:13:22 -0300 Subject: Add dungeon party finder qol features (#532) Feature: Dungeon party finder QOL improvements #532 --- src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt | 6 +- .../skyhanni/config/features/DungeonConfig.java | 26 +++ .../features/dungeon/DungeonFinderFeatures.kt | 177 +++++++++++++++++++++ .../skyhanni/features/dungeon/DungeonLevelColor.kt | 55 ------- 4 files changed, 206 insertions(+), 58 deletions(-) create mode 100644 src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonFinderFeatures.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonLevelColor.kt (limited to 'src/main/java/at/hannibal2/skyhanni') diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt index 32bd2a252..88618e4c7 100644 --- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt +++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt @@ -71,9 +71,9 @@ import at.hannibal2.skyhanni.features.dungeon.DungeonChatFilter import at.hannibal2.skyhanni.features.dungeon.DungeonCleanEnd import at.hannibal2.skyhanni.features.dungeon.DungeonCopilot import at.hannibal2.skyhanni.features.dungeon.DungeonDeathCounter +import at.hannibal2.skyhanni.features.dungeon.DungeonFinderFeatures import at.hannibal2.skyhanni.features.dungeon.DungeonHideItems import at.hannibal2.skyhanni.features.dungeon.DungeonHighlightClickedBlocks -import at.hannibal2.skyhanni.features.dungeon.DungeonLevelColor import at.hannibal2.skyhanni.features.dungeon.DungeonLividFinder import at.hannibal2.skyhanni.features.dungeon.DungeonMilestonesDisplay import at.hannibal2.skyhanni.features.dungeon.DungeonRankTabListColor @@ -454,7 +454,6 @@ class SkyHanniMod { loadModule(BurrowWarpHelper()) loadModule(CollectionTracker()) loadModule(HighlightBonzoMasks()) - loadModule(DungeonLevelColor()) loadModule(BazaarCancelledBuyOrderClipboard()) loadModule(CompactSplashPotionMessage()) loadModule(CroesusUnopenedChestTracker()) @@ -608,6 +607,7 @@ class SkyHanniMod { loadModule(PartyMemberOutlines()) loadModule(ShiftClickEquipment()) loadModule(LockMouseLook) + loadModule(DungeonFinderFeatures()) init() @@ -685,4 +685,4 @@ class SkyHanniMod { logger.log(Level.INFO, message) } } -} \ No newline at end of file +} diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/DungeonConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/DungeonConfig.java index e51e6067d..7c00afcd0 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/DungeonConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/DungeonConfig.java @@ -5,6 +5,7 @@ import at.hannibal2.skyhanni.config.core.config.Position; import com.google.gson.annotations.Expose; import io.github.moulberry.moulconfig.annotations.Accordion; import io.github.moulberry.moulconfig.annotations.ConfigEditorBoolean; +import io.github.moulberry.moulconfig.annotations.ConfigEditorSlider; import io.github.moulberry.moulconfig.annotations.ConfigOption; public class DungeonConfig { @@ -174,6 +175,31 @@ public class DungeonConfig { @ConfigEditorBoolean @FeatureToggle public boolean coloredClassLevel = true; + + @Expose + @ConfigOption(name = "Floor Stack Size", desc = "Display the party finder floor as the item stack size.") + @ConfigEditorBoolean + public boolean floorAsStackSize = true; + + @Expose + @ConfigOption(name = "Mark Paid Carries", desc = "Highlight paid carries with a red background to make them easier to find/skip.") + @ConfigEditorBoolean + public boolean markPaidCarries = true; + + @Expose + @ConfigOption(name = "Mark Low Levels", desc = "Highlight groups with players at or below the specified level to make them easier to find/skip.") + @ConfigEditorSlider(minValue = 0, maxValue = 50, minStep = 1) + public int markGroupsBelowLevel = 0; + + @Expose + @ConfigOption(name = "Mark Ineligible Groups", desc = "Highlight groups with requirements that you do not meet.") + @ConfigEditorBoolean + public boolean markIneligibleGroups = true; + + @Expose + @ConfigOption(name = "Mark Missing Class", desc = "Highlight groups that don't currently have any members of your selected dungeon class.") + @ConfigEditorBoolean + public boolean markMissingClass = true; } @Expose diff --git a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonFinderFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonFinderFeatures.kt new file mode 100644 index 000000000..5661c9e2a --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonFinderFeatures.kt @@ -0,0 +1,177 @@ +package at.hannibal2.skyhanni.features.dungeon + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator +import at.hannibal2.skyhanni.events.GuiContainerEvent +import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent +import at.hannibal2.skyhanni.events.RenderItemTipEvent +import at.hannibal2.skyhanni.utils.InventoryUtils +import at.hannibal2.skyhanni.utils.InventoryUtils.getInventoryName +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.LorenzUtils +import at.hannibal2.skyhanni.utils.LorenzUtils.equalsOneOf +import at.hannibal2.skyhanni.utils.NumberUtil.romanToDecimalIfNeeded +import at.hannibal2.skyhanni.utils.RenderUtils.highlight +import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher +import at.hannibal2.skyhanni.utils.StringUtils.removeColor +import net.minecraft.client.gui.inventory.GuiChest +import net.minecraft.inventory.ContainerChest +import net.minecraftforge.event.entity.player.ItemTooltipEvent +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +class DungeonFinderFeatures { + private val config get() = SkyHanniMod.feature.dungeon.partyFinder + + private val pricePattern = "([0-9]{2,3}K|[0-9]{1,3}M|[0-9]+\\.[0-9]M|[0-9] ?mil)".toRegex(RegexOption.IGNORE_CASE) + private val carryPattern = "(carry|cary|carries|caries|comp|to cata [0-9]{2})".toRegex(RegexOption.IGNORE_CASE) + private val memberPattern = "^ §.*?§.: §.([A-Z]+)§. \\(§.([0-9]+)§.\\)".toRegex(RegexOption.IGNORE_CASE) + private val ineligiblePattern = "^§c(Requires .*$|You don't meet the requirement!$)".toRegex() + private val classLevelPattern = " §.(?.*)§f: §e(?.*)§b \\(§e(?.*)§b\\)".toPattern() + private val notePattern = "^(§7§7Note: |§f[^§])".toRegex() + + private var selectedClass = "" + + @SubscribeEvent + fun onRenderItemTip(event: RenderItemTipEvent) { + if (!LorenzUtils.inSkyBlock || LorenzUtils.skyBlockArea != "Dungeon Hub") return + if (!config.floorAsStackSize) return + + val itemName = event.stack.name?.removeColor() ?: "" + val invName = InventoryUtils.openInventoryName() + + if (invName == "Select Floor") { + if (itemName == "Any") { + event.stackTip = "A" + } else if (itemName == "Entrance") { + event.stackTip = "E" + } else if (itemName.startsWith("Floor ")) { + event.stackTip = itemName.split(' ').last().romanToDecimalIfNeeded().toString() + } + } else if (itemName.startsWith("The Catacombs - ") || itemName.startsWith("MM Catacombs -")) { + val floor = itemName.split(" - ").last().removeColor() + val floorNum = floor.split(' ').last().romanToDecimalIfNeeded().toString() + val isMasterMode = itemName.contains("MM ") + + event.stackTip = if (floor.contains("Entrance")) { + "E" + } else if (isMasterMode) { + "M${floorNum}" + } else { + "F${floorNum}" + } + } else if (itemName.endsWith("'s Party")) { + val floor = event.stack.getLore().find { it.startsWith("§7Floor: ") } ?: return + val dungeon = event.stack.getLore().find { it.startsWith("§7Dungeon: ") } ?: return + val floorNum = floor.split(' ').last().romanToDecimalIfNeeded().toString() + val isMasterMode = dungeon.contains("Master Mode") + + event.stackTip = if (floor.contains("Entrance")) { + "E" + } else if (isMasterMode) { + "M${floorNum}" + } else { + "F${floorNum}" + } + } + } + + @SubscribeEvent + fun onInventoryOpen(event: InventoryFullyOpenedEvent) { + if (!LorenzUtils.inSkyBlock || LorenzUtils.skyBlockArea != "Dungeon Hub") return + if (event.inventoryName != "Catacombs Gate") return + + val lore = event.inventoryItems[45]?.getLore() ?: return + + if (lore[0] == "§7View and select a dungeon class.") { + selectedClass = lore[2].split(" ").last().removeColor() + } + } + + @SubscribeEvent + fun onBackgroundDrawn(event: GuiContainerEvent.BackgroundDrawnEvent) { + if (!LorenzUtils.inSkyBlock || LorenzUtils.skyBlockArea != "Dungeon Hub") return + if (event.gui !is GuiChest) return + + val chest = event.gui.inventorySlots as ContainerChest + val inventoryName = chest.getInventoryName() + if (inventoryName != "Party Finder") return + + for (slot in chest.inventorySlots) { + if (slot == null) continue + if (slot.slotNumber != slot.slotIndex) continue + if (slot.stack == null) continue + + val itemName = slot.stack.name ?: continue + if (!itemName.endsWith(" Party")) continue + + if (config.markIneligibleGroups && slot.stack.getLore().any { ineligiblePattern.matches(it) }) { + slot highlight LorenzColor.DARK_RED + continue + } + + if (config.markPaidCarries) { + val note = slot.stack.getLore().filter { notePattern.containsMatchIn(it) }.joinToString(" ") ?: "" + + if (pricePattern.containsMatchIn(note) && carryPattern.containsMatchIn(note)) { + slot highlight LorenzColor.RED + continue + } + } + + val members = slot.stack.getLore().filter { memberPattern.matches(it) } + val memberLevels = members.map { memberPattern.matchEntire(it)?.groupValues?.get(2)?.toInt() ?: 0 } + val memberClasses = members.map { memberPattern.matchEntire(it)?.groupValues?.get(1) ?: "" } + + if (memberLevels.any { it <= config.markGroupsBelowLevel }) { + slot highlight LorenzColor.YELLOW + continue + } + + if (config.markMissingClass && memberClasses.none { it == selectedClass }) { + slot highlight LorenzColor.GREEN + } + } + } + + @SubscribeEvent + fun onItemTooltip(event: ItemTooltipEvent) { + if (!LorenzUtils.inSkyBlock) return + if (!config.coloredClassLevel) return + + if (event.toolTip == null) return + val chestName = InventoryUtils.openInventoryName() + if (chestName != "Party Finder") return + + val stack = event.itemStack + + for ((index, line) in stack.getLore().withIndex()) { + classLevelPattern.matchMatcher(line) { + val playerName = group("playerName") + val className = group("className") + val level = group("level").toInt() + val color = getColor(level) + event.toolTip[index + 1] = " §b$playerName§f: §e$className $color$level" + } + } + } + + @SubscribeEvent + fun onConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) { + event.move(2, "dungeon.partyFinderColoredClassLevel", "dungeon.partyFinder.coloredClassLevel") + } + +} + +fun getColor(level: Int): String { + if (level >= 50) return "§c§l" + if (level >= 45) return "§c" + if (level >= 40) return "§d" + if (level >= 35) return "§6" + if (level >= 30) return "§5" + if (level >= 25) return "§9" + if (level >= 20) return "§a" + if (level >= 10) return "§f" + return "§7" +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonLevelColor.kt b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonLevelColor.kt deleted file mode 100644 index b15cdabb7..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonLevelColor.kt +++ /dev/null @@ -1,55 +0,0 @@ -package at.hannibal2.skyhanni.features.dungeon - -import at.hannibal2.skyhanni.SkyHanniMod -import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator -import at.hannibal2.skyhanni.utils.InventoryUtils -import at.hannibal2.skyhanni.utils.ItemUtils.getLore -import at.hannibal2.skyhanni.utils.LorenzUtils -import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher -import net.minecraftforge.event.entity.player.ItemTooltipEvent -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent - -class DungeonLevelColor { - private val pattern = " §.(?.*)§f: §e(?.*)§b \\(§e(?.*)§b\\)".toPattern() - - @SubscribeEvent - fun onItemTooltip(event: ItemTooltipEvent) { - if (!LorenzUtils.inSkyBlock) return - if (!SkyHanniMod.feature.dungeon.partyFinder.coloredClassLevel) return - - if (event.toolTip == null) return - val chestName = InventoryUtils.openInventoryName() - if (chestName != "Party Finder") return - - val stack = event.itemStack - var index = 0 - for (line in stack.getLore()) { - index++ - - pattern.matchMatcher(line) { - val playerName = group("playerName") - val className = group("className") - val level = group("level").toInt() - val color = getColor(level) - event.toolTip[index] = " §b$playerName§f: §e$className $color$level" - } - } - } - - @SubscribeEvent - fun onConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) { - event.move(3, "dungeon.partyFinderColoredClassLevel", "dungeon.partyFinder.coloredClassLevel") - } -} - -fun getColor(level: Int): String { - if (level >= 50) return "§c§l" - if (level >= 45) return "§c" - if (level >= 40) return "§d" - if (level >= 35) return "§6" - if (level >= 30) return "§5" - if (level >= 25) return "§9" - if (level >= 20) return "§a" - if (level >= 10) return "§f" - return "§7" -} \ No newline at end of file -- cgit