diff options
author | Linnea Gräf <nea@nea.moe> | 2024-12-28 15:52:17 +0100 |
---|---|---|
committer | Linnea Gräf <nea@nea.moe> | 2024-12-28 15:52:17 +0100 |
commit | c82d0b07033e02f7a6a23adbc1607ab3d41afdad (patch) | |
tree | bb48f950d7c4ed1ca96e087824ab6653500e0de4 /src/main | |
parent | 4d0de990e38632da9ad5c8b2d6ff90d259b2fcc6 (diff) | |
download | LocalTransactionLedger-c82d0b07033e02f7a6a23adbc1607ab3d41afdad.tar.gz LocalTransactionLedger-c82d0b07033e02f7a6a23adbc1607ab3d41afdad.tar.bz2 LocalTransactionLedger-c82d0b07033e02f7a6a23adbc1607ab3d41afdad.zip |
feat: Add draonic sacrifice tracker
Diffstat (limited to 'src/main')
-rw-r--r-- | src/main/kotlin/moe/nea/ledger/DebouncedValue.kt | 38 | ||||
-rw-r--r-- | src/main/kotlin/moe/nea/ledger/ExpiringValue.kt | 6 | ||||
-rw-r--r-- | src/main/kotlin/moe/nea/ledger/ItemId.kt | 1 | ||||
-rw-r--r-- | src/main/kotlin/moe/nea/ledger/ItemIdProvider.kt | 10 | ||||
-rw-r--r-- | src/main/kotlin/moe/nea/ledger/Ledger.kt | 2 | ||||
-rw-r--r-- | src/main/kotlin/moe/nea/ledger/TransactionType.kt | 1 | ||||
-rw-r--r-- | src/main/kotlin/moe/nea/ledger/modules/DragonSacrificeDetection.kt | 71 |
7 files changed, 126 insertions, 3 deletions
diff --git a/src/main/kotlin/moe/nea/ledger/DebouncedValue.kt b/src/main/kotlin/moe/nea/ledger/DebouncedValue.kt new file mode 100644 index 0000000..66fba8d --- /dev/null +++ b/src/main/kotlin/moe/nea/ledger/DebouncedValue.kt @@ -0,0 +1,38 @@ +package moe.nea.ledger + +import kotlin.time.Duration +import kotlin.time.Duration.Companion.nanoseconds +import kotlin.time.Duration.Companion.seconds + +class DebouncedValue<T>(private val value: T) { + companion object { + fun <T> farFuture(): DebouncedValue<T> { + val value = DebouncedValue(Unit) + value.take() + @Suppress("UNCHECKED_CAST") + return value as DebouncedValue<T> + } + } + + val lastSeenAt = System.nanoTime() + val age get() = (System.nanoTime() - lastSeenAt).nanoseconds + var taken = false + private set + + fun get(debounce: Duration): T? { + return if (!taken && age >= debounce) value + else null + } + + fun replace(): T? { + return consume(0.seconds) + } + + fun consume(debounce: Duration): T? { + return get(debounce)?.also { take() } + } + + fun take() { + taken = true + } +}
\ No newline at end of file diff --git a/src/main/kotlin/moe/nea/ledger/ExpiringValue.kt b/src/main/kotlin/moe/nea/ledger/ExpiringValue.kt index dac4751..b50b14e 100644 --- a/src/main/kotlin/moe/nea/ledger/ExpiringValue.kt +++ b/src/main/kotlin/moe/nea/ledger/ExpiringValue.kt @@ -7,8 +7,10 @@ class ExpiringValue<T>(private val value: T) { val lastSeenAt: Long = System.nanoTime() val age get() = (System.nanoTime() - lastSeenAt).nanoseconds var taken = false + private set + fun get(expiry: Duration): T? { - return if (!taken && expiry > age) value + return if (!taken && age < expiry) value else null } @@ -21,7 +23,7 @@ class ExpiringValue<T>(private val value: T) { } } - fun consume(expiry: Duration): T? = get(expiry).also { take() } + fun consume(expiry: Duration): T? = get(expiry)?.also { take() } fun take() { taken = true } diff --git a/src/main/kotlin/moe/nea/ledger/ItemId.kt b/src/main/kotlin/moe/nea/ledger/ItemId.kt index 56917e8..f627d08 100644 --- a/src/main/kotlin/moe/nea/ledger/ItemId.kt +++ b/src/main/kotlin/moe/nea/ledger/ItemId.kt @@ -21,6 +21,7 @@ value class ItemId( val GEMSTONE_POWDER = ItemId("SKYBLOCK_POWDER_GEMSTONE") val MITHRIL_POWDER = ItemId("SKYBLOCK_POWDER_MITHRIL") val GOLD_ESSENCE = ItemId("ESSENCE_GOLD") + val DRAGON_ESSENCE = ItemId("ESSENCE_DRAGON") val PELT = ItemId("SKYBLOCK_PELT") val COINS = ItemId("SKYBLOCK_COIN") val FINE_FLOUR = ItemId("FINE_FLOUR") diff --git a/src/main/kotlin/moe/nea/ledger/ItemIdProvider.kt b/src/main/kotlin/moe/nea/ledger/ItemIdProvider.kt index 7fe0206..4d85713 100644 --- a/src/main/kotlin/moe/nea/ledger/ItemIdProvider.kt +++ b/src/main/kotlin/moe/nea/ledger/ItemIdProvider.kt @@ -105,6 +105,7 @@ class ItemIdProvider { private val coinRegex = "(?<amount>$SHORT_NUMBER_PATTERN) Coins?".toPattern() private val stackedItemRegex = "(?<name>.*) x(?<count>$SHORT_NUMBER_PATTERN)".toPattern() + private val reverseStackedItemRegex = "(?<count>$SHORT_NUMBER_PATTERN)x (?<name>.*)".toPattern() private val essenceRegex = "(?<essence>.*) Essence x(?<count>$SHORT_NUMBER_PATTERN)".toPattern() private val numberedItemRegex = "(?<count>$SHORT_NUMBER_PATTERN) (?<what>.*)".toPattern() @@ -156,7 +157,14 @@ class ItemIdProvider { parseShortNumber(group("count"))) } stackedItemRegex.useMatcher(properName) { - var item = findForName(group("name"), fallbackToGenerated) + val item = findForName(group("name"), fallbackToGenerated) + if (item != null) { + val count = parseShortNumber(group("count")) + return Pair(item, count) + } + } + reverseStackedItemRegex.useMatcher(properName) { + val item = findForName(group("name"), fallbackToGenerated) if (item != null) { val count = parseShortNumber(group("count")) return Pair(item, count) diff --git a/src/main/kotlin/moe/nea/ledger/Ledger.kt b/src/main/kotlin/moe/nea/ledger/Ledger.kt index ee21efb..ed3c6a2 100644 --- a/src/main/kotlin/moe/nea/ledger/Ledger.kt +++ b/src/main/kotlin/moe/nea/ledger/Ledger.kt @@ -18,6 +18,7 @@ import moe.nea.ledger.modules.BazaarOrderDetection import moe.nea.ledger.modules.BitsDetection import moe.nea.ledger.modules.BitsShopDetection import moe.nea.ledger.modules.DragonEyePlacementDetection +import moe.nea.ledger.modules.`DragonSacrificeDetection` import moe.nea.ledger.modules.DungeonChestDetection import moe.nea.ledger.modules.ExternalDataProvider import moe.nea.ledger.modules.ForgeDetection @@ -122,6 +123,7 @@ class Ledger { Database::class.java, DebugDataCommand::class.java, DragonEyePlacementDetection::class.java, + DragonSacrificeDetection::class.java, DungeonChestDetection::class.java, ErrorUtil::class.java, ExternalDataProvider::class.java, diff --git a/src/main/kotlin/moe/nea/ledger/TransactionType.kt b/src/main/kotlin/moe/nea/ledger/TransactionType.kt index 51105e2..57f7535 100644 --- a/src/main/kotlin/moe/nea/ledger/TransactionType.kt +++ b/src/main/kotlin/moe/nea/ledger/TransactionType.kt @@ -16,6 +16,7 @@ enum class TransactionType { COMMUNITY_SHOP_BUY, CORPSE_DESECRATED, DIE_ROLLED, + DRACONIC_SACRIFICE, DUNGEON_CHEST_OPEN, FORGED, KAT_TIMESKIP, diff --git a/src/main/kotlin/moe/nea/ledger/modules/DragonSacrificeDetection.kt b/src/main/kotlin/moe/nea/ledger/modules/DragonSacrificeDetection.kt new file mode 100644 index 0000000..20934d2 --- /dev/null +++ b/src/main/kotlin/moe/nea/ledger/modules/DragonSacrificeDetection.kt @@ -0,0 +1,71 @@ +package moe.nea.ledger.modules + +import moe.nea.ledger.DebouncedValue +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.SHORT_NUMBER_PATTERN +import moe.nea.ledger.TransactionType +import moe.nea.ledger.events.ChatReceived +import moe.nea.ledger.parseShortNumber +import moe.nea.ledger.useMatcher +import moe.nea.ledger.utils.di.Inject +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import net.minecraftforge.fml.common.gameevent.TickEvent +import kotlin.time.Duration.Companion.seconds + +class DragonSacrificeDetection { + //SACRIFICE! You turned Holy Dragon Boots into 30 Dragon Essence! + //BONUS LOOT! You also received 17x Holy Dragon Fragment from your sacrifice! + @Inject + lateinit var itemIdProvider: ItemIdProvider + + @Inject + lateinit var logger: LedgerLogger + + val sacrificePattern = + "SACRIFICE! You turned (?<sacrifice>.*) into (?<amount>$SHORT_NUMBER_PATTERN) Dragon Essence!".toPattern() + val bonusLootPattern = "BONUS LOOT! You also received (?<bonus>.*) from your sacrifice!".toPattern() + + var lastSacrifice: DebouncedValue<LedgerEntry> = DebouncedValue.farFuture() + + + @SubscribeEvent + fun onChat(event: ChatReceived) { + sacrificePattern.useMatcher(event.message) { + val sacrifice = itemIdProvider.findForName(group("sacrifice")) ?: return + val lootEssence = parseShortNumber(group("amount")) + consume(lastSacrifice.replace()) + lastSacrifice = DebouncedValue(LedgerEntry( + TransactionType.DRACONIC_SACRIFICE, + event.timestamp, + listOf( + ItemChange.lose(sacrifice, 1), + ItemChange.gain(ItemId.DRAGON_ESSENCE, lootEssence) + ) + )) + } + bonusLootPattern.useMatcher(event.message) { + val bonusItem = itemIdProvider.findStackableItemByName( + group("bonus"), true + ) ?: return + lastSacrifice.replace()?.let { + consume( + it.copy(items = it.items + ItemChange.unpairGain(bonusItem)) + ) + } + } + } + + @SubscribeEvent + fun onTick(event: TickEvent) { + consume(lastSacrifice.consume(4.seconds)) + } + + fun consume(entry: LedgerEntry?) { + if (entry != null) + logger.logEntry(entry) + } +}
\ No newline at end of file |