diff options
author | hannibal2 <24389977+hannibal002@users.noreply.github.com> | 2023-11-24 03:01:01 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-24 03:01:01 +0100 |
commit | 43f0e576509d54bb7b12ab59be292c261a0b050d (patch) | |
tree | a61aa63d2393ac88e1ddbf577a67065a2753efaa | |
parent | dd2a77f37504f81e09806e1c277451957ea455ac (diff) | |
download | skyhanni-43f0e576509d54bb7b12ab59be292c261a0b050d.tar.gz skyhanni-43f0e576509d54bb7b12ab59be292c261a0b050d.tar.bz2 skyhanni-43f0e576509d54bb7b12ab59be292c261a0b050d.zip |
fishing v2 (#729)
Prevent wrong fishing item pickup #729
9 files changed, 189 insertions, 50 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/api/CollectionAPI.kt b/src/main/java/at/hannibal2/skyhanni/api/CollectionAPI.kt index cd7fa0c59..8698d9f28 100644 --- a/src/main/java/at/hannibal2/skyhanni/api/CollectionAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/api/CollectionAPI.kt @@ -70,8 +70,11 @@ class CollectionAPI { @SubscribeEvent fun onItemAdd(event: ItemAddInInventoryEvent) { - // TODO add support for replenish (higher collection than actual items in inv) val internalName = event.internalName + val (_, amount) = NEUItems.getMultiplier(internalName) + if (amount > 1) return + + // TODO add support for replenish (higher collection than actual items in inv) if (internalName.getItemStackOrNull() == null) { LorenzUtils.debug("CollectionAPI.addFromInventory: item is null for '$internalName'") return diff --git a/src/main/java/at/hannibal2/skyhanni/data/MinecraftData.kt b/src/main/java/at/hannibal2/skyhanni/data/MinecraftData.kt index bfcc8df5f..56d565299 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/MinecraftData.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/MinecraftData.kt @@ -6,6 +6,7 @@ import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent import at.hannibal2.skyhanni.events.PacketEvent import at.hannibal2.skyhanni.events.PlaySoundEvent import at.hannibal2.skyhanni.events.ReceiveParticleEvent +import at.hannibal2.skyhanni.utils.DelayedRun import at.hannibal2.skyhanni.utils.InventoryUtils import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName import at.hannibal2.skyhanni.utils.LorenzUtils @@ -71,6 +72,7 @@ object MinecraftData { Minecraft.getMinecraft().thePlayer ?: return totalTicks++ LorenzTickEvent(totalTicks).postAndCatch() + DelayedRun.checkRuns() } @SubscribeEvent @@ -78,8 +80,8 @@ object MinecraftData { if (!LorenzUtils.inSkyBlock) return val hand = InventoryUtils.getItemInHand() val newItem = hand?.getInternalName() ?: NEUInternalName.NONE - if (newItem != InventoryUtils.itemInHandId) { - ItemInHandChangeEvent(newItem, hand).postAndCatch() + val oldItem = InventoryUtils.itemInHandId + if (newItem != oldItem) { InventoryUtils.recentItemsInHand.keys.removeIf { it + 30_000 > System.currentTimeMillis() } if (newItem != NEUInternalName.NONE) { @@ -87,6 +89,7 @@ object MinecraftData { } InventoryUtils.itemInHandId = newItem InventoryUtils.latestItemInHand = hand + ItemInHandChangeEvent(newItem, oldItem).postAndCatch() } } diff --git a/src/main/java/at/hannibal2/skyhanni/data/OwnInventoryData.kt b/src/main/java/at/hannibal2/skyhanni/data/OwnInventoryData.kt index 4c6058b26..f3c04a0c6 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/OwnInventoryData.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/OwnInventoryData.kt @@ -1,23 +1,28 @@ package at.hannibal2.skyhanni.data -import at.hannibal2.skyhanni.events.InventoryCloseEvent +import at.hannibal2.skyhanni.events.GuiContainerEvent import at.hannibal2.skyhanni.events.LorenzTickEvent import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent import at.hannibal2.skyhanni.events.OwnInventoryItemUpdateEvent import at.hannibal2.skyhanni.events.PacketEvent import at.hannibal2.skyhanni.events.entity.ItemAddInInventoryEvent import at.hannibal2.skyhanni.features.bazaar.BazaarApi +import at.hannibal2.skyhanni.features.bazaar.BazaarApi.Companion.isBazaarItem import at.hannibal2.skyhanni.utils.InventoryUtils import at.hannibal2.skyhanni.utils.ItemUtils.getInternalNameOrNull import at.hannibal2.skyhanni.utils.ItemUtils.name import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.LorenzUtils.editCopy -import at.hannibal2.skyhanni.utils.NEUItems +import at.hannibal2.skyhanni.utils.NEUInternalName +import at.hannibal2.skyhanni.utils.SimpleTimeMark +import net.minecraft.client.Minecraft import net.minecraft.item.ItemStack import net.minecraft.network.play.server.S0DPacketCollectItem import net.minecraft.network.play.server.S2FPacketSetSlot import net.minecraftforge.fml.common.eventhandler.EventPriority import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import kotlin.time.Duration +import kotlin.time.Duration.Companion.milliseconds typealias SlotNumber = Int typealias ItemName = String @@ -58,7 +63,12 @@ class OwnInventoryData { val old = items[slot] val new = itemStack.itemToPair() if (old != new) { - item(slot, new, itemStack) + itemStack?.let { + calculateDifference(slot, new, it) + } + items = items.editCopy { + this[slot] = new + } } } } @@ -78,59 +88,65 @@ class OwnInventoryData { private fun ItemStack?.itemToPair(): ItemData = this?.let { (name ?: "null") to stackSize } ?: Pair("null", 0) - private fun item(slot: SlotNumber, new: ItemData, itemStack: ItemStack?) { + private fun calculateDifference(slot: SlotNumber, new: ItemData, itemStack: ItemStack) { val (oldItem, oldAmount) = items[slot] ?: Pair("null", 0) val (name, amount) = new if (name == oldItem) { val diff = amount - oldAmount - if (amount > oldAmount) { - add(itemStack, diff) + if (diff > 0) { + addItem(itemStack, diff) } } else { if (name != "null") { - add(itemStack!!, amount) + addItem(itemStack, amount) } } - items = items.editCopy { - this[slot] = new - } } @SubscribeEvent - fun onInventoryClose(event: InventoryCloseEvent) { - BazaarApi.inBazaarInventory = false - lastClose = System.currentTimeMillis() + fun onInventoryClose(event: GuiContainerEvent.CloseWindowEvent) { + val item = Minecraft.getMinecraft().thePlayer.inventory.itemStack ?: return + val internalNameOrNull = item.getInternalNameOrNull() ?: return + ignoreItem(500.milliseconds) { it == internalNameOrNull } } - private var lastClose = 0L + @SubscribeEvent + fun onSlotClick(event: GuiContainerEvent.SlotClickEvent) { + if (BazaarApi.inBazaarInventory) { + ignoreItem(500.milliseconds) { it.isBazaarItem() } + } + } + + private fun ignoreItem(duration: Duration, condition: (NEUInternalName) -> Boolean) { + ignoredItemsUntil.add(IgnoredItem(condition, SimpleTimeMark.now() + duration)) + } - private fun add(item_: ItemStack?, add: Int) { - val item = item_ ?: return - val diffClose = System.currentTimeMillis() - lastClose - if (diffClose < 500) return + private val ignoredItemsUntil = mutableListOf<IgnoredItem>() + class IgnoredItem(val condition: (NEUInternalName) -> Boolean, val blockedUntil: SimpleTimeMark) + + private fun addItem(item: ItemStack, add: Int) { val diffWorld = System.currentTimeMillis() - LorenzUtils.lastWorldSwitch if (diffWorld < 3_000) return - val internalName = item.getInternalNameOrNull() - item.name?.let { if (it == "§8Quiver Arrow") { return } } - if (internalName == null) { - LorenzUtils.debug("OwnInventoryData add is empty for: '${item.name}'") + val internalName = item.getInternalNameOrNull() ?: run { + LorenzUtils.debug("OwnInventoryData add is null for: '${item.name}'") return } - if (internalName.startsWith("MAP-")) return - val (_, amount) = NEUItems.getMultiplier(internalName) - if (amount > 1) return + ignoredItemsUntil.removeIf { it.blockedUntil.isInPast() } + if (ignoredItemsUntil.any { it.condition(internalName) }) return + + if (internalName.startsWith("MAP-")) return ItemAddInInventoryEvent(internalName, add).postAndCatch() + LorenzUtils.debug("added item internalName: $internalName") } - } diff --git a/src/main/java/at/hannibal2/skyhanni/data/SkillExperience.kt b/src/main/java/at/hannibal2/skyhanni/data/SkillExperience.kt index 78c25e799..470c8d171 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/SkillExperience.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/SkillExperience.kt @@ -3,6 +3,7 @@ package at.hannibal2.skyhanni.data import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent import at.hannibal2.skyhanni.events.LorenzActionBarEvent import at.hannibal2.skyhanni.events.ProfileJoinEvent +import at.hannibal2.skyhanni.events.SkillExpGainEvent import at.hannibal2.skyhanni.utils.ItemUtils.getLore import at.hannibal2.skyhanni.utils.ItemUtils.name import at.hannibal2.skyhanni.utils.LorenzUtils @@ -32,7 +33,14 @@ class SkillExperience { val neededForNextLevel = group("needed").formatNumber() val nextLevel = getLevelForExpExactly(neededForNextLevel) val baseExp = getExpForLevel(nextLevel - 1) - skillExp[skill] = baseExp + overflow + val totalExp = baseExp + overflow + skillExp[skill] = totalExp + SkillExpGainEvent(skill).postAndCatch() + } + val pattern = ".*§3+(?<add>.+) (?<skill>.*) \\((?<percentage>.*)%\\).*".toPattern() + pattern.matchMatcher(event.message) { + val skill = group("skill").lowercase() + SkillExpGainEvent(skill).postAndCatch() } } diff --git a/src/main/java/at/hannibal2/skyhanni/events/ItemInHandChangeEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/ItemInHandChangeEvent.kt index 3f5b94b3c..4ef39df43 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/ItemInHandChangeEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/ItemInHandChangeEvent.kt @@ -1,6 +1,5 @@ package at.hannibal2.skyhanni.events import at.hannibal2.skyhanni.utils.NEUInternalName -import net.minecraft.item.ItemStack -class ItemInHandChangeEvent(val internalName: NEUInternalName, val stack: ItemStack?) : LorenzEvent()
\ No newline at end of file +class ItemInHandChangeEvent(val newItem: NEUInternalName, val oldItem: NEUInternalName) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/SkillExpGainEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/SkillExpGainEvent.kt new file mode 100644 index 000000000..c6c7be5cc --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/events/SkillExpGainEvent.kt @@ -0,0 +1,4 @@ +package at.hannibal2.skyhanni.events + +// does not know how much exp is there, also gets called multiple times +class SkillExpGainEvent(val skill: String) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/features/fishing/FishingAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/fishing/FishingAPI.kt index 035525c01..3224b286b 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/fishing/FishingAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/fishing/FishingAPI.kt @@ -35,7 +35,9 @@ object FishingAPI { FishingBobberCastEvent(entity).postAndCatch() } - fun hasFishingRodInHand() = InventoryUtils.itemInHandId.asString().contains("ROD") + fun hasFishingRodInHand() = InventoryUtils.itemInHandId.isFishingRod() + + fun NEUInternalName.isFishingRod() = contains("ROD") fun ItemStack.isBait(): Boolean { val name = name ?: return false diff --git a/src/main/java/at/hannibal2/skyhanni/features/fishing/FishingProfitTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/fishing/FishingProfitTracker.kt index 50a9e6e1f..bbc5fd7f8 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/fishing/FishingProfitTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/fishing/FishingProfitTracker.kt @@ -4,14 +4,18 @@ import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.events.EntityMoveEvent import at.hannibal2.skyhanni.events.FishingBobberCastEvent import at.hannibal2.skyhanni.events.GuiRenderEvent +import at.hannibal2.skyhanni.events.ItemInHandChangeEvent import at.hannibal2.skyhanni.events.LorenzChatEvent import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent import at.hannibal2.skyhanni.events.RepositoryReloadEvent import at.hannibal2.skyhanni.events.SackChangeEvent +import at.hannibal2.skyhanni.events.SkillExpGainEvent import at.hannibal2.skyhanni.events.entity.ItemAddInInventoryEvent import at.hannibal2.skyhanni.features.bazaar.BazaarApi.Companion.getBazaarData +import at.hannibal2.skyhanni.features.fishing.FishingAPI.isFishingRod import at.hannibal2.skyhanni.test.PriceSource -import at.hannibal2.skyhanni.utils.ItemUtils.getItemName +import at.hannibal2.skyhanni.utils.DelayedRun +import at.hannibal2.skyhanni.utils.ItemUtils.nameWithEnchantment import at.hannibal2.skyhanni.utils.KeyboardManager import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.LorenzUtils.addAsSingletonList @@ -19,6 +23,7 @@ import at.hannibal2.skyhanni.utils.LorenzUtils.addSelector import at.hannibal2.skyhanni.utils.LorenzUtils.sortedDesc import at.hannibal2.skyhanni.utils.NEUInternalName import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName +import at.hannibal2.skyhanni.utils.NEUItems.getItemStack import at.hannibal2.skyhanni.utils.NEUItems.getNpcPriceOrNull import at.hannibal2.skyhanni.utils.NEUItems.getPriceOrNull import at.hannibal2.skyhanni.utils.NumberUtil @@ -32,8 +37,11 @@ import at.hannibal2.skyhanni.utils.renderables.Renderable import at.hannibal2.skyhanni.utils.tracker.SkyHanniTracker import at.hannibal2.skyhanni.utils.tracker.TrackerData import com.google.gson.annotations.Expose +import io.github.moulberry.notenoughupdates.NotEnoughUpdates import net.minecraft.client.Minecraft import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import kotlin.time.Duration.Companion.milliseconds +import kotlin.time.Duration.Companion.minutes import kotlin.time.Duration.Companion.seconds object FishingProfitTracker { @@ -42,6 +50,8 @@ object FishingProfitTracker { private val coinsChatPattern = ".* CATCH! §r§bYou found §r§6(?<coins>.*) Coins§r§b\\.".toPattern() private var lastClickDelay = 0L + private var lastFishingTime = SimpleTimeMark.farPast() + private val tracker = SkyHanniTracker("Fishing Profit Tracker", { Data() }, { it.fishing.fishingProfitTracker }) { drawDisplay(it) } @@ -71,11 +81,11 @@ object FishingProfitTracker { var hidden = false override fun toString() = "FishingItem{" + - "internalName='" + internalName + '\'' + - ", timesDropped=" + timesCaught + - ", totalAmount=" + totalAmount + - ", hidden=" + hidden + - '}' + "internalName='" + internalName + '\'' + + ", timesDropped=" + timesCaught + + ", totalAmount=" + totalAmount + + ", hidden=" + hidden + + '}' var lastTimeUpdated = SimpleTimeMark.farPast() } @@ -102,8 +112,9 @@ object FishingProfitTracker { itemProfit.timesCaught } else amount - val cleanName = if (internalName == SKYBLOCK_COIN) "§6Coins" else internalName.getItemName() - var name = cleanName + val cleanName = + if (internalName == SKYBLOCK_COIN) "§6Coins" else internalName.getItemStack().nameWithEnchantment + var name = cleanName ?: error("no name for $internalName") val priceFormat = NumberUtil.format(price) val hidden = itemProfit.hidden @@ -211,7 +222,9 @@ object FishingProfitTracker { fun onItemAdd(event: ItemAddInInventoryEvent) { if (!isEnabled()) return - maybeAddItem(event.internalName, event.amount) + DelayedRun.runDelayed(500.milliseconds) { + maybeAddItem(event.internalName, event.amount) + } } @SubscribeEvent @@ -235,6 +248,28 @@ object FishingProfitTracker { } @SubscribeEvent + fun onItemInHandChange(event: ItemInHandChangeEvent) { + if (event.oldItem.isFishingRod()) { + lastFishingTime = SimpleTimeMark.now() + } + if (event.newItem.isFishingRod()) { + DelayedRun.runDelayed(1.seconds) { + lastFishingTime = SimpleTimeMark.now() + } + } + } + + @SubscribeEvent + fun onSkillExpGain(event: SkillExpGainEvent) { + val skill = event.skill + if (isEnabled()) { + if (skill != "fishing") { + lastFishingTime = SimpleTimeMark.farPast() + } + } + } + + @SubscribeEvent fun onRenderOverlay(event: GuiRenderEvent) { if (!isEnabled()) return if (!FishingAPI.hasFishingRodInHand()) return @@ -244,6 +279,8 @@ object FishingProfitTracker { } private fun maybeAddItem(internalName: NEUInternalName, amount: Int) { + if (lastFishingTime.passedSince() > 10.minutes) return + if (!isAllowedItem(internalName)) { LorenzUtils.debug("Ignored non-fishing item pickup: $internalName'") return @@ -252,23 +289,69 @@ object FishingProfitTracker { addItem(internalName, amount) } - private var itemCategories = mutableMapOf<String, List<NEUInternalName>>() + private var itemCategories = mapOf<String, List<NEUInternalName>>() + + private var shItemCategories = mapOf<String, List<NEUInternalName>>() + private var neuItemCategories = mapOf<String, List<NEUInternalName>>() @SubscribeEvent fun onRepoReload(event: RepositoryReloadEvent) { - itemCategories = event.getConstant<FishingProfitItemsJson>("FishingProfitItems").categories + shItemCategories = event.getConstant<FishingProfitItemsJson>("FishingProfitItems").categories + updateItemCategories() } - private fun isAllowedItem(internalName: NEUInternalName): Boolean { - for ((name, items) in itemCategories) { - if (internalName in items) { - return true + private fun updateItemCategories() { + itemCategories = shItemCategories + neuItemCategories + } + + @SubscribeEvent + fun onNeuRepoReload(event: io.github.moulberry.notenoughupdates.events.RepositoryReloadEvent) { + val totalDrops = mutableListOf<String>() + val dropCategories = mutableMapOf<String, MutableList<NEUInternalName>>() + for ((seaCreature, data) in NotEnoughUpdates.INSTANCE.manager.itemInformation.filter { it.key.endsWith("_SC") }) { + val asJsonObject = data.getAsJsonArray("recipes")[0].asJsonObject + val drops = asJsonObject.getAsJsonArray("drops") + .map { it.asJsonObject.get("id").asString }.map { it.split(":").first() } + val asJsonArray = asJsonObject.get("extra") + val extra = asJsonArray?.let { + asJsonArray.asJsonArray.toList() + .map { it.toString() } + .filter { !it.contains("Fishing Skill") && !it.contains("Requirements:") && !it.contains("Fished from water") } + .joinToString(" + ") + } ?: "null" + val category = if (extra.contains("Fishing Festival")) { + "Fishing Festival" + } else if (extra.contains("Spooky Festival")) { + "Spooky Festival" + } else if (extra.contains("Jerry's Workshop")) { + "Jerry's Workshop" + } else if (extra.contains("Oasis")) { + "Oasis" + } else if (extra.contains("Magma Fields") || extra.contains("Precursor Remnants") || + extra.contains("Goblin Holdout") + ) { + "Crystal Hollows" + } else if (extra.contains("Crimson Isle Lava")) { + "Crimson Isle Lava" + } else { + if (extra.isNotEmpty()) { + println("unknown extra: $extra = $seaCreature ($drops)") + } + "Water" + } + " Sea Creatures" + for (drop in drops) { + if (drop !in totalDrops) { + totalDrops.add(drop) + dropCategories.getOrPut(category) { mutableListOf() }.add(drop.asInternalName()) + } } } - - return false + neuItemCategories = dropCategories + updateItemCategories() } + private fun isAllowedItem(internalName: NEUInternalName) = itemCategories.any { internalName in it.value } + private fun getPrice(internalName: NEUInternalName) = when (config.priceFrom) { 0 -> internalName.getBazaarData()?.sellPrice ?: internalName.getPriceOrNull() ?: 0.0 1 -> internalName.getBazaarData()?.buyPrice ?: internalName.getPriceOrNull() ?: 0.0 diff --git a/src/main/java/at/hannibal2/skyhanni/utils/DelayedRun.kt b/src/main/java/at/hannibal2/skyhanni/utils/DelayedRun.kt new file mode 100644 index 000000000..0fa9152cd --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/utils/DelayedRun.kt @@ -0,0 +1,21 @@ +package at.hannibal2.skyhanni.utils + +import kotlin.time.Duration + +object DelayedRun { + val map = mutableMapOf<() -> Any, SimpleTimeMark>() + + fun runDelayed(duration: Duration, run: () -> Unit) { + map[run] = SimpleTimeMark.now() + duration + } + + fun checkRuns() { + map.entries.removeIf { (runnable, time) -> + val inPast = time.isInPast() + if (inPast) { + runnable() + } + inPast + } + } +} |