aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/at/hannibal2/skyhanni/features/misc/DraconicSacrificeTracker.kt
blob: 61fff44ff7d2906faf68ffd8ab25a17e9689d8f6 (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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package at.hannibal2.skyhanni.features.misc

import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.api.event.HandleEvent
import at.hannibal2.skyhanni.config.commands.CommandCategory
import at.hannibal2.skyhanni.config.commands.CommandRegistrationEvent
import at.hannibal2.skyhanni.data.IslandType
import at.hannibal2.skyhanni.events.GuiRenderEvent
import at.hannibal2.skyhanni.events.LorenzChatEvent
import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
import at.hannibal2.skyhanni.utils.CollectionUtils.addOrPut
import at.hannibal2.skyhanni.utils.CollectionUtils.addSearchString
import at.hannibal2.skyhanni.utils.LocationUtils.isPlayerInside
import at.hannibal2.skyhanni.utils.LorenzUtils
import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland
import at.hannibal2.skyhanni.utils.NEUInternalName
import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName
import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators
import at.hannibal2.skyhanni.utils.RegexUtils.groupOrNull
import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher
import at.hannibal2.skyhanni.utils.renderables.Renderable
import at.hannibal2.skyhanni.utils.renderables.Searchable
import at.hannibal2.skyhanni.utils.renderables.toSearchable
import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern
import at.hannibal2.skyhanni.utils.tracker.ItemTrackerData
import at.hannibal2.skyhanni.utils.tracker.SkyHanniItemTracker
import com.google.gson.annotations.Expose
import net.minecraft.util.AxisAlignedBB
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent

@SkyHanniModule
object DraconicSacrificeTracker {

    private val config get() = SkyHanniMod.feature.combat.endIsland.draconicSacrificeTracker
    private val patternGroup = RepoPattern.group("misc.draconicsacrifice")

    /**
     * REGEX-TEST: §c§lSACRIFICE! §r§eYou turned §r§5Ender Boots §r§einto §r§d3 Dragon Essence§r§e!
     * REGEX-TEST: §c§lSACRIFICE! §r§eYou turned §r§5Ender Helmet §r§einto §r§d3 Dragon Essence§r§e!
     * REGEX-TEST: §c§lSACRIFICE! §r§eYou turned §r§6Old Dragon Helmet §r§einto §r§d25 Dragon Essence§r§e!
     * REGEX-TEST: §c§lSACRIFICE! §r§eYou turned §r§6Wise Dragon Helmet §r§einto §r§d25 Dragon Essence§r§e!
     */
    private val sacrificeLoot by patternGroup.pattern(
        "sacrifice",
        "§c§lSACRIFICE! §r§eYou turned §r(?<item>.*) §r§einto §r§d(?<amount>\\d+) Dragon Essence§r§e!",
    )

    /**
     * REGEX-TEST: §c§lBONUS LOOT! §r§eYou also received §r§817x §r§5Wise Dragon Fragment §r§efrom your sacrifice!
     */
    private val bonusLoot by patternGroup.pattern(
        "bonus",
        "§c§lBONUS LOOT! §r§eYou also received §r(?:§\\w(?<amount>\\d+)?x)?(?: §r)?(?<item>.*) §r§efrom your sacrifice!",
    )

    private val tracker =
        SkyHanniItemTracker("Draconic Sacrifice Profit Tracker", { Data() }, { it.draconicSacrificeTracker }) {
            drawDisplay(it)
        }

    private val altarArea = AxisAlignedBB(-601.0, 4.0, -282.0, -586.0, 15.0, -269.0)
    private val ESSENCE_DRAGON = "ESSENCE_DRAGON".asInternalName()

    class Data : ItemTrackerData() {
        override fun resetItems() {
            sacrificedItemsMap.clear()
            itemsSacrificed = 0
        }

        override fun getDescription(timesGained: Long): List<String> {
            val percentage = timesGained.toDouble() / itemsSacrificed
            val dropRate = LorenzUtils.formatPercentage(percentage.coerceAtMost(1.0))
            return listOf(
                "§7Dropped §e${timesGained.addSeparators()} §7times.",
                "§7Your drop rate: §c$dropRate.",
            )
        }

        override fun getCoinName(item: TrackedItem) = "§dDragon Essence"

        override fun getCoinDescription(item: TrackedItem): List<String> {
            val essences = item.totalAmount.addSeparators()
            return listOf(
                "§7Sacrificed items give you dragon essence.",
                "§7You got §6$essences essence §7that way.",
            )
        }

        @Expose
        var itemsSacrificed = 0L

        @Expose
        var sacrificedItemsMap: MutableMap<String, Long> = mutableMapOf()
    }

    private fun drawDisplay(data: Data): List<Searchable> = buildList {
        addSearchString("§5§lDraconic Sacrifice Profit Tracker")
        val profit = tracker.drawItems(data, { true }, this)

        add(
            Renderable.hoverTips(
                "§b${data.itemsSacrificed.addSeparators()} §6Items Sacrificed",
                data.sacrificedItemsMap.map { (item, amount) -> "$item: §b$amount" },
            ).toSearchable()
        )

        add(tracker.addTotalProfit(profit, data.itemsSacrificed, "sacrifice"))

        tracker.addPriceFromButton(this)
    }

    @SubscribeEvent
    fun onChat(event: LorenzChatEvent) {
        sacrificeLoot.matchMatcher(event.message) {
            val amount = group("amount").toInt()
            val item = group("item")
            tracker.addItem(ESSENCE_DRAGON, amount, command = false)
            tracker.modify {
                it.itemsSacrificed += 1
                it.sacrificedItemsMap.addOrPut(item, 1)
            }
        }

        bonusLoot.matchMatcher(event.message) {
            val item = group("item")
            val amount = groupOrNull("amount")?.toInt() ?: 1
            val internalName = NEUInternalName.fromItemNameOrNull(item) ?: return
            tracker.addItem(internalName, amount, command = false)
        }
        tracker.update()
    }

    @SubscribeEvent
    fun onRender(event: GuiRenderEvent) {
        if (!isEnabled()) return
        if (config.onlyInVoidSlate && !altarArea.isPlayerInside()) return

        tracker.renderDisplay(config.position)
    }

    @HandleEvent
    fun onCommandRegistration(event: CommandRegistrationEvent) {
        event.register("shresetdraconicsacrificetracker") {
            description = "Resets the Draconic Sacrifice Tracker."
            category = CommandCategory.USERS_RESET
            callback { tracker.resetCommand() }
        }
    }

    private fun isEnabled() = IslandType.THE_END.isInIsland() && config.enabled
}