aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/at
diff options
context:
space:
mode:
authorEmpa <42304516+ItsEmpa@users.noreply.github.com>2024-04-13 08:35:51 +0200
committerGitHub <noreply@github.com>2024-04-13 08:35:51 +0200
commit0d41a281c8d87128a0004fed96dada8b1b5e950a (patch)
tree1f4492d4dfb646178c3e7409e519abaea5543efd /src/main/java/at
parent2d3368725ea962d8ff42d17cf1623a2229da7b4f (diff)
downloadskyhanni-0d41a281c8d87128a0004fed96dada8b1b5e950a.tar.gz
skyhanni-0d41a281c8d87128a0004fed96dada8b1b5e950a.tar.bz2
skyhanni-0d41a281c8d87128a0004fed96dada8b1b5e950a.zip
Feature: Quiver Display (#1190)
Co-authored-by: Cal <cwolfson58@gmail.com> 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.kt6
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/combat/CombatConfig.java5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/combat/QuiverConfig.java40
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/combat/QuiverDisplayConfig.java51
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/dev/DevConfig.java5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/inventory/InventoryConfig.java7
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/OwnInventoryData.kt3
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/QuiverAPI.kt176
-rw-r--r--src/main/java/at/hannibal2/skyhanni/events/OwnInventoryItemUpdateEvent.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/events/QuiverUpdateEvent.kt5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/gui/quiver/QuiverDisplay.kt98
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/gui/quiver/QuiverWarning.kt118
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/inventory/QuiverNotification.kt26
14 files changed, 435 insertions, 109 deletions
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
@@ -20,6 +20,11 @@ public class CombatConfig {
public GhostCounterConfig ghostCounter = new GhostCounterConfig();
@Expose
+ @ConfigOption(name = "Quiver", desc = "")
+ @Accordion
+ public QuiverConfig quiverConfig = new QuiverConfig();
+
+ @Expose
@ConfigOption(name = "Summonings", desc = "")
@Accordion
public SummoningsConfig summonings = new SummoningsConfig();
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<Boolean> showIcon = Property.of(true);
+
+ @Expose
+ @ConfigOption(
+ name = "When to show",
+ desc = "Decides in what conditions to show the display."
+ )
+ @ConfigEditorDropdown
+ public Property<ShowWhen> 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
@@ -45,11 +45,6 @@ public class DevConfig {
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")
@ConfigEditorBoolean
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<NEUInternalName, Float> arrowAmount = new HashMap<>();
+ public Map<NEUInternalName, Integer> 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<NEUInternalName, Float>
+ var arrowAmount: MutableMap<NEUInternalName, Int>
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<ArrowType> = 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 §.(?<arrow>.*)§a!")
private val fillUpJaxPattern by chatGroup.pattern(
"fillupjax",
- "(§.)*Jax forged (§.)*(?<type>.*?)(§.)* x(?<amount>[\\d,]+)( (§.)*for (§.)*(?<coins>[\\d,]+) Coins)?(§.)*!"
+ "(?:§.)*Jax forged (?:§.)*(?<type>.*?)(?:§.)* x(?<amount>[\\d,]+)(?: (?:§.)*for (?:§.)*(?<coins>[\\d,]+) Coins)?(?:§.)*!"
)
private val fillUpPattern by chatGroup.pattern(
"fillup",
"§aYou filled your quiver with §f(?<flintAmount>.*) §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(?<type>.*)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 (§.)*(?<type>.*) x(?<amount>.*) (§.)*to your quiver!"
+ "(?:§.)*You've added (?:§.)*(?<type>.*) x(?<amount>.*) (?:§.)*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: §.(?<type>.*) §7\\(§e(?<amount>.*)§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<Renderable>()
+ 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<ArrowType>()
+ private var arrowsToAlert = mutableListOf<String>()
+ 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 (?<arrowsLeft>.*) 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)
- }
- }
-}