diff options
| author | J10a1n15 <45315647+j10a1n15@users.noreply.github.com> | 2024-03-12 19:59:55 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-03-12 19:59:55 +0100 |
| commit | 4352ffb08d4bfffc06adad2a068f375ab9874333 (patch) | |
| tree | b8ce745fca8ab82ffa04f6ab87334139a6b7192b /src/main/java/at/hannibal2/skyhanni/data | |
| parent | eb863d60e82b5541a9f42d2608f61cb97ada209b (diff) | |
| download | skyhanni-4352ffb08d4bfffc06adad2a068f375ab9874333.tar.gz skyhanni-4352ffb08d4bfffc06adad2a068f375ab9874333.tar.bz2 skyhanni-4352ffb08d4bfffc06adad2a068f375ab9874333.zip | |
Feature: CustomScoreboard (#893)
Co-authored-by: Thunderblade73 <85900443+Thunderblade73@users.noreply.github.com>
Co-authored-by: Thunderblade73 <gaidermarkus@gmail.com>
Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com>
Diffstat (limited to 'src/main/java/at/hannibal2/skyhanni/data')
18 files changed, 962 insertions, 93 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/data/ArrowType.kt b/src/main/java/at/hannibal2/skyhanni/data/ArrowType.kt new file mode 100644 index 000000000..5ce7dd33f --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/data/ArrowType.kt @@ -0,0 +1,9 @@ +package at.hannibal2.skyhanni.data + +import at.hannibal2.skyhanni.utils.NEUInternalName + +data class ArrowType(val arrow: String, val internalName: NEUInternalName) { + override fun toString(): String { + return internalName.asString() + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/data/BitsAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/BitsAPI.kt new file mode 100644 index 000000000..2802399bf --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/data/BitsAPI.kt @@ -0,0 +1,200 @@ +package at.hannibal2.skyhanni.data + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.data.FameRanks.getFameRankByNameOrNull +import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent +import at.hannibal2.skyhanni.events.LorenzChatEvent +import at.hannibal2.skyhanni.events.ScoreboardChangeEvent +import at.hannibal2.skyhanni.test.command.ErrorManager +import at.hannibal2.skyhanni.utils.ChatUtils +import at.hannibal2.skyhanni.utils.ItemUtils.getLore +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.NumberUtil.formatInt +import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher +import at.hannibal2.skyhanni.utils.StringUtils.matches +import at.hannibal2.skyhanni.utils.StringUtils.removeResets +import at.hannibal2.skyhanni.utils.StringUtils.trimWhiteSpace +import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +object BitsAPI { + private val profileStorage get() = ProfileStorageData.profileSpecific?.bits + private val playerStorage get() = SkyHanniMod.feature.storage + + var bits: Int + get() = profileStorage?.bits ?: 0 + private set(value) { + profileStorage?.bits = value + } + var currentFameRank: FameRank? + get() = playerStorage?.currentFameRank?.let { getFameRankByNameOrNull(it) } + private set(value) { + if (value != null) { + playerStorage?.currentFameRank = value.name + } + } + var bitsToClaim: Int + get() = profileStorage?.bitsToClaim ?: 0 + private set(value) { + profileStorage?.bitsToClaim = value + } + + private const val defaultcookiebits = 4800 + + private val bitsDataGroup = RepoPattern.group("data.bits") + + // Scoreboard patterns + val bitsScoreboardPattern by bitsDataGroup.pattern( + "scoreboard", + "^Bits: §b(?<amount>[\\d,.]+).*$" + ) + + // Chat patterns + private val bitsChatGroup = bitsDataGroup.group("chat") + + private val bitsFromFameRankUpChatPattern by bitsChatGroup.pattern( + "famerankup", + "§eYou gained §3(?<amount>.*) Bits Available §ecompounded from all your §epreviously eaten §6cookies§e! Click here to open §6cookie menu§e!" + ) + + private val boosterCookieAte by bitsChatGroup.pattern( + "boostercookieate", + "§eYou consumed a §6Booster Cookie§e!.*" + ) + + // GUI patterns + private val bitsGuiGroup = bitsDataGroup.group("gui") + + private val bitsAvailableMenuPattern by bitsGuiGroup.pattern( + "availablemenu", + "§7Bits Available: §b(?<toClaim>[\\d,]+)(§3.+)?" + ) + + private val fameRankSbMenuPattern by bitsGuiGroup.pattern( + "sbmenufamerank", + "§7Your rank: §e(?<rank>.*)" + ) + + private val fameRankCommunityShopPattern by bitsGuiGroup.pattern( + "communityshopfamerank", + "§7Fame Rank: §e(?<rank>.*)" + ) + + private val bitsGuiNamePattern by bitsGuiGroup.pattern( + "mainmenuname", + "^SkyBlock Menu$" + ) + + private val bitsGuiStackPattern by bitsGuiGroup.pattern( + "mainmenustack", + "^§6Booster Cookie$" + ) + + private val fameRankGuiNamePattern by bitsGuiGroup.pattern( + "famerankmenuname", + "^(Community Shop|Booster Cookie)$" + ) + + private val fameRankGuiStackPattern by bitsGuiGroup.pattern( + "famerankmenustack", + "^(§aCommunity Shop|§eFame Rank)$" + ) + + @SubscribeEvent + fun onScoreboardChange(event: ScoreboardChangeEvent) { + if (!isEnabled()) return + for (line in event.newList) { + val message = line.trimWhiteSpace().removeResets() + + bitsScoreboardPattern.matchMatcher(message) { + val amount = group("amount").formatInt() + + if (amount > bits) { + bitsToClaim -= amount - bits + ChatUtils.debug("You have gained §3${amount - bits} Bits §7according to the scoreboard!") + } + bits = amount + + return + } + } + } + + @SubscribeEvent + fun onChat(event: LorenzChatEvent) { + if (!isEnabled()) return + val message = event.message.trimWhiteSpace().removeResets() + + bitsFromFameRankUpChatPattern.matchMatcher(message) { + val amount = group("amount").formatInt() + bitsToClaim += amount + + return + } + + boosterCookieAte.matchMatcher(message) { + bitsToClaim += (defaultcookiebits * (currentFameRank?.bitsMultiplier ?: return)).toInt() + + return + } + } + + @SubscribeEvent + fun onInventoryFullyLoaded(event: InventoryFullyOpenedEvent) { + if (!isEnabled()) return + + val stacks = event.inventoryItems + + if (bitsGuiNamePattern.matches(event.inventoryName)) { + val cookieStack = stacks.values.lastOrNull { bitsGuiStackPattern.matches(it.displayName) } ?: return + for (line in cookieStack.getLore()) { + bitsAvailableMenuPattern.matchMatcher(line) { + bitsToClaim = group("toClaim").formatInt() + + return + } + } + return + } + + if (fameRankGuiNamePattern.matches(event.inventoryName)) { + val fameRankStack = stacks.values.lastOrNull { fameRankGuiStackPattern.matches(it.displayName) } ?: return + + line@ for (line in fameRankStack.getLore()) { + fameRankCommunityShopPattern.matchMatcher(line) { + val rank = group("rank") + + currentFameRank = getFameRankByNameOrNull(rank) + ?: return ErrorManager.logErrorWithData( + FameRankNotFoundException(rank), + "FameRank $rank not found", + "Rank" to rank, + "Lore" to fameRankStack.getLore(), + "FameRanks" to FameRanks.fameRanks + ) + + continue@line + } + + fameRankSbMenuPattern.matchMatcher(line) { + val rank = group("rank") + + currentFameRank = getFameRankByNameOrNull(rank) + ?: return ErrorManager.logErrorWithData( + FameRankNotFoundException(rank), + "FameRank $rank not found", + "Rank" to rank, + "Lore" to fameRankStack.getLore(), + "FameRanks" to FameRanks.fameRanks + ) + + continue@line + } + } + } + } + + fun isEnabled() = LorenzUtils.inSkyBlock && profileStorage != null + + class FameRankNotFoundException(rank: String) : Exception("FameRank not found: $rank") +} diff --git a/src/main/java/at/hannibal2/skyhanni/data/FameRanks.kt b/src/main/java/at/hannibal2/skyhanni/data/FameRanks.kt new file mode 100644 index 000000000..663e2b970 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/data/FameRanks.kt @@ -0,0 +1,26 @@ +package at.hannibal2.skyhanni.data + +import at.hannibal2.skyhanni.data.jsonobjects.repo.FameRankJson +import at.hannibal2.skyhanni.events.RepositoryReloadEvent +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +object FameRanks { + var fameRanks = emptyMap<String, FameRank>() + private set + + fun getFameRankByNameOrNull(name: String) = fameRanks[name] + + @SubscribeEvent + fun onRepoReload(event: RepositoryReloadEvent) { + val ranks = event.getConstant<FameRankJson>("FameRank") + fameRanks = ranks.fame_rank.values.map { FameRank(it.name, it.fame_required, it.bits_multiplier, it.votes) } + .associateBy { it.name } + } +} + +data class FameRank( + val name: String, + val fameRequired: Int, + val bitsMultiplier: Double, + val electionVotes: Int +) diff --git a/src/main/java/at/hannibal2/skyhanni/data/GuiEditManager.kt b/src/main/java/at/hannibal2/skyhanni/data/GuiEditManager.kt index 4fbebe958..ee9a6a23a 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/GuiEditManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/GuiEditManager.kt @@ -3,8 +3,10 @@ package at.hannibal2.skyhanni.data import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.config.core.config.Position import at.hannibal2.skyhanni.config.core.config.gui.GuiPositionEditor +import at.hannibal2.skyhanni.events.GuiPositionMovedEvent import at.hannibal2.skyhanni.events.GuiRenderEvent import at.hannibal2.skyhanni.events.LorenzKeyPressEvent +import at.hannibal2.skyhanni.events.LorenzTickEvent import at.hannibal2.skyhanni.test.SkyHanniDebugsAndTests import at.hannibal2.skyhanni.utils.ChatUtils import at.hannibal2.skyhanni.utils.LorenzUtils.isRancherSign @@ -51,11 +53,20 @@ class GuiEditManager { currentPositions.clear() } + @SubscribeEvent + fun onTick(event: LorenzTickEvent) { + lastMovedGui?.let { + GuiPositionMovedEvent(it).postAndCatch() + lastMovedGui = null + } + } + companion object { var currentPositions = mutableMapOf<String, Position>() private var latestPositions = mapOf<String, Position>() private var currentBorderSize = mutableMapOf<String, Pair<Int, Int>>() + private var lastMovedGui: String? = null @JvmStatic fun add(position: Position, posLabel: String, x: Int, y: Int) { @@ -116,6 +127,10 @@ class GuiEditManager { fun GuiProfileViewer.anyTextBoxFocused() = this.getPropertiesWithType<GuiElementTextField>().any { it.focus } + + fun handleGuiPositionMoved(guiName: String) { + lastMovedGui = guiName + } } } diff --git a/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt b/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt index b206eb565..c347fcdba 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt @@ -300,9 +300,12 @@ class HypixelData { private fun checkIsland() { var newIsland = "" var guesting = false + TabListData.fullyLoaded = false + for (line in TabListData.getTabList()) { islandNamePattern.matchMatcher(line) { newIsland = group("island").removeColor() + TabListData.fullyLoaded = true } if (line == " Status: §r§9Guest") { guesting = true diff --git a/src/main/java/at/hannibal2/skyhanni/data/MaxwellAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/MaxwellAPI.kt new file mode 100644 index 000000000..0f19854f7 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/data/MaxwellAPI.kt @@ -0,0 +1,152 @@ +package at.hannibal2.skyhanni.data + +import at.hannibal2.skyhanni.data.jsonobjects.repo.MaxwellPowersJson +import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent +import at.hannibal2.skyhanni.events.LorenzChatEvent +import at.hannibal2.skyhanni.events.RepositoryReloadEvent +import at.hannibal2.skyhanni.test.command.ErrorManager +import at.hannibal2.skyhanni.utils.ItemUtils.getLore +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland +import at.hannibal2.skyhanni.utils.NumberUtil.formatInt +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.StringUtils.removeResets +import at.hannibal2.skyhanni.utils.StringUtils.trimWhiteSpace +import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern +import net.minecraft.enchantment.Enchantment +import net.minecraft.enchantment.Enchantment.power +import net.minecraft.item.ItemStack +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +object MaxwellAPI { + + private val storage get() = ProfileStorageData.profileSpecific + + var currentPower: String? + get() = storage?.maxwell?.currentPower + set(value) { + storage?.maxwell?.currentPower = value ?: return + } + var magicalPower: Int? + get() = storage?.maxwell?.magicalPower + set(value) { + storage?.maxwell?.magicalPower = value ?: return + } + + private var powers = mutableListOf<String>() + + private val group = RepoPattern.group("data.maxwell") + private val chatPowerpattern by group.pattern( + "chat.power", + "§eYou selected the §a(?<power>.*) §e(power )?for your §aAccessory Bag§e!" + ) + private val inventoryPowerPattern by group.pattern( + "inventory.power", + "§7Selected Power: §a(?<power>.*)" + ) + private val inventoryMPPattern by group.pattern( + "inventory.magicalpower", + "§7Magical Power: §6(?<mp>[\\d,]+)" + ) + private val thaumaturgyGuiPattern by group.pattern( + "gui.thaumaturgy", + "Accessory Bag Thaumaturgy" + ) + private val yourBagsGuiPattern by group.pattern( + "gui.yourbags", + "Your Bags" + ) + private val powerSelectedPattern by group.pattern( + "gui.selectedpower", + "§aPower is selected!" + ) + + @SubscribeEvent + fun onChat(event: LorenzChatEvent) { + if (!isEnabled()) return + val message = event.message.trimWhiteSpace().removeResets() + + chatPowerpattern.matchMatcher(message) { + val power = group("power") + currentPower = getPowerByNameOrNull(power) + ?: return ErrorManager.logErrorWithData( + UnknownMaxwellPower("Unknown power: $power"), + "Unknown power: $power", + "power" to power, + "message" to message + ) + } + } + + @SubscribeEvent + fun onInventoryFullyLoaded(event: InventoryFullyOpenedEvent) { + if (!isEnabled()) return + + if (thaumaturgyGuiPattern.matches(event.inventoryName)) { + val selectedPowerStack = + event.inventoryItems.values.find { + powerSelectedPattern.matches(it.getLore().lastOrNull()) + } ?: return + val displayName = selectedPowerStack.displayName.removeColor() + + currentPower = getPowerByNameOrNull(displayName) + ?: return ErrorManager.logErrorWithData( + UnknownMaxwellPower("Unknown power: $power"), + "Unknown power: $power", + "power" to power, + "displayName" to displayName, + "lore" to selectedPowerStack.getLore() + ) + return + } + + if (yourBagsGuiPattern.matches(event.inventoryName)) { + val stacks = event.inventoryItems + + for (stack in stacks.values) { + processStack(stack) + } + } + } + + private fun processStack(stack: ItemStack) { + for (line in stack.getLore()) { + inventoryMPPattern.matchMatcher(line) { + // MagicalPower is boosted in catacombs + if (IslandType.CATACOMBS.isInIsland()) return@matchMatcher + + val mp = group("mp") + magicalPower = mp.formatInt() + return@matchMatcher + } + + inventoryPowerPattern.matchMatcher(line) { + val power = group("power") + currentPower = getPowerByNameOrNull(power) + ?: return@matchMatcher ErrorManager.logErrorWithData( + UnknownMaxwellPower("Unknown power: ${Enchantment.power}"), + "Unknown power: ${Enchantment.power}", + "power" to Enchantment.power, + "displayName" to stack.displayName, + "lore" to stack.getLore() + ) + return@matchMatcher + } + } + } + + private fun getPowerByNameOrNull(name: String) = powers.find { it == name } + + fun isEnabled() = LorenzUtils.inSkyBlock && storage != null + + // Load powers from repo + @SubscribeEvent + fun onRepoLoad(event: RepositoryReloadEvent) { + val data = event.getConstant<MaxwellPowersJson>("MaxwellPowers") + powers = data.powers + } + + class UnknownMaxwellPower(message: String) : Exception(message) +} diff --git a/src/main/java/at/hannibal2/skyhanni/data/MayorAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/MayorAPI.kt new file mode 100644 index 000000000..bc937a5a2 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/data/MayorAPI.kt @@ -0,0 +1,121 @@ +package at.hannibal2.skyhanni.data + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.config.ConfigManager +import at.hannibal2.skyhanni.data.Mayor.Companion.setMayorWithActivePerks +import at.hannibal2.skyhanni.data.jsonobjects.local.MayorJson +import at.hannibal2.skyhanni.events.DebugDataCollectEvent +import at.hannibal2.skyhanni.events.LorenzTickEvent +import at.hannibal2.skyhanni.utils.APIUtil +import at.hannibal2.skyhanni.utils.CollectionUtils.put +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.SimpleTimeMark +import at.hannibal2.skyhanni.utils.SimpleTimeMark.Companion.asTimeMark +import io.github.moulberry.notenoughupdates.util.SkyBlockTime +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import kotlin.time.Duration +import kotlin.time.Duration.Companion.minutes + +object MayorAPI { + var lastUpdate = SimpleTimeMark.farPast() + private var dispatcher = Dispatchers.IO + + private var rawMayorData: MayorJson? = null + var candidates = mapOf<Int, MayorJson.Candidate>() + private set + var currentMayor: Mayor? = null + private set + var timeTillNextMayor = Duration.ZERO + private set + + private const val ELECTION_END_MONTH = 3 //Late Spring + private const val ELECTION_END_DAY = 27 + + /** + * @param input: The name of the mayor + * @return: The neu color of the mayor; If no mayor was found, it will return "§cUnknown: §7" + */ + fun mayorNameToColorCode(input: String): String { + return Mayor.getMayorFromName(input).color + } + + /** + * @param input: The name of the mayor + * @return: The neu color of the mayor + the name of the mayor; If no mayor was found, it will return "§cUnknown: §7[input]" + */ + fun mayorNameWithColorCode(input: String) = mayorNameToColorCode(input) + input + + @SubscribeEvent + fun onTick(event: LorenzTickEvent) { + if (!LorenzUtils.onHypixel) return + + if (event.repeatSeconds(2)) { + checkHypixelAPI() + getTimeTillNextMayor() + } + } + + private fun calculateNextMayorTime(): SimpleTimeMark { + var mayorYear = SkyBlockTime.now().year + + // Check if either the month is already over or the day is after 27th in the third month + if (SkyBlockTime.now().month > ELECTION_END_MONTH || (SkyBlockTime.now().day >= ELECTION_END_DAY && SkyBlockTime.now().month == ELECTION_END_MONTH)) { + // If so, the next mayor will be in the next year + mayorYear++ + } + + return SkyBlockTime(mayorYear, ELECTION_END_MONTH, day = ELECTION_END_DAY).asTimeMark() + } + + private fun getTimeTillNextMayor() { + val nextMayorTime = calculateNextMayorTime() + timeTillNextMayor = nextMayorTime - SimpleTimeMark.now() + } + + private fun checkCurrentMayor() { + val nextMayorTime = calculateNextMayorTime() + + // Check if it is still the mayor from the old SkyBlock year + currentMayor = candidates[nextMayorTime.toSkyBlockTime().year - 1]?.let { + // TODO: Once Jerry is active, add the sub mayor perks in here + setMayorWithActivePerks(it.name, it.perks) + } + } + + private fun checkHypixelAPI() { + if (lastUpdate.passedSince() < 20.minutes) return + lastUpdate = SimpleTimeMark.now() + + SkyHanniMod.coroutineScope.launch { + val url = "https://api.hypixel.net/v2/resources/skyblock/election" + val jsonObject = withContext(dispatcher) { APIUtil.getJSONResponse(url) } + rawMayorData = ConfigManager.gson.fromJson(jsonObject, MayorJson::class.java) + val data = rawMayorData ?: return@launch + val map = mutableMapOf<Int, MayorJson.Candidate>() + map put data.mayor.election.getPairs() + data.current?.let { + map put data.current.getPairs() + } + candidates = map + checkCurrentMayor() + } + } + + private fun MayorJson.Election.getPairs() = year + 1 to candidates.bestCandidate() + + private fun List<MayorJson.Candidate>.bestCandidate() = maxBy { it.votes } + + @SubscribeEvent + fun onDebugDataCollect(event: DebugDataCollectEvent) { + event.title("Mayor") + event.addIrrelevant { + add("Current Mayor: ${currentMayor?.name ?: "Unknown"}") + add("Active Perks: ${currentMayor?.activePerks}") + add("Last Update: $lastUpdate (${lastUpdate.passedSince()} ago)") + add("Time Till Next Mayor: $timeTillNextMayor") + } + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/data/MayorElection.kt b/src/main/java/at/hannibal2/skyhanni/data/MayorElection.kt deleted file mode 100644 index e73a6bf14..000000000 --- a/src/main/java/at/hannibal2/skyhanni/data/MayorElection.kt +++ /dev/null @@ -1,79 +0,0 @@ -package at.hannibal2.skyhanni.data - -import at.hannibal2.skyhanni.SkyHanniMod -import at.hannibal2.skyhanni.config.ConfigManager -import at.hannibal2.skyhanni.data.jsonobjects.local.MayorJson -import at.hannibal2.skyhanni.events.LorenzTickEvent -import at.hannibal2.skyhanni.utils.APIUtil -import at.hannibal2.skyhanni.utils.CollectionUtils.put -import at.hannibal2.skyhanni.utils.LorenzUtils -import at.hannibal2.skyhanni.utils.SimpleTimeMark -import io.github.moulberry.notenoughupdates.util.SkyBlockTime -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent -import kotlin.time.Duration.Companion.minutes - -class MayorElection { - - private var lastUpdate = SimpleTimeMark.farPast() - private var dispatcher = Dispatchers.IO - - companion object { - - var rawMayorData: MayorJson? = null - var candidates = mapOf<Int, MayorJson.Candidate>() - var currentCandidate: MayorJson.Candidate? = null - - fun isPerkActive(mayor: String, perk: String) = currentCandidate?.let { currentCandidate -> - currentCandidate.name == mayor && currentCandidate.perks.any { it.name == perk } - } ?: false - } - - @SubscribeEvent - fun onTick(event: LorenzTickEvent) { - if (!LorenzUtils.onHypixel) return - - if (event.repeatSeconds(3)) { - check() - } - } - - private fun check() { - if (lastUpdate.passedSince() < 20.minutes) return - lastUpdate = SimpleTimeMark.now() - - SkyHanniMod.coroutineScope.launch { - val url = "https://api.hypixel.net/v2/resources/skyblock/election" - val jsonObject = withContext(dispatcher) { APIUtil.getJSONResponse(url) } - rawMayorData = ConfigManager.gson.fromJson(jsonObject, MayorJson::class.java) - val data = rawMayorData ?: return@launch - val map = mutableMapOf<Int, MayorJson.Candidate>() - map put data.mayor.election.getPairs() - data.current?.let { - map put data.current.getPairs() - } - candidates = map - checkCurrentMayor() - } - } - - private fun checkCurrentMayor() { - var currentYear = SkyBlockTime.now().year - - // The time in the current SkyBlock year when the election circle will restart - val month = 3 // Late Spring - val nextMayorTime = SkyBlockTime(currentYear, month, day = 27).toMillis() - - // Is it still the mayor from old sb year? - if (nextMayorTime > System.currentTimeMillis()) { - currentYear-- - } - currentCandidate = candidates[currentYear] - } - - private fun MayorJson.Election.getPairs() = year + 1 to candidates.bestCandidate() - - private fun List<MayorJson.Candidate>.bestCandidate() = maxBy { it.votes } -} diff --git a/src/main/java/at/hannibal2/skyhanni/data/Mayors.kt b/src/main/java/at/hannibal2/skyhanni/data/Mayors.kt new file mode 100644 index 000000000..cd6205c7a --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/data/Mayors.kt @@ -0,0 +1,105 @@ +package at.hannibal2.skyhanni.data + +import at.hannibal2.skyhanni.data.jsonobjects.local.MayorJson + +enum class Mayor( + val mayorName: String, + val color: String, + private vararg val perks: Perk, +) { + AATROX("Aatrox", "§3", Perk.SLASHED_PRICING, Perk.SLAYER_XP_BUFF, Perk.PATHFINDER), + COLE("Cole", "§e", Perk.PROSPECTION, Perk.MINING_XP_BUFF, Perk.MINING_FIESTA), + DIANA("Diana", "§2", Perk.LUCKY, Perk.MYTHOLOGICAL_RITUAL, Perk.PET_XP_BUFF), + DIAZ("Diaz", "§6", Perk.BARRIER_STREET, Perk.SHOPPING_SPREE), + FINNEGAN("Finnegan", "§c", Perk.FARMING_SIMULATOR, Perk.PELT_POCALYPSE, Perk.GOATED), + FOXY("Foxy", "§d", Perk.SWEET_TOOTH, Perk.BENEVOLENCE, Perk.EXTRA_EVENT), + MARINA("Marina", "§b", Perk.FISHING_XP_BUFF, Perk.LUCK_OF_THE_SEA, Perk.FISHING_FESTIVAL), + PAUL("Paul", "§c", Perk.MARAUDER, Perk.EZPZ, Perk.BENEDICTION), + + SCORPIUS("Scorpius", "§d", Perk.BRIBE, Perk.DARKER_AUCTIONS), + JERRY("Jerry", "§d", Perk.PERKPOCALYPSE, Perk.STATSPOCALYPSE, Perk.JERRYPOCALYPSE), + DERPY("Derpy", "§d", Perk.TURBO_MINIONS, Perk.AH_CLOSED, Perk.DOUBLE_MOBS_HP, Perk.MOAR_SKILLZ), + + UNKNOWN("Unknown", "§c"), + ; + + val activePerks: MutableList<Perk> = mutableListOf() + + companion object { + fun getMayorFromName(name: String) = entries.firstOrNull { it.mayorName == name } ?: UNKNOWN + + fun setMayorWithActivePerks(name: String, perks: ArrayList<MayorJson.Perk>): Mayor { + val mayor = getMayorFromName(name) + + mayor.perks.forEach { it.isActive = false } + mayor.activePerks.clear() + perks.mapNotNull { perk -> Perk.entries.firstOrNull { it.perkName == perk.name } } + .filter { mayor.perks.contains(it) }.forEach { + it.isActive = true + mayor.activePerks.add(it) + } + + return mayor + } + } +} + +enum class Perk(val perkName: String) { + // Aatrox + SLASHED_PRICING("SLASHED Pricing"), + SLAYER_XP_BUFF("Slayer XP Buff"), + PATHFINDER("Pathfinder"), + + // Cole + PROSPECTION("Prospection"), + MINING_XP_BUFF("Mining XP Buff"), + MINING_FIESTA("Mining Fiesta"), + + // Diana + LUCKY("Lucky!"), + MYTHOLOGICAL_RITUAL("Mythological Ritual"), + PET_XP_BUFF("Pet XP Buff"), + + // Diaz + BARRIER_STREET("Barrier Street"), + SHOPPING_SPREE("Shopping Spree"), + + // Finnegan + FARMING_SIMULATOR("Farming Simulator"), + PELT_POCALYPSE("Pelt-pocalypse"), + GOATED("GOATed"), + + // Foxy + SWEET_TOOTH("Sweet Tooth"), + BENEVOLENCE("Benevolence"), + EXTRA_EVENT("Extra Event"), + + // Marina + FISHING_XP_BUFF("Fishing XP Buff"), + LUCK_OF_THE_SEA("Luck of the Sea 2.0"), + FISHING_FESTIVAL("Fishing Festival"), + + // Paul + MARAUDER("Marauder"), + EZPZ("EZPZ"), + BENEDICTION("Benediction"), + + + // Scorpius + BRIBE("Bribe"), + DARKER_AUCTIONS("Darker Auctions"), + + // Jerry + PERKPOCALYPSE("Perkpocalypse"), + STATSPOCALYPSE("Statspocalypse"), + JERRYPOCALYPSE("Jerrypocalypse"), + + // Derpy + TURBO_MINIONS("TURBO MINIONS!!!"), + AH_CLOSED("AH CLOSED!!!"), + DOUBLE_MOBS_HP("DOUBLE MOBS HP!!!"), + MOAR_SKILLZ("MOAR SKILLZ!!!"), + ; + + var isActive = false +} |
