diff options
6 files changed, 124 insertions, 26 deletions
diff --git a/.idea/dictionaries/default_user.xml b/.idea/dictionaries/default_user.xml index 1cc3cc669..a153ecd75 100644 --- a/.idea/dictionaries/default_user.xml +++ b/.idea/dictionaries/default_user.xml @@ -126,6 +126,7 @@ <w>opti</w> <w>oruo</w> <w>packmaster</w> + <w>perkpocalypse</w> <w>pickblock</w> <w>pickonimbus</w> <w>preinitialization</w> diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/MayorConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/MayorConfig.java index 0dbc4da0f..ed6abdc7c 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/MayorConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/MayorConfig.java @@ -14,4 +14,10 @@ public class MayorConfig { @ConfigOption(name = "Show Time till next mayor", desc = "Show the time till the next mayor is elected.") @ConfigEditorBoolean public boolean showTimeTillNextMayor = true; + + @Expose + // TODO: Same Toggle toggles ministers + @ConfigOption(name = "Show Extra Mayor", desc = "Show the Perkacolypse Mayor without their perks.") + @ConfigEditorBoolean + public boolean showExtraMayor = true; } diff --git a/src/main/java/at/hannibal2/skyhanni/data/MayorAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/MayorAPI.kt index 584d2291f..a2d2300b1 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/MayorAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/MayorAPI.kt @@ -2,55 +2,81 @@ package at.hannibal2.skyhanni.data import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.config.ConfigManager +import at.hannibal2.skyhanni.data.Mayor.Companion.getMayorFromPerk import at.hannibal2.skyhanni.data.Mayor.Companion.setAssumeMayor import at.hannibal2.skyhanni.data.Mayor.Companion.setAssumeMayorJson +import at.hannibal2.skyhanni.data.Perk.Companion.getPerkFromName import at.hannibal2.skyhanni.data.jsonobjects.other.MayorCandidate import at.hannibal2.skyhanni.data.jsonobjects.other.MayorElection import at.hannibal2.skyhanni.data.jsonobjects.other.MayorJson import at.hannibal2.skyhanni.events.ConfigLoadEvent import at.hannibal2.skyhanni.events.DebugDataCollectEvent +import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent import at.hannibal2.skyhanni.events.LorenzChatEvent import at.hannibal2.skyhanni.events.SecondPassedEvent import at.hannibal2.skyhanni.utils.APIUtil +import at.hannibal2.skyhanni.utils.ChatUtils +import at.hannibal2.skyhanni.utils.CollectionUtils.nextAfter import at.hannibal2.skyhanni.utils.CollectionUtils.put import at.hannibal2.skyhanni.utils.ConditionalUtils.onToggle +import at.hannibal2.skyhanni.utils.HypixelCommands +import at.hannibal2.skyhanni.utils.ItemUtils.getLore import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.RegexUtils.matches import at.hannibal2.skyhanni.utils.SimpleTimeMark import at.hannibal2.skyhanni.utils.SimpleTimeMark.Companion.asTimeMark import at.hannibal2.skyhanni.utils.SkyBlockTime +import at.hannibal2.skyhanni.utils.SkyBlockTime.Companion.SKYBLOCK_YEAR_MILLIS +import at.hannibal2.skyhanni.utils.StringUtils.removeColor import at.hannibal2.skyhanni.utils.json.fromJson import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import net.minecraft.item.ItemStack import net.minecraftforge.fml.common.eventhandler.SubscribeEvent -import kotlin.time.Duration +import kotlin.time.Duration.Companion.hours +import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.minutes object MayorAPI { - val group = RepoPattern.group("mayorapi") + private val group = RepoPattern.group("mayorapi") val foxyExtraEventPattern by group.pattern( "foxy.extraevent", "Schedules an extra §.(?<event>.*) §.event during the year\\." ) - private val electionOver by group.pattern( + private val electionOverPattern by group.pattern( "election.over", "§eThe election room is now closed\\. Clerk Seraphine is doing a final count of the votes\\.\\.\\." ) + private val calendarGuiPattern by group.pattern( + "calendar.gui", + "Calendar and Events" + ) + private val jerryHeadPattern by group.pattern( + "jerry.head", + "§dMayor Jerry" + ) + // TODO add regex tests + private val perkpocalypsePerksPattern by group.pattern( + "perkpocalypse", + "§9Perkpocalypse Perks:" + ) + var currentMayor: Mayor? = null + private set + var jerryExtraMayor: Pair<Mayor?, SimpleTimeMark> = null to SimpleTimeMark.farPast() + private set private var lastMayor: Mayor? = null - var lastUpdate = SimpleTimeMark.farPast() + private var lastUpdate = SimpleTimeMark.farPast() private var dispatcher = Dispatchers.IO private var rawMayorData: MayorJson? = null - var candidates = mapOf<Int, MayorCandidate>() - private set - var currentMayor: Mayor? = null - private set - var timeTillNextMayor = Duration.ZERO + private var candidates = mapOf<Int, MayorCandidate>() + + var nextMayorTimestamp = SimpleTimeMark.farPast() private set private const val ELECTION_END_MONTH = 3 // Late Spring @@ -75,18 +101,52 @@ object MayorAPI { checkHypixelAPI() getTimeTillNextMayor() } + + if (!LorenzUtils.inSkyBlock) return + if (jerryExtraMayor.first != null && jerryExtraMayor.second.isInPast() && Mayor.JERRY.isActive()) { + jerryExtraMayor = null to SimpleTimeMark.farPast() + ChatUtils.clickableChat( + "The Perkpocalypse Mayor has expired! Click here to update to the new temporary Mayor.", + onClick = { HypixelCommands.calendar() } + ) + } } @SubscribeEvent fun onChat(event: LorenzChatEvent) { - if (!LorenzUtils.onHypixel) return + if (!LorenzUtils.inSkyBlock) return - if (electionOver.matches(event.message)) { + if (electionOverPattern.matches(event.message)) { lastMayor = currentMayor currentMayor = Mayor.UNKNOWN } } + @SubscribeEvent + fun onInventory(event: InventoryFullyOpenedEvent) { + if (!LorenzUtils.inSkyBlock) return + + if (!calendarGuiPattern.matches(event.inventoryName)) return + + val stack: ItemStack = + event.inventoryItems.values.firstOrNull { jerryHeadPattern.matches(it.displayName) } ?: return + + stack.getLore().nextAfter( + { perkpocalypsePerksPattern.matches(it) } + )?.let { perk -> + // This is one Perk of the Perkpocalypse Mayor + val jerryMayor = getMayorFromPerk(getPerkFromName(perk.removeColor()) ?: return)?.addAllPerks() ?: return + + val lastMayorTimestamp = nextMayorTimestamp - SKYBLOCK_YEAR_MILLIS.milliseconds + + val expireTime = (1..21).map { lastMayorTimestamp + (6.hours * it) }.first { it.isInFuture() } + + ChatUtils.debug("Jerry Mayor found: ${jerryMayor.name} expiring at: ${expireTime.timeUntil()}") + + jerryExtraMayor = jerryMayor to expireTime + } + } + private fun calculateNextMayorTime(): SimpleTimeMark { var mayorYear = SkyBlockTime.now().year @@ -100,8 +160,7 @@ object MayorAPI { } private fun getTimeTillNextMayor() { - val nextMayorTime = calculateNextMayorTime() - timeTillNextMayor = nextMayorTime - SimpleTimeMark.now() + nextMayorTimestamp = calculateNextMayorTime() } private fun checkCurrentMayor() { @@ -160,7 +219,10 @@ object MayorAPI { add("Current Mayor: ${currentMayor?.name ?: "Unknown"}") add("Active Perks: ${currentMayor?.activePerks}") add("Last Update: $lastUpdate (${lastUpdate.passedSince()} ago)") - add("Time Till Next Mayor: $timeTillNextMayor") + add("Time Till Next Mayor: ${nextMayorTimestamp.timeUntil()}") + if (jerryExtraMayor.first != null) { + add("Jerry Mayor: ${jerryExtraMayor.first?.name} expiring at: ${jerryExtraMayor.second.timeUntil()}") + } } } } diff --git a/src/main/java/at/hannibal2/skyhanni/data/Mayors.kt b/src/main/java/at/hannibal2/skyhanni/data/Mayors.kt index 04c1464e0..ccf74aec2 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/Mayors.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/Mayors.kt @@ -1,5 +1,6 @@ package at.hannibal2.skyhanni.data +import at.hannibal2.skyhanni.data.MayorAPI.currentMayor import at.hannibal2.skyhanni.data.MayorAPI.foxyExtraEventPattern import at.hannibal2.skyhanni.data.jsonobjects.other.MayorPerk import at.hannibal2.skyhanni.test.command.ErrorManager @@ -39,10 +40,20 @@ enum class Mayor( override fun toString() = mayorName + fun addAllPerks(): Mayor { + activePerks.addAll(perks) + perks.forEach { it.isActive = true } + return this + } + + fun isActive() = this == currentMayor + companion object { fun getMayorFromName(name: String): Mayor? = entries.firstOrNull { it.mayorName == name } + fun getMayorFromPerk(perk: Perk): Mayor? = entries.firstOrNull { it.perks.contains(perk) } + fun setAssumeMayorJson(name: String, perksJson: List<MayorPerk>): Mayor? { val mayor = getMayorFromName(name) if (mayor == null) { @@ -146,4 +157,8 @@ enum class Perk(val perkName: String) { ; var isActive = false + + companion object { + fun getPerkFromName(name: String): Perk? = entries.firstOrNull { it.perkName == name } + } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardElements.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardElements.kt index 4bc3fe36a..ef02cf2ba 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardElements.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardElements.kt @@ -745,20 +745,34 @@ private fun getEventsDisplayPair(): List<ScoreboardElementType> { private fun getEventsShowWhen() = ScoreboardEvents.getEvent().isNotEmpty() private fun getMayorDisplayPair() = buildList { - add( - ((MayorAPI.currentMayor?.mayorName?.let { MayorAPI.mayorNameWithColorCode(it) } - ?: "<hidden>") + - (if (mayorConfig.showTimeTillNextMayor) { - "§7 (§e${MayorAPI.timeTillNextMayor.format(maxUnits = 2)}§7)" - } else { - "" - })) to HorizontalAlignment.LEFT - ) + val currentMayorName = MayorAPI.currentMayor?.mayorName?.let { MayorAPI.mayorNameWithColorCode(it) } ?: "<hidden>" + val timeTillNextMayor = if (mayorConfig.showTimeTillNextMayor) { + "§7 (§e${MayorAPI.nextMayorTimestamp.timeUntil().format(maxUnits = 2)}§7)" + } else { + "" + } + + add((currentMayorName + timeTillNextMayor) to HorizontalAlignment.LEFT) + if (mayorConfig.showMayorPerks) { - MayorAPI.currentMayor?.activePerks?.forEach { - add(" §7- §e${it.perkName}" to HorizontalAlignment.LEFT) + MayorAPI.currentMayor?.activePerks?.forEach { perk -> + add(" §7- §e${perk.perkName}" to HorizontalAlignment.LEFT) } } + + if (!mayorConfig.showExtraMayor) return@buildList + val jerryExtraMayor = MayorAPI.jerryExtraMayor + val extraMayor = jerryExtraMayor.first ?: return@buildList + + val extraMayorName = extraMayor.mayorName.let { MayorAPI.mayorNameWithColorCode(it) } + val extraTimeTillNextMayor = if (mayorConfig.showTimeTillNextMayor) { + "§7 (§6${jerryExtraMayor.second.timeUntil().format(maxUnits = 2)}§7)" + } else { + "" + } + + add((extraMayorName + extraTimeTillNextMayor) to HorizontalAlignment.LEFT) + } private fun getMayorShowWhen() = diff --git a/src/main/java/at/hannibal2/skyhanni/utils/SkyBlockTime.kt b/src/main/java/at/hannibal2/skyhanni/utils/SkyBlockTime.kt index b07729715..1fc21df52 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/SkyBlockTime.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/SkyBlockTime.kt @@ -27,7 +27,7 @@ data class SkyBlockTime( companion object { private const val SKYBLOCK_EPOCH_START_MILLIS = 1559829300000L // Day 1, Year 1 - private const val SKYBLOCK_YEAR_MILLIS = 124 * 60 * 60 * 1000L + const val SKYBLOCK_YEAR_MILLIS = 124 * 60 * 60 * 1000L private const val SKYBLOCK_MONTH_MILLIS = SKYBLOCK_YEAR_MILLIS / 12 private const val SKYBLOCK_DAY_MILLIS = SKYBLOCK_MONTH_MILLIS / 31 private const val SKYBLOCK_HOUR_MILLIS = SKYBLOCK_DAY_MILLIS / 24 |