aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.idea/dictionaries/default_user.xml1
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/rift/PunchcardConfig.java48
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/rift/RiftConfig.java5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java1
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/rift/everywhere/PunchcardHighlight.kt253
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)
+ }
+ }
+}