diff options
author | martimavocado <39881008+martimavocado@users.noreply.github.com> | 2024-06-16 23:33:04 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-17 00:33:04 +0200 |
commit | 420b43c2ac553d1c99b10bd1d5aba948c12bd803 (patch) | |
tree | 3f0becf91eddcdfae6ddd5dfc55714eb5b49769f | |
parent | dadf6c04d526c11237ccd9bd1162a08d3fc8a5f6 (diff) | |
download | skyhanni-420b43c2ac553d1c99b10bd1d5aba948c12bd803.tar.gz skyhanni-420b43c2ac553d1c99b10bd1d5aba948c12bd803.tar.bz2 skyhanni-420b43c2ac553d1c99b10bd1d5aba948c12bd803.zip |
Feature: Add player highlighting for the Punchcard Artifact (#1089)
Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com>
6 files changed, 312 insertions, 1 deletions
diff --git a/.idea/dictionaries/default_user.xml b/.idea/dictionaries/default_user.xml index db558db8d..574a90453 100644 --- a/.idea/dictionaries/default_user.xml +++ b/.idea/dictionaries/default_user.xml @@ -155,6 +155,7 @@ <w>polarvoid</w> <w>preinitialization</w> <w>procs</w> + <w>punchcard</w> <w>pyrochaos</w> <w>quazii</w> <w>rclick</w> 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 bd94462c4..92a723707 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt +++ b/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt @@ -65,6 +65,7 @@ import at.hannibal2.skyhanni.features.misc.massconfiguration.DefaultConfigFeatur import at.hannibal2.skyhanni.features.misc.update.UpdateManager import at.hannibal2.skyhanni.features.misc.visualwords.VisualWordGui import at.hannibal2.skyhanni.features.rift.area.westvillage.VerminTracker +import at.hannibal2.skyhanni.features.rift.everywhere.PunchcardHighlight import at.hannibal2.skyhanni.features.slayer.SlayerProfitTracker import at.hannibal2.skyhanni.test.DebugCommand import at.hannibal2.skyhanni.test.GraphEditor @@ -408,6 +409,10 @@ object Commands { "shclearsavedrabbits", "Clears the saved rabbits on this profile.", ) { HoppityCollectionStats.clearSavedRabbits() } + registerCommand( + "shresetpunchcard", + "Resets the Rift Punchcard Artifact player list." + ) { PunchcardHighlight.clearList() } } private fun developersDebugFeatures() { diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/rift/PunchcardConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/rift/PunchcardConfig.java new file mode 100644 index 000000000..3ef21ba0a --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/config/features/rift/PunchcardConfig.java @@ -0,0 +1,48 @@ +package at.hannibal2.skyhanni.config.features.rift; + +import at.hannibal2.skyhanni.config.FeatureToggle; +import at.hannibal2.skyhanni.config.core.config.Position; +import com.google.gson.annotations.Expose; +import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean; +import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorColour; +import io.github.notenoughupdates.moulconfig.annotations.ConfigLink; +import io.github.notenoughupdates.moulconfig.annotations.ConfigOption; +import io.github.notenoughupdates.moulconfig.observer.Property; + +public class PunchcardConfig { + @Expose + @ConfigOption(name = "Highlight", desc = "Highlights unpunched players in the Rift.") + @ConfigEditorBoolean + @FeatureToggle + public Property<Boolean> highlight = Property.of(false); + + @Expose + @ConfigOption(name = "Color", desc = "Color used for highlighting.") + @ConfigEditorColour + public Property<String> color = Property.of("0:163:122:11:143"); + + @Expose + @ConfigOption(name = "Enable Overlay", desc = "Shows an overlay with the amount of punched players.") + @ConfigEditorBoolean + @FeatureToggle + public Property<Boolean> gui = Property.of(false); + + @Expose + @ConfigOption(name = "Compact Overlay", desc = "Compacts the overlay, requires it to be enabled.") + @ConfigEditorBoolean + public Property<Boolean> compact = Property.of(false); + + @Expose + @ConfigOption(name = "Countdown Overlay", desc = "Shows the amount of remaining players in the overlay.") + @ConfigEditorBoolean + public Property<Boolean> reverseGUI = Property.of(false); + + @Expose + @ConfigOption(name = "Only punched players", desc = "Highlights only punched players instead.") + @ConfigEditorBoolean + public Property<Boolean> reverse = Property.of(false); + + @Expose + @ConfigLink(owner = PunchcardConfig.class, field = "gui") + public Position position = new Position(10, 27); +} diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/rift/RiftConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/rift/RiftConfig.java index 68bfb0954..147709752 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/rift/RiftConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/rift/RiftConfig.java @@ -40,6 +40,11 @@ public class RiftConfig { public MotesOrbsConfig motesOrbs = new MotesOrbsConfig(); @Expose + @ConfigOption(name = "Punchcard Artifact", desc = "") + @Accordion + public PunchcardConfig punchcard = new PunchcardConfig(); + + @Expose @ConfigOption(name = "Highlight Guide", desc = "Highlight things to do in the Rift Guide.") @ConfigEditorBoolean @FeatureToggle diff --git a/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java b/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java index 2887d0230..8cd2c6e3b 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java +++ b/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java @@ -476,7 +476,6 @@ public class ProfileSpecificStorage { @Expose public VerminTracker.Data verminTracker = new VerminTracker.Data(); - } @Expose diff --git a/src/main/java/at/hannibal2/skyhanni/features/rift/everywhere/PunchcardHighlight.kt b/src/main/java/at/hannibal2/skyhanni/features/rift/everywhere/PunchcardHighlight.kt new file mode 100644 index 000000000..10be4a54a --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/rift/everywhere/PunchcardHighlight.kt @@ -0,0 +1,253 @@ +package at.hannibal2.skyhanni.features.rift.everywhere + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.data.HypixelData +import at.hannibal2.skyhanni.data.IslandType +import at.hannibal2.skyhanni.data.mob.MobData +import at.hannibal2.skyhanni.events.ConfigLoadEvent +import at.hannibal2.skyhanni.events.EntityClickEvent +import at.hannibal2.skyhanni.events.GuiRenderEvent +import at.hannibal2.skyhanni.events.IslandChangeEvent +import at.hannibal2.skyhanni.events.LorenzChatEvent +import at.hannibal2.skyhanni.events.MobEvent +import at.hannibal2.skyhanni.features.rift.RiftAPI +import at.hannibal2.skyhanni.mixins.hooks.RenderLivingEntityHelper +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.test.command.ErrorManager +import at.hannibal2.skyhanni.utils.ChatUtils +import at.hannibal2.skyhanni.utils.ColorUtils.toChromaColor +import at.hannibal2.skyhanni.utils.ColorUtils.withAlpha +import at.hannibal2.skyhanni.utils.ConditionalUtils +import at.hannibal2.skyhanni.utils.DelayedRun +import at.hannibal2.skyhanni.utils.EntityUtils.isNPC +import at.hannibal2.skyhanni.utils.InventoryUtils +import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland +import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName +import at.hannibal2.skyhanni.utils.NEUItems.getItemStack +import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher +import at.hannibal2.skyhanni.utils.RegexUtils.matches +import at.hannibal2.skyhanni.utils.RenderUtils.renderRenderable +import at.hannibal2.skyhanni.utils.SimpleTimeMark +import at.hannibal2.skyhanni.utils.renderables.Renderable +import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern +import net.minecraft.client.entity.AbstractClientPlayer +import net.minecraft.entity.EntityLivingBase +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import kotlin.time.Duration.Companion.milliseconds +import kotlin.time.Duration.Companion.seconds + +@SkyHanniModule +object PunchcardHighlight { + private val config get() = SkyHanniMod.feature.rift.punchcard + private var lastRiftServer: String = "" + + private var listening = false + + private val patternGroup = RepoPattern.group("rift.punchcard") + + /** + * REGEX-TEST: §5§lPUNCHCARD! §r§eYou punched §r§b[MVP§r§c+§r§b] ThorQOM§r§f §r§eand both regained §r§a+25ф Rift Time§r§e! + * REGEX-TEST: §5§lPUNCHCARD! §r§eYou punched §r§7Metafighter§r§7 §r§eand both regained §r§a+25ф Rift Time§r§e! + * REGEX-TEST: §5§lPUNCHCARD! §r§eYou punched §r§a[VIP] RickyLafleur22§r§f §r§eand both regained §r§a+25ф Rift Time§r§e! + */ + private val punchedPattern by patternGroup.pattern( + "new", + "§5§lPUNCHCARD! §r§eYou punched §r§.(?:.*?)?(?<name>\\w+)§r§. §r§eand both regained §r§a\\+25ф Rift Time§r§e!", + ) + + /** + * REGEX-TEST: §c§lAWKWARD! §r§cThis player has already been punched by you... somehow! + */ + private val repeatPattern by patternGroup.pattern( + "repeat", + "§c§lAWKWARD! §r§cThis player has already been punched by you\\.\\.\\. somehow!", + ) + + /** + * REGEX-TEST: §c§lUH OH! §r§cYou reached the limit of 20 players you can punch in one session! + */ + private val limitPattern by patternGroup.pattern( + "limit", + "§c§lUH OH! §r§cYou reached the limit of 20 players you can punch in one session!", + ) + + private val playerList: MutableSet<String> = mutableSetOf() + private var playerQueue = mutableListOf<String>() + + private val displayIcon by lazy { "PUNCHCARD_ARTIFACT".asInternalName().getItemStack() } + private var display: Renderable = Renderable.string("hello") + + @SubscribeEvent + fun onPlayerSpawn(event: MobEvent.Spawn.Player) { + if (!config.highlight.get()) return + if (!IslandType.THE_RIFT.isInIsland()) return + if (config.reverse.get()) return + val size = playerList.size + if (size >= 20) return + val entity = event.mob + if (!playerList.contains(entity.name)) { + colorPlayer(entity.baseEntity) + } + } + + @SubscribeEvent + fun onToggle(event: ConfigLoadEvent) { + ConditionalUtils.onToggle( + config.highlight, + config.color, + config.reverse, + ) { + reloadColors() + } + ConditionalUtils.onToggle( + config.gui, + config.compact, + config.reverseGUI, + ) { + display = drawDisplay() + } + ConditionalUtils.onToggle( + config.highlight, + config.color, + ) { + checkPunchcard() + } + } + + private var warningCooldown = SimpleTimeMark.farPast() + + private fun checkPunchcard() { + if (!RiftAPI.inRift()) return + + val hasPunchcard = InventoryUtils.isItemInInventory("PUNCHCARD_ARTIFACT".asInternalName()) + if (!hasPunchcard && warningCooldown.passedSince() > 30.seconds) { + warningCooldown = SimpleTimeMark.now() + ChatUtils.chat("You don't seem to own a Punchcard Artifact, this feature will not work without one.") + } + } + + @SubscribeEvent + fun onWorldSwitch(event: IslandChangeEvent) { + DelayedRun.runDelayed(1500.milliseconds) { + if (playerList.isEmpty()) return@runDelayed + if (event.newIsland != IslandType.THE_RIFT) return@runDelayed + + if (HypixelData.server.isNotEmpty() && lastRiftServer != HypixelData.server) { + reloadColors() + lastRiftServer = HypixelData.server + playerList.clear() + } + display = drawDisplay() + } + } + + private fun colorPlayer(entity: EntityLivingBase) { + val color = config.color.get().toChromaColor() + val alpha = when (color.alpha) { + 0 -> 0 + 255 -> 1 + else -> 255 - color.alpha + } + RenderLivingEntityHelper.setEntityColor(entity, color.withAlpha(alpha)) { IslandType.THE_RIFT.isInIsland() } + } + + private fun removePlayerColor(entity: EntityLivingBase) { + RenderLivingEntityHelper.removeEntityColor(entity) + } + + fun clearList() { + playerList.clear() + playerQueue.clear() + if (config.reverse.get()) { + MobData.players.forEach { + colorPlayer(it.baseEntity) + } + } else { + MobData.players.forEach { + removePlayerColor(it.baseEntity) + } + } + } + + @SubscribeEvent + fun onPunch(event: EntityClickEvent) { + if (!RiftAPI.inRift()) return + val entity = event.clickedEntity + if (entity !is AbstractClientPlayer) return + if (entity.isNPC()) return + val name = entity.name + if (name in playerList || name in playerQueue) return + playerQueue.add(name) + listening = true + DelayedRun.runDelayed(1.seconds) { + if (name in playerQueue) playerQueue.remove(name) + listening = false + } + } + + @SubscribeEvent + fun onChat(event: LorenzChatEvent) { + if (!IslandType.THE_RIFT.isInIsland()) return + if (!listening) return + if (playerQueue.isEmpty()) return + val message = event.message + val queuedName = playerQueue[0] + punchedPattern.matchMatcher(message) { + val name = group("name") + if (queuedName == name) { + addPunch(name) + } else ErrorManager.logErrorStateWithData( + "Error finding punched player", "queuedName and capturedName were different", + "queuedName" to queuedName, + "capturedName" to name, + noStackTrace = true, + betaOnly = true, + ) + return + } + if (limitPattern.matches(message) || repeatPattern.matches(message)) addPunch(queuedName) + } + + private fun addPunch(playerName: String) { + playerList.add(playerName) + playerQueue.remove(playerName) + val player = MobData.players.firstOrNull { it.name == playerName } ?: return + if (!config.reverse.get()) removePlayerColor(player.baseEntity) + else colorPlayer(player.baseEntity) + display = drawDisplay() + } + + @SubscribeEvent + fun onRenderUI(event: GuiRenderEvent.GuiOverlayRenderEvent) { + if (!config.gui.get()) return + if (!RiftAPI.inRift()) return + + config.position.renderRenderable(display, "Punchcard Overlay") + } + + private fun drawDisplay(): Renderable { + var string = "" + if (!config.compact.get()) string += "Punchcard Artifact: " + string += "§d" + if (!config.reverseGUI.get()) playerList.size + else 20 - playerList.size + + return Renderable.horizontalContainer( + listOf( + Renderable.itemStack(displayIcon), + Renderable.string(string), + ), + spacing = 1, + ) + } + + private fun reloadColors() { + MobData.players.forEach { + removePlayerColor(it.baseEntity) + } + if (!config.highlight.get()) return + val reverse = config.reverse.get() + for (player in MobData.players.filter { (reverse && it.name in playerList) || (!reverse && it.name !in playerList) }) { + colorPlayer(player.baseEntity) + } + } +} |