-
-
Notifications
You must be signed in to change notification settings - Fork 194
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feature: Hoppity Call Warning (#2272)
Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com>
- Loading branch information
1 parent
9352ace
commit 3db3627
Showing
5 changed files
with
220 additions
and
0 deletions.
There are no files selected for viewing
47 changes: 47 additions & 0 deletions
47
...in/java/at/hannibal2/skyhanni/config/features/event/hoppity/HoppityCallWarningConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
155 changes: 155 additions & 0 deletions
155
src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCallWarning.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters