aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/at
diff options
context:
space:
mode:
authorThunderblade73 <85900443+Thunderblade73@users.noreply.github.com>2024-03-09 21:46:04 +0100
committerGitHub <noreply@github.com>2024-03-09 21:46:04 +0100
commitea8d09297d037807f00b62778f99901060f4e375 (patch)
treecbae93e981dcc5da3f00e3e8760b32fe00cdc044 /src/main/java/at
parentabedb7ead429d461ee2bab4d1e7977ba1e42b7de (diff)
downloadskyhanni-ea8d09297d037807f00b62778f99901060f4e375.tar.gz
skyhanni-ea8d09297d037807f00b62778f99901060f4e375.tar.bz2
skyhanni-ea8d09297d037807f00b62778f99901060f4e375.zip
Feature: Kismet Feather Tracker (#1011)
Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com>
Diffstat (limited to 'src/main/java/at')
-rw-r--r--src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt4
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/Storage.java35
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/dungeon/DungeonChestConfig.java22
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/dungeon/DungeonConfig.java7
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/SackAPI.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/events/DungeonCompleteEvent.kt3
-rw-r--r--src/main/java/at/hannibal2/skyhanni/events/InventoryFullyOpenedEvent.kt3
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/dungeon/CroesusChestTracker.kt275
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/dungeon/CroesusUnopenedChestTracker.kt33
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonAPI.kt28
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/InventoryUtils.kt6
11 files changed, 381 insertions, 37 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt
index 373acc031..dfaac0e6d 100644
--- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt
+++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt
@@ -90,7 +90,7 @@ import at.hannibal2.skyhanni.features.commands.tabcomplete.PlayerTabComplete
import at.hannibal2.skyhanni.features.commands.tabcomplete.WarpTabComplete
import at.hannibal2.skyhanni.features.cosmetics.ArrowTrail
import at.hannibal2.skyhanni.features.cosmetics.CosmeticFollowingLine
-import at.hannibal2.skyhanni.features.dungeon.CroesusUnopenedChestTracker
+import at.hannibal2.skyhanni.features.dungeon.CroesusChestTracker
import at.hannibal2.skyhanni.features.dungeon.DungeonAPI
import at.hannibal2.skyhanni.features.dungeon.DungeonBossHideDamageSplash
import at.hannibal2.skyhanni.features.dungeon.DungeonBossMessages
@@ -576,7 +576,7 @@ class SkyHanniMod {
loadModule(HighlightBonzoMasks())
loadModule(BazaarCancelledBuyOrderClipboard())
loadModule(CompactSplashPotionMessage())
- loadModule(CroesusUnopenedChestTracker())
+ loadModule(CroesusChestTracker())
loadModule(CompactBingoChat())
loadModule(BrewingStandOverlay())
loadModule(FishingTimer())
diff --git a/src/main/java/at/hannibal2/skyhanni/config/Storage.java b/src/main/java/at/hannibal2/skyhanni/config/Storage.java
index 014eccee2..597d3a7eb 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/Storage.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/Storage.java
@@ -5,6 +5,8 @@ import at.hannibal2.skyhanni.data.model.ComposterUpgrade;
import at.hannibal2.skyhanni.features.bingo.card.goals.BingoGoal;
import at.hannibal2.skyhanni.features.combat.endernodetracker.EnderNodeTracker;
import at.hannibal2.skyhanni.features.combat.ghostcounter.GhostData;
+import at.hannibal2.skyhanni.features.dungeon.CroesusChestTracker;
+import at.hannibal2.skyhanni.features.dungeon.CroesusChestTracker.Companion.OpenedState;
import at.hannibal2.skyhanni.features.dungeon.DungeonAPI;
import at.hannibal2.skyhanni.features.event.diana.DianaProfitTracker;
import at.hannibal2.skyhanni.features.event.diana.MythologicalCreatureTracker;
@@ -30,6 +32,7 @@ import at.hannibal2.skyhanni.utils.LorenzVec;
import at.hannibal2.skyhanni.utils.NEUInternalName;
import at.hannibal2.skyhanni.utils.tracker.SkyHanniTracker;
import com.google.gson.annotations.Expose;
+import jline.internal.Nullable;
import net.minecraft.item.ItemStack;
import java.util.ArrayList;
@@ -39,6 +42,8 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
public class Storage {
@@ -460,6 +465,36 @@ public class Storage {
@Expose
public Map<DungeonAPI.DungeonFloor, Integer> bosses = new HashMap<>();
+
+ @Expose
+ public List<DungeonRunInfo> runs = Stream.generate(DungeonRunInfo::new)
+ .limit(CroesusChestTracker.Companion.getMaxChests())
+ .collect(Collectors.toCollection(ArrayList::new));
+
+
+ public static class DungeonRunInfo {
+
+ public DungeonRunInfo() {
+ }
+
+ public DungeonRunInfo(String floor) {
+ this.floor = floor;
+ this.openState = OpenedState.UNOPENED;
+ }
+
+ @Nullable
+ @Expose
+ public String floor = null;
+
+ @Expose
+ @Nullable
+ public OpenedState openState = null;
+
+ @Expose
+ @Nullable
+ public Boolean kismetUsed = null;
+
+ }
}
@Expose
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/dungeon/DungeonChestConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/dungeon/DungeonChestConfig.java
new file mode 100644
index 000000000..e58bf0252
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/dungeon/DungeonChestConfig.java
@@ -0,0 +1,22 @@
+package at.hannibal2.skyhanni.config.features.dungeon;
+
+import at.hannibal2.skyhanni.config.FeatureToggle;
+import com.google.gson.annotations.Expose;
+import io.github.moulberry.moulconfig.annotations.ConfigEditorBoolean;
+import io.github.moulberry.moulconfig.annotations.ConfigOption;
+
+public class DungeonChestConfig {
+
+
+ @Expose
+ @ConfigOption(name = "Kismet", desc = "Adds a visual highlight for used kismet feather to the Croesus inventory.")
+ @ConfigEditorBoolean
+ @FeatureToggle
+ public boolean kismet = true;
+
+ @Expose
+ @ConfigOption(name = "Kismet Amount", desc = "Shows the amount of kismet feathers as stack size.")
+ @ConfigEditorBoolean
+ @FeatureToggle
+ public boolean kismetStackSize = true;
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/dungeon/DungeonConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/dungeon/DungeonConfig.java
index 0b1eecff6..516346d33 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/dungeon/DungeonConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/dungeon/DungeonConfig.java
@@ -100,8 +100,13 @@ public class DungeonConfig {
public boolean highlightSkeletonSkull = true;
@Expose
+ @ConfigOption(name = "Chests Config", desc = "")
+ @Accordion
+ public DungeonChestConfig chest = new DungeonChestConfig();
+
+ @Expose
@ConfigOption(name = "Croesus Chest", desc = "Adds a visual highlight to the Croesus inventory that " +
- "shows unopened chests.")
+ "shows unopened chests.") // TODO move( , "dungeon.croesusUnopenedChestTracker" ,"dungeon.chest.showUnopened" )
@ConfigEditorBoolean
@FeatureToggle
public boolean croesusUnopenedChestTracker = true;
diff --git a/src/main/java/at/hannibal2/skyhanni/data/SackAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/SackAPI.kt
index e42bdb8af..f72d2d5d2 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/SackAPI.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/SackAPI.kt
@@ -340,6 +340,7 @@ data class SackItem(
) {
fun getStatus() = status ?: SackStatus.MISSING
+ fun statusIsCorrectOrAlright() = getStatus().let { it == SackStatus.CORRECT || it == SackStatus.ALRIGHT }
}
private val gemstoneMap = mapOf(
@@ -355,7 +356,6 @@ private val gemstoneMap = mapOf(
// ideally should be correct but using alright should also be fine unless they sold their whole sacks
enum class SackStatus {
-
MISSING,
CORRECT,
ALRIGHT,
diff --git a/src/main/java/at/hannibal2/skyhanni/events/DungeonCompleteEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/DungeonCompleteEvent.kt
new file mode 100644
index 000000000..d278753cb
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/events/DungeonCompleteEvent.kt
@@ -0,0 +1,3 @@
+package at.hannibal2.skyhanni.events
+
+class DungeonCompleteEvent(val floor: String) : LorenzEvent()
diff --git a/src/main/java/at/hannibal2/skyhanni/events/InventoryFullyOpenedEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/InventoryFullyOpenedEvent.kt
index bc9e97ed8..f8d6c4ab4 100644
--- a/src/main/java/at/hannibal2/skyhanni/events/InventoryFullyOpenedEvent.kt
+++ b/src/main/java/at/hannibal2/skyhanni/events/InventoryFullyOpenedEvent.kt
@@ -9,6 +9,9 @@ open class InventoryOpenEvent(private val inventory: OtherInventoryData.Inventor
val inventoryName: String by lazy { inventory.title }
val inventorySize: Int by lazy { inventory.slotCount }
val inventoryItems: Map<Int, ItemStack> by lazy { inventory.items }
+ val inventoryItemsWithNull: Map<Int, ItemStack?> by lazy {
+ (0 until inventorySize).associateWith { inventoryItems[it] }
+ }
val fullyOpenedOnce: Boolean get() = inventory.fullyOpenedOnce
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/dungeon/CroesusChestTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/dungeon/CroesusChestTracker.kt
new file mode 100644
index 000000000..e831a2a11
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/dungeon/CroesusChestTracker.kt
@@ -0,0 +1,275 @@
+package at.hannibal2.skyhanni.features.dungeon
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.config.Storage.ProfileSpecific.DungeonStorage.DungeonRunInfo
+import at.hannibal2.skyhanni.data.ProfileStorageData
+import at.hannibal2.skyhanni.data.SackAPI
+import at.hannibal2.skyhanni.events.DungeonCompleteEvent
+import at.hannibal2.skyhanni.events.GuiContainerEvent
+import at.hannibal2.skyhanni.events.InventoryCloseEvent
+import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent
+import at.hannibal2.skyhanni.events.RenderInventoryItemTipEvent
+import at.hannibal2.skyhanni.events.RenderItemTipEvent
+import at.hannibal2.skyhanni.features.dungeon.DungeonAPI.DungeonChest
+import at.hannibal2.skyhanni.test.command.ErrorManager
+import at.hannibal2.skyhanni.utils.InventoryUtils
+import at.hannibal2.skyhanni.utils.ItemUtils.getLore
+import at.hannibal2.skyhanni.utils.ItemUtils.name
+import at.hannibal2.skyhanni.utils.LorenzColor
+import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName
+import at.hannibal2.skyhanni.utils.NumberUtil.romanToDecimal
+import at.hannibal2.skyhanni.utils.RenderUtils.highlight
+import at.hannibal2.skyhanni.utils.StringUtils.anyMatches
+import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher
+import at.hannibal2.skyhanni.utils.StringUtils.matches
+import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern
+import net.minecraft.init.Items
+import net.minecraft.item.ItemStack
+import net.minecraftforge.fml.common.eventhandler.EventPriority
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+
+class CroesusChestTracker {
+
+ private val config get() = SkyHanniMod.feature.dungeon.chest
+
+ private val repoGroup = RepoPattern.group("dungeon.croesus")
+
+ private val croesusPattern by repoGroup.pattern("inventory", "Croesus")
+ private val croesusEmptyPattern by repoGroup.pattern("empty", "§cNo treasures!")
+ private val kismetPattern by repoGroup.pattern("kismet.reroll", "§aReroll Chest")
+ private val kismetUsedPattern by repoGroup.pattern("kismet.used", "§aYou already rerolled a chest!")
+
+ private val floorPattern by repoGroup.pattern("chest.floor", "§7Tier: §eFloor (?<floor>[IV]+)")
+ private val masterPattern by repoGroup.pattern("chest.master", ".*Master.*")
+
+ private val keyUsedPattern by repoGroup.pattern("chest.state.keyused", "§aNo more Chests to open!")
+ private val openedPattern by repoGroup.pattern("chest.state.opened", "§8Opened Chest:.*")
+ private val unopenedPattern by repoGroup.pattern("chest.state.unopened", "§8No Chests Opened!")
+
+ private val kismetSlotId = 50
+ private val emptySlotId = 22
+ private val frontArrowSlotId = 53
+ private val backArrowSlotId = 45
+
+ private val kismetInternalName = "KISMET_FEATHER".asInternalName()
+
+ private var inCroesusInventory = false
+ private var croesusEmpty = false
+ private var currentPage = 0
+ private var pageSwitchable = false
+
+ private var chestInventory: DungeonChest? = null
+
+ private var currentRunIndex = 0
+
+ private var kismetAmountCache = 0
+
+ @SubscribeEvent(priority = EventPriority.LOW)
+ fun onBackgroundDrawn(event: GuiContainerEvent.BackgroundDrawnEvent) {
+ if (!LorenzUtils.inSkyBlock) return
+ if (!SkyHanniMod.feature.dungeon.croesusUnopenedChestTracker) return
+
+ if (inCroesusInventory && !croesusEmpty) {
+ for ((run, slot) in InventoryUtils.getItemsInOpenChest()
+ .mapNotNull { slot -> runSlots(slot.slotIndex, slot) }) {
+
+ // If one chest is null every followup chest is null. Therefore, an early return is possible
+ if (run.floor == null) return
+
+ val state = run.openState ?: OpenedState.UNOPENED
+
+ if (state != OpenedState.KEY_USED) {
+ slot highlight if (state == OpenedState.OPENED) LorenzColor.DARK_AQUA else LorenzColor.DARK_PURPLE
+ }
+ }
+ }
+ }
+
+ @SubscribeEvent
+ fun onInventoryOpen(event: InventoryFullyOpenedEvent) {
+ if (!LorenzUtils.inSkyBlock) return
+ if ((SkyHanniMod.feature.dungeon.croesusUnopenedChestTracker || config.kismet) && croesusPattern.matches(event.inventoryName)) {
+ pageSetup(event)
+
+ if (croesusEmpty) {
+ croesusChests?.forEach {
+ it.setValuesNull()
+ }
+ return
+ }
+
+ // With null, since if an item is missing the chest will be set null
+ checkChests(event.inventoryItemsWithNull)
+
+ return
+ }
+ if (config.kismet || config.kismetStackSize) {
+ kismetDungeonChestSetup(event)
+ }
+ }
+
+ private fun kismetDungeonChestSetup(event: InventoryFullyOpenedEvent) {
+ chestInventory = DungeonChest.getByInventoryName(event.inventoryName) ?: return
+ if (config.kismetStackSize) {
+ kismetAmountCache = getKismetAmount().toInt()
+ }
+ if (config.kismet) {
+ val kismetItem = event.inventoryItems[kismetSlotId] ?: return
+ if (config.kismet && kismetUsedPattern.matches(kismetItem.getLore().lastOrNull()))
+ setKismetUsed()
+ }
+ }
+
+ private fun checkChests(inventory: Map<Int, ItemStack?>) {
+ for ((run, item) in inventory.mapNotNull { (key, value) -> runSlots(key, value) }) {
+ if (item == null) {
+ run.setValuesNull()
+ continue
+ }
+
+ val lore = item.getLore()
+
+ if (run.floor == null) run.floor =
+ (if (masterPattern.matches(item.name)) "M" else "F") + (lore.firstNotNullOfOrNull {
+ floorPattern.matchMatcher(it) { group("floor").romanToDecimal() }
+ } ?: "0")
+ run.openState = when {
+ keyUsedPattern.anyMatches(lore) -> OpenedState.KEY_USED
+ openedPattern.anyMatches(lore) -> OpenedState.OPENED
+ unopenedPattern.anyMatches(lore) -> OpenedState.UNOPENED
+ else -> ErrorManager.logErrorStateWithData(
+ "Croesus Chest couldn't be read correctly.",
+ "Openstate check failed for chest.",
+ "run" to run,
+ "lore" to lore
+ ).run { null }
+ }
+ }
+ }
+
+ private fun pageSetup(event: InventoryFullyOpenedEvent) {
+ inCroesusInventory = true
+ pageSwitchable = true
+ croesusEmpty = croesusEmptyPattern.matches(event.inventoryItems[emptySlotId]?.name)
+ if (event.inventoryItems[backArrowSlotId]?.item != Items.arrow) {
+ currentPage = 0
+ }
+ }
+
+ private fun DungeonRunInfo.setValuesNull() {
+ floor = null
+ openState = null
+ kismetUsed = null
+ }
+
+ @SubscribeEvent
+ fun onInventoryClose(event: InventoryCloseEvent) {
+ inCroesusInventory = false
+ chestInventory = null
+ }
+
+ @SubscribeEvent
+ fun onSlotClicked(event: GuiContainerEvent.SlotClickEvent) {
+ if (!LorenzUtils.inSkyBlock) return
+ if (!config.kismet) return
+ if (chestInventory != null && event.slotId == kismetSlotId) {
+ setKismetUsed()
+ return
+ }
+ if (inCroesusInventory && !croesusEmpty) {
+ if (event.slot == null) return
+ when (event.slotId) {
+ frontArrowSlotId -> if (pageSwitchable && event.slot.stack.isArrow()) {
+ pageSwitchable = false
+ currentPage++
+ }
+
+ backArrowSlotId -> if (pageSwitchable && event.slot.stack.isArrow()) {
+ pageSwitchable = false
+ currentPage--
+ }
+
+ else -> croesusSlotMapToRun(event.slotId)?.let { currentRunIndex = it }
+ }
+ }
+ }
+
+ @SubscribeEvent
+ fun onRenderItemTipAmount(event: RenderItemTipEvent) {
+ if (!LorenzUtils.inSkyBlock) return
+ if (!config.kismetStackSize) return
+ if (chestInventory == null) return
+ if (!kismetPattern.matches(event.stack.name)) return
+ if (kismetUsedPattern.matches(event.stack.getLore().lastOrNull())) return
+ event.stackTip = "§a$kismetAmountCache"
+ }
+
+ @SubscribeEvent
+ fun onRenderItemTipIsKismetable(event: RenderInventoryItemTipEvent) {
+ if (!LorenzUtils.inSkyBlock) return
+ if (!config.kismet) return
+ if (!inCroesusInventory) return
+ if (event.slot.slotIndex != event.slot.slotNumber) return
+ val run = croesusSlotMapToRun(event.slot.slotIndex) ?: return
+ if (!getKismetUsed(run)) return
+ event.offsetY = -1
+ event.offsetX = -9
+ event.stackTip = "§a✔"
+ }
+
+ @SubscribeEvent
+ fun onDungeonComplete(event: DungeonCompleteEvent) {
+ if (event.floor == "E") return
+ croesusChests?.add(0, DungeonRunInfo(event.floor))
+ currentRunIndex = 0
+ if ((croesusChests?.size ?: 0) > maxChests) {
+ croesusChests?.dropLast(1)
+ }
+ }
+
+ private fun Int.getRun() = getRun0(this)
+
+ private fun getRun0(run: Int = currentRunIndex) = croesusChests?.takeIf { run < it.size }?.get(run)
+
+ private fun setKismetUsed() {
+ getRun0()?.kismetUsed = true
+ }
+
+ private fun getKismetUsed(runIndex: Int) = getRun0(runIndex)?.kismetUsed ?: false
+
+ private fun getKismetAmount() =
+ (SackAPI.fetchSackItem(kismetInternalName).takeIf { it.statusIsCorrectOrAlright() }?.amount
+ ?: 0) + InventoryUtils.getAmountOfItemInInventory(kismetInternalName)
+
+ private fun croesusSlotMapToRun(slotId: Int) = when (slotId) {
+ in 10..16 -> slotId - 10 // 0 - 6
+ in 19..25 -> slotId - 12 // 7 - 13
+ in 28..34 -> slotId - 14 // 14 - 20
+ in 37..43 -> slotId - 16 // 21 - 27
+ else -> null
+ }?.let { it + currentPage * 28 }
+
+ private fun ItemStack.isArrow() = this.item == Items.arrow
+
+ private inline fun <reified T> runSlots(slotId: Int, any: T) =
+ croesusSlotMapToRun(slotId)?.getRun()?.let { it to any }
+
+ companion object {
+ val maxChests = 60
+
+ private val croesusChests get() = ProfileStorageData.profileSpecific?.dungeons?.runs
+
+ fun getLastActiveChest(includeDungeonKey: Boolean = false) =
+ (croesusChests?.indexOfLast {
+ it.floor != null &&
+ (it.openState == OpenedState.UNOPENED || (includeDungeonKey && it.openState == OpenedState.OPENED))
+ } ?: -1) + 1
+
+ enum class OpenedState {
+ UNOPENED,
+ OPENED,
+ KEY_USED,
+ }
+ }
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/dungeon/CroesusUnopenedChestTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/dungeon/CroesusUnopenedChestTracker.kt
deleted file mode 100644
index 7c52f4154..000000000
--- a/src/main/java/at/hannibal2/skyhanni/features/dungeon/CroesusUnopenedChestTracker.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-package at.hannibal2.skyhanni.features.dungeon
-
-import at.hannibal2.skyhanni.SkyHanniMod
-import at.hannibal2.skyhanni.events.GuiContainerEvent
-import at.hannibal2.skyhanni.utils.InventoryUtils
-import at.hannibal2.skyhanni.utils.ItemUtils.getLore
-import at.hannibal2.skyhanni.utils.LorenzColor
-import at.hannibal2.skyhanni.utils.LorenzUtils
-import at.hannibal2.skyhanni.utils.RenderUtils.highlight
-import net.minecraftforge.fml.common.eventhandler.EventPriority
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
-
-class CroesusUnopenedChestTracker {
-
- @SubscribeEvent(priority = EventPriority.LOW)
- fun onBackgroundDrawn(event: GuiContainerEvent.BackgroundDrawnEvent) {
- if (!LorenzUtils.inSkyBlock) return
- if (!SkyHanniMod.feature.dungeon.croesusUnopenedChestTracker) return
-
- val chestName = InventoryUtils.openInventoryName()
-
- if (chestName == "Croesus") {
- for (slot in InventoryUtils.getItemsInOpenChest()) {
- val stack = slot.stack
- val lore = stack.getLore()
- if ("§eClick to view chests!" in lore && "§aNo more Chests to open!" !in lore) {
- val hasOpenedChests = lore.any { it.contains("Opened Chest") }
- slot highlight if (hasOpenedChests) LorenzColor.DARK_AQUA else LorenzColor.DARK_PURPLE
- }
- }
- }
- }
-} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonAPI.kt
index bb38d09b9..7b5afb875 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonAPI.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonAPI.kt
@@ -4,6 +4,7 @@ import at.hannibal2.skyhanni.data.ProfileStorageData
import at.hannibal2.skyhanni.data.ScoreboardData
import at.hannibal2.skyhanni.events.DebugDataCollectEvent
import at.hannibal2.skyhanni.events.DungeonBossRoomEnterEvent
+import at.hannibal2.skyhanni.events.DungeonCompleteEvent
import at.hannibal2.skyhanni.events.DungeonEnterEvent
import at.hannibal2.skyhanni.events.DungeonStartEvent
import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent
@@ -20,6 +21,7 @@ import at.hannibal2.skyhanni.utils.NumberUtil.romanToDecimalIfNecessary
import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher
import at.hannibal2.skyhanni.utils.StringUtils.removeColor
import at.hannibal2.skyhanni.utils.TabListData
+import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern
import net.minecraft.item.ItemStack
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
@@ -49,6 +51,13 @@ class DungeonAPI {
private val timePattern =
"Time Elapsed:( )?(?:(?<minutes>\\d+)m)? (?<seconds>\\d+)s".toPattern() // Examples: Time Elapsed: 10m 10s, Time Elapsed: 2s
+ private val patternGroup = RepoPattern.group("dungeon")
+
+ private val dungeonComplete by patternGroup.pattern(
+ "complete",
+ "§.\\s+§.§.(?:The|Master Mode) Catacombs §.§.- §.§.Floor (?<floor>M?[IV]{1,3}|Entrance)"
+ )
+
fun inDungeon() = dungeonFloor != null
fun isOneOf(vararg floors: String) = dungeonFloor?.equalsOneOf(*floors) == true
@@ -153,6 +162,11 @@ class DungeonAPI {
if (matches() && boss != null && boss !in bossCollections) {
bossCollections.addOrPut(boss, 1)
}
+ return
+ }
+ dungeonComplete.matchMatcher(event.message) {
+ DungeonCompleteEvent(floor).postAndCatch()
+ return
}
}
@@ -261,4 +275,18 @@ class DungeonAPI {
MAGE("Mage"),
TANK("Tank")
}
+
+ enum class DungeonChest(val inventory: String) {
+ WOOD("Wood Chest"),
+ GOLD("Gold Chest"),
+ DIAMOND("Diamond Chest"),
+ EMERALD("Emerald Chest"),
+ OBSIDIAN("Obsidian Chest"),
+ BEDROCK("Bedrock Chest"),
+ ;
+
+ companion object {
+ fun getByInventoryName(inventory: String) = entries.firstOrNull { it.inventory == inventory }
+ }
+ }
}
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/InventoryUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/InventoryUtils.kt
index 4774e4e7a..c0b5e04df 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/InventoryUtils.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/InventoryUtils.kt
@@ -1,6 +1,7 @@
package at.hannibal2.skyhanni.utils
import at.hannibal2.skyhanni.test.command.ErrorManager
+import at.hannibal2.skyhanni.utils.ItemUtils.getInternalNameOrNull
import io.github.moulberry.notenoughupdates.NotEnoughUpdates
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.inventory.GuiChest
@@ -74,4 +75,9 @@ object InventoryUtils {
val screen = Minecraft.getMinecraft().currentScreen as? GuiContainer ?: return false
return screen.slotUnderMouse.inventory is InventoryPlayer && screen.slotUnderMouse.stack == itemStack
}
+
+ fun getAmountOfItemInInventory(name: NEUInternalName) =
+ countItemsInLowerInventory { it.getInternalNameOrNull() == name }
+
+ fun isItemInInventory(name: NEUInternalName) = getAmountOfItemInInventory(name) > 0
}