aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/event/hoppity/HoppityCallWarningConfig.java47
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/event/hoppity/HoppityEggsConfig.java5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCallWarning.kt155
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/HypixelCommands.kt4
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt9
5 files changed, 220 insertions, 0 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/event/hoppity/HoppityCallWarningConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/event/hoppity/HoppityCallWarningConfig.java
new file mode 100644
index 000000000..6e4ccf027
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/event/hoppity/HoppityCallWarningConfig.java
@@ -0,0 +1,47 @@
+package at.hannibal2.skyhanni.config.features.event.hoppity;
+
+import at.hannibal2.skyhanni.config.FeatureToggle;
+import at.hannibal2.skyhanni.utils.OSUtils;
+import com.google.gson.annotations.Expose;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorButton;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorColour;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorKeybind;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorText;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigOption;
+import io.github.notenoughupdates.moulconfig.observer.Property;
+import org.lwjgl.input.Keyboard;
+
+public class HoppityCallWarningConfig {
+
+ @Expose
+ @ConfigOption(name = "Hoppity Call Warning", desc = "Warn when hoppity is calling you.")
+ @ConfigEditorBoolean
+ @FeatureToggle
+ public boolean enabled = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Accept Call Hotkey",
+ desc = "Accept the call from hoppity by pressing this keybind."
+ )
+ @ConfigEditorKeybind(defaultKey = Keyboard.KEY_NONE)
+ public int acceptHotkey = Keyboard.KEY_NONE;
+
+ @Expose
+ @ConfigOption(name = "Warning Sound", desc = "The sound that plays when hoppity calls.\n" +
+ "§eYou can use custom sounds, put it in the §bskyhanni/sounds §efolder in your resource pack.\n" +
+ "§eThen write §bskyhanni:yourfilename\n" +
+ "§cMust be a .ogg file")
+ @ConfigEditorText
+ public Property<String> hoppityCallSound = Property.of("note.pling");
+
+ @Expose
+ @ConfigOption(name = "Flash Color", desc = "Color of the screen when flashing")
+ @ConfigEditorColour
+ public String flashColor = "0:127:0:238:255";
+
+ @ConfigOption(name = "Sounds", desc = "Click to open the list of available sounds.")
+ @ConfigEditorButton(buttonText = "OPEN")
+ public Runnable sounds = () -> OSUtils.openBrowser("https://www.minecraftforum.net/forums/mapping-and-modding-java-edition/mapping-and-modding-tutorials/2213619-1-8-all-playsound-sound-arguments");
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/event/hoppity/HoppityEggsConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/event/hoppity/HoppityEggsConfig.java
index 50a5731a5..c270dae8b 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/event/hoppity/HoppityEggsConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/event/hoppity/HoppityEggsConfig.java
@@ -15,6 +15,11 @@ import io.github.notenoughupdates.moulconfig.annotations.ConfigOption;
public class HoppityEggsConfig {
@Expose
+ @ConfigOption(name = "Hoppity Abiphone Calls", desc = "")
+ @Accordion
+ public HoppityCallWarningConfig hoppityCallWarning = new HoppityCallWarningConfig();
+
+ @Expose
@ConfigOption(name = "Event Summary", desc = "")
@Accordion
public HoppityEventSummaryConfig eventSummary = new HoppityEventSummaryConfig();
diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCallWarning.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCallWarning.kt
new file mode 100644
index 000000000..57bc0975f
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCallWarning.kt
@@ -0,0 +1,155 @@
+package at.hannibal2.skyhanni.features.event.hoppity
+
+import at.hannibal2.skyhanni.events.ConfigLoadEvent
+import at.hannibal2.skyhanni.events.GuiRenderEvent
+import at.hannibal2.skyhanni.events.LorenzChatEvent
+import at.hannibal2.skyhanni.events.LorenzKeyPressEvent
+import at.hannibal2.skyhanni.events.SecondPassedEvent
+import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryAPI
+import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
+import at.hannibal2.skyhanni.utils.ColorUtils.toChromaColorInt
+import at.hannibal2.skyhanni.utils.ConditionalUtils
+import at.hannibal2.skyhanni.utils.DelayedRun
+import at.hannibal2.skyhanni.utils.HypixelCommands
+import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.RegexUtils.matches
+import at.hannibal2.skyhanni.utils.SoundUtils
+import at.hannibal2.skyhanni.utils.StringUtils.isValidUuid
+import net.minecraft.client.Minecraft
+import net.minecraft.client.gui.Gui
+import net.minecraft.client.renderer.GlStateManager
+import net.minecraftforge.fml.common.eventhandler.EventPriority
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import org.lwjgl.input.Keyboard
+import java.time.Instant
+import kotlin.math.sin
+import kotlin.time.Duration.Companion.seconds
+
+@SkyHanniModule
+object HoppityCallWarning {
+
+ /**
+ * Test messages (and the real ones from Hypixel) have a space at the end of
+ * them that the IDE kills. So it's "§r§e ✆ "
+ *
+ * REGEX-TEST: §e✆ §r§bHoppity§r§e ✆
+ * REGEX-TEST: §e✆ §r§aHoppity§r§e ✆
+ */
+ private val initHoppityCallPattern by ChocolateFactoryAPI.patternGroup.pattern(
+ "hoppity.call.init",
+ "§e✆ §r(?:§a|§b)Hoppity§r§e ✆.*",
+ )
+
+ /**
+ * REGEX-TEST: §a✆ RING... §r §r§2§l[PICK UP]
+ * REGEX-TEST: §a✆ RING... RING... §r §r§2§l[PICK UP]
+ * REGEX-TEST: §a✆ RING... RING... RING... §r §r§2§l[PICK UP]
+ * REGEX-TEST: §a✆ RING... RING... RING...
+ */
+ private val callRingPattern by ChocolateFactoryAPI.patternGroup.pattern(
+ "hoppity.call.ring",
+ "§a✆ (?:RING\\.{3} ?){1,3}(?:§r §r§2§l\\[PICK UP])?",
+ )
+
+ /**
+ * REGEX-TEST: §e[NPC] §aHoppity§f: §b✆ §f§rWhat's up, §boBlazin§f?
+ */
+ private val pickupHoppityCallPattern by ChocolateFactoryAPI.patternGroup.pattern(
+ "hoppity.call.pickup",
+ "§e\\[NPC] §aHoppity§f: §b✆ §f§rWhat's up, .*§f\\?",
+ )
+
+ private val config get() = HoppityEggsManager.config.hoppityCallWarning
+ private var warningSound = SoundUtils.createSound("note.pling", 1f)
+ private var activeWarning = false
+ private var nextWarningTime: Instant? = null
+ private var finalWarningTime: Instant? = null
+ private val callLength = 7.seconds
+ private var acceptUUID: String? = null
+
+ @SubscribeEvent
+ fun onKeyPress(event: LorenzKeyPressEvent) {
+ if (config.acceptHotkey == Keyboard.KEY_NONE || config.acceptHotkey != event.keyCode) return
+ acceptUUID?.let {
+ HypixelCommands.callback(acceptUUID!!)
+ acceptUUID = null
+ }
+ }
+
+ @SubscribeEvent
+ fun onConfigLoad(event: ConfigLoadEvent) {
+ val soundProperty = config.hoppityCallSound
+ ConditionalUtils.onToggle(soundProperty) {
+ warningSound = SoundUtils.createSound(soundProperty.get(), 1f)
+ }
+ nextWarningTime = null
+ finalWarningTime = null
+ }
+
+ @SubscribeEvent(priority = EventPriority.HIGHEST)
+ fun onChat(event: LorenzChatEvent) {
+ if (callRingPattern.matches(event.message) && acceptUUID == null) readPickupUuid(event)
+ if (!isEnabled()) return
+ if (initHoppityCallPattern.matches(event.message)) startWarningUser()
+ if (pickupHoppityCallPattern.matches(event.message)) stopWarningUser()
+ }
+
+ @SubscribeEvent
+ fun onTick(event: SecondPassedEvent) {
+ if (!isEnabled()) return
+ if (!activeWarning) return
+ if (nextWarningTime == null || finalWarningTime == null) return
+ val currentTime = Instant.now()
+ if (currentTime.isAfter(nextWarningTime)) {
+ SoundUtils.repeatSound(100, 10, warningSound)
+ nextWarningTime = currentTime.plusMillis(100)
+ }
+ if (currentTime >= finalWarningTime) stopWarningUser()
+ }
+
+ @SubscribeEvent
+ fun onRender(event: GuiRenderEvent.GuiOverlayRenderEvent) {
+ if (!isEnabled() || !activeWarning) return
+ val minecraft = Minecraft.getMinecraft()
+ // Calculate a fluctuating alpha value based on the sine of time, for a smooth oscillation
+ val randomizationAlphaDouble = ((2 + sin(Instant.now().toEpochMilli().toDouble() / 1000)) * 255 / 4)
+ // Ensure the alpha value is an integer and within the valid range (0-255)
+ val randomizationAlphaInt = randomizationAlphaDouble.toInt().coerceIn(0..255)
+ // Shift the alpha value 24 bits to the left to position it in the color's alpha channel.
+ val shiftedRandomAlpha = randomizationAlphaInt shl 24
+ Gui.drawRect(
+ 0,
+ 0,
+ minecraft.displayWidth,
+ minecraft.displayHeight,
+ // Apply the shifted alpha and combine it with the RGB components of flashColor.
+ shiftedRandomAlpha or (config.flashColor.toChromaColorInt() and 0xFFFFFF),
+ )
+ GlStateManager.color(1F, 1F, 1F, 1F)
+ }
+
+ private fun readPickupUuid(event: LorenzChatEvent) {
+ val siblings = event.chatComponent.siblings.takeIf { it.size >= 3 } ?: return
+ val clickEvent = siblings[2]?.chatStyle?.chatClickEvent ?: return
+ if (clickEvent.action.name.lowercase() != "run_command" || !clickEvent.value.lowercase().startsWith("/cb")) return
+ acceptUUID = clickEvent.value.lowercase().replace("/cb ", "").takeIf { it.isValidUuid() }
+ if (acceptUUID != null) DelayedRun.runDelayed(12.seconds) { acceptUUID = null }
+ }
+
+ private fun startWarningUser() {
+ if (activeWarning) return
+ activeWarning = true
+ SoundUtils.repeatSound(100, 10, warningSound)
+ val currentTime = Instant.now()
+ nextWarningTime = currentTime.plusMillis(100)
+ finalWarningTime = finalWarningTime ?: currentTime.plusMillis(callLength.inWholeMilliseconds)
+ }
+
+ private fun stopWarningUser() {
+ activeWarning = false
+ finalWarningTime = null
+ nextWarningTime = null
+ }
+
+ private fun isEnabled() = LorenzUtils.inSkyBlock && config.enabled
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/HypixelCommands.kt b/src/main/java/at/hannibal2/skyhanni/utils/HypixelCommands.kt
index c788d019a..176afe8c0 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/HypixelCommands.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/HypixelCommands.kt
@@ -150,6 +150,10 @@ object HypixelCommands {
send("chatprompt $prompt")
}
+ fun callback(uuid: String) {
+ send("cb $uuid")
+ }
+
private fun send(command: String) {
@Suppress("DEPRECATION")
// TODO rename function
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt
index 14e4a989f..e1a01e5df 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt
@@ -561,4 +561,13 @@ object StringUtils {
fun String.width(): Int = Minecraft.getMinecraft().fontRendererObj.getStringWidth(this)
fun String.lastColorCode(): String? = minecraftColorCodesPattern.findAll(this).lastOrNull()
+
+ fun String.isValidUuid(): Boolean {
+ return try {
+ UUID.fromString(this)
+ true
+ } catch (e: IllegalArgumentException) {
+ false
+ }
+ }
}