aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLinnea Gräf <nea@nea.moe>2024-12-07 21:18:21 +0100
committerLinnea Gräf <nea@nea.moe>2024-12-07 21:18:21 +0100
commit6955c99b2e241cf7e4070424e8dbf29f80bb63fd (patch)
tree5abb4d0474cac2c579902e4bbf0266cdce0efaa0 /src
parente3ace3c1b781b8d07f8eca60ba90df35da6c9d21 (diff)
downloadLocalTransactionLedger-6955c99b2e241cf7e4070424e8dbf29f80bb63fd.tar.gz
LocalTransactionLedger-6955c99b2e241cf7e4070424e8dbf29f80bb63fd.tar.bz2
LocalTransactionLedger-6955c99b2e241cf7e4070424e8dbf29f80bb63fd.zip
feat: Add kat upgrade and flower detection
Diffstat (limited to 'src')
-rw-r--r--src/main/kotlin/moe/nea/ledger/ItemIdProvider.kt67
-rw-r--r--src/main/kotlin/moe/nea/ledger/ItemUtil.kt53
-rw-r--r--src/main/kotlin/moe/nea/ledger/Ledger.kt19
-rw-r--r--src/main/kotlin/moe/nea/ledger/LedgerLogger.kt2
-rw-r--r--src/main/kotlin/moe/nea/ledger/events/BeforeGuiAction.kt7
-rw-r--r--src/main/kotlin/moe/nea/ledger/modules/KatDetection.kt100
6 files changed, 212 insertions, 36 deletions
diff --git a/src/main/kotlin/moe/nea/ledger/ItemIdProvider.kt b/src/main/kotlin/moe/nea/ledger/ItemIdProvider.kt
index 43f2cb7..f582015 100644
--- a/src/main/kotlin/moe/nea/ledger/ItemIdProvider.kt
+++ b/src/main/kotlin/moe/nea/ledger/ItemIdProvider.kt
@@ -1,11 +1,12 @@
package moe.nea.ledger
import moe.nea.ledger.events.BeforeGuiAction
-import net.minecraft.client.gui.inventory.GuiChest
-import net.minecraft.inventory.ContainerChest
+import net.minecraft.client.Minecraft
+import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import net.minecraftforge.client.event.GuiScreenEvent
import net.minecraftforge.common.MinecraftForge
+import net.minecraftforge.fml.common.eventhandler.EventPriority
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import org.lwjgl.input.Mouse
@@ -24,24 +25,39 @@ class ItemIdProvider {
private val knownNames = mutableMapOf<String, ItemId>()
- @SubscribeEvent
- fun saveInventoryIds(event: BeforeGuiAction) {
- val chest = (event.gui as? GuiChest) ?: return
- val slots = chest.inventorySlots as ContainerChest
+ @SubscribeEvent(priority = EventPriority.HIGH)
+ fun savePlayerInventoryIds(event: BeforeGuiAction) {
+ val player = Minecraft.getMinecraft().thePlayer ?: return
+ val inventory = player.inventory ?: return
+ inventory.mainInventory?.forEach { saveFromSlot(it) }
+ inventory.armorInventory?.forEach { saveFromSlot(it) }
+ }
+
+ fun saveFromSlot(stack: ItemStack?, preprocessName: (String) -> String = { it }) {
+ if (stack == null) return
+ val nbt = stack.tagCompound ?: NBTTagCompound()
+ val display = nbt.getCompoundTag("display")
+ var name = display.getString("Name").unformattedString()
+ name = preprocessName(name)
+ name = name.trim()
+ val id = stack.getInternalId()
+ if (id != null && name.isNotBlank()) {
+ knownNames[name] = id
+ }
+ }
+
+ @SubscribeEvent(priority = EventPriority.HIGH)
+ fun saveChestInventoryIds(event: BeforeGuiAction) {
+ val slots = event.chestSlots ?: return
val chestName = slots.lowerChestInventory.name.unformattedString()
val isOrderMenu = chestName == "Your Bazaar Orders" || chestName == "Co-op Bazaar Orders"
+ val preprocessor: (String) -> String = if (isOrderMenu) {
+ { it.removePrefix("BUY ").removePrefix("SELL ") }
+ } else {
+ { it }
+ }
slots.inventorySlots.forEach {
- val stack = it.stack ?: return@forEach
- val nbt = stack.tagCompound ?: NBTTagCompound()
- val display = nbt.getCompoundTag("display")
- var name = display.getString("Name").unformattedString()
- if (isOrderMenu)
- name = name.removePrefix("BUY ").removePrefix("SELL ")
- name = name.trim()
- val id = stack.getInternalId()
- if (id != null && name.isNotBlank()) {
- knownNames[name] = id
- }
+ saveFromSlot(it?.stack, preprocessor)
}
}
@@ -49,4 +65,21 @@ class ItemIdProvider {
return knownNames[name]
}
+ private val coinRegex = "(?<amount>$SHORT_NUMBER_PATTERN) Coins?".toPattern()
+ private val stackedItem = "(?<name>.*) x(?<count>$SHORT_NUMBER_PATTERN)".toPattern()
+
+ fun findFromLore(name: String): Pair<ItemId, Double>? {
+ val properName = name.unformattedString()
+ coinRegex.useMatcher(properName) {
+ return Pair(ItemId.COINS, parseShortNumber(group("amount")))
+ }
+ stackedItem.useMatcher(properName) {
+ val item = findForName(group("name"))
+ if (item != null) {
+ val count = parseShortNumber(group("count"))
+ return Pair(item, count)
+ }
+ }
+ return findForName(properName)?.let { Pair(it, 1.0) }
+ }
} \ No newline at end of file
diff --git a/src/main/kotlin/moe/nea/ledger/ItemUtil.kt b/src/main/kotlin/moe/nea/ledger/ItemUtil.kt
index b82c97f..38c2b50 100644
--- a/src/main/kotlin/moe/nea/ledger/ItemUtil.kt
+++ b/src/main/kotlin/moe/nea/ledger/ItemUtil.kt
@@ -4,25 +4,56 @@ import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
+fun ItemStack.getExtraAttributes(): NBTTagCompound {
+ val nbt = this.tagCompound ?: return NBTTagCompound()
+ return nbt.getCompoundTag("ExtraAttributes")
+}
+
fun ItemStack.getInternalId(): ItemId? {
- val nbt = this.tagCompound ?: NBTTagCompound()
- val extraAttributes = nbt.getCompoundTag("ExtraAttributes")
- val id = extraAttributes.getString("id")
- return id.takeIf { it.isNotBlank() }?.let(::ItemId)
+ val extraAttributes = getExtraAttributes()
+ var id = extraAttributes.getString("id")
+ id = id.takeIf { it.isNotBlank() }
+ if (id == "PET") {
+ id = getPetId() ?: id
+ }
+ return id?.let(::ItemId)
+}
+
+class PetInfo {
+ var type: String? = null
+ var tier: String? = null
}
+fun ItemStack.getPetId(): String? {
+ val petInfoStr = getExtraAttributes().getString("petInfo")
+ val petInfo = Ledger.gson.fromJson(petInfoStr, PetInfo::class.java)
+ if (petInfo.type == null || petInfo.tier == null) return null
+ return petInfo.type + ";" + rarityToIndex(petInfo.tier ?: "")
+}
+
+fun rarityToIndex(rarity: String): Int {
+ return when (rarity) {
+ "COMMON" -> 0
+ "UNCOMMON" -> 1
+ "RARE" -> 2
+ "EPIC" -> 3
+ "LEGENDARY" -> 4
+ "MYTHIC" -> 5
+ else -> -1
+ }
+}
fun ItemStack.getLore(): List<String> {
- val nbt = this.tagCompound ?: NBTTagCompound()
- val extraAttributes = nbt.getCompoundTag("display")
- val lore = extraAttributes.getTagList("Lore", 8)
- return (0 until lore.tagCount()).map { lore.getStringTagAt(it) }
+ val nbt = this.tagCompound ?: NBTTagCompound()
+ val extraAttributes = nbt.getCompoundTag("display")
+ val lore = extraAttributes.getTagList("Lore", 8)
+ return (0 until lore.tagCount()).map { lore.getStringTagAt(it) }
}
fun ItemStack.getDisplayNameU(): String {
- val nbt = this.tagCompound ?: NBTTagCompound()
- val extraAttributes = nbt.getCompoundTag("display")
- return extraAttributes.getString("Name")
+ val nbt = this.tagCompound ?: NBTTagCompound()
+ val extraAttributes = nbt.getCompoundTag("display")
+ return extraAttributes.getString("Name")
}
diff --git a/src/main/kotlin/moe/nea/ledger/Ledger.kt b/src/main/kotlin/moe/nea/ledger/Ledger.kt
index cfbab1c..8a4b850 100644
--- a/src/main/kotlin/moe/nea/ledger/Ledger.kt
+++ b/src/main/kotlin/moe/nea/ledger/Ledger.kt
@@ -1,5 +1,6 @@
package moe.nea.ledger
+import com.google.gson.Gson
import io.github.notenoughupdates.moulconfig.managed.ManagedConfig
import moe.nea.ledger.config.LedgerConfig
import moe.nea.ledger.database.Database
@@ -12,6 +13,7 @@ import moe.nea.ledger.modules.BazaarOrderDetection
import moe.nea.ledger.modules.BitsDetection
import moe.nea.ledger.modules.BitsShopDetection
import moe.nea.ledger.modules.DungeonChestDetection
+import moe.nea.ledger.modules.KatDetection
import moe.nea.ledger.modules.MinionDetection
import moe.nea.ledger.modules.NpcDetection
import moe.nea.ledger.utils.DI
@@ -71,6 +73,7 @@ class Ledger {
val managedConfig = ManagedConfig.create(File("config/money-ledger/config.json"), LedgerConfig::class.java) {
checkExpose = false
}
+ val gson = Gson()
private val tickQueue = ConcurrentLinkedQueue<Runnable>()
fun runLater(runnable: Runnable) {
tickQueue.add(runnable)
@@ -84,21 +87,23 @@ class Ledger {
val di = DI()
di.registerSingleton(this)
di.registerInjectableClasses(
- LedgerLogger::class.java,
- ItemIdProvider::class.java,
+ AuctionHouseDetection::class.java,
BankDetection::class.java,
BazaarDetection::class.java,
- DungeonChestDetection::class.java,
BazaarOrderDetection::class.java,
- AuctionHouseDetection::class.java,
BitsDetection::class.java,
BitsShopDetection::class.java,
+ ConfigCommand::class.java,
+ Database::class.java,
+ DungeonChestDetection::class.java,
+ ItemIdProvider::class.java,
+ KatDetection::class.java,
+ LedgerLogger::class.java,
+ LogChatCommand::class.java,
MinionDetection::class.java,
NpcDetection::class.java,
- LogChatCommand::class.java,
- ConfigCommand::class.java,
- Database::class.java
)
+ di.registerSingleton(gson)
di.instantiateAll()
di.getAllInstances().forEach(MinecraftForge.EVENT_BUS::register)
di.getAllInstances().filterIsInstance<ICommand>()
diff --git a/src/main/kotlin/moe/nea/ledger/LedgerLogger.kt b/src/main/kotlin/moe/nea/ledger/LedgerLogger.kt
index 045c6b1..76b8741 100644
--- a/src/main/kotlin/moe/nea/ledger/LedgerLogger.kt
+++ b/src/main/kotlin/moe/nea/ledger/LedgerLogger.kt
@@ -146,6 +146,8 @@ enum class TransactionType {
BOOSTER_COOKIE_ATE,
COMMUNITY_SHOP_BUY,
DUNGEON_CHEST_OPEN,
+ KAT_TIMESKIP,
+ KAT_UPGRADE,
KISMET_REROLL,
NPC_BUY,
NPC_SELL,
diff --git a/src/main/kotlin/moe/nea/ledger/events/BeforeGuiAction.kt b/src/main/kotlin/moe/nea/ledger/events/BeforeGuiAction.kt
index 69362bd..098912a 100644
--- a/src/main/kotlin/moe/nea/ledger/events/BeforeGuiAction.kt
+++ b/src/main/kotlin/moe/nea/ledger/events/BeforeGuiAction.kt
@@ -1,6 +1,11 @@
package moe.nea.ledger.events
import net.minecraft.client.gui.GuiScreen
+import net.minecraft.client.gui.inventory.GuiChest
+import net.minecraft.inventory.ContainerChest
import net.minecraftforge.fml.common.eventhandler.Event
-data class BeforeGuiAction(val gui: GuiScreen) : Event()
+data class BeforeGuiAction(val gui: GuiScreen) : Event() {
+ val chest = gui as? GuiChest
+ val chestSlots = chest?.inventorySlots as ContainerChest?
+}
diff --git a/src/main/kotlin/moe/nea/ledger/modules/KatDetection.kt b/src/main/kotlin/moe/nea/ledger/modules/KatDetection.kt
new file mode 100644
index 0000000..8a2aa19
--- /dev/null
+++ b/src/main/kotlin/moe/nea/ledger/modules/KatDetection.kt
@@ -0,0 +1,100 @@
+package moe.nea.ledger.modules
+
+import moe.nea.ledger.ItemChange
+import moe.nea.ledger.ItemId
+import moe.nea.ledger.ItemIdProvider
+import moe.nea.ledger.LedgerEntry
+import moe.nea.ledger.LedgerLogger
+import moe.nea.ledger.TransactionType
+import moe.nea.ledger.events.BeforeGuiAction
+import moe.nea.ledger.events.ChatReceived
+import moe.nea.ledger.getInternalId
+import moe.nea.ledger.getLore
+import moe.nea.ledger.unformattedString
+import moe.nea.ledger.useMatcher
+import moe.nea.ledger.utils.Inject
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+
+
+class KatDetection {
+ @Inject
+ lateinit var log: LedgerLogger
+
+ @Inject
+ lateinit var itemIdProvider: ItemIdProvider
+
+ val giftNameToIdMap = mapOf(
+ "flower" to ItemId("KAT_FLOWER"),
+ "bouquet" to ItemId("KAT_BOUQUET"),
+ )
+ val katGift = "\\[NPC\\] Kat: A (?<gift>.*)\\? For me\\? How sweet!".toPattern()
+
+ @SubscribeEvent
+ fun onChat(event: ChatReceived) {
+ katGift.useMatcher(event.message) {
+ val giftName = group("gift")
+ val giftId = giftNameToIdMap[giftName]
+ log.logEntry(LedgerEntry(
+ TransactionType.KAT_TIMESKIP,
+ event.timestamp,
+ listOf(
+ ItemChange.lose(giftId ?: ItemId.NIL, 1)
+ )
+ ))
+ }
+ }
+
+ val confirmSlot = 9 + 9 + 4
+ val petSlot = 9 + 4
+
+ data class PetUpgrade(
+ val beforePetId: ItemId,
+ val cost: List<Pair<ItemId, Double>>
+ )
+
+ var lastPetUpgradeScheduled: PetUpgrade? = null
+
+ @SubscribeEvent
+ fun onClick(event: BeforeGuiAction) {
+ val slots = event.chestSlots ?: return
+ val petItem = slots.lowerChestInventory.getStackInSlot(petSlot) ?: return
+ val beforePetId = petItem.getInternalId() ?: return
+ val confirmItem = slots.lowerChestInventory.getStackInSlot(confirmSlot) ?: return
+ val lore = confirmItem.getLore()
+ val cost = lore.iterator().asSequence()
+ .dropWhile { it.unformattedString() != "Cost" }.drop(1)
+ .takeWhile { it != "" }
+ .map { itemIdProvider.findFromLore(it) ?: Pair(ItemId.NIL, 1.0) }
+ .toList()
+ lastPetUpgradeScheduled = PetUpgrade(beforePetId, cost)
+ }
+
+ val petUpgradeDialogue = "\\[NPC\\] Kat: I'll get your (?<type>.*) upgraded to (?<tier>.*) in no time!".toPattern()
+ fun upgradePetTier(itemId: ItemId): ItemId {
+ val str = itemId.string.split(";", limit = 2)
+ if (str.size == 2) {
+ val (type, tier) = str
+ val tierT = tier.toIntOrNull()
+ if (tierT != null)
+ return ItemId(type + ";" + (tierT + 1))
+ }
+ return itemId
+ }
+
+ @SubscribeEvent
+ fun onPetUpgrade(event: ChatReceived) {
+ petUpgradeDialogue.useMatcher(event.message) {
+ val upgrade = lastPetUpgradeScheduled ?: return
+ lastPetUpgradeScheduled = null
+ log.logEntry(LedgerEntry(
+ TransactionType.KAT_UPGRADE,
+ event.timestamp,
+ listOf(
+ ItemChange.lose(upgrade.beforePetId, 1),
+ ItemChange.gain(upgradePetTier(upgrade.beforePetId), 1),
+ ) + upgrade.cost.map { ItemChange.lose(it.first, it.second) },
+ ))
+ }
+ }
+
+} \ No newline at end of file