aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authormartimavocado <39881008+martimavocado@users.noreply.github.com>2024-03-09 12:19:52 +0000
committerGitHub <noreply@github.com>2024-03-09 13:19:52 +0100
commitd902e7db8a51ff7d6ca6ed50e0d0e62793c9f502 (patch)
tree86415b9f5ecc671645c4dc46bce50d696e9d656c /src/main/java
parentafbd5b2798be6c6ea611be521a9f7cd0e43497d1 (diff)
downloadskyhanni-d902e7db8a51ff7d6ca6ed50e0d0e62793c9f502.tar.gz
skyhanni-d902e7db8a51ff7d6ca6ed50e0d0e62793c9f502.tar.bz2
skyhanni-d902e7db8a51ff7d6ca6ed50e0d0e62793c9f502.zip
Feature: Limbo time PB v2 (#848)
Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com>
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt6
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt4
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/Storage.java15
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt10
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/misc/MiscConfig.java3
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/commands/PartyCommands.kt5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/LimboTimeTracker.kt85
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/MiscFeatures.kt5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/limbo/LimboPlaytime.kt139
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/limbo/LimboTimeTracker.kt192
10 files changed, 373 insertions, 91 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt
index f1591f5c6..465e2efc2 100644
--- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt
+++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt
@@ -257,7 +257,6 @@ import at.hannibal2.skyhanni.features.misc.HideArmor
import at.hannibal2.skyhanni.features.misc.InGameDateDisplay
import at.hannibal2.skyhanni.features.misc.JoinCrystalHollows
import at.hannibal2.skyhanni.features.misc.LesserOrbHider
-import at.hannibal2.skyhanni.features.misc.LimboTimeTracker
import at.hannibal2.skyhanni.features.misc.LockMouseLook
import at.hannibal2.skyhanni.features.misc.MarkedPlayerManager
import at.hannibal2.skyhanni.features.misc.MiscFeatures
@@ -287,6 +286,8 @@ import at.hannibal2.skyhanni.features.misc.items.AuctionHouseCopyUnderbidPrice
import at.hannibal2.skyhanni.features.misc.items.EstimatedItemValue
import at.hannibal2.skyhanni.features.misc.items.EstimatedWardrobePrice
import at.hannibal2.skyhanni.features.misc.items.GlowingDroppedItems
+import at.hannibal2.skyhanni.features.misc.limbo.LimboPlaytime
+import at.hannibal2.skyhanni.features.misc.limbo.LimboTimeTracker
import at.hannibal2.skyhanni.features.misc.massconfiguration.DefaultConfigFeatures
import at.hannibal2.skyhanni.features.misc.teleportpad.TeleportPadCompactName
import at.hannibal2.skyhanni.features.misc.teleportpad.TeleportPadInventoryNumber
@@ -732,7 +733,7 @@ class SkyHanniMod {
loadModule(FixNEUHeavyPearls())
loadModule(QuickCraftFeatures())
loadModule(SkyBlockKickDuration())
- loadModule(LimboTimeTracker())
+ loadModule(LimboTimeTracker)
loadModule(PartyMemberOutlines())
loadModule(ArrowTrail())
loadModule(ShiftClickEquipment())
@@ -762,6 +763,7 @@ class SkyHanniMod {
loadModule(MaxPurseItems())
loadModule(SuperCraftFeatures())
loadModule(InfernoMinionFeatures())
+ loadModule(LimboPlaytime())
init()
diff --git a/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt b/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt
index 824cb4e9f..fd6fba7e6 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt
+++ b/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt
@@ -1,6 +1,7 @@
package at.hannibal2.skyhanni.config
import at.hannibal2.skyhanni.events.LorenzEvent
+import at.hannibal2.skyhanni.features.misc.limbo.LimboTimeTracker
import at.hannibal2.skyhanni.utils.LorenzLogger
import at.hannibal2.skyhanni.utils.LorenzUtils.asIntOrNull
import com.google.gson.JsonElement
@@ -10,7 +11,7 @@ import com.google.gson.JsonPrimitive
object ConfigUpdaterMigrator {
val logger = LorenzLogger("ConfigMigration")
- const val CONFIG_VERSION = 26
+ const val CONFIG_VERSION = 27
fun JsonElement.at(chain: List<String>, init: Boolean): JsonElement? {
if (chain.isEmpty()) return this
if (this !is JsonObject) return null
@@ -81,6 +82,7 @@ object ConfigUpdaterMigrator {
return
}
movesPerformed++
+ if (np == listOf("#player", "personalBest")) LimboTimeTracker.workaroundMigration(oldElem.asInt)
newParentElement.add(np.last(), transform(oldElem))
logger.log("Moved element from $oldPath to $newPath")
}
diff --git a/src/main/java/at/hannibal2/skyhanni/config/Storage.java b/src/main/java/at/hannibal2/skyhanni/config/Storage.java
index fd6f5da69..014eccee2 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/Storage.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/Storage.java
@@ -119,6 +119,21 @@ public class Storage {
@Expose
public Map<Integer, BingoGoal> goals = new HashMap<>();
}
+
+ @Expose
+ public LimboStats limbo = new LimboStats();
+
+ public static class LimboStats {
+
+ @Expose
+ public int playtime = 0;
+
+ @Expose
+ public int personalBest = 0;
+
+ @Expose
+ public float userLuck = 0f;
+ }
}
public static class ProfileSpecific {
diff --git a/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt b/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt
index 68f3f1acc..e0a9a74b6 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt
+++ b/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt
@@ -48,7 +48,9 @@ import at.hannibal2.skyhanni.features.minion.MinionFeatures
import at.hannibal2.skyhanni.features.misc.CollectionTracker
import at.hannibal2.skyhanni.features.misc.LockMouseLook
import at.hannibal2.skyhanni.features.misc.MarkedPlayerManager
+import at.hannibal2.skyhanni.features.misc.MiscFeatures
import at.hannibal2.skyhanni.features.misc.discordrpc.DiscordRPCManager
+import at.hannibal2.skyhanni.features.misc.limbo.LimboTimeTracker
import at.hannibal2.skyhanni.features.misc.massconfiguration.DefaultConfigFeatures
import at.hannibal2.skyhanni.features.misc.visualwords.VisualWordGui
import at.hannibal2.skyhanni.features.rift.area.westvillage.VerminTracker
@@ -280,6 +282,14 @@ object Commands {
{ SkillAPI.onCommand(it) },
SkillAPI::onComplete
)
+ registerCommand(
+ "shlimbostats",
+ "Prints your Limbo Stats!"
+ ) { LimboTimeTracker.printStats() }
+ registerCommand(
+ "shlimbo",
+ "Warps you to Limbo."
+ ) { MiscFeatures().goToLimbo() }
}
private fun usersBugFix() {
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/misc/MiscConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/misc/MiscConfig.java
index 0532d9424..077bd8303 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/misc/MiscConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/misc/MiscConfig.java
@@ -251,9 +251,6 @@ public class MiscConfig {
public Position inventoryLoadPos = new Position(394, 124, false, true);
@Expose
- public int limboTimePB = 0;
-
- @Expose
@ConfigOption(name = "Fix Ghost Entities", desc = "Removes ghost entities caused by a Hypixel bug. " +
"This included Diana, Dungeon and Crimson Isle mobs and nametags.")
@ConfigEditorBoolean
diff --git a/src/main/java/at/hannibal2/skyhanni/features/commands/PartyCommands.kt b/src/main/java/at/hannibal2/skyhanni/features/commands/PartyCommands.kt
index 8fcee01d0..25101ce62 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/commands/PartyCommands.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/commands/PartyCommands.kt
@@ -5,6 +5,7 @@ import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator
import at.hannibal2.skyhanni.data.FriendAPI
import at.hannibal2.skyhanni.data.PartyAPI
import at.hannibal2.skyhanni.events.MessageSendToServerEvent
+import at.hannibal2.skyhanni.features.misc.limbo.LimboTimeTracker
import at.hannibal2.skyhanni.utils.ChatUtils
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
@@ -42,6 +43,10 @@ object PartyCommands {
fun transfer(args: Array<String>) {
if (args.isEmpty()) {
+ if (LimboTimeTracker.inLimbo) {
+ LimboTimeTracker.printStats(true)
+ return
+ }
ChatUtils.sendCommandToServer("pt")
return
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/LimboTimeTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/LimboTimeTracker.kt
deleted file mode 100644
index fbddd5fb0..000000000
--- a/src/main/java/at/hannibal2/skyhanni/features/misc/LimboTimeTracker.kt
+++ /dev/null
@@ -1,85 +0,0 @@
-package at.hannibal2.skyhanni.features.misc
-
-import at.hannibal2.skyhanni.SkyHanniMod
-import at.hannibal2.skyhanni.events.GuiRenderEvent
-import at.hannibal2.skyhanni.events.LorenzChatEvent
-import at.hannibal2.skyhanni.events.LorenzTickEvent
-import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent
-import at.hannibal2.skyhanni.utils.ChatUtils
-import at.hannibal2.skyhanni.utils.LorenzUtils
-import at.hannibal2.skyhanni.utils.LorenzUtils.round
-import at.hannibal2.skyhanni.utils.RenderUtils.renderString
-import at.hannibal2.skyhanni.utils.SimpleTimeMark
-import at.hannibal2.skyhanni.utils.TimeUtils.format
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
-import kotlin.time.Duration
-import kotlin.time.Duration.Companion.seconds
-import kotlin.time.DurationUnit
-
-class LimboTimeTracker {
-
- private val config get() = SkyHanniMod.feature.misc
-
- private var limboJoinTime = SimpleTimeMark.farPast()
- private var inLimbo = false
- private var shownPB = false
- private var oldPB: Duration = 0.seconds
-
- @SubscribeEvent
- fun onChat(event: LorenzChatEvent) {
- if (event.message == "§cYou are AFK. Move around to return from AFK." || event.message == "§cYou were spawned in Limbo.") {
- limboJoinTime = SimpleTimeMark.now()
- inLimbo = true
- }
- }
-
- @SubscribeEvent
- fun onTick(event: LorenzTickEvent) {
- if (inLimbo && !shownPB && limboJoinTime.passedSince() >= config.limboTimePB.seconds && config.limboTimePB != 0) {
- shownPB = true
- oldPB = config.limboTimePB.seconds
- ChatUtils.chat("§d§lPERSONAL BEST§f! You've surpassed your previous record of §e$oldPB§f!")
- ChatUtils.chat("§fKeep it up!")
- }
- }
-
- @SubscribeEvent
- fun onWorldChange(event: LorenzWorldChangeEvent) {
- if (!inLimbo) return
- leaveLimbo()
- }
-
- @SubscribeEvent
- fun onRenderOverlay(event: GuiRenderEvent.GuiOverlayRenderEvent) {
- if (!isEnabled()) return
- if (!inLimbo) return
-
- if (LorenzUtils.inSkyBlock) {
- leaveLimbo()
- return
- }
-
- val duration = limboJoinTime.passedSince().format()
- config.showTimeInLimboPosition.renderString("§eIn limbo since §b$duration", posLabel = "Limbo Time Tracker")
- }
-
- private fun leaveLimbo() {
- inLimbo = false
- if (!isEnabled()) return
- val passedSince = limboJoinTime.passedSince()
- val duration = passedSince.format()
- val userLuckMultiplier = 0.000810185
- val currentPB = config.limboTimePB.seconds
- if (passedSince > currentPB) {
- oldPB = currentPB
- config.limboTimePB = passedSince.toInt(DurationUnit.SECONDS)
- ChatUtils.chat("§fYou were AFK in Limbo for §e$duration§f! §d§lPERSONAL BEST§r§f!")
- ChatUtils.chat("§fYour previous Personal Best was §e$oldPB.")
- val userLuck = config.limboTimePB * userLuckMultiplier
- ChatUtils.chat("§fYour §aPersonal Bests§f perk is now granting you §a+${userLuck.round(2)}✴ SkyHanni User Luck§f!")
- } else ChatUtils.chat("§fYou were AFK in Limbo for §e$duration§f.")
- shownPB = false
- }
-
- fun isEnabled() = config.showTimeInLimbo
-}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/MiscFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/MiscFeatures.kt
index 3b52ee478..32d412d85 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/misc/MiscFeatures.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/MiscFeatures.kt
@@ -3,6 +3,7 @@ package at.hannibal2.skyhanni.features.misc
import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator
import at.hannibal2.skyhanni.events.ReceiveParticleEvent
+import at.hannibal2.skyhanni.utils.ChatUtils
import at.hannibal2.skyhanni.utils.LorenzUtils
import net.minecraft.util.EnumParticleTypes
import net.minecraftforge.client.event.RenderBlockOverlayEvent
@@ -51,4 +52,8 @@ class MiscFeatures {
fun onConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) {
event.move(2, "mobs", "combat.mobs")
}
+
+ fun goToLimbo() {
+ ChatUtils.sendMessageToServer("§")
+ }
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/limbo/LimboPlaytime.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/limbo/LimboPlaytime.kt
new file mode 100644
index 000000000..ceb18770e
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/limbo/LimboPlaytime.kt
@@ -0,0 +1,139 @@
+package at.hannibal2.skyhanni.features.misc.limbo
+
+import at.hannibal2.skyhanni.data.ProfileStorageData
+import at.hannibal2.skyhanni.events.InventoryOpenEvent
+import at.hannibal2.skyhanni.events.LorenzToolTipEvent
+import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.LorenzUtils.round
+import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName
+import at.hannibal2.skyhanni.utils.NEUItems.getItemStack
+import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators
+import at.hannibal2.skyhanni.utils.SimpleTimeMark
+import at.hannibal2.skyhanni.utils.StringUtils.matches
+import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern
+import io.github.moulberry.notenoughupdates.events.ReplaceItemEvent
+import io.github.moulberry.notenoughupdates.util.Utils
+import net.minecraft.client.player.inventory.ContainerLocalMenu
+import net.minecraft.item.ItemStack
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import kotlin.time.Duration.Companion.seconds
+
+class LimboPlaytime {
+ private lateinit var modifiedList: MutableList<String>
+ private var setMinutes = false
+ private val patternGroup = RepoPattern.group("misc.limbo.tooltip")
+ private val minutesPattern by patternGroup.pattern(
+ "minutes",
+ "§5§o§a([\\d.,]+) minutes.+\$"
+ )
+ private val hoursPattern by patternGroup.pattern(
+ "hours",
+ "§5§o§b([\\d.,]+) hours.+\$"
+ )
+
+ private var wholeMinutes: Long = 0
+ private var hoursString: String = ""
+
+ private val storage get() = ProfileStorageData.playerSpecific?.limbo
+
+ private val itemID = "ENDER_PEARL".asInternalName()
+ private val itemName = "§aLimbo"
+ private lateinit var limboItem: ItemStack
+ private var lastCreateCooldown = SimpleTimeMark.farPast()
+
+ @SubscribeEvent
+ fun replaceItem(event: ReplaceItemEvent) {
+ if (event.inventory !is ContainerLocalMenu) return
+ if (event.inventory.displayName.unformattedText != "Detailed /playtime") return
+ if (event.slotNumber != 43) return
+ if (storage?.playtime == 0) return
+
+ if (lastCreateCooldown.passedSince() > 3.seconds) {
+ lastCreateCooldown = SimpleTimeMark.now()
+ limboItem = if (wholeMinutes >= 60) Utils.createItemStack(
+ itemID.getItemStack().item,
+ itemName,
+ "§7Playtime: §a${wholeMinutes.addSeparators()} minutes",
+ "§7Or: §b$hoursString hours"
+ )
+ else Utils.createItemStack(itemID.getItemStack().item, itemName, "§7Playtime: §a$wholeMinutes minutes")
+ }
+ event.replaceWith(limboItem)
+ }
+
+ @SubscribeEvent
+ fun onHoverItem(event: LorenzToolTipEvent) {
+ if (!LorenzUtils.inSkyBlock) return
+ if (!event.slot.inventory.displayName.unformattedText.startsWith("Detailed /playtime")) return
+ if (event.slot.slotIndex != 4) return
+ if (storage?.playtime == 0) return
+
+ val lore = event.toolTip
+ val hoursList = lore.filter { hoursPattern.matches(it) }.toMutableList()
+ val minutesList = lore.filter { minutesPattern.matches(it) }.toMutableList()
+
+ addLimbo(hoursList, minutesList)
+ remakeList(event.toolTip, minutesList, hoursList)
+ }
+
+ @SubscribeEvent
+ fun onRenderGUI(event: InventoryOpenEvent) {
+ if (event.inventoryName != "Detailed /playtime") return
+ val storedPlaytime = storage?.playtime ?: 0
+ if (storedPlaytime < 60) return
+ val playtime = storedPlaytime.seconds
+ val wholeHours = playtime.inWholeHours
+ wholeMinutes = playtime.inWholeMinutes
+ if ((wholeMinutes % 60).toInt() == 0) {
+ hoursString = "$wholeHours"
+ } else {
+ val minutes: Float = ((wholeMinutes - wholeHours * 60).toFloat() / 60)
+ hoursString = wholeHours.addSeparators() + minutes.round(1).toString().replace("0", "")
+ }
+ }
+
+ private fun addLimbo(hoursList: MutableList<String>, minutesList: MutableList<String>) {
+ val storedPlaytime = storage?.playtime ?: 0
+ if (wholeMinutes >= 60) {
+ val hours = storedPlaytime.seconds.inWholeHours
+ val minutes = (storedPlaytime.seconds.inWholeMinutes - (hours * 60).toFloat() / 6).toInt()
+ modifiedList = hoursList
+ if (minutes == 0) modifiedList.add("§5§o§b$hours hours §7on Limbo")
+ else modifiedList.add("§5§o§b$hoursString hours §7on Limbo")
+ modifiedList = modifiedList.sortedByDescending {
+ val matcher = hoursPattern.matcher(it)
+ if (matcher.find()) {
+ matcher.group(1).replace(",", "").toDoubleOrNull() ?: 0.0
+ } else 0.0
+ }.toMutableList()
+ setMinutes = false
+ } else {
+ val minutes = storedPlaytime.seconds.inWholeMinutes
+ modifiedList = minutesList
+ modifiedList.add("§a$minutes minutes §7on Limbo")
+ modifiedList = modifiedList.sortedByDescending {
+ it.substringAfter("§a").substringBefore(" minutes").toDoubleOrNull()
+ }.toMutableList()
+ setMinutes = true
+ }
+ }
+
+ private fun remakeList(
+ toolTip: MutableList<String>,
+ minutesList: MutableList<String>,
+ hoursList: MutableList<String>
+ ) {
+ val firstLine = toolTip.first()
+ val totalPlaytime = toolTip.last()
+ toolTip.clear()
+ toolTip.add(firstLine)
+ if (!setMinutes) {
+ toolTip.addAll(modifiedList)
+ toolTip.addAll(minutesList)
+ } else {
+ toolTip.addAll(hoursList)
+ toolTip.addAll(modifiedList)
+ }
+ toolTip.add(totalPlaytime)
+ }
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/limbo/LimboTimeTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/limbo/LimboTimeTracker.kt
new file mode 100644
index 000000000..fae469050
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/limbo/LimboTimeTracker.kt
@@ -0,0 +1,192 @@
+package at.hannibal2.skyhanni.features.misc.limbo
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator
+import at.hannibal2.skyhanni.data.HypixelData
+import at.hannibal2.skyhanni.data.ProfileStorageData
+import at.hannibal2.skyhanni.events.DebugDataCollectEvent
+import at.hannibal2.skyhanni.events.GuiRenderEvent
+import at.hannibal2.skyhanni.events.HypixelJoinEvent
+import at.hannibal2.skyhanni.events.LorenzChatEvent
+import at.hannibal2.skyhanni.events.LorenzTickEvent
+import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent
+import at.hannibal2.skyhanni.events.MessageSendToServerEvent
+import at.hannibal2.skyhanni.utils.ChatUtils
+import at.hannibal2.skyhanni.utils.LocationUtils.isPlayerInside
+import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.LorenzUtils.round
+import at.hannibal2.skyhanni.utils.RenderUtils.renderString
+import at.hannibal2.skyhanni.utils.SimpleTimeMark
+import at.hannibal2.skyhanni.utils.TimeUtils.format
+import net.minecraft.client.Minecraft
+import net.minecraft.util.AxisAlignedBB
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import kotlin.time.Duration
+import kotlin.time.Duration.Companion.seconds
+import kotlin.time.DurationUnit
+
+object LimboTimeTracker {
+ private val storage get() = ProfileStorageData.playerSpecific?.limbo
+ private val config get() = SkyHanniMod.feature.misc
+
+ private var limboJoinTime = SimpleTimeMark.farPast()
+ var inLimbo = false
+ private var inFakeLimbo = false
+ private var shownPB = false
+ private var oldPB: Duration = 0.seconds
+ private var userLuck: Float = 0.0F
+ private const val USER_LUCK_MULTIPLIER = 0.000810185F
+ private const val FIRE_MULTIPLIER = 1.01F
+ private var onFire = false
+
+ private val bedwarsLobbyLimbo = AxisAlignedBB(-662.0, 43.0, -76.0, -619.0, 86.0, -27.0)
+
+ private var doMigrate = false
+ private var unmigratedPB = 0
+
+ @SubscribeEvent
+ fun onChat(event: LorenzChatEvent) {
+ if (event.message == "§cYou are AFK. Move around to return from AFK." || event.message == "§cYou were spawned in Limbo.") {
+ limboJoinTime = SimpleTimeMark.now()
+ inLimbo = true
+ onFire = Minecraft.getMinecraft().thePlayer.isBurning
+ }
+ }
+
+ @SubscribeEvent
+ fun catchPlaytime(event: MessageSendToServerEvent) {
+ if (event.message.startsWith("/playtime") && inLimbo) {
+ event.isCanceled
+ printStats(true)
+ }
+ }
+
+ @SubscribeEvent
+ fun onTick(event: LorenzTickEvent) {
+ val personalBest = storage?.personalBest ?: 0
+ if (inLimbo && !shownPB && limboJoinTime.passedSince() >= personalBest.seconds && personalBest != 0) {
+ shownPB = true
+ oldPB = personalBest.seconds
+ ChatUtils.chat("§d§lPERSONAL BEST§f! You've surpassed your previous record of §e$oldPB§f!")
+ ChatUtils.chat("§fKeep it up!")
+ }
+ val lobbyName: String? = HypixelData.locrawData?.get("lobbyname")?.asString
+ if (lobbyName.toString().startsWith("bedwarslobby")) {
+ if (bedwarsLobbyLimbo.isPlayerInside()) {
+ if (inFakeLimbo) return
+ limboJoinTime = SimpleTimeMark.now()
+ inLimbo = true
+ inFakeLimbo = true
+ } else {
+ if (inLimbo) {
+ leaveLimbo()
+ inFakeLimbo = false
+ }
+ }
+ }
+ }
+
+ @SubscribeEvent
+ fun onWorldChange(event: LorenzWorldChangeEvent) {
+ if (!inLimbo) return
+ leaveLimbo()
+ }
+
+ @SubscribeEvent
+ fun onRenderOverlay(event: GuiRenderEvent.GuiOverlayRenderEvent) {
+ if (!isEnabled()) return
+ if (!inLimbo) return
+ if (LorenzUtils.inSkyBlock) {
+ leaveLimbo()
+ return
+ }
+ val duration = limboJoinTime.passedSince().format()
+ config.showTimeInLimboPosition.renderString("§eIn limbo since §b$duration", posLabel = "Limbo Time Tracker")
+ }
+
+ private fun leaveLimbo() {
+ inLimbo = false
+ if (!isEnabled()) return
+ val passedSince = limboJoinTime.passedSince()
+ val duration = passedSince.format()
+ val currentPB = (storage?.personalBest ?: 0).seconds
+ val oldLuck = storage?.userLuck ?: 0f
+ if (passedSince > currentPB) {
+ oldPB = currentPB
+ storage?.personalBest = passedSince.toInt(DurationUnit.SECONDS)
+ userLuck = ((storage?.personalBest ?: 0) * USER_LUCK_MULTIPLIER).round(2)
+ if (onFire) userLuck *= FIRE_MULTIPLIER
+ ChatUtils.chat("§fYou were in Limbo for §e$duration§f! §d§lPERSONAL BEST§r§f!")
+ ChatUtils.chat("§fYour previous Personal Best was §e$oldPB.")
+ } else ChatUtils.chat("§fYou were in Limbo for §e$duration§f.")
+ if (userLuck > oldLuck) {
+ if (onFire) {
+ ChatUtils.chat("§fYour §aPersonal Bests§f perk is now granting you §a+${userLuck.round(2)}§c✴ §aSkyHanni User Luck§f! ")
+ } else {
+ ChatUtils.chat("§fYour §aPersonal Bests§f perk is now granting you §a+${userLuck.round(2)}✴ SkyHanni User Luck§f!")
+ }
+ storage?.userLuck = userLuck
+ }
+ storage?.playtime = storage?.playtime?.plus(passedSince.toInt(DurationUnit.SECONDS)) ?: 0
+ onFire = false
+ shownPB = false
+ }
+
+ @SubscribeEvent
+ fun onConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) {
+ event.move(27, oldPath = "misc.limboTimePB", newPath = "#player.personalBest")
+ }
+
+ fun printStats(onlyPlaytime: Boolean = false) {
+ val timeInLimbo: Int = if (inLimbo) limboJoinTime.passedSince().inWholeSeconds.toInt() else 0
+ val playtime: Int = if (inLimbo) (storage?.playtime
+ ?: 0) + limboJoinTime.passedSince().inWholeSeconds.toInt() else storage?.playtime ?: 0
+ if (onlyPlaytime) {
+ ChatUtils.chat("§aYou have ${playtime / 3600} hours and ${playtime % 3600 / 60} minutes playtime!", false)
+ } else {
+ val currentPB = storage?.personalBest ?: 0
+ val userLuck = storage?.userLuck ?: 0f
+ val limboPB: Int = if (currentPB < timeInLimbo) timeInLimbo else currentPB
+ ChatUtils.chat("§fYour current PB is §e${limboPB.seconds}§f, granting you §a+${userLuck.round(2)}✴ §fSkyHanni User Luck!")
+ ChatUtils.chat("§fYou have §e${playtime.seconds} §fof playtime!")
+ }
+ }
+
+ @SubscribeEvent
+ fun onDebugCollect(event: DebugDataCollectEvent) {
+ event.title("Limbo")
+ if (!inLimbo) {
+ event.addIrrelevant("not in limbo")
+ return
+ }
+
+ event.addData {
+ add("inLimbo: $inLimbo")
+ add("isLimboFake: $inFakeLimbo")
+ add("since: ${limboJoinTime.passedSince()}")
+ }
+ }
+
+ fun workaroundMigration(personalBest: Int) {
+ doMigrate = true
+ unmigratedPB = personalBest
+ }
+
+ @SubscribeEvent
+ fun onLogin(event: HypixelJoinEvent) {
+ if (!doMigrate) return
+ if (unmigratedPB != 0) {
+ ChatUtils.debug("Migrating limbo personalBest")
+ storage?.personalBest = unmigratedPB
+ storage?.userLuck = unmigratedPB * USER_LUCK_MULTIPLIER
+ }
+ if ((storage?.personalBest ?: 0) > (storage?.playtime ?: 0)) {
+ ChatUtils.debug("Migrating limbo playtime")
+ storage?.playtime = (storage?.personalBest ?: 0)
+ }
+ doMigrate = false
+ unmigratedPB = 0
+ }
+
+ fun isEnabled() = config.showTimeInLimbo
+}