diff options
Diffstat (limited to 'src/main/java/at/hannibal2/skyhanni/data/SackAPI.kt')
-rw-r--r-- | src/main/java/at/hannibal2/skyhanni/data/SackAPI.kt | 291 |
1 files changed, 289 insertions, 2 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/data/SackAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/SackAPI.kt index 3990e13d6..4534e49a5 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/SackAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/SackAPI.kt @@ -1,13 +1,192 @@ package at.hannibal2.skyhanni.data +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.events.InventoryCloseEvent +import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent import at.hannibal2.skyhanni.events.LorenzChatEvent import at.hannibal2.skyhanni.events.SackChangeEvent +import at.hannibal2.skyhanni.features.fishing.trophy.TrophyFishManager +import at.hannibal2.skyhanni.features.fishing.trophy.TrophyRarity +import at.hannibal2.skyhanni.features.inventory.SackDisplay +import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName +import at.hannibal2.skyhanni.utils.ItemUtils.getLore +import at.hannibal2.skyhanni.utils.ItemUtils.name +import at.hannibal2.skyhanni.utils.LorenzUtils.editCopy import at.hannibal2.skyhanni.utils.NEUInternalName +import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName +import at.hannibal2.skyhanni.utils.NEUItems.getNpcPriceOrNull +import at.hannibal2.skyhanni.utils.NEUItems.getPrice +import at.hannibal2.skyhanni.utils.NumberUtil.formatNumber +import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher import at.hannibal2.skyhanni.utils.StringUtils.removeColor +import com.google.gson.annotations.Expose +import net.minecraft.item.ItemStack import net.minecraftforge.fml.common.eventhandler.SubscribeEvent -class SackAPI { +object SackAPI { + private val sackDisplayConfig get() = SkyHanniMod.feature.inventory.sackDisplay + private var lastOpenedInventory = "" + + var inSackInventory = false + private val sackPattern = "^(.* Sack|Enchanted .* Sack)$".toPattern() + private val numPattern = + "(?:(?:§[0-9a-f](?<level>I{1,3})§7:)?|(?:§7Stored:)?) (?<color>§[0-9a-f])(?<stored>[0-9.,kKmMbB]+)§7/(?<total>\\d+(?:[0-9.,]+)?[kKmMbB]?)".toPattern() + private val gemstonePattern = + " §[0-9a-f](?<gemrarity>[A-z]*): §[0-9a-f](?<stored>\\d+(?:\\.\\d+)?(?:(?:,\\d+)?)+[kKmM]?)(?: §[0-9a-f]\\(\\d+(?:\\.\\d+)?(?:(?:,\\d+)?)+[kKmM]?\\))?".toPattern() + + private var isRuneSack = false + private var isGemstoneSack = false + var isTrophySack = false + private var sackRarity: TrophyRarity? = null + + val sackItem = mutableMapOf<String, SackOtherItem>() + val runeItem = mutableMapOf<String, SackRune>() + val gemstoneItem = mutableMapOf<String, SackGemstone>() + private val stackList = mutableMapOf<Int, ItemStack>() + + @SubscribeEvent + fun onInventoryClose(event: InventoryCloseEvent) { + inSackInventory = false + isRuneSack = false + isGemstoneSack = false + isTrophySack = false + runeItem.clear() + gemstoneItem.clear() + sackItem.clear() + stackList.clear() + } + + @SubscribeEvent + fun onInventoryOpen(event: InventoryFullyOpenedEvent) { + val inventoryName = event.inventoryName + val isNewInventory = inventoryName != lastOpenedInventory + lastOpenedInventory = inventoryName + val match = sackPattern.matcher(inventoryName).matches() + if (!match) return + val stacks = event.inventoryItems + isRuneSack = inventoryName == "Runes Sack" + isGemstoneSack = inventoryName == "Gemstones Sack" + isTrophySack = inventoryName.contains("Trophy Fishing Sack") + sackRarity = inventoryName.getTrophyRarity() + inSackInventory = true + stackList.putAll(stacks) + SackDisplay.update(isNewInventory) + } + + private fun String.getTrophyRarity(): TrophyRarity? { + return if (this.startsWith("Bronze")) + TrophyRarity.BRONZE + else + if (this.startsWith("Silver")) + TrophyRarity.SILVER + else null + } + + private fun NEUInternalName.sackPrice(stored: String) = when (sackDisplayConfig.priceFrom) { + 0 -> (getPrice(true) * stored.formatNumber()).toInt().let { if (it < 0) 0 else it } + + 1 -> try { + val npcPrice = getNpcPriceOrNull() ?: 0.0 + (npcPrice * stored.formatNumber()).toInt() + } catch (e: Exception) { + 0 + } + + else -> 0 + } + + fun getSacksData(savingSacks: Boolean) { + if (savingSacks) sackData = ProfileStorageData.sackProfiles?.sackContents ?: return + for ((_, stack) in stackList) { + val name = stack.name ?: continue + val lore = stack.getLore() + val gem = SackGemstone() + val rune = SackRune() + val item = SackOtherItem() + loop@ for (line in lore) { + if (isGemstoneSack) { + gemstonePattern.matchMatcher(line) { + val rarity = group("gemrarity") + val stored = group("stored") + gem.internalName = gemstoneMap[name.removeColor()] ?: NEUInternalName.NONE + if (gemstoneMap.containsKey(name.removeColor())) { + val internalName = "${rarity.uppercase()}_${ + name.uppercase().split(" ")[0].removeColor() + }_GEM".asInternalName() + + when (rarity) { + "Rough" -> { + gem.rough = stored + gem.roughPrice = internalName.sackPrice(stored) + if (savingSacks) setSackItem(internalName, stored.formatNumber().toInt()) + } + + "Flawed" -> { + gem.flawed = stored + gem.flawedPrice = internalName.sackPrice(stored) + if (savingSacks) setSackItem(internalName, stored.formatNumber().toInt()) + } + + "Fine" -> { + gem.fine = stored + gem.finePrice = internalName.sackPrice(stored) + if (savingSacks) setSackItem(internalName, stored.formatNumber().toInt()) + } + + "Flawless" -> { + gem.flawless = stored + gem.flawlessPrice = internalName.sackPrice(stored) + if (savingSacks) setSackItem(internalName, stored.formatNumber().toInt()) + } + } + gemstoneItem[name] = gem + } + } + } else { + numPattern.matchMatcher(line) { + val stored = group("stored") + val internalName = stack.getInternalName() + item.internalName = internalName + item.colorCode = group("color") + item.stored = stored + item.total = group("total") + if (savingSacks) setSackItem(item.internalName, item.stored.formatNumber().toInt()) + item.price = if (isTrophySack) { + val trophyName = + internalName.asString().lowercase().substringBeforeLast("_").replace("_", "") + val filletValue = + TrophyFishManager.getInfoByName(trophyName)?.getFilletValue(sackRarity!!) ?: 0 + val storedNumber = stored.formatNumber().toInt() + "MAGMA_FISH".asInternalName().sackPrice((filletValue * storedNumber).toString()) + } else internalName.sackPrice(stored).coerceAtLeast(0) + + if (isRuneSack) { + val level = group("level") + rune.stack = stack + if (level == "I") { + rune.lvl1 = stored + continue@loop + } + if (level == "II") { + rune.lvl2 = stored + continue@loop + } + if (level == "III") { + rune.lvl3 = stored + } + runeItem.put(name, rune) + } else { + sackItem.put(name, item) + } + } + } + } + } + if (savingSacks) saveSackData() + } + + private var sackData = mapOf<NEUInternalName, SackItem>() data class SackChange(val delta: Int, val internalName: NEUInternalName, val sacks: List<String>) @@ -16,7 +195,7 @@ class SackAPI { @SubscribeEvent fun onChat(event: LorenzChatEvent) { if (!event.message.removeColor().startsWith("[Sacks]")) return - + val sackAddText = event.chatComponent.siblings.firstNotNullOfOrNull { sibling -> sibling.chatStyle?.chatHoverEvent?.value?.formattedText?.removeColor()?.takeIf { it.startsWith("Added") @@ -45,4 +224,112 @@ class SackAPI { } SackChangeEvent(sackChanges, otherItemsAdded, otherItemsRemoved).postAndCatch() } + + @SubscribeEvent + fun sackChange(event: SackChangeEvent) { + sackData = ProfileStorageData.sackProfiles?.sackContents ?: return + + // if it gets added and subtracted but only 1 shows it will be outdated + val justChanged = mutableMapOf<NEUInternalName, Int>() + + for (change in event.sackChanges) { + if (change.internalName in justChanged) { + justChanged[change.internalName] = (justChanged[change.internalName] ?: 0) + change.delta + } else { + justChanged[change.internalName] = change.delta + } + } + + for (item in justChanged) { + if (sackData.containsKey(item.key)) { + val oldData = sackData[item.key] + var newAmount = oldData!!.amount + item.value + var changed = newAmount - oldData.amount + if (newAmount < 0) { + newAmount = 0 + changed = 0 + } + sackData = sackData.editCopy { this[item.key] = SackItem(newAmount, changed, oldData.outdatedStatus) } + } else { + val newAmount = if (item.value > 0) item.value else 0 + sackData = sackData.editCopy { this[item.key] = SackItem(newAmount, newAmount, 2) } + } + } + + if (event.otherItemsAdded || event.otherItemsRemoved) { + for (item in sackData) { + if (item.key in justChanged) continue + val oldData = sackData[item.key] + sackData = sackData.editCopy { this[item.key] = SackItem(oldData!!.amount, 0, 1) } + } + } + saveSackData() + } + + private fun setSackItem(item: NEUInternalName, amount: Int) { + sackData = sackData.editCopy { this[item] = SackItem(amount, 0, 0) } + } + + fun fetchSackItem(item: NEUInternalName): SackItem? { + sackData = ProfileStorageData.sackProfiles?.sackContents ?: return SackItem(0, 0, -1) + + if (sackData.containsKey(item)) { + return sackData[item] + } + + sackData = sackData.editCopy { this[item] = SackItem(0, 0, 2) } + return sackData[item] + } + + private fun saveSackData() { + ProfileStorageData.sackProfiles?.sackContents = sackData + SkyHanniMod.configManager.saveSackData("shutdown-hook") + } + + data class SackGemstone( + var internalName: NEUInternalName = NEUInternalName.NONE, + var rough: String = "0", + var flawed: String = "0", + var fine: String = "0", + var flawless: String = "0", + var roughPrice: Int = 0, + var flawedPrice: Int = 0, + var finePrice: Int = 0, + var flawlessPrice: Int = 0, + ) + + data class SackRune( + var stack: ItemStack? = null, + var lvl1: String = "0", + var lvl2: String = "0", + var lvl3: String = "0", + ) + + data class SackOtherItem( + var internalName: NEUInternalName = NEUInternalName.NONE, + var colorCode: String = "", + var stored: String = "0", + var total: String = "0", + var price: Int = 0, + ) } + +// status -1 = fetching data failed, 0 = < 1% of being wrong, 1 = 10% of being wrong, 2 = is 100% wrong +// lastChange is set to 0 when value is refreshed in the sacks gui and when being set initially +// if it didn't change in an update the lastChange value will stay the same and not be set to 0 +data class SackItem( + @Expose val amount: Int, + @Expose val lastChange: Int, + @Expose val outdatedStatus: Int +) + +private val gemstoneMap = mapOf( + "Jade Gemstones" to "ROUGH_JADE_GEM".asInternalName(), + "Amber Gemstones" to "ROUGH_AMBER_GEM".asInternalName(), + "Topaz Gemstones" to "ROUGH_TOPAZ_GEM".asInternalName(), + "Sapphire Gemstones" to "ROUGH_SAPPHIRE_GEM".asInternalName(), + "Amethyst Gemstones" to "ROUGH_AMETHYST_GEM".asInternalName(), + "Jasper Gemstones" to "ROUGH_JASPER_GEM".asInternalName(), + "Ruby Gemstones" to "ROUGH_RUBY_GEM".asInternalName(), + "Opal Gemstones" to "ROUGH_OPAL_GEM".asInternalName(), +) |