aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/at/hannibal2/skyhanni/features/dungeon
diff options
context:
space:
mode:
authorConutik <60240193+Conutik@users.noreply.github.com>2024-03-19 11:53:48 +0300
committerGitHub <noreply@github.com>2024-03-19 09:53:48 +0100
commit27e909463ea5c2553c7ac89eb350e70627aa8fc9 (patch)
treebb8b2f4090758ddf95d41c8dfbeb9e151f868558 /src/main/java/at/hannibal2/skyhanni/features/dungeon
parentb6c3d55d39362cdcda69902a524b43996e2358db (diff)
downloadskyhanni-27e909463ea5c2553c7ac89eb350e70627aa8fc9.tar.gz
skyhanni-27e909463ea5c2553c7ac89eb350e70627aa8fc9.tar.bz2
skyhanni-27e909463ea5c2553c7ac89eb350e70627aa8fc9.zip
Backend: Rewrote DungeonFinderFeatures.kt (#1180)
Co-authored-by: Thunderblade73 <85900443+Thunderblade73@users.noreply.github.com> Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com>
Diffstat (limited to 'src/main/java/at/hannibal2/skyhanni/features/dungeon')
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonFinderFeatures.kt400
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonRankTabListColor.kt2
2 files changed, 281 insertions, 121 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonFinderFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonFinderFeatures.kt
index 3dfa31493..00f57b519 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonFinderFeatures.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonFinderFeatures.kt
@@ -3,194 +3,354 @@ 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.InventoryCloseEvent
+import at.hannibal2.skyhanni.events.InventoryOpenEvent
import at.hannibal2.skyhanni.events.LorenzToolTipEvent
-import at.hannibal2.skyhanni.events.RenderItemTipEvent
-import at.hannibal2.skyhanni.utils.InventoryUtils
-import at.hannibal2.skyhanni.utils.InventoryUtils.getInventoryName
-import at.hannibal2.skyhanni.utils.InventoryUtils.getUpperItems
+import at.hannibal2.skyhanni.events.RenderInventoryItemTipEvent
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.NumberUtil.romanToDecimalIfNecessary
import at.hannibal2.skyhanni.utils.RenderUtils.highlight
+import at.hannibal2.skyhanni.utils.StringUtils.anyMatches
import at.hannibal2.skyhanni.utils.StringUtils.createCommaSeparatedList
import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher
+import at.hannibal2.skyhanni.utils.StringUtils.matches
import at.hannibal2.skyhanni.utils.StringUtils.removeColor
-import net.minecraft.client.gui.inventory.GuiChest
-import net.minecraft.inventory.ContainerChest
+import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern
+import net.minecraft.item.ItemStack
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 nonPugPattern = "(perm|vc|discord)".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!|Complete previous floor first!$)".toRegex()
- private val classLevelPattern = " §.(?<playerName>.*)§f: §e(?<className>.*)§b \\(§e(?<level>.*)§b\\)".toPattern()
- private val notePattern = "^(§7§7Note: |§f[^§])".toRegex()
+ // Repo group and patterns
+ private val patternGroup = RepoPattern.group("dungeon.finder")
+ private val pricePattern by patternGroup.pattern(
+ "price",
+ "([0-9]{2,3}K|[0-9]{1,3}M|[0-9]+\\.[0-9]M|[0-9] ?MIL)"
+ )
+ private val carryPattern by patternGroup.pattern(
+ "carry",
+ "(CARRY|CARY|CARRIES|CARIES|COMP|TO CATA [0-9]{2})"
+ )
+ private val nonPugPattern by patternGroup.pattern(
+ "nonpug",
+ "(PERM|VC|DISCORD)"
+ )
+ private val memberPattern by patternGroup.pattern(
+ "member",
+ ".*§.(?<playerName>.*)§f: §e(?<className>.*)§b \\(§e(?<level>.*)§b\\)"
+ )
+ private val ineligiblePattern by patternGroup.pattern(
+ "ineligible",
+ "§c(Requires .*$|You don't meet the requirement!|Complete previous floor first!$)"
+ )
+ private val classLevelPattern by patternGroup.pattern(
+ "class.level",
+ " §.(?<playerName>.*)§f: §e(?<className>.*)§b \\(§e(?<level>.*)§b\\)"
+ )
+ private val notePattern by patternGroup.pattern(
+ "note",
+ "(§7§7Note: |§f[^§])"
+ )
+ private val floorTypePattern by patternGroup.pattern(
+ "floor.type",
+ "(The Catacombs).*|.*(MM Catacombs).*"
+ )
+ private val checkIfPartyPattern by patternGroup.pattern(
+ "check.if.party",
+ ".*('s Party)"
+ )
+ private val partyFinderTitlePattern by patternGroup.pattern(
+ "party.finder.title",
+ "(Party Finder)"
+ )
+ private val catacombsGatePattern by patternGroup.pattern(
+ "catacombs.gate",
+ "(Catacombs Gate)"
+ )
+ private val selectFloorPattern by patternGroup.pattern(
+ "select.floor",
+ "(Select Floor)"
+ )
+ private val entranceFloorPattern by patternGroup.pattern(
+ "entrance",
+ "(.*Entrance)"
+ )
+ private val floorPattern by patternGroup.pattern(
+ "floor",
+ "(Floor .*)"
+ )
+ private val anyFloorPattern by patternGroup.pattern(
+ "floor.any",
+ "(Any)"
+ )
+ private val masterModeFloorPattern by patternGroup.pattern(
+ "floor.mastermode",
+ "(MM )|(.*Master Mode Catacombs)"
+ )
+ private val dungeonFloorPattern by patternGroup.pattern(
+ "floor.dungeon",
+ "(Dungeon: .*)"
+ )
+ private val floorFloorPattern by patternGroup.pattern(
+ "floor.pattern",
+ "(Floor: .*)"
+ )
+ private val floorNumberPattern by patternGroup.pattern(
+ "floor.number",
+ ".* (?<floorNum>[IV\\d]+)"
+ )
+ private val getDungeonClassPattern by patternGroup.pattern(
+ "get.dungeon.class",
+ ".* (?<class>.*)"
+ )
+ private val detectDungeonClassPattern by patternGroup.pattern(
+ "detect.dungeon.class",
+ "(View and select a dungeon class.)"
+ )
private val allowedSlots = (10..34).filter { it !in listOf(17, 18, 26, 27) }
+ // Variables used
private var selectedClass = ""
+ private var floorStackSize = mapOf<Int, String>()
+ private var highlightParty = mapOf<Int, LorenzColor>()
+ private var toolTipMap = mapOf<Int, List<String>>()
+ private var inInventory = false
@SubscribeEvent
- fun onRenderItemTip(event: RenderItemTipEvent) {
- if (!LorenzUtils.inSkyBlock || LorenzUtils.skyBlockArea != "Dungeon Hub") return
- if (!config.floorAsStackSize) return
+ fun onInventoryOpen(event: InventoryOpenEvent) {
+ if (!isEnabled()) return
- val itemName = event.stack.name.removeColor()
- val invName = InventoryUtils.openInventoryName()
+ floorStackSize = stackTip(event)
+ highlightParty = highlightingHandler(event)
+ toolTipMap = toolTipHandler(event)
+ }
- 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().romanToDecimalIfNecessary().toString()
- }
- } else if (itemName.startsWith("The Catacombs - ") || itemName.startsWith("MM Catacombs -")) {
- val floor = itemName.split(" - ").last().removeColor()
- val floorNum = floor.split(' ').last().romanToDecimalIfNecessary().toString()
- val isMasterMode = itemName.contains("MM ")
+ private fun stackTip(event: InventoryOpenEvent): Map<Int, String> {
+ val map = mutableMapOf<Int, String>()
+ val inventoryName = event.inventoryName
+ if (catacombsGatePattern.matches(inventoryName)) catacombsGateStackTip(event.inventoryItems, map)
+ if (!config.floorAsStackSize) return map
+ if (selectFloorPattern.matches(inventoryName)) selectFloorStackTip(event.inventoryItems, map)
+ if (partyFinderTitlePattern.matches(inventoryName)) partyFinderStackTip(event.inventoryItems, map)
+ return map
+ }
- event.stackTip = if (floor.contains("Entrance")) {
+ private fun selectFloorStackTip(inventoryItems: Map<Int, ItemStack>, map: MutableMap<Int, String>) {
+ inInventory = true
+ for ((slot, stack) in inventoryItems) {
+ val name = stack.displayName.removeColor()
+ map[slot] = if (anyFloorPattern.matches(name)) {
+ "A"
+ } else if (entranceFloorPattern.matches(name)) {
"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().romanToDecimalIfNecessary().toString()
- val isMasterMode = dungeon.contains("Master Mode")
+ } else if (floorPattern.matches(name)) {
+ floorNumberPattern.matchMatcher(name) {
+ group("floorNum").romanToDecimalIfNecessary().toString()
+ } ?: continue
+ } else continue
+ }
+ }
- event.stackTip = if (floor.contains("Entrance")) {
+ private fun partyFinderStackTip(inventoryItems: Map<Int, ItemStack>, map: MutableMap<Int, String>) {
+ inInventory = true
+ for ((slot, stack) in inventoryItems) {
+ val name = stack.displayName.removeColor()
+ if (!checkIfPartyPattern.matches(name)) continue
+ val lore = stack.getLore()
+ val floor = lore.find { floorFloorPattern.matches(it.removeColor()) } ?: continue
+ val dungeon = lore.find { dungeonFloorPattern.matches(it.removeColor()) } ?: continue
+ val floorNum = floorNumberPattern.matchMatcher(floor) {
+ group("floorNum").romanToDecimalIfNecessary()
+ }
+ map[slot] = if (entranceFloorPattern.matches(floor)) {
"E"
- } else if (isMasterMode) {
- "M${floorNum}"
+ } else if (masterModeFloorPattern.matches(dungeon)) {
+ "M$floorNum"
} else {
- "F${floorNum}"
+ "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()
+ private fun catacombsGateStackTip(inventoryItems: Map<Int, ItemStack>, map: MutableMap<Int, String>) {
+ val dungeonClassItemIndex = 45
+ inInventory = true
+ inventoryItems[dungeonClassItemIndex]?.getLore()?.let {
+ if (it.size > 3 && detectDungeonClassPattern.matches(it[0])) {
+ getDungeonClassPattern.matchMatcher(it[2].removeColor()) {
+ selectedClass = group("class")
+ }
+ }
}
- }
- @SubscribeEvent
- fun onBackgroundDrawn(event: GuiContainerEvent.BackgroundDrawnEvent) {
- if (!LorenzUtils.inSkyBlock) return
- if (event.gui !is GuiChest) return
-
- val chest = event.gui.inventorySlots as ContainerChest
- val inventoryName = chest.getInventoryName()
- if (inventoryName != "Party Finder") return
+ if (!config.floorAsStackSize) return
+ for ((slot, stack) in inventoryItems) {
+ val name = stack.displayName.removeColor()
+ if (!floorTypePattern.matches(name)) continue
+ val floorNum = floorNumberPattern.matchMatcher(name) {
+ group("floorNum").romanToDecimalIfNecessary()
+ } ?: continue
+ map[slot] = if (entranceFloorPattern.matches(name)) {
+ "E"
+ } else if (masterModeFloorPattern.matches(name)) {
+ "M$floorNum"
+ } else {
+ "F$floorNum"
+ }
+ }
- for ((slot, stack) in chest.getUpperItems()) {
- if (!stack.name.endsWith(" Party")) continue
+ }
- if (config.markIneligibleGroups && stack.getLore().any { ineligiblePattern.matches(it) }) {
- slot highlight LorenzColor.DARK_RED
+ private fun highlightingHandler(event: InventoryOpenEvent): Map<Int, LorenzColor> {
+ val map = mutableMapOf<Int, LorenzColor>()
+ if (!partyFinderTitlePattern.matches(event.inventoryName)) return map
+ inInventory = true
+ for ((slot, stack) in event.inventoryItems) {
+ val lore = stack.getLore()
+ if (!checkIfPartyPattern.matches(stack.displayName)) continue
+ if (config.markIneligibleGroups && ineligiblePattern.anyMatches(lore)) {
+ map[slot] = LorenzColor.DARK_RED
continue
}
if (config.markPaidCarries) {
- val note = stack.getLore().filter { notePattern.containsMatchIn(it) }.joinToString(" ")
+ val note = lore.filter { notePattern.matches(it) }.joinToString(" ").uppercase()
- if (pricePattern.containsMatchIn(note) && carryPattern.containsMatchIn(note)) {
- slot highlight LorenzColor.RED
+ if (pricePattern.matches(note) && carryPattern.matches(note)) {
+ map[slot] = LorenzColor.RED
continue
}
}
if (config.markNonPugs) {
- val note = slot.stack.getLore().filter { notePattern.containsMatchIn(it) }.joinToString(" ")
+ val note = lore.filter { notePattern.matches(it) }.joinToString(" ").uppercase()
- if (nonPugPattern.containsMatchIn(note)) {
- slot highlight LorenzColor.LIGHT_PURPLE
+ if (nonPugPattern.matches(note)) {
+ map[slot] = LorenzColor.LIGHT_PURPLE
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.markBelowClassLevel }) {
- slot highlight LorenzColor.YELLOW
+ val members = lore.filter { memberPattern.matches(it) }
+ val memberLevels = members.map {
+ memberPattern.matchMatcher(it) {
+ group("level").toInt()
+ }
+ }
+ val memberClasses = members.map {
+ memberPattern.matchMatcher(it) {
+ group("className")
+ }
+ }
+ if (memberLevels.any { (it ?: Integer.MAX_VALUE) <= config.markBelowClassLevel }) {
+ map[slot] = LorenzColor.YELLOW
continue
}
if (config.markMissingClass && memberClasses.none { it == selectedClass }) {
- slot highlight LorenzColor.GREEN
+ map[slot] = LorenzColor.GREEN
+ }
+ }
+ return map
+ }
+
+ private fun toolTipHandler(event: InventoryOpenEvent): Map<Int, List<String>> {
+ val map = mutableMapOf<Int, List<String>>()
+ val inventoryName = event.inventoryName
+ if (!partyFinderTitlePattern.matches(inventoryName)) return map
+ inInventory = true
+ for ((slot, stack) in event.inventoryItems) {
+ val classNames = mutableListOf("Healer", "Mage", "Berserk", "Archer", "Tank")
+ val toolTip = stack.getLore().toMutableList()
+ 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)
+ if (config.coloredClassLevel) toolTip[index] = " §b$playerName§f: §e$className $color$level"
+ classNames.remove(className)
+ }
+ }
+ val name = stack.getLore().firstOrNull()?.removeColor()
+ if (config.showMissingClasses && dungeonFloorPattern.matches(name)) {
+ if (classNames.contains(selectedClass)) {
+ classNames[classNames.indexOf(selectedClass)] = "§a${selectedClass}§7"
+ }
+ toolTip.add("")
+ toolTip.add("§cMissing: §7" + classNames.createCommaSeparatedList())
+ }
+ if (toolTip.isNotEmpty()) {
+ map[slot] = toolTip
}
}
+ return map
}
@SubscribeEvent
- fun onItemTooltip(event: LorenzToolTipEvent) {
- if (!LorenzUtils.inSkyBlock) return
+ fun onToolTipRender(event: LorenzToolTipEvent) {
+ if (!isEnabled()) return
+ if (!inInventory) return
+ val toolTip = toolTipMap[event.slot.slotIndex]
+ if (toolTip.isNullOrEmpty()) return
+ // TODO @Thunderblade73 fix that to "event.toolTip = toolTip"
+ val oldToolTip = event.toolTip
+ for ((index, line) in toolTip.withIndex()) {
+ if (index >= event.toolTip.size - 1) {
+ event.toolTip.add(line)
+ continue
+ }
+ if (oldToolTip[index] != line) event.toolTip[index + 1] = line
+ }
+ }
- if (InventoryUtils.openInventoryName() != "Party Finder") return
- if (event.slot.slotNumber !in allowedSlots) return
+ @SubscribeEvent
+ fun onRenderItemTip(event: RenderInventoryItemTipEvent) {
+ if (!isEnabled()) return
+ if (!config.floorAsStackSize) return
+ event.stackTip = (floorStackSize[event.slot.slotIndex]
+ ?.takeIf { it.isNotEmpty() } ?: return)
+ }
- val stack = event.itemStack
+ @SubscribeEvent
+ fun onBackgroundDrawn(event: GuiContainerEvent.BackgroundDrawnEvent) {
+ if (!isEnabled()) return
+ if (!inInventory) return
- val classNames = mutableListOf("Healer", "Mage", "Berserk", "Archer", "Tank")
- 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)
- if (config.coloredClassLevel) event.toolTip[index + 1] = " §b$playerName§f: §e$className $color$level"
- classNames.remove(className)
+ event.gui.inventorySlots.inventorySlots
+ .associateWith { highlightParty[it.slotNumber] }
+ .forEach { (slot, color) ->
+ color?.let { slot.highlight(it) }
}
- }
- if (!config.showMissingClasses) return
- if (stack.getLore().firstOrNull()?.removeColor()?.startsWith("Dungeon:") == false) return
- var uncoloredSelectedClass = ""
- if (classNames.contains(selectedClass)) {
- uncoloredSelectedClass = selectedClass
- selectedClass = "§a${selectedClass}§7"
- }
- event.toolTip.add("")
- event.toolTip.add("§cMissing: §7" + classNames.createCommaSeparatedList())
- if (uncoloredSelectedClass.isNotEmpty()) selectedClass = uncoloredSelectedClass
+ }
+
+ @SubscribeEvent
+ fun onInventoryClose(event: InventoryCloseEvent) {
+ inInventory = false
+ floorStackSize = emptyMap()
+ highlightParty = emptyMap()
+ toolTipMap = emptyMap()
}
@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"
+ companion object {
+ fun getColor(level: Int): String = when {
+ level >= 30 -> "§a"
+ level >= 25 -> "§b"
+ level >= 20 -> "§e"
+ level >= 15 -> "§6"
+ level >= 10 -> "§c"
+ else -> "§4"
+ }
+ }
+
+ fun isEnabled() = LorenzUtils.inSkyBlock && LorenzUtils.skyBlockArea == "Dungeon Hub"
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonRankTabListColor.kt b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonRankTabListColor.kt
index eda282161..8eec8dfaa 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonRankTabListColor.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonRankTabListColor.kt
@@ -25,7 +25,7 @@ class DungeonRankTabListColor {
val className = group("className")
val level = group("classLevel").romanToDecimal()
- val color = getColor(level)
+ val color = DungeonFinderFeatures.getColor(level)
event.text = "$sbLevel $cleanName §7(§e$className $color$level§7)"
}