From 175379be77dd530bc019e34d3937950df22e4f8a Mon Sep 17 00:00:00 2001 From: Linnea Gräf Date: Thu, 19 Dec 2024 22:13:32 +0100 Subject: feat: Items bought for other items at NPCs --- src/main/kotlin/moe/nea/ledger/ItemChange.kt | 1 + src/main/kotlin/moe/nea/ledger/ItemIdProvider.kt | 16 ++++++-- src/main/kotlin/moe/nea/ledger/ItemUtil.kt | 22 ++++++++++- .../kotlin/moe/nea/ledger/modules/NpcDetection.kt | 46 +++++++++++++++++++++- 4 files changed, 79 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/moe/nea/ledger/ItemChange.kt b/src/main/kotlin/moe/nea/ledger/ItemChange.kt index 186a4e3..fda709c 100644 --- a/src/main/kotlin/moe/nea/ledger/ItemChange.kt +++ b/src/main/kotlin/moe/nea/ledger/ItemChange.kt @@ -59,6 +59,7 @@ data class ItemChange( } fun unpairGain(pair: Pair) = unpair(ChangeDirection.GAINED, pair) + fun unpairLose(pair: Pair) = unpair(ChangeDirection.LOST, pair) fun gain(itemId: ItemId, amount: Number): ItemChange { return ItemChange(itemId, amount.toDouble(), ChangeDirection.GAINED) diff --git a/src/main/kotlin/moe/nea/ledger/ItemIdProvider.kt b/src/main/kotlin/moe/nea/ledger/ItemIdProvider.kt index 30610e9..72f1d09 100644 --- a/src/main/kotlin/moe/nea/ledger/ItemIdProvider.kt +++ b/src/main/kotlin/moe/nea/ledger/ItemIdProvider.kt @@ -29,16 +29,24 @@ class ItemIdProvider { private val knownNames = mutableMapOf() + fun createLookupTagFromDisplayName(itemName: String): String { + return itemName.unformattedString().trim().lowercase() + } + + fun saveKnownItem(itemName: String, itemId: ItemId) { + knownNames[createLookupTagFromDisplayName(itemName)] = itemId + } + @SubscribeEvent fun onDataLoaded(event: ExternalDataProvider.DataLoaded) { event.provider.itemNames.forEach { (itemId, itemName) -> - knownNames[itemName.unformattedString().trim()] = ItemId(itemId) + saveKnownItem(itemName, ItemId(itemId)) } } @SubscribeEvent fun onRegistrationFinished(event: RegistrationFinishedEvent) { - MinecraftForge.EVENT_BUS.post(ExtraSupplyIdEvent(knownNames::put)) + MinecraftForge.EVENT_BUS.post(ExtraSupplyIdEvent(::saveKnownItem)) } @SubscribeEvent(priority = EventPriority.HIGH) @@ -63,7 +71,7 @@ class ItemIdProvider { name = name.trim() val id = stack.getInternalId() if (id != null && name.isNotBlank()) { - knownNames[name] = id + saveKnownItem(name, id) } } @@ -84,7 +92,7 @@ class ItemIdProvider { // TODO: make use of colour fun findForName(name: String, fallbackToGenerated: Boolean = true): ItemId? { - var id = knownNames[name] + var id = knownNames[createLookupTagFromDisplayName(name)] if (id == null && fallbackToGenerated) { id = generateName(name) } diff --git a/src/main/kotlin/moe/nea/ledger/ItemUtil.kt b/src/main/kotlin/moe/nea/ledger/ItemUtil.kt index 949f58a..a3d8162 100644 --- a/src/main/kotlin/moe/nea/ledger/ItemUtil.kt +++ b/src/main/kotlin/moe/nea/ledger/ItemUtil.kt @@ -1,5 +1,6 @@ package moe.nea.ledger +import net.minecraft.inventory.IInventory import net.minecraft.item.ItemStack import net.minecraft.nbt.NBTTagCompound @@ -37,7 +38,10 @@ class PetInfo { fun ItemStack.getPetId(): String? { val petInfoStr = getExtraAttributes().getString("petInfo") - val petInfo = runCatching { Ledger.gson.fromJson(petInfoStr, PetInfo::class.java) }.getOrNull() // TODO: error reporting to sentry + val petInfo = runCatching { + Ledger.gson.fromJson(petInfoStr, + PetInfo::class.java) + }.getOrNull() // TODO: error reporting to sentry if (petInfo?.type == null || petInfo.tier == null) return null return petInfo.type + ";" + rarityToIndex(petInfo.tier ?: "") } @@ -62,6 +66,22 @@ fun ItemStack.getLore(): List { } +fun IInventory.asIterable(): Iterable = object : Iterable { + override fun iterator(): Iterator { + return object : Iterator { + var i = 0 + override fun hasNext(): Boolean { + return i < this@asIterable.sizeInventory + } + + override fun next(): ItemStack? { + if (!hasNext()) throw NoSuchElementException("$i is out of range for inventory ${this@asIterable}") + return this@asIterable.getStackInSlot(i++) + } + } + } +} + fun ItemStack.getDisplayNameU(): String { val nbt = this.tagCompound ?: NBTTagCompound() val extraAttributes = nbt.getCompoundTag("display") diff --git a/src/main/kotlin/moe/nea/ledger/modules/NpcDetection.kt b/src/main/kotlin/moe/nea/ledger/modules/NpcDetection.kt index 5906562..c17cdc8 100644 --- a/src/main/kotlin/moe/nea/ledger/modules/NpcDetection.kt +++ b/src/main/kotlin/moe/nea/ledger/modules/NpcDetection.kt @@ -7,9 +7,16 @@ import moe.nea.ledger.LedgerEntry import moe.nea.ledger.LedgerLogger import moe.nea.ledger.SHORT_NUMBER_PATTERN import moe.nea.ledger.TransactionType +import moe.nea.ledger.asIterable +import moe.nea.ledger.events.BeforeGuiAction import moe.nea.ledger.events.ChatReceived +import moe.nea.ledger.getDisplayNameU +import moe.nea.ledger.getInternalId +import moe.nea.ledger.getLore import moe.nea.ledger.parseShortNumber +import moe.nea.ledger.unformattedString import moe.nea.ledger.useMatcher +import moe.nea.ledger.utils.ErrorUtil import moe.nea.ledger.utils.di.Inject import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import java.util.regex.Pattern @@ -21,7 +28,44 @@ class NpcDetection @Inject constructor(val ledger: LedgerLogger, val ids: ItemId val npcSellPattern = Pattern.compile("You sold (?.*) (x(?$SHORT_NUMBER_PATTERN) )?for (?$SHORT_NUMBER_PATTERN) Coins?!") - // TODO: IMPROVE BUYING FROM NPC TO INCLUDE ITEMS OTHER THAN COINS (KUUDRA KEYS ARE CHEAP) + // You bought InfiniDirt™ Wand! + // You bought Prismapump x4! + val npcBuyWithItemPattern = + "You bought (?.*?)!".toPattern() + var storedPurchases = mutableMapOf>() + + @SubscribeEvent + fun onClick(event: BeforeGuiAction) { + (event.chestSlots?.lowerChestInventory?.asIterable() ?: listOf()) + .filterNotNull().forEach { + val name = it.getDisplayNameU().unformattedString() + val id = it.getInternalId() ?: return@forEach + val count = it.stackSize + val cost = ids.findCostItemsFromSpan(it.getLore()) + storedPurchases[name] = listOf(ItemChange.gain(id, count)) + cost.map { ItemChange.unpairLose(it) } + } + } + + @Inject + lateinit var errorUtil: ErrorUtil + + @SubscribeEvent + fun onBarteredItemBought(event: ChatReceived) { + npcBuyWithItemPattern.useMatcher(event.message) { + val changes = storedPurchases[group("what")] + if (changes == null) { + errorUtil.reportAdHoc("Item bought for items without associated cost") + } + storedPurchases.clear() + ledger.logEntry( + LedgerEntry( + TransactionType.NPC_BUY, + event.timestamp, + changes ?: listOf() + ) + ) + } + } @SubscribeEvent fun onNpcBuy(event: ChatReceived) { -- cgit