blob: e31b5fc3e9ce467d37161822cc74a820302de294 (
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
|
package at.hannibal2.skyhanni.features.garden
import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator
import at.hannibal2.skyhanni.data.ProfileStorageData
import at.hannibal2.skyhanni.events.ConfigLoadEvent
import at.hannibal2.skyhanni.events.GuiRenderEvent
import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent
import at.hannibal2.skyhanni.events.LorenzChatEvent
import at.hannibal2.skyhanni.events.LorenzToolTipEvent
import at.hannibal2.skyhanni.events.ProfileJoinEvent
import at.hannibal2.skyhanni.utils.ChatUtils
import at.hannibal2.skyhanni.utils.ConditionalUtils
import at.hannibal2.skyhanni.utils.HypixelCommands
import at.hannibal2.skyhanni.utils.InventoryUtils
import at.hannibal2.skyhanni.utils.ItemUtils.getLore
import at.hannibal2.skyhanni.utils.ItemUtils.name
import at.hannibal2.skyhanni.utils.LorenzUtils
import at.hannibal2.skyhanni.utils.LorenzUtils.groupOrNull
import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators
import at.hannibal2.skyhanni.utils.NumberUtil.format
import at.hannibal2.skyhanni.utils.NumberUtil.formatLong
import at.hannibal2.skyhanni.utils.NumberUtil.romanToDecimalIfNecessary
import at.hannibal2.skyhanni.utils.NumberUtil.toRoman
import at.hannibal2.skyhanni.utils.RenderUtils.renderString
import at.hannibal2.skyhanni.utils.StringUtils
import at.hannibal2.skyhanni.utils.StringUtils.isRoman
import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher
import at.hannibal2.skyhanni.utils.StringUtils.matches
import at.hannibal2.skyhanni.utils.StringUtils.removeColor
import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import kotlin.time.Duration.Companion.milliseconds
class GardenLevelDisplay {
private val config get() = GardenAPI.config.gardenLevels
private var useRomanNumerals: Boolean
get() = ProfileStorageData.playerSpecific?.useRomanNumerals ?: true
set(value) {
ProfileStorageData.playerSpecific?.useRomanNumerals = value
}
private val patternGroup = RepoPattern.group("garden.level")
private val expToNextLevelPattern by patternGroup.pattern(
"inventory.nextxp",
".* §e(?<nextLevelExp>.*)§6/.*"
)
private val gardenItemNamePattern by patternGroup.pattern(
"inventory.name",
"Garden (?:Desk|Level (?<currentLevel>.*))"
)
private val overflowPattern by patternGroup.pattern(
"inventory.overflow",
".*§r §6(?<overflow>.*)"
)
private val gardenLevelPattern by patternGroup.pattern(
"inventory.levelprogress",
"§7Progress to Level (?<currentLevel>[^:]*).*"
)
private val gardenMaxLevelPattern by patternGroup.pattern(
"inventory.max",
"§5§o§7§8Max level reached!"
)
private val visitorRewardPattern by patternGroup.pattern(
"chat.increase",
" {4}§r§8\\+§r§2(?<exp>.*) §r§7Garden Experience"
)
private var display = ""
@SubscribeEvent
fun onProfileJoin(event: ProfileJoinEvent) {
update()
}
@SubscribeEvent(receiveCanceled = true)
fun onChat(event: LorenzChatEvent) {
if (!GardenAPI.inGarden()) return
visitorRewardPattern.matchMatcher(event.message) {
addExp(group("exp").toInt())
}
}
private fun addExp(moreExp: Int) {
val gardenExp = GardenAPI.gardenExp ?: return
val oldLevel = GardenAPI.getGardenLevel()
GardenAPI.gardenExp = gardenExp + moreExp
update()
if (!config.overflowChat) return
val newLevel = GardenAPI.getGardenLevel()
if (newLevel != oldLevel + 1 || newLevel <= 15) return
LorenzUtils.runDelayed(50.milliseconds) {
// TODO utils function that is shared with Crop Milestone Display
ChatUtils.clickableChat(
" \n§b§lGARDEN LEVEL UP §8$oldLevel ➜ §b$newLevel\n" +
" §8+§aRespect from Elite Farmers and SkyHanni members :)\n ",
onClick = {
HypixelCommands.gardenLevels()
},
prefix = false
)
}
}
@SubscribeEvent
fun onInventoryOpen(event: InventoryFullyOpenedEvent) {
if (!GardenAPI.inGarden()) return
val item = when (event.inventoryName) {
"Desk" -> event.inventoryItems[4] ?: return
"SkyBlock Menu" -> event.inventoryItems[10] ?: return
else -> return
}
gardenItemNamePattern.matchMatcher(item.name.removeColor()) {
val level = groupOrNull("currentLevel")
if (level != null) useRomanNumerals = level.isRoman()
} ?: return
var nextLevelExp = 0L
var currentLevel = 0
for (line in item.getLore()) {
gardenLevelPattern.matchMatcher(line) {
currentLevel = group("currentLevel").romanToDecimalIfNecessary() - 1
}
if (line == "§7§8Max level reached!") currentLevel = 15
expToNextLevelPattern.matchMatcher(line) {
nextLevelExp = group("nextLevelExp").formatLong()
}
overflowPattern.matchMatcher(line) {
val overflow = group("overflow").formatLong()
GardenAPI.gardenExp = overflow
update()
return
}
}
val expForLevel = GardenAPI.getExpForLevel(currentLevel).toInt()
GardenAPI.gardenExp = expForLevel + nextLevelExp
update()
}
@SubscribeEvent
fun onTooltip(event: LorenzToolTipEvent) {
if (!GardenAPI.inGarden()) return
if (!config.overflow.get()) return
val slotIndex = event.slot.slotIndex
val name = InventoryUtils.openInventoryName()
if (!((name == "Desk" && slotIndex == 4) || (name == "SkyBlock Menu" && slotIndex == 10))) return
val gardenExp = GardenAPI.gardenExp ?: return
val currentLevel = GardenAPI.getGardenLevel()
if (currentLevel < 15) return
val needForLevel = GardenAPI.getExpForLevel(currentLevel).toInt()
val overflow = (gardenExp - needForLevel).toDouble()
val overflowTotal = (gardenExp - GardenAPI.getExpForLevel(15)).toInt()
val needForNextLevel = GardenAPI.getExpForLevel(currentLevel + 1).toInt()
val needForOnlyNextLvl = needForNextLevel - needForLevel
val iterator = event.toolTip.listIterator()
if (slotIndex == 4 && currentLevel > 15) {
event.itemStack.name = "§aGarden Level ${currentLevel.toRomanIfNecessary()}"
}
var next = false
for (line in iterator) {
if (gardenMaxLevelPattern.matches(line)) {
iterator.set("§7Progress to Level ${(currentLevel + 1).toRomanIfNecessary()}")
next = true
continue
}
if (next && line.contains(" ")) {
val progress = overflow / needForOnlyNextLvl
val progressBar = StringUtils.progressBar(progress, 20)
iterator.set("$progressBar §e${overflow.addSeparators()}§6/§e${format(needForOnlyNextLvl)}")
iterator.add("")
iterator.add("§b§lOVERFLOW XP:")
iterator.add("§7▸ ${overflowTotal.addSeparators()}")
return
}
}
}
private fun update() {
display = drawDisplay()
}
private fun drawDisplay(): String {
val gardenExp = GardenAPI.gardenExp ?: return "§aGarden Level ? §cOpen the desk!"
val currentLevel = GardenAPI.getGardenLevel(overflow = config.overflow.get())
val isMax = !config.overflow.get() && currentLevel == 15
val needForLevel = GardenAPI.getExpForLevel(currentLevel).toInt()
val overflow = gardenExp - needForLevel
return "§aGarden level $currentLevel " + if (isMax) {
"§7(§e${overflow.addSeparators()}§7)"
} else {
val needForNextLevel = GardenAPI.getExpForLevel(currentLevel + 1).toInt()
val needForOnlyNextLevel = needForNextLevel - needForLevel
"§7(§e${overflow.addSeparators()}§7/§e${needForOnlyNextLevel.addSeparators()}§7)"
}
}
private fun Int.toRomanIfNecessary(): String {
return if (useRomanNumerals) this.toRoman() else this.toString()
}
@SubscribeEvent
fun onRenderOverlay(event: GuiRenderEvent.GuiOverlayRenderEvent) {
if (!isEnabled()) return
if (GardenAPI.hideExtraGuis()) return
config.pos.renderString(display, posLabel = "Garden Level")
}
@SubscribeEvent
fun onConfigLoad(event: ConfigLoadEvent) {
ConditionalUtils.onToggle(config.overflow) { update() }
}
private fun isEnabled() = GardenAPI.inGarden() && config.display
@SubscribeEvent
fun onConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent)
|