From 0d41a281c8d87128a0004fed96dada8b1b5e950a Mon Sep 17 00:00:00 2001 From: Empa <42304516+ItsEmpa@users.noreply.github.com> Date: Sat, 13 Apr 2024 08:35:51 +0200 Subject: Feature: Quiver Display (#1190) Co-authored-by: Cal Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com> --- src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt | 6 +- .../config/features/combat/CombatConfig.java | 5 + .../config/features/combat/QuiverConfig.java | 40 +++++ .../features/combat/QuiverDisplayConfig.java | 51 ++++++ .../skyhanni/config/features/dev/DevConfig.java | 5 - .../config/features/inventory/InventoryConfig.java | 7 - .../config/storage/ProfileSpecificStorage.java | 2 +- .../at/hannibal2/skyhanni/data/OwnInventoryData.kt | 3 +- .../java/at/hannibal2/skyhanni/data/QuiverAPI.kt | 176 +++++++++++++-------- .../skyhanni/events/OwnInventoryItemUpdateEvent.kt | 2 +- .../hannibal2/skyhanni/events/QuiverUpdateEvent.kt | 5 + .../skyhanni/features/gui/quiver/QuiverDisplay.kt | 98 ++++++++++++ .../skyhanni/features/gui/quiver/QuiverWarning.kt | 118 ++++++++++++++ .../features/inventory/QuiverNotification.kt | 26 --- 14 files changed, 435 insertions(+), 109 deletions(-) create mode 100644 src/main/java/at/hannibal2/skyhanni/config/features/combat/QuiverConfig.java create mode 100644 src/main/java/at/hannibal2/skyhanni/config/features/combat/QuiverDisplayConfig.java create mode 100644 src/main/java/at/hannibal2/skyhanni/events/QuiverUpdateEvent.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/quiver/QuiverDisplay.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/gui/quiver/QuiverWarning.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/inventory/QuiverNotification.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 b55b037b0..622c0d5f8 100644 --- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt +++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt @@ -231,6 +231,8 @@ import at.hannibal2.skyhanni.features.garden.visitor.VisitorListener import at.hannibal2.skyhanni.features.garden.visitor.VisitorRewardWarning import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardPattern +import at.hannibal2.skyhanni.features.gui.quiver.QuiverDisplay +import at.hannibal2.skyhanni.features.gui.quiver.QuiverWarning import at.hannibal2.skyhanni.features.inventory.AuctionsHighlighter import at.hannibal2.skyhanni.features.inventory.ChestValue import at.hannibal2.skyhanni.features.inventory.DojoRankDisplay @@ -242,7 +244,6 @@ import at.hannibal2.skyhanni.features.inventory.ItemStars import at.hannibal2.skyhanni.features.inventory.MaxPurseItems import at.hannibal2.skyhanni.features.inventory.PowerStoneGuideFeatures import at.hannibal2.skyhanni.features.inventory.QuickCraftFeatures -import at.hannibal2.skyhanni.features.inventory.QuiverNotification import at.hannibal2.skyhanni.features.inventory.RngMeterInventory import at.hannibal2.skyhanni.features.inventory.SackDisplay import at.hannibal2.skyhanni.features.inventory.ShiftClickBrewing @@ -825,7 +826,6 @@ class SkyHanniMod { loadModule(VerminTracker) loadModule(SkillProgress) loadModule(SkillTooltip()) - loadModule(QuiverNotification) loadModule(MaxPurseItems()) loadModule(SuperCraftFeatures()) loadModule(InfernoMinionFeatures()) @@ -835,6 +835,8 @@ class SkyHanniMod { loadModule(DungeonShadowAssassinNotification()) loadModule(PestProfitTracker) loadModule(NoBitsWarning()) + loadModule(QuiverDisplay()) + loadModule(QuiverWarning()) init() diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/combat/CombatConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/combat/CombatConfig.java index a05ac751b..0504a918d 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/combat/CombatConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/combat/CombatConfig.java @@ -19,6 +19,11 @@ public class CombatConfig { @Category(name = "Ghost Counter", desc = "Ghost counter settings") public GhostCounterConfig ghostCounter = new GhostCounterConfig(); + @Expose + @ConfigOption(name = "Quiver", desc = "") + @Accordion + public QuiverConfig quiverConfig = new QuiverConfig(); + @Expose @ConfigOption(name = "Summonings", desc = "") @Accordion diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/combat/QuiverConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/combat/QuiverConfig.java new file mode 100644 index 000000000..174af713b --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/config/features/combat/QuiverConfig.java @@ -0,0 +1,40 @@ +package at.hannibal2.skyhanni.config.features.combat; + +import at.hannibal2.skyhanni.config.FeatureToggle; +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.ConfigEditorSlider; +import io.github.notenoughupdates.moulconfig.annotations.ConfigOption; + +public class QuiverConfig { + @Expose + @ConfigOption(name = "Quiver Display", desc = "") + @Accordion + public QuiverDisplayConfig quiverDisplay = new QuiverDisplayConfig(); + + @Expose + @ConfigOption( + name = "Low Quiver Alert", + desc = "Notifies you when your quiver\n" + + "reaches an amount of arrows." + ) + @ConfigEditorBoolean + @FeatureToggle + public boolean lowQuiverNotification = true; + + @Expose + @ConfigOption( + name = "Reminder After Run", + desc = "Reminds you to buy arrows after\n" + + "a Dungeons/Kuudra run if you're low." + ) + @ConfigEditorBoolean + @FeatureToggle + public boolean reminderAfterRun = true; + + @Expose + @ConfigOption(name = "Low Quiver Amount", desc = "Amount at which to notify you.") + @ConfigEditorSlider(minValue = 50, maxValue = 500, minStep = 50) + public int lowQuiverAmount = 100; +} diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/combat/QuiverDisplayConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/combat/QuiverDisplayConfig.java new file mode 100644 index 000000000..626c73f99 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/config/features/combat/QuiverDisplayConfig.java @@ -0,0 +1,51 @@ +package at.hannibal2.skyhanni.config.features.combat; + +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.ConfigEditorDropdown; +import io.github.notenoughupdates.moulconfig.annotations.ConfigOption; +import io.github.notenoughupdates.moulconfig.observer.Property; + +public class QuiverDisplayConfig { + @Expose + @ConfigOption(name = "Enable", desc = "Show the number of arrows you have.") + @ConfigEditorBoolean + @FeatureToggle + public boolean enabled = true; + + @Expose + public Position quiverDisplayPos = new Position(260, 80); + + @Expose + @ConfigOption(name = "Show arrow icon", desc = "Displays an icon next to the Quiver Display.") + @ConfigEditorBoolean + public Property showIcon = Property.of(true); + + @Expose + @ConfigOption( + name = "When to show", + desc = "Decides in what conditions to show the display." + ) + @ConfigEditorDropdown + public Property whenToShow = Property.of(ShowWhen.ONLY_BOW_HAND); + + public enum ShowWhen { + ALWAYS("Always"), + ONLY_BOW_INVENTORY("Bow in inventory"), + ONLY_BOW_HAND("Bow in hand"), + + ; + private final String str; + + ShowWhen(String str) { + this.str = str; + } + + @Override + public String toString() { + return str; + } + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/dev/DevConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/dev/DevConfig.java index 60dbf508e..14b16c136 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/dev/DevConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/dev/DevConfig.java @@ -44,11 +44,6 @@ public class DevConfig { @ConfigEditorBoolean public boolean worldEdit = false; - @Expose - @ConfigOption(name = "Bow Sound distance", desc = "The distance in blocks where the sound of shooting a bow will be used for the QuiverAPI.") - @ConfigEditorSlider(minValue = 0, maxValue = 50, minStep = 1) - public int bowSoundDistance = 5; - @Expose @ConfigOption(name = "Unknown Lines warning", desc = "Gives a chat warning when unknown lines are found in the scoreboard." + "\nCustom Scoreboard debug option") 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 b0f525ada..1bef14366 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 @@ -219,11 +219,4 @@ public class InventoryConfig { @ConfigEditorBoolean @FeatureToggle public boolean shiftClickBrewing = false; - - @Expose - @ConfigOption(name = "Low Quiver Alert", desc = "Notifies you when your Quiver runs out of arrows.") - @ConfigEditorBoolean - @FeatureToggle - public boolean quiverAlert = 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 f10d3d01c..7e40825fe 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java +++ b/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java @@ -69,7 +69,7 @@ public class ProfileSpecificStorage { public String currentArrow = null; @Expose - public Map arrowAmount = new HashMap<>(); + public Map arrowAmount = new HashMap<>(); } @Expose diff --git a/src/main/java/at/hannibal2/skyhanni/data/OwnInventoryData.kt b/src/main/java/at/hannibal2/skyhanni/data/OwnInventoryData.kt index 759254ff6..dc158c118 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/OwnInventoryData.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/OwnInventoryData.kt @@ -48,9 +48,10 @@ class OwnInventoryData { if (packet is S2FPacketSetSlot) { val windowId = packet.func_149175_c() if (windowId == 0) { + val slot = packet.func_149173_d() val item = packet.func_149174_e() ?: return DelayedRun.runNextTick { - OwnInventoryItemUpdateEvent(item).postAndCatch() + OwnInventoryItemUpdateEvent(item, slot).postAndCatch() } } } diff --git a/src/main/java/at/hannibal2/skyhanni/data/QuiverAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/QuiverAPI.kt index 4fbe0be37..702e29cb5 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/QuiverAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/QuiverAPI.kt @@ -1,32 +1,33 @@ package at.hannibal2.skyhanni.data -import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.data.jsonobjects.repo.ArrowTypeJson import at.hannibal2.skyhanni.data.jsonobjects.repo.ItemsJson import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent import at.hannibal2.skyhanni.events.LorenzChatEvent -import at.hannibal2.skyhanni.events.PlaySoundEvent +import at.hannibal2.skyhanni.events.LorenzTickEvent +import at.hannibal2.skyhanni.events.OwnInventoryItemUpdateEvent +import at.hannibal2.skyhanni.events.QuiverUpdateEvent import at.hannibal2.skyhanni.events.RepositoryReloadEvent import at.hannibal2.skyhanni.test.command.ErrorManager import at.hannibal2.skyhanni.utils.CollectionUtils.addOrPut import at.hannibal2.skyhanni.utils.InventoryUtils import at.hannibal2.skyhanni.utils.ItemCategory +import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName import at.hannibal2.skyhanni.utils.ItemUtils.getInternalNameOrNull import at.hannibal2.skyhanni.utils.ItemUtils.getItemCategoryOrNull +import at.hannibal2.skyhanni.utils.ItemUtils.getLore import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.LorenzUtils.round import at.hannibal2.skyhanni.utils.NEUInternalName import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName -import at.hannibal2.skyhanni.utils.NumberUtil.formatFloat -import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getEnchantments +import at.hannibal2.skyhanni.utils.NumberUtil.formatInt +import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getExtraAttributes import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher import at.hannibal2.skyhanni.utils.StringUtils.matches import at.hannibal2.skyhanni.utils.StringUtils.removeResets import at.hannibal2.skyhanni.utils.StringUtils.trimWhiteSpace import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern -import net.minecraft.client.Minecraft import net.minecraft.item.ItemBow -import net.minecraftforge.fml.common.eventhandler.EventPriority import net.minecraftforge.fml.common.eventhandler.SubscribeEvent private var infinityQuiverLevelMultiplier = 0.03f @@ -38,7 +39,7 @@ object QuiverAPI { set(value) { storage?.arrows?.currentArrow = value?.toString() ?: return } - var arrowAmount: MutableMap + var arrowAmount: MutableMap get() = storage?.arrows?.arrowAmount ?: mutableMapOf() set(value) { storage?.arrows?.arrowAmount = value @@ -46,11 +47,14 @@ object QuiverAPI { var currentAmount: Int get() = arrowAmount[currentArrow?.internalName]?.toInt() ?: 0 set(value) { - arrowAmount[currentArrow?.internalName ?: return] = value.toFloat() + arrowAmount[currentArrow?.internalName ?: return] = value } private var arrows: List = listOf() + private var wearingSkeletonMasterChestplate = false + private var hasBow = false + const val MAX_ARROW_AMOUNT = 2880 private val SKELETON_MASTER_CHESTPLATE = "SKELETON_MASTER_CHESTPLATE".asInternalName() @@ -62,22 +66,33 @@ object QuiverAPI { private val selectPattern by chatGroup.pattern("select", "§aYou set your selected arrow type to §.(?.*)§a!") private val fillUpJaxPattern by chatGroup.pattern( "fillupjax", - "(§.)*Jax forged (§.)*(?.*?)(§.)* x(?[\\d,]+)( (§.)*for (§.)*(?[\\d,]+) Coins)?(§.)*!" + "(?:§.)*Jax forged (?:§.)*(?.*?)(?:§.)* x(?[\\d,]+)(?: (?:§.)*for (?:§.)*(?[\\d,]+) Coins)?(?:§.)*!" ) private val fillUpPattern by chatGroup.pattern( "fillup", "§aYou filled your quiver with §f(?.*) §aextra arrows!" ) - private val clearedPattern by chatGroup.pattern("cleared", "§aCleared your quiver!") + private val clearedPattern by chatGroup.pattern( + "cleared", + "§aCleared your quiver!|§c§lYour quiver is now completely empty!" + ) + private val arrowRanOutPattern by chatGroup.pattern( + "ranout", + "§c§lQUIVER! §cYou have run out of §f(?.*)s§c!" + ) private val arrowResetPattern by chatGroup.pattern("arrowreset", "§cYour favorite arrow has been reset!") private val addedToQuiverPattern by chatGroup.pattern( "addedtoquiver", - "(§.)*You've added (§.)*(?.*) x(?.*) (§.)*to your quiver!" + "(?:§.)*You've added (?:§.)*(?.*) x(?.*) (?:§.)*to your quiver!" ) // Bows that don't use the players arrows, checked using the SkyBlock Id private val fakeBowsPattern by group.pattern("fakebows", "^(BOSS_SPIRIT_BOW|CRYPT_BOW)$") private val quiverInventoryNamePattern by group.pattern("quivername", "^Quiver$") + private val quiverInventoryPattern by group.pattern( + "quiver.inventory", + "§7Active Arrow: §.(?.*) §7\\(§e(?.*)§7\\)" + ) @SubscribeEvent fun onChat(event: LorenzChatEvent) { @@ -92,12 +107,25 @@ object QuiverAPI { "Unknown arrow type: $type", "message" to message, ) + QuiverUpdateEvent(currentArrow, currentAmount, shouldHideAmount()).postAndCatch() return } + arrowRanOutPattern.matchMatcher(message) { + val type = group("type") + val ranOutType = getArrowByNameOrNull(type) + ?: return ErrorManager.logErrorWithData( + UnknownArrowType("Unknown arrow type: $type"), + "Unknown arrow type: $type", + "message" to message, + ) + arrowAmount[ranOutType.internalName] = 0 + QuiverUpdateEvent(ranOutType, currentAmount, shouldHideAmount()).postAndCatch() + } + fillUpJaxPattern.matchMatcher(message) { val type = group("type") - val amount = group("amount").formatFloat() + val amount = group("amount").formatInt() val filledUpType = getArrowByNameOrNull(type) ?: return ErrorManager.logErrorWithData( UnknownArrowType("Unknown arrow type: $type"), @@ -106,19 +134,27 @@ object QuiverAPI { ) arrowAmount.addOrPut(filledUpType.internalName, amount) + if (filledUpType == currentArrow) { + QuiverUpdateEvent(filledUpType, currentAmount, shouldHideAmount()).postAndCatch() + } return + } fillUpPattern.matchMatcher(message) { - val flintAmount = group("flintAmount").formatFloat() + val flintAmount = group("flintAmount").formatInt() FLINT_ARROW_TYPE?.let { arrowAmount.addOrPut(it.internalName, flintAmount) } + + if (currentArrow == FLINT_ARROW_TYPE) { + QuiverUpdateEvent(currentArrow, currentAmount, shouldHideAmount()).postAndCatch() + } return } addedToQuiverPattern.matchMatcher(message) { val type = group("type") - val amount = group("amount").formatFloat() + val amount = group("amount").formatInt() val filledUpType = getArrowByNameOrNull(type) ?: return ErrorManager.logErrorWithData( @@ -128,24 +164,31 @@ object QuiverAPI { ) arrowAmount.addOrPut(filledUpType.internalName, amount) + if (filledUpType == currentArrow) { + QuiverUpdateEvent(currentArrow, currentAmount, shouldHideAmount()).postAndCatch() + } return } clearedPattern.matchMatcher(message) { currentAmount = 0 arrowAmount.clear() + + QuiverUpdateEvent(currentArrow, currentAmount, shouldHideAmount()).postAndCatch() return } arrowResetPattern.matchMatcher(message) { currentArrow = NONE_ARROW_TYPE currentAmount = 0 + + QuiverUpdateEvent(currentArrow, currentAmount, shouldHideAmount()).postAndCatch() return } } @SubscribeEvent - fun onInventoryOpen(event: InventoryFullyOpenedEvent) { + fun onInventoryFullyLoaded(event: InventoryFullyOpenedEvent) { if (!isEnabled()) return if (!quiverInventoryNamePattern.matches(event.inventoryName)) return @@ -159,67 +202,43 @@ object QuiverAPI { val arrow = stack.getInternalNameOrNull() ?: continue val arrowType = getArrowByNameOrNull(arrow) ?: continue - arrowAmount.addOrPut(arrowType.internalName, stack.stackSize.toFloat()) + arrowAmount.addOrPut(arrowType.internalName, stack.stackSize) } } - /* - Modified method to remove arrows from SkyblockFeatures QuiverOverlay - Original method source: - https://github.com/MrFast-js/SkyblockFeatures/blob/ae4bf0b91ed0fb17114d9cdaccaa9aef9a6c8d01/src/main/java/mrfast/sbf/features/overlays/QuiverOverlay.java#L127 - - Changes made: - - Added "fake bows" check - - Added "infinite quiver" check - - Added "sneaking" check - - Added "bow sound distance" check - - Added "skeleton master chestplate" check - */ - @SubscribeEvent(priority = EventPriority.HIGHEST) - fun onPlaySound(event: PlaySoundEvent) { - if (!isEnabled()) return - if (event.soundName != "random.bow") return - - val holdingBow = InventoryUtils.getItemInHand()?.item is ItemBow - && !fakeBowsPattern.matches(InventoryUtils.getItemInHand()?.getInternalNameOrNull()?.asString() ?: "") - - if (!holdingBow) return - - // check if sound location is more than configAmount block away from player - val soundLocation = event.distanceToPlayer - if (soundLocation > SkyHanniMod.feature.dev.bowSoundDistance) return - - val arrowType = currentArrow?.internalName ?: return - val amount = arrowAmount[arrowType] ?: return - if (amount <= 0) return - - if (InventoryUtils.getChestplate() - // The chestplate has the ability to not use arrows - // https://hypixel-skyblock.fandom.com/wiki/Skeleton_Master_Armor - ?.getInternalNameOrNull() == SKELETON_MASTER_CHESTPLATE - ) return - - val infiniteQuiverLevel = InventoryUtils.getItemInHand()?.getEnchantments()?.get("infinite_quiver") ?: 0 - - val amountToRemove = { - when (Minecraft.getMinecraft().thePlayer.isSneaking) { - true -> 1.0f - false -> { - when (infiniteQuiverLevel) { - in 1..10 -> 1 - (infinityQuiverLevelMultiplier * infiniteQuiverLevel) - else -> 1.0f + @SubscribeEvent + fun onInventoryUpdate(event: OwnInventoryItemUpdateEvent) { + if (!isEnabled() && event.slot != 44) return + val stack = event.itemStack + if (stack.getExtraAttributes()?.hasKey("quiver_arrow") == true) { + for (line in stack.getLore()) { + quiverInventoryPattern.matchMatcher(line) { + val type = group("type") + val amount = group("amount").formatInt() + val currentArrowType = getArrowByNameOrNull(type) + ?: return ErrorManager.logErrorWithData( + UnknownArrowType("Unknown arrow type: $type"), + "Unknown arrow type: $type", + "line" to line, + ) + if (currentArrowType != currentArrow || amount != currentAmount) { + currentArrow = currentArrowType + currentAmount = amount + QuiverUpdateEvent(currentArrowType, currentAmount, shouldHideAmount()).postAndCatch() } } } } - - arrowAmount[arrowType] = amount - amountToRemove() } fun Int.asArrowPercentage() = ((this.toFloat() / MAX_ARROW_AMOUNT) * 100).round(1) - fun hasBowInInventory(): Boolean { - return InventoryUtils.getItemsInOwnInventory().any { it.item is ItemBow } + fun hasBowInInventory() = hasBow + + fun isHoldingBow(): Boolean { + InventoryUtils.getItemInHand()?.let { + return it.item is ItemBow && !fakeBowsPattern.matches(it.getInternalName().asString()) + } ?: return false } fun getArrowByNameOrNull(name: String): ArrowType? { @@ -234,6 +253,31 @@ object QuiverAPI { fun isEnabled() = LorenzUtils.inSkyBlock && storage != null + private fun shouldHideAmount() = wearingSkeletonMasterChestplate + + private fun checkBowInventory() { + hasBow = InventoryUtils.getItemsInOwnInventory().any { + it.item is ItemBow && !fakeBowsPattern.matches(it.getInternalName().asString()) + } + } + + private fun checkChestplate() { + val wasWearing = wearingSkeletonMasterChestplate + wearingSkeletonMasterChestplate = InventoryUtils.getChestplate()?.getInternalName()?.equals( + SKELETON_MASTER_CHESTPLATE) ?: false + if (wasWearing != wearingSkeletonMasterChestplate) { + QuiverUpdateEvent(currentArrow, currentAmount, shouldHideAmount()).postAndCatch() + } + } + + @SubscribeEvent + fun onTick(event: LorenzTickEvent) { + if (!isEnabled()) return + if (event.repeatSeconds(2)) { + checkChestplate() + checkBowInventory() + } + } // Load arrows from repo @SubscribeEvent @@ -245,7 +289,7 @@ object QuiverAPI { arrows = arrowData.arrows.map { ArrowType(it.value.arrow, it.key.asInternalName()) } NONE_ARROW_TYPE = getArrowByNameOrNull("NONE".asInternalName()) - FLINT_ARROW_TYPE = getArrowByNameOrNull("FLINT".asInternalName()) + FLINT_ARROW_TYPE = getArrowByNameOrNull("ARROW".asInternalName()) } class UnknownArrowType(message: String) : Exception(message) diff --git a/src/main/java/at/hannibal2/skyhanni/events/OwnInventoryItemUpdateEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/OwnInventoryItemUpdateEvent.kt index 32e19e751..56264e198 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/OwnInventoryItemUpdateEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/OwnInventoryItemUpdateEvent.kt @@ -2,4 +2,4 @@ package at.hannibal2.skyhanni.events import net.minecraft.item.ItemStack -data class OwnInventoryItemUpdateEvent(val itemStack: ItemStack) : LorenzEvent() +data class OwnInventoryItemUpdateEvent(val itemStack: ItemStack, val slot: Int) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/QuiverUpdateEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/QuiverUpdateEvent.kt new file mode 100644 index 000000000..a084a1741 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/events/QuiverUpdateEvent.kt @@ -0,0 +1,5 @@ +package at.hannibal2.skyhanni.events + +import at.hannibal2.skyhanni.data.ArrowType + +class QuiverUpdateEvent(val currentArrow: ArrowType?, val currentAmount: Int, val hideAmount: Boolean) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/quiver/QuiverDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/quiver/QuiverDisplay.kt new file mode 100644 index 000000000..608b66b2b --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/gui/quiver/QuiverDisplay.kt @@ -0,0 +1,98 @@ +package at.hannibal2.skyhanni.features.gui.quiver + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.config.features.combat.QuiverDisplayConfig.ShowWhen +import at.hannibal2.skyhanni.data.ArrowType +import at.hannibal2.skyhanni.data.QuiverAPI +import at.hannibal2.skyhanni.data.QuiverAPI.NONE_ARROW_TYPE +import at.hannibal2.skyhanni.events.ConfigLoadEvent +import at.hannibal2.skyhanni.events.GuiRenderEvent +import at.hannibal2.skyhanni.events.ProfileJoinEvent +import at.hannibal2.skyhanni.events.QuiverUpdateEvent +import at.hannibal2.skyhanni.utils.ConditionalUtils +import at.hannibal2.skyhanni.utils.ItemUtils.getItemRarityOrNull +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.NEUItems +import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators +import at.hannibal2.skyhanni.utils.RenderUtils +import at.hannibal2.skyhanni.utils.RenderUtils.renderRenderables +import at.hannibal2.skyhanni.utils.StringUtils +import at.hannibal2.skyhanni.utils.renderables.Renderable +import net.minecraft.init.Items +import net.minecraft.item.ItemStack +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +class QuiverDisplay { + + private val config get() = SkyHanniMod.feature.combat.quiverConfig.quiverDisplay + + private var display = emptyList() + private var arrow: ArrowType? = null + private var amount = QuiverAPI.currentAmount + private var hideAmount = false + + @SubscribeEvent + fun onProfileJoin(event: ProfileJoinEvent) { + display = emptyList() + arrow = QuiverAPI.currentArrow + amount = QuiverAPI.currentAmount + updateDisplay() + } + + private fun updateDisplay() { + display = drawDisplay() + } + + private fun drawDisplay() = buildList { + val arrow = arrow ?: return@buildList + val itemStack = NEUItems.getItemStackOrNull(arrow.internalName.asString()) ?: ItemStack(Items.arrow) + + val rarity = itemStack.getItemRarityOrNull()?.chatColorCode ?: "§f" + val arrowDisplayName = + if (hideAmount || arrow == NONE_ARROW_TYPE) arrow.arrow else StringUtils.pluralize(amount, arrow.arrow) + + if (config.showIcon.get()) { + add(Renderable.itemStack(itemStack, 1.0)) + } + if (!hideAmount) { + add(Renderable.string("§b${amount.addSeparators()}x")) + } + add(Renderable.string(" $rarity$arrowDisplayName")) + } + + @SubscribeEvent + fun onQuiverUpdate(event: QuiverUpdateEvent) { + arrow = event.currentArrow + amount = event.currentAmount + hideAmount = event.hideAmount + + updateDisplay() + } + + @SubscribeEvent + fun onRenderOverlay(event: GuiRenderEvent.GuiOverlayRenderEvent) { + if (!isEnabled()) return + if (display.isEmpty()) updateDisplay() + val whenToShow = config.whenToShow.get() + if (whenToShow == ShowWhen.ALWAYS || + whenToShow == ShowWhen.ONLY_BOW_INVENTORY && QuiverAPI.hasBowInInventory() || + whenToShow == ShowWhen.ONLY_BOW_HAND && QuiverAPI.isHoldingBow() + ) { + val content = + Renderable.horizontalContainer(display, 1, verticalAlign = RenderUtils.VerticalAlignment.CENTER) + config.quiverDisplayPos.renderRenderables(listOf(content), posLabel = "Quiver Display") + } + } + + @SubscribeEvent + fun onConfigLoad(event: ConfigLoadEvent) { + ConditionalUtils.onToggle( + config.whenToShow, + config.showIcon + ) { + updateDisplay() + } + } + + fun isEnabled() = LorenzUtils.inSkyBlock && config.enabled +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/quiver/QuiverWarning.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/quiver/QuiverWarning.kt new file mode 100644 index 000000000..7ee69c9c8 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/gui/quiver/QuiverWarning.kt @@ -0,0 +1,118 @@ +package at.hannibal2.skyhanni.features.gui.quiver + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator +import at.hannibal2.skyhanni.data.ArrowType +import at.hannibal2.skyhanni.data.QuiverAPI +import at.hannibal2.skyhanni.data.QuiverAPI.arrowAmount +import at.hannibal2.skyhanni.data.TitleManager +import at.hannibal2.skyhanni.events.DungeonCompleteEvent +import at.hannibal2.skyhanni.events.DungeonEnterEvent +import at.hannibal2.skyhanni.events.KuudraCompleteEvent +import at.hannibal2.skyhanni.events.KuudraEnterEvent +import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent +import at.hannibal2.skyhanni.events.QuiverUpdateEvent +import at.hannibal2.skyhanni.utils.ChatUtils +import at.hannibal2.skyhanni.utils.DelayedRun +import at.hannibal2.skyhanni.utils.ItemUtils.getItemRarityOrNull +import at.hannibal2.skyhanni.utils.NEUItems.getItemStackOrNull +import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators +import at.hannibal2.skyhanni.utils.SimpleTimeMark +import at.hannibal2.skyhanni.utils.SoundUtils +import at.hannibal2.skyhanni.utils.StringUtils.createCommaSeparatedList +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import kotlin.time.Duration.Companion.seconds + +class QuiverWarning { + + private val config get() = SkyHanniMod.feature.combat.quiverConfig + + private var arrow: ArrowType? = null + private var amount = QuiverAPI.currentAmount + private var lastLowQuiverReminder = SimpleTimeMark.farPast() + private var arrowsUsedInRun = mutableListOf() + private var arrowsToAlert = mutableListOf() + private var inInstance = false + + @SubscribeEvent + fun onWorldChange(event: LorenzWorldChangeEvent) { + arrowsUsedInRun = mutableListOf() + arrowsToAlert = mutableListOf() + inInstance = false + } + + @SubscribeEvent + fun onDungeonEnter(event: DungeonEnterEvent) { + onInstanceEnter() + } + + @SubscribeEvent + fun onKuudraEnter(event: KuudraEnterEvent) { + onInstanceEnter() + } + + private fun onInstanceEnter() { + arrowsUsedInRun = mutableListOf() + arrowsToAlert = mutableListOf() + inInstance = true + } + + @SubscribeEvent + fun onDungeonComplete(event: DungeonCompleteEvent) { + onInstanceComplete() + } + + @SubscribeEvent + fun onKuudraComplete(event: KuudraCompleteEvent) { + onInstanceComplete() + } + + private fun onInstanceComplete() { + if (!config.reminderAfterRun) return + if (arrowsUsedInRun.isEmpty()) return + for (arrow in arrowsUsedInRun) { + val internalName = arrow.internalName + val amount = arrowAmount[internalName] ?: continue + if (amount > config.lowQuiverAmount) continue + val rarity = internalName.getItemStackOrNull()?.getItemRarityOrNull()?.chatColorCode ?: "§f" + arrowsToAlert.add(rarity + arrow.arrow) + } + if (arrowsToAlert.isNotEmpty()) instanceAlert() + } + + private fun instanceAlert() { + DelayedRun.runNextTick { + TitleManager.sendTitle("§cLow on arrows!", 5.seconds, 3.6, 7f) + ChatUtils.chat("Low on ${arrowsToAlert.createCommaSeparatedList()}!") + SoundUtils.repeatSound(100, 30, SoundUtils.plingSound) + } + } + + private fun lowQuiverAlert() { + if (lastLowQuiverReminder.passedSince() < 30.seconds) return + lastLowQuiverReminder = SimpleTimeMark.now() + val itemStack = getItemStackOrNull(arrow?.internalName?.asString() ?: return) ?: return + val rarity = itemStack.getItemRarityOrNull()?.chatColorCode ?: "§f" + TitleManager.sendTitle("§cLow on $rarity${arrow?.arrow}!", 5.seconds, 3.6, 7f) + ChatUtils.chat("Low on $rarity${arrow?.arrow} §e(${amount.addSeparators()} left)") + } + + @SubscribeEvent + fun onQuiverUpdate(event: QuiverUpdateEvent) { + val lastArrow = arrow + val lastAmount = amount + + if (config.lowQuiverNotification && amount <= config.lowQuiverAmount) { + if (arrow != lastArrow || (arrow == lastArrow && amount <= lastAmount)) lowQuiverAlert() + } + + if (inInstance) { + if (!arrowsUsedInRun.contains(arrow)) arrowsUsedInRun.add(arrow ?: return) + } + } + + @SubscribeEvent + fun onConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) { + event.move(35, "inventory.quiverAlert", "combat.quiverConfig.lowQuiverNotification") + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/QuiverNotification.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/QuiverNotification.kt deleted file mode 100644 index 9063fcb0d..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/QuiverNotification.kt +++ /dev/null @@ -1,26 +0,0 @@ -package at.hannibal2.skyhanni.features.inventory - -import at.hannibal2.skyhanni.SkyHanniMod -import at.hannibal2.skyhanni.data.TitleManager -import at.hannibal2.skyhanni.events.LorenzChatEvent -import at.hannibal2.skyhanni.utils.SoundUtils -import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher -import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent -import kotlin.time.Duration.Companion.seconds - -object QuiverNotification { - private val quiverChatPattern by RepoPattern.pattern( - "inventory.quiver.chat.low", - "§cYou only have (?.*) arrows left in your Quiver!" - ) - - @SubscribeEvent - fun onChat(event: LorenzChatEvent) { - if (!SkyHanniMod.configManager.features.inventory.quiverAlert) return - quiverChatPattern.matchMatcher(event.message) { - TitleManager.sendTitle("§c${group("arrowsLeft")} arrows left!", 3.seconds, 3.6, 7f) - SoundUtils.repeatSound(100, 30, SoundUtils.plingSound) - } - } -} -- cgit