diff options
-rw-r--r-- | CHANGELOG.md | 1 | ||||
-rw-r--r-- | FEATURES.md | 3 | ||||
-rw-r--r-- | src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java | 1 | ||||
-rw-r--r-- | src/main/java/at/hannibal2/skyhanni/config/Features.java | 5 | ||||
-rw-r--r-- | src/main/java/at/hannibal2/skyhanni/config/features/Misc.java | 17 | ||||
-rw-r--r-- | src/main/java/at/hannibal2/skyhanni/features/NonGodPotEffectDisplay.kt | 206 | ||||
-rw-r--r-- | src/main/java/at/hannibal2/skyhanni/features/minion/MinionFeatures.kt | 2 | ||||
-rw-r--r-- | src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt | 12 |
8 files changed, 240 insertions, 7 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index efb269193..c1eb7ba94 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ ### Misc + Added Lord Jawbus to damage indicator ++ Display the active non-god potion effects. ### Changes + Showing Thunder Sparks while in lava diff --git a/FEATURES.md b/FEATURES.md index 4aa6ebe4e..b53e76766 100644 --- a/FEATURES.md +++ b/FEATURES.md @@ -134,4 +134,5 @@ - Highlight the voidling extremist in pink color. - Highlight corrupted mobs in purple color. - Option to hide all damage splashes, from anywhere in Skyblock. -- Hide armor or just helmet of other player or yourself
\ No newline at end of file +- Hide armor or just helmet of other player or yourself +- Display the active non-god potion effects.
\ No newline at end of file diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java index 5c36395a1..8f6343093 100644 --- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java +++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java @@ -153,6 +153,7 @@ public class SkyHanniMod { registerEvent(new HideArmor()); registerEvent(new SlayerQuestWarning()); registerEvent(new StatsTuning()); + registerEvent(new NonGodPotEffectDisplay()); Commands.init(); diff --git a/src/main/java/at/hannibal2/skyhanni/config/Features.java b/src/main/java/at/hannibal2/skyhanni/config/Features.java index adf1262d3..1f12d920b 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/Features.java +++ b/src/main/java/at/hannibal2/skyhanni/config/Features.java @@ -112,6 +112,11 @@ public class Features extends Config { HideArmor.Companion.updateArmor(); return; } + + if (runnableId.equals("nonGodPotEffect")) { + editOverlay(activeConfigCategory, 200, 16, misc.nonGodPotEffectPos); + return; + } } @Expose diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/Misc.java b/src/main/java/at/hannibal2/skyhanni/config/features/Misc.java index 0cab88e7a..2521a9654 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/Misc.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/Misc.java @@ -106,4 +106,21 @@ public class Misc { @ConfigOption(name = "Config Button", desc = "Add a button to the pause menu to configure SkyHanni.") @ConfigEditorBoolean public boolean configButtonOnPause = true; + + @Expose + @ConfigOption(name = "Potion Effects", desc = "") + @ConfigEditorAccordion(id = 5) + public boolean potionEffects = false; + + @Expose + @ConfigOption(name = "Non-God Pot Effects", desc = "Display the active non-god potion effects.") + @ConfigEditorBoolean + @ConfigAccordionId(id = 5) + public boolean nonGodPotEffectDisplay = false; + + @Expose + @ConfigOption(name = "Real Time Position", desc = "") + @ConfigEditorButton(runnableId = "nonGodPotEffect", buttonText = "Edit") + @ConfigAccordionId(id = 5) + public Position nonGodPotEffectPos = new Position(10, 10, false, true); }
\ No newline at end of file diff --git a/src/main/java/at/hannibal2/skyhanni/features/NonGodPotEffectDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/NonGodPotEffectDisplay.kt new file mode 100644 index 000000000..86c7b96eb --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/NonGodPotEffectDisplay.kt @@ -0,0 +1,206 @@ +package at.hannibal2.skyhanni.features + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.events.LorenzChatEvent +import at.hannibal2.skyhanni.events.PacketEvent +import at.hannibal2.skyhanni.events.ProfileApiDataLoadedEvent +import at.hannibal2.skyhanni.test.GriffinJavaUtils +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.RenderUtils.renderStrings +import at.hannibal2.skyhanni.utils.StringUtils +import net.minecraft.network.play.server.S30PacketWindowItems +import net.minecraft.network.play.server.S47PacketPlayerListHeaderFooter +import net.minecraftforge.client.event.RenderGameOverlayEvent +import net.minecraftforge.event.world.WorldEvent +import net.minecraftforge.fml.common.eventhandler.EventPriority +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import net.minecraftforge.fml.common.gameevent.TickEvent +import java.util.regex.Pattern + +class NonGodPotEffectDisplay { + + private var checkFooter = false + private val activeEffects = mutableMapOf<String, Long>() + private val textToRender = mutableListOf<String>() + private var lastTick = 0L + + private var nonGodPotEffects = mapOf( + "smoldering_polarization" to "§aSmoldering Polarization I", + "mushed_glowy_tonic" to "§2Mushed Glowy Tonic I", + "wisp_ice" to "§bWisp's Ice-Flavored Water I", + ) + + private var patternEffectsCount = Pattern.compile("§7You have §e(\\d+) §7non-god effects\\.") + private var totalEffectsCount = 0 + + @SubscribeEvent + fun onChatMessage(event: LorenzChatEvent) { + if (event.message == "§aYou ate a §r§aRe-heated Gummy Polar Bear§r§a!") { + checkFooter = true + activeEffects["§aSmoldering Polarization I"] = System.currentTimeMillis() + 1000 * 60 * 60 + format() + } + + if (event.message == "§a§lBUFF! §fYou have gained §r§2Mushed Glowy Tonic I§r§f! Press TAB or type /effects to view your active effects!") { + checkFooter = true + activeEffects["§2Mushed Glowy Tonic I"] = System.currentTimeMillis() + 1000 * 60 * 60 + format() + } + + if (event.message == "§a§lBUFF! §fYou splashed yourself with §r§bWisp's Ice-Flavored Water I§r§f! Press TAB or type /effects to view your active effects!") { + checkFooter = true + activeEffects["§bWisp's Ice-Flavored Water I"] = System.currentTimeMillis() + 1000 * 60 * 5 + format() + } + } + + private fun format() { + val now = System.currentTimeMillis() + textToRender.clear() + if (activeEffects.values.removeIf { now > it }) { + //to fetch the real amount of active pots + totalEffectsCount = 0 + checkFooter = true + } + for (effect in GriffinJavaUtils.sortByValue(activeEffects)) { + val label = effect.key + val until = effect.value + val seconds = (until - now) / 1000 + val format = StringUtils.formatDuration(seconds) + + val color = colorForTime(seconds) + + textToRender.add("$label $color$format") + } + val diff = totalEffectsCount - activeEffects.size + if (diff > 0) { + textToRender.add("§eOpen the /effects inventory") + textToRender.add("§eto show the missing $diff effects!") + checkFooter = true + } + } + + private fun colorForTime(seconds: Long): String { + return if (seconds <= 60) { + "§c" + } else if (seconds <= 60 * 3) { + "§6" + } else if (seconds <= 60 * 10) { + "§e" + } else { + "§f" + } + } + + @SubscribeEvent + fun onTick(event: TickEvent.ClientTickEvent) { + if (!isEnabled()) return + if (lastTick + 1_000 > System.currentTimeMillis()) return + lastTick = System.currentTimeMillis() + + format() + } + + @SubscribeEvent + fun onWorldChange(event: WorldEvent.Load) { + checkFooter = true + } + + @SubscribeEvent(priority = EventPriority.LOW, receiveCanceled = true) + fun onChatPacket(event: PacketEvent.ReceiveEvent) { + val packet = event.packet + if (packet is S30PacketWindowItems) { + for (stack in packet.itemStacks) { + val name = stack?.name ?: continue + if (name in nonGodPotEffects.values) { + for (line in stack.getLore()) { + if (line.contains("Remaining")) { + val duration = readDuration(line.split("§f")[1]) + activeEffects[name] = System.currentTimeMillis() + duration + format() + } + } + } + } + } + + if (!checkFooter) return + if (packet is S47PacketPlayerListHeaderFooter) { + val formattedText = packet.footer.formattedText + val lines = formattedText.replace("§r", "").split("\n") + + if (!lines.any { it.contains("§a§lActive Effects") }) return + checkFooter = false + + for (line in lines) { + if (line.startsWith("§2Mushed Glowy Tonic I")) { + val duration = readDuration(line.split("§f")[1]) + activeEffects["§2Mushed Glowy Tonic I"] = System.currentTimeMillis() + duration + format() + } + val matcher = patternEffectsCount.matcher(line) + if (matcher.matches()) { + val group = matcher.group(1) + totalEffectsCount = group.toInt() + } + } + } + } + + private fun readDuration(text: String): Int { + val split = text.split(":") + return when (split.size) { + 3 -> { + val hours = split[0].toInt() * 1000 * 60 * 60 + val minutes = split[1].toInt() * 1000 * 60 + val seconds = split[2].toInt() * 1000 + seconds + minutes + hours + } + + 2 -> { + val minutes = split[0].toInt() * 1000 * 60 + val seconds = split[1].toInt() * 1000 + seconds + minutes + } + + 1 -> { + split[0].toInt() * 1000 + } + + else -> { + throw RuntimeException("Invalid format: '$text'") + } + } + } + + @SubscribeEvent + fun renderOverlay(event: RenderGameOverlayEvent.Post) { + if (event.type != RenderGameOverlayEvent.ElementType.ALL) return + if (!isEnabled()) return + + SkyHanniMod.feature.misc.nonGodPotEffectPos.renderStrings(textToRender) + } + + @SubscribeEvent + fun onProfileDataLoad(event: ProfileApiDataLoadedEvent) { + val profileData = event.profileData + val effects = profileData["active_effects"]?.asJsonArray ?: return + for (element in effects) { + val effect = element.asJsonObject + val name = effect["effect"].asString + val label = nonGodPotEffects[name] ?: continue + + val time = effect["ticks_remaining"].asLong / 20 + val newValue = System.currentTimeMillis() + time * 1000 + val old = activeEffects.getOrDefault(label, 0) + val diff = newValue - old + activeEffects[label] = newValue + } + } + + private fun isEnabled(): Boolean { + return LorenzUtils.inSkyblock && SkyHanniMod.feature.misc.nonGodPotEffectDisplay && !LorenzUtils.inDungeons && !LorenzUtils.inKuudraFight + } +}
\ No newline at end of file diff --git a/src/main/java/at/hannibal2/skyhanni/features/minion/MinionFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/minion/MinionFeatures.kt index 756b2b285..12ddf6f78 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/minion/MinionFeatures.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/minion/MinionFeatures.kt @@ -199,7 +199,7 @@ class MinionFeatures { val lastEmptied = minion.value if (lastEmptied == 0L) continue val duration = System.currentTimeMillis() - lastEmptied - val format = StringUtils.formatDuration(duration / 1000) + val format = StringUtils.formatDuration(duration / 1000) + " ago" if (LocationUtils.canSee(playerEyeLocation, location)) { val text = "§eHopper Emptied: $format" event.drawString(location.add(0.0, 2.0, 0.0), text, true) diff --git a/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt index 52a58c4a6..aa4126de1 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt @@ -53,16 +53,16 @@ object StringUtils { val formatSeconds = durationFormat.format(sec) if (days > 0) { - return "${days}d $formatHours:$formatMinutes:$formatSeconds ago" + return "${days}d $formatHours:$formatMinutes:$formatSeconds" } if (hours > 0) { - return "$formatHours:$formatMinutes:$formatSeconds ago" + return "$formatHours:$formatMinutes:$formatSeconds".removeAtBeginning("0") } if (minutes > 0) { - return "$formatMinutes:$formatSeconds ago" + return "$formatMinutes:$formatSeconds".removeAtBeginning("0") } if (sec > 0) { - return "${sec}s ago" + return "${sec}s" } return "Now" @@ -88,4 +88,6 @@ object StringUtils { return toString().replace("-", "") } -}
\ No newline at end of file +} + +private fun String.removeAtBeginning(text: String): String = if (this.startsWith(text)) substring(text.length) else this |