aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md1
-rw-r--r--FEATURES.md3
-rw-r--r--src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java1
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/Features.java5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/Misc.java17
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/NonGodPotEffectDisplay.kt206
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/minion/MinionFeatures.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt12
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