aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/moe/nea/ledger/modules/DungeonChestDetection.kt
blob: e747be9a0d6daa3aff23e5462e98dce28e5ab51d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package moe.nea.ledger.modules

import moe.nea.ledger.ExpiringValue
import moe.nea.ledger.ItemChange
import moe.nea.ledger.LedgerEntry
import moe.nea.ledger.LedgerLogger
import moe.nea.ledger.TransactionType
import moe.nea.ledger.events.ChatReceived
import moe.nea.ledger.events.ExtraSupplyIdEvent
import moe.nea.ledger.events.GuiClickEvent
import moe.nea.ledger.gen.ItemIds
import moe.nea.ledger.getDisplayNameU
import moe.nea.ledger.unformattedString
import moe.nea.ledger.useMatcher
import moe.nea.ledger.utils.di.Inject
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import java.time.Instant
import java.util.concurrent.locks.ReentrantLock
import kotlin.time.Duration.Companion.seconds

class DungeonChestDetection @Inject constructor(val logger: LedgerLogger) : ChestDetection() {

	@SubscribeEvent
	fun onKismetClick(event: GuiClickEvent) {
		val slot = event.slotIn ?: return
		if (!slot.inventory.displayName.unformattedText.unformattedString().endsWith(" Chest")) return
		val stack = slot.stack ?: return
		if (stack.getDisplayNameU() == "§aReroll Chest") {
			logger.logEntry(
				LedgerEntry(
					TransactionType.KISMET_REROLL,
					Instant.now(),
					listOf(
						ItemChange.lose(ItemIds.KISMET_FEATHER, 1)
					)
				)
			)
		}
	}


	var lastOpenedChest = ExpiringValue.empty<ChestCost>()

	@SubscribeEvent
	fun supplyExtraIds(event: ExtraSupplyIdEvent) {
		event.store("Dungeon Chest Key", ItemIds.DUNGEON_CHEST_KEY)
		event.store("Kismet Feather", ItemIds.KISMET_FEATHER)
	}

	@SubscribeEvent
	fun onRewardChestClick(event: GuiClickEvent) {
		lastOpenedChest = ExpiringValue(scrapeChestReward(event.slotIn ?: return) ?: return)
	}

	class Mutex<T>(defaultValue: T) {
		private var value: T = defaultValue
		val lock = ReentrantLock()

		fun getUnsafeLockedValue(): T {
			if (!lock.isHeldByCurrentThread)
				error("Accessed unsafe locked value, without holding the lock.")
			return value
		}

		fun <R> withLock(func: (T) -> R): R {
			lock.lockInterruptibly()
			try {
				val ret = func(value)
				if (ret === value) {
					error("Please don't smuggle out the locked value. If this is unintentional, please append a `Unit` instruction to the end of your `withLock` call: `.withLock { /* your existing code */; Unit }`.")
				}
				return ret
			} finally {
				lock.unlock()
			}
		}
	}

	val rewardMessage = " (WOOD|GOLD|DIAMOND|EMERALD|OBSIDIAN|BEDROCK) CHEST REWARDS".toPattern()

	@SubscribeEvent
	fun onChatMessage(event: ChatReceived) {
		if (event.message == "You don't have that many coins in the bank!") {
			lastOpenedChest.take()
		}
		rewardMessage.useMatcher(event.message) {
			val chest = lastOpenedChest.consume(3.seconds) ?: return
			logger.logEntry(LedgerEntry(
				TransactionType.DUNGEON_CHEST_OPEN,
				chest.timestamp,
				chest.diff,
			))
		}
	}
}