From 3acf36fbd07686431b8fbb5484f1f70b52651dc5 Mon Sep 17 00:00:00 2001 From: Linnea Gräf Date: Sat, 7 Dec 2024 23:10:13 +0100 Subject: Add kuudra chest detection --- src/main/kotlin/moe/nea/ledger/ItemIdProvider.kt | 2 +- src/main/kotlin/moe/nea/ledger/Ledger.kt | 5 +- src/main/kotlin/moe/nea/ledger/LedgerLogger.kt | 8 ++- .../moe/nea/ledger/modules/ChestDetection.kt | 48 +++++++++++++++++ .../nea/ledger/modules/DungeonChestDetection.kt | 63 +--------------------- .../moe/nea/ledger/modules/KuudraChestDetection.kt | 45 ++++++++++++++++ 6 files changed, 107 insertions(+), 64 deletions(-) create mode 100644 src/main/kotlin/moe/nea/ledger/modules/ChestDetection.kt create mode 100644 src/main/kotlin/moe/nea/ledger/modules/KuudraChestDetection.kt (limited to 'src/main') diff --git a/src/main/kotlin/moe/nea/ledger/ItemIdProvider.kt b/src/main/kotlin/moe/nea/ledger/ItemIdProvider.kt index f4a0232..d6ca05b 100644 --- a/src/main/kotlin/moe/nea/ledger/ItemIdProvider.kt +++ b/src/main/kotlin/moe/nea/ledger/ItemIdProvider.kt @@ -86,7 +86,7 @@ class ItemIdProvider { fun findStackableItemByName(name: String): Pair? { val properName = name.unformattedString() - if (properName == "FREE") { + if (properName == "FREE" || properName == "This Chest is Free!") { return Pair(ItemId.COINS, 0.0) } coinRegex.useMatcher(properName) { diff --git a/src/main/kotlin/moe/nea/ledger/Ledger.kt b/src/main/kotlin/moe/nea/ledger/Ledger.kt index ee15a83..3b14884 100644 --- a/src/main/kotlin/moe/nea/ledger/Ledger.kt +++ b/src/main/kotlin/moe/nea/ledger/Ledger.kt @@ -15,6 +15,7 @@ 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.KuudraChestDetection import moe.nea.ledger.modules.MinionDetection import moe.nea.ledger.modules.NpcDetection import moe.nea.ledger.utils.DI @@ -87,6 +88,8 @@ class Ledger { val di = DI() di.registerSingleton(this) + di.registerSingleton(Minecraft.getMinecraft()) + di.registerSingleton(gson) di.registerInjectableClasses( AuctionHouseDetection::class.java, BankDetection::class.java, @@ -99,12 +102,12 @@ class Ledger { DungeonChestDetection::class.java, ItemIdProvider::class.java, KatDetection::class.java, + KuudraChestDetection::class.java, LedgerLogger::class.java, LogChatCommand::class.java, MinionDetection::class.java, NpcDetection::class.java, ) - di.registerSingleton(gson) di.instantiateAll() di.getAllInstances().forEach(MinecraftForge.EVENT_BUS::register) di.getAllInstances().filterIsInstance() diff --git a/src/main/kotlin/moe/nea/ledger/LedgerLogger.kt b/src/main/kotlin/moe/nea/ledger/LedgerLogger.kt index e8c15ea..5403d92 100644 --- a/src/main/kotlin/moe/nea/ledger/LedgerLogger.kt +++ b/src/main/kotlin/moe/nea/ledger/LedgerLogger.kt @@ -149,6 +149,7 @@ enum class TransactionType { KAT_TIMESKIP, KAT_UPGRADE, KISMET_REROLL, + KUUDRA_CHEST_OPEN, NPC_BUY, NPC_SELL, } @@ -158,9 +159,14 @@ value class ItemId( val string: String ) { fun singleItem(): Pair { - return Pair(this, 1.0) + return withStackSize(1) } + fun withStackSize(size: Number): Pair { + return Pair(this, size.toDouble()) + } + + companion object { val COINS = ItemId("SKYBLOCK_COIN") val BITS = ItemId("SKYBLOCK_BIT") diff --git a/src/main/kotlin/moe/nea/ledger/modules/ChestDetection.kt b/src/main/kotlin/moe/nea/ledger/modules/ChestDetection.kt new file mode 100644 index 0000000..48c040a --- /dev/null +++ b/src/main/kotlin/moe/nea/ledger/modules/ChestDetection.kt @@ -0,0 +1,48 @@ +package moe.nea.ledger.modules + +import moe.nea.ledger.ItemChange +import moe.nea.ledger.ItemId +import moe.nea.ledger.ItemIdProvider +import moe.nea.ledger.getDisplayNameU +import moe.nea.ledger.getInternalId +import moe.nea.ledger.getLore +import moe.nea.ledger.unformattedString +import moe.nea.ledger.utils.Inject +import net.minecraft.init.Blocks +import net.minecraft.inventory.Slot +import net.minecraft.item.Item +import java.time.Instant + +abstract class ChestDetection { + data class ChestCost( + val diff: List, + val timestamp: Instant, + ) + + @Inject + lateinit var itemIdProvider: ItemIdProvider + fun scrapeChestReward(rewardSlot: Slot): ChestCost? { + val inventory = rewardSlot.inventory + if (!inventory.displayName.unformattedText.unformattedString() + .endsWith(" Chest") + ) return null + val rewardStack = rewardSlot.stack ?: return null + val name = rewardStack.getDisplayNameU() + if (name != "§aOpen Reward Chest") return null + val lore = rewardStack.getLore() + val cost = itemIdProvider.findCostItemsFromSpan(lore) + val gain = (9..18) + .mapNotNull { inventory.getStackInSlot(it) } + .filter { it.item != Item.getItemFromBlock(Blocks.stained_glass_pane) } + .map { + it.getInternalId()?.withStackSize(it.stackSize) + ?: itemIdProvider.findStackableItemByName(it.displayName) + ?: ItemId.NIL.withStackSize(it.stackSize) + } + return ChestCost( + cost.map { ItemChange.lose(it.first, it.second) } + gain.map { ItemChange.gain(it.first, it.second) }, + Instant.now() + ) + } + +} \ No newline at end of file diff --git a/src/main/kotlin/moe/nea/ledger/modules/DungeonChestDetection.kt b/src/main/kotlin/moe/nea/ledger/modules/DungeonChestDetection.kt index c50e9eb..4be5228 100644 --- a/src/main/kotlin/moe/nea/ledger/modules/DungeonChestDetection.kt +++ b/src/main/kotlin/moe/nea/ledger/modules/DungeonChestDetection.kt @@ -3,7 +3,6 @@ package moe.nea.ledger.modules import moe.nea.ledger.ExpiringValue 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 @@ -11,49 +10,14 @@ import moe.nea.ledger.events.ChatReceived import moe.nea.ledger.events.ExtraSupplyIdEvent import moe.nea.ledger.events.GuiClickEvent import moe.nea.ledger.getDisplayNameU -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.minecraft.init.Blocks -import net.minecraft.item.Item import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import java.time.Instant import kotlin.time.Duration.Companion.seconds -class DungeonChestDetection @Inject constructor(val logger: LedgerLogger) { - - /*{ - id: "minecraft:chest", - Count: 1b, - tag: { - display: { - Lore: ["§7Purchase this chest to receive the", "§7rewards above. You can only open", "§7one chest per Dungeons run -", "§7choose wisely!", "", "§7Cost", "§625,000 Coins", "§9Dungeon Chest Key", "", "§7§cNOTE: Coins are withdrawn from your", "§cbank if you don't have enough in", "§cyour purse."], - Name: "§aOpen Reward Chest" - } - }, - Damage: 0s - } - - { - id: "minecraft:feather", - Count: 1b, - tag: { - overrideMeta: 1b, - ench: [], - HideFlags: 254, - display: { - Lore: ["§7Consume a §9Kismet Feather §7to reroll", "§7the loot within this chest.", "", "§7You may only use a feather once", "§7per dungeon run.", "", "§eClick to reroll this chest!"], - Name: "§aReroll Chest" - }, - AttributeModifiers: [] - }, - Damage: 0s -} - */ - @Inject - lateinit var itemIdProvider: ItemIdProvider +class DungeonChestDetection @Inject constructor(val logger: LedgerLogger) : ChestDetection() { @SubscribeEvent fun onKismetClick(event: GuiClickEvent) { @@ -73,10 +37,6 @@ class DungeonChestDetection @Inject constructor(val logger: LedgerLogger) { } } - data class ChestCost( - val diff: List, - val timestamp: Instant, - ) var lastOpenedChest = ExpiringValue.empty() @@ -88,26 +48,7 @@ class DungeonChestDetection @Inject constructor(val logger: LedgerLogger) { @SubscribeEvent fun onRewardChestClick(event: GuiClickEvent) { - val slot = event.slotIn ?: return - if (!slot.inventory.displayName.unformattedText.unformattedString().endsWith(" Chest")) return - val stack = slot.stack ?: return - val name = stack.getDisplayNameU() - if (name != "§aOpen Reward Chest") return - val lore = stack.getLore() - val cost = itemIdProvider.findCostItemsFromSpan(lore) - val gain = (9..18) - .mapNotNull { slot.inventory.getStackInSlot(it) } - .filter { it.item != Item.getItemFromBlock(Blocks.stained_glass_pane) } - .map { - it.getInternalId()?.singleItem() - ?: itemIdProvider.findStackableItemByName(it.displayName) - ?: Pair(ItemId.NIL, it.stackSize.toDouble()) - } - lastOpenedChest = ExpiringValue(ChestCost( - cost.map { ItemChange.lose(it.first, it.second) } - + gain.map { ItemChange.gain(it.first, it.second) }, - Instant.now() - )) + lastOpenedChest = ExpiringValue(scrapeChestReward(event.slotIn ?: return) ?: return) } val rewardMessage = " .* CHEST REWARDS".toPattern() diff --git a/src/main/kotlin/moe/nea/ledger/modules/KuudraChestDetection.kt b/src/main/kotlin/moe/nea/ledger/modules/KuudraChestDetection.kt new file mode 100644 index 0000000..bc072ba --- /dev/null +++ b/src/main/kotlin/moe/nea/ledger/modules/KuudraChestDetection.kt @@ -0,0 +1,45 @@ +package moe.nea.ledger.modules + +import moe.nea.ledger.ItemChange +import moe.nea.ledger.ItemId +import moe.nea.ledger.LedgerEntry +import moe.nea.ledger.LedgerLogger +import moe.nea.ledger.TransactionType +import moe.nea.ledger.events.GuiClickEvent +import moe.nea.ledger.getInternalId +import moe.nea.ledger.utils.Inject +import net.minecraft.client.Minecraft +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +class KuudraChestDetection : ChestDetection() { + // TODO: extra essence for kuudra pet (how?), item SALVAGE detection + // TODO: save uuid along side item id + + val kuudraKeyPattern = "KUUDRA_.*_TIER_KEY".toPattern() + + @Inject + lateinit var log: LedgerLogger + + @Inject + lateinit var minecraft: Minecraft + fun hasKey(keyItem: ItemId): Boolean { + val p = minecraft.thePlayer ?: return false + return p.inventory.mainInventory.any { it.getInternalId() == keyItem } + } + + @SubscribeEvent + fun onRewardChestClick(event: GuiClickEvent) { + val diffs = scrapeChestReward(event.slotIn ?: return) ?: return + val requiredKey = diffs.diff.find { + it.direction == ItemChange.ChangeDirection.LOST && kuudraKeyPattern.asPredicate().test(it.itemId.string) + }?.itemId + if (requiredKey != null && !hasKey(requiredKey)) { + return + } + log.logEntry(LedgerEntry( + TransactionType.KUUDRA_CHEST_OPEN, + diffs.timestamp, + diffs.diff, + )) + } +} \ No newline at end of file -- cgit