Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Add player highlighting for the Punchcard Artifact #1089

Merged
merged 64 commits into from
Jun 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
4f7ffc6
init punchcard highlighting
martimavocado Mar 2, 2024
83c269c
Merge branch 'beta' into rift-punchcard
martimavocado Mar 2, 2024
825242b
add 20 player limit, fix hardcoded ign check
martimavocado Mar 2, 2024
b7b1a75
hardcode fixing alpha
martimavocado Mar 2, 2024
494ca5b
add /shresetpunchcard
martimavocado Mar 2, 2024
8429f70
move out of storage
martimavocado Mar 2, 2024
76b543e
change default color
martimavocado Mar 2, 2024
912f309
remove unused pattern
martimavocado Mar 4, 2024
ec6a57e
Merge branch 'beta' into rift-punchcard
martimavocado Mar 4, 2024
8ce814d
Merge branch 'beta' into fork/rift-punchcard
hannibal002 Mar 7, 2024
06d7794
Merge branch 'beta' into fork/rift-punchcard
hannibal002 Mar 9, 2024
adffcda
various fixes
martimavocado Mar 12, 2024
887b33d
Merge branch 'beta' into rift-punchcard
martimavocado Mar 12, 2024
4c7221e
move to EntityJoinWorldEvent
martimavocado Mar 12, 2024
50d3f11
Merge remote-tracking branch 'origin/rift-punchcard' into rift-punchcard
martimavocado Mar 12, 2024
64e0e61
Merge branch 'beta' into fork/rift-punchcard
hannibal002 Mar 14, 2024
3f9c07c
Merge branch 'beta' into fork/rift-punchcard
hannibal002 Mar 15, 2024
0dc1fc1
fixed merge conflicts
hannibal002 Mar 15, 2024
a0256f5
Merge branch 'beta' into fork/rift-punchcard
hannibal002 Apr 3, 2024
7df7962
move
hannibal002 Apr 3, 2024
43d711f
Merge branch 'refs/heads/beta' into rift-punchcard
martimavocado Apr 10, 2024
20d6eab
cleanup, move to mobdetection
martimavocado Apr 10, 2024
b9eae01
fix config
martimavocado Apr 10, 2024
e5832dc
make regex more readable
martimavocado Apr 10, 2024
92ce403
Merge branch 'refs/heads/beta' into rift-punchcard
martimavocado Apr 19, 2024
e3dc84e
fix maybe
martimavocado Apr 19, 2024
a92d0df
gg
martimavocado Apr 19, 2024
b016779
stop checking for ownign
martimavocado Apr 20, 2024
8bf1007
Merge remote-tracking branch 'refs/remotes/hannibal002/beta' into rif…
martimavocado Apr 28, 2024
2b02f0f
Merge branch 'refs/heads/beta' into rift-punchcard
martimavocado Apr 28, 2024
9a3f0c4
start working on proper punch detection
martimavocado Apr 28, 2024
0f40da7
sleeping is cool sometimes
martimavocado Apr 29, 2024
6d1f2b1
Merge remote-tracking branch 'refs/remotes/hannibal002/beta' into rif…
martimavocado Apr 29, 2024
0a7077d
Merge remote-tracking branch 'refs/remotes/hannibal002/beta' into rif…
martimavocado Apr 30, 2024
0687820
bam
martimavocado Apr 30, 2024
e848f91
fix? config
martimavocado May 1, 2024
159b317
fix world switching to same server
martimavocado May 1, 2024
0acc0ea
better default position
martimavocado May 1, 2024
7eb0619
restore debug command
martimavocado May 1, 2024
692e0e6
cleanup
martimavocado May 1, 2024
ab27c1b
more
martimavocado May 1, 2024
495f223
separate reverser toggles
martimavocado May 1, 2024
5b8c921
Merge remote-tracking branch 'refs/remotes/hannibal002/beta' into rif…
martimavocado May 10, 2024
1613994
fix clear command
martimavocado May 10, 2024
eedc5d6
Merge remote-tracking branch 'refs/remotes/hannibal/beta' into rift-p…
martimavocado Jun 9, 2024
ad70e4c
fix merge
martimavocado Jun 9, 2024
33d4c51
format
martimavocado Jun 9, 2024
bb2c823
move to renderable
martimavocado Jun 9, 2024
a91bf76
is ktlint happy now
martimavocado Jun 12, 2024
ff5453b
the answer was no
martimavocado Jun 12, 2024
98a4ee1
use regexutils
martimavocado Jun 12, 2024
28a539d
Merge branch 'refs/heads/beta' into fork/martimavocado/rift-punchcard
hannibal002 Jun 16, 2024
02ed0e1
code cleanup
hannibal002 Jun 16, 2024
cd1653b
Merge remote-tracking branch 'hannibal/beta' into rift-punchcard
martimavocado Jun 16, 2024
e7e891c
add hanni's suggestions
martimavocado Jun 16, 2024
e1b43c7
fix display not updating
martimavocado Jun 16, 2024
3683f29
faeture toggle
martimavocado Jun 16, 2024
04c1b59
rename
martimavocado Jun 16, 2024
d9f0ad6
simplify island change logic
martimavocado Jun 16, 2024
3b37a78
Merge branch 'refs/heads/beta' into fork/martimavocado/rift-punchcard
hannibal002 Jun 16, 2024
f60cbb7
code cleanup
hannibal002 Jun 16, 2024
47ae6e1
add warning, reorder islandchange function
martimavocado Jun 16, 2024
cdacfc1
Merge remote-tracking branch 'martimavocado/rift-punchcard' into rift…
martimavocado Jun 16, 2024
eb37fce
code cleanup
hannibal002 Jun 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .idea/dictionaries/default_user.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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() {
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ public class RiftConfig {
@Accordion
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,6 @@ public static class RiftStorage {

@Expose
public VerminTracker.Data verminTracker = new VerminTracker.Data();

}

@Expose
Expand Down
Original file line number Diff line number Diff line change
@@ -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(
martimavocado marked this conversation as resolved.
Show resolved Hide resolved
"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
martimavocado marked this conversation as resolved.
Show resolved Hide resolved
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) {
martimavocado marked this conversation as resolved.
Show resolved Hide resolved
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
martimavocado marked this conversation as resolved.
Show resolved Hide resolved
if (!RiftAPI.inRift()) return
martimavocado marked this conversation as resolved.
Show resolved Hide resolved

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)
}
}
}
Loading