From d32e0c37b6b514b31cd2e21294c81b3e56e3050f Mon Sep 17 00:00:00 2001 From: hannibal2 <24389977+hannibal00212@users.noreply.github.com> Date: Fri, 16 Sep 2022 00:05:11 +0200 Subject: added support for links in player chat --- CHANGELOG.md | 1 + .../java/at/hannibal2/skyhanni/SkyHanniMod.java | 6 +- .../at/hannibal2/skyhanni/config/Features.java | 6 +- .../hannibal2/skyhanni/config/features/Chat.java | 4 +- .../skyhanni/features/chat/PlayerChatFilter.kt | 179 ----------------- .../skyhanni/features/chat/PlayerChatFormatter.kt | 220 +++++++++++++++++++++ .../features/chat/SkyBlockLevelChatMessage.kt | 39 ---- .../java/at/hannibal2/skyhanni/test/LorenzTest.kt | 22 ++- 8 files changed, 247 insertions(+), 230 deletions(-) delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/chat/PlayerChatFilter.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/chat/PlayerChatFormatter.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/chat/SkyBlockLevelChatMessage.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 491df8974..90c4416b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - Added option to hide all damage splashes, from anywhere in Skyblock. - Added highlight Thunder Sparks after killing a Thunder - Added Thunder to damage indicator +- Added support for links in player chat ## Version 0.8 diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java index a5fda4100..0d4afe7de 100644 --- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java +++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java @@ -12,8 +12,7 @@ import at.hannibal2.skyhanni.features.bazaar.BazaarBestSellMethod; import at.hannibal2.skyhanni.features.bazaar.BazaarOrderHelper; import at.hannibal2.skyhanni.features.chat.ChatFilter; import at.hannibal2.skyhanni.features.chat.HideFarDeathMessages; -import at.hannibal2.skyhanni.features.chat.PlayerChatFilter; -import at.hannibal2.skyhanni.features.chat.SkyBlockLevelChatMessage; +import at.hannibal2.skyhanni.features.chat.PlayerChatFormatter; import at.hannibal2.skyhanni.features.commands.WikiCommand; import at.hannibal2.skyhanni.features.damageindicator.DamageIndicatorManager; import at.hannibal2.skyhanni.features.dungeon.*; @@ -80,8 +79,7 @@ public class SkyHanniMod { registerEvent(new BazaarOrderHelper()); registerEvent(new ChatFilter()); - registerEvent(new PlayerChatFilter()); - registerEvent(new SkyBlockLevelChatMessage()); + registerEvent(new PlayerChatFormatter()); registerEvent(new DungeonChatFilter()); registerEvent(new HideNotClickableItems()); registerEvent(new ItemDisplayOverlayFeatures()); diff --git a/src/main/java/at/hannibal2/skyhanni/config/Features.java b/src/main/java/at/hannibal2/skyhanni/config/Features.java index 76f6a754d..70307c9f4 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/Features.java +++ b/src/main/java/at/hannibal2/skyhanni/config/Features.java @@ -8,7 +8,7 @@ import at.hannibal2.skyhanni.config.core.config.Position; import at.hannibal2.skyhanni.config.core.config.annotations.Category; import at.hannibal2.skyhanni.config.core.config.gui.GuiPositionEditor; import at.hannibal2.skyhanni.config.features.*; -import at.hannibal2.skyhanni.features.chat.PlayerChatFilter; +import at.hannibal2.skyhanni.features.chat.PlayerChatFormatter; import com.google.gson.annotations.Expose; import net.minecraft.client.Minecraft; @@ -87,12 +87,12 @@ public class Features extends Config { } if (runnableId.equals("testAllChat")) { - PlayerChatFilter.Companion.testAllChat(); + PlayerChatFormatter.Companion.testAllChat(); return; } if (runnableId.equals("testGuildChat")) { - PlayerChatFilter.Companion.testGuildChat(); + PlayerChatFormatter.Companion.testGuildChat(); return; } } diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/Chat.java b/src/main/java/at/hannibal2/skyhanni/config/features/Chat.java index 0d34e2744..26e409c00 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/Chat.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/Chat.java @@ -85,8 +85,8 @@ public class Chat { desc = "Change the design of the Elite position in the chat." ) @ConfigEditorDropdown( - values = {"§6[⌬55]", - "§6§l⌬55", + values = {"§6[⌬499]", + "§6§l⌬499", "§cHide Elite Position"} ) @ConfigAccordionId(id = 1) diff --git a/src/main/java/at/hannibal2/skyhanni/features/chat/PlayerChatFilter.kt b/src/main/java/at/hannibal2/skyhanni/features/chat/PlayerChatFilter.kt deleted file mode 100644 index fcde746d9..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/chat/PlayerChatFilter.kt +++ /dev/null @@ -1,179 +0,0 @@ -package at.hannibal2.skyhanni.features.chat - -import at.hannibal2.skyhanni.SkyHanniMod -import at.hannibal2.skyhanni.events.LorenzChatEvent -import at.hannibal2.skyhanni.events.PlayerSendChatEvent -import at.hannibal2.skyhanni.utils.LorenzLogger -import at.hannibal2.skyhanni.utils.LorenzUtils -import at.hannibal2.skyhanni.utils.StringUtils.removeColor -import net.minecraft.client.Minecraft -import net.minecraft.util.ChatComponentText -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent -import java.util.regex.Pattern - -class PlayerChatFilter { - - private val loggerPlayerChat = LorenzLogger("chat/player") - - //§6[⌬57] §r§8[§r§b235§r§8] §r§6[MVP§r§c++§r§6] hannibal2§r§f: Hello World! - private val patternElitePrefix = Pattern.compile("§6\\[⌬(\\d+)] (.+)") - - //§8[§9109§8] §b[MVP§c+§b] 4Apex§f§r§f: omg selling - private val patternSkyBlockLevel = Pattern.compile("§8\\[§(.)(\\d+)§8] (.+)") - - //§dTo §r§b[MVP§r§3+§r§b] Skyfall55§r§7: §r§7hello :) - var patternPrivateMessage: Pattern = Pattern.compile("§d(To|From) §r(.+)§r§7: §r§7(.+)") - - @SubscribeEvent - fun onChatMessage(event: LorenzChatEvent) { - if (!LorenzUtils.isOnHypixel) return - - if (shouldBlock(event.message)) { - event.blockedReason = "player_chat" - } - } - - private fun shouldBlock(originalMessage: String): Boolean { - if (handlePrivateMessage(originalMessage)) return true - - //since hypixel sends own chat messages really weird " §r§8[§r§d205§r§8] §r§6[MVP§r§c++§r§6] hannibal2" - var rawMessage = originalMessage.replace("§r", "").trim() - - val matcherElite = patternElitePrefix.matcher(rawMessage) - val elitePrefix = if (matcherElite.matches()) { - val elitePosition = matcherElite.group(1).toInt() - rawMessage = matcherElite.group(2) - when (SkyHanniMod.feature.chat.eliteFormat) { - 0 -> "§6[⌬$elitePosition] " - 1 -> "§6§l⌬$elitePosition " - 2 -> "" - else -> "" - } - } else { - "" - } - SkyBlockLevelChatMessage.elitePrefix = elitePrefix - - val matcher = patternSkyBlockLevel.matcher(rawMessage) - if (matcher.matches()) { - SkyBlockLevelChatMessage.levelColor = matcher.group(1) - SkyBlockLevelChatMessage.level = matcher.group(2).toInt() - rawMessage = matcher.group(3) - } - - val split = if (rawMessage.contains("§7§7: ")) { - rawMessage.split("§7§7: ") - } else if (rawMessage.contains("§f: ")) { - rawMessage.split("§f: ") - } else { - return false - } - - var rawName = split[0] - val channel = grabChannel(rawName) - - rawName = rawName.substring(channel.originalPrefix.length) - val name = grabName(rawName) ?: return false - - val message = split[1] - send(channel, name, message.removeColor(), if (elitePrefix != "") " $elitePrefix" else elitePrefix) - return true - } - - private fun handlePrivateMessage(originalMessage: String): Boolean { - - val matcher = patternPrivateMessage.matcher(originalMessage) - if (!matcher.matches()) return false - val direction = matcher.group(1) - val rawName = matcher.group(2) - val name = grabName(rawName) ?: return false - - val message = matcher.group(3) - val colon = if (SkyHanniMod.feature.chat.playerColonHider) "" else ":" - LorenzUtils.chat("§d$direction $name§f$colon $message") - loggerPlayerChat.log("[Msg_$direction] $name: $message") - return true - } - - private fun grabChannel(name: String): PlayerMessageChannel { - return PlayerMessageChannel.values() - .find { it != PlayerMessageChannel.ALL && name.startsWith(it.originalPrefix) } - ?: PlayerMessageChannel.ALL - } - - private fun grabName(rawName: String): String? { - val nameSplit = rawName.removeColor().split(" ") - val last = nameSplit.last() - val cleanName = if (last.endsWith("]")) { - nameSplit[nameSplit.size - 2] - } else { - last - } - - val first = nameSplit[0] - if (first != cleanName) { - if (!first.contains("VIP") && !first.contains("MVP")) { - //TODO support yt + admin - return null - } - } - return if (SkyHanniMod.feature.chat.playerRankHider) { - "§b$cleanName" - } else { - rawName - } - } - - private fun send(channel: PlayerMessageChannel, name: String, message: String, elitePrefix: String) { - loggerPlayerChat.log("[$channel] ${name.removeColor()}: $message") - val event = PlayerSendChatEvent(channel, name, message) - event.postAndCatch() - - if (event.cancelledReason != "") { - loggerPlayerChat.log("cancelled: " + event.cancelledReason) - return - } - - val finalMessage = event.message - if (finalMessage != message) { - loggerPlayerChat.log("message changed: $finalMessage") - } - - val channelPrefix = getChannelPrefix(channel) - val colon = if (SkyHanniMod.feature.chat.playerColonHider) "" else ":" - LorenzUtils.chat("$channelPrefix$elitePrefix$name§f$colon $finalMessage") - } - - companion object { - - fun getChannelPrefix(channel: PlayerMessageChannel): String { - if (channel == PlayerMessageChannel.ALL && !SkyHanniMod.feature.chat.allChannelPrefix) return "" - - val color = channel.prefixColor - val small = channel.prefixSmall - val large = channel.prefixLarge - return when (SkyHanniMod.feature.chat.channelDesign) { - 0 -> "$color$large §8> " - 1 -> "$color$small> " - 2 -> "§8<$color$small§8> " - 3 -> "§8[$color$small§8] " - 4 -> "§8($color$small§8) " - else -> "$color$large §8> " - } - } - - fun testAllChat() { - val name = Minecraft.getMinecraft().thePlayer.name - val message = - "§6[⌬499] §8[§b123§8] §6[MVP§c++§6] $name§f: This is a all chat test message and will not be sent to hypixel." - LorenzChatEvent(message, ChatComponentText(message)).postAndCatch() - } - - fun testGuildChat() { - val name = Minecraft.getMinecraft().thePlayer.name - val message = - "§2Guild > §6[MVP§f++§6] $name §2[GuildRank]§f: This is a guild chat test message and will not be sent to hypixel." - LorenzChatEvent(message, ChatComponentText(message)).postAndCatch() - } - } -} \ No newline at end of file diff --git a/src/main/java/at/hannibal2/skyhanni/features/chat/PlayerChatFormatter.kt b/src/main/java/at/hannibal2/skyhanni/features/chat/PlayerChatFormatter.kt new file mode 100644 index 000000000..72ee33195 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/chat/PlayerChatFormatter.kt @@ -0,0 +1,220 @@ +package at.hannibal2.skyhanni.features.chat + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.events.LorenzChatEvent +import at.hannibal2.skyhanni.events.PlayerSendChatEvent +import at.hannibal2.skyhanni.utils.LorenzLogger +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.StringUtils.removeColor +import net.minecraft.client.Minecraft +import net.minecraft.event.ClickEvent +import net.minecraft.util.ChatComponentText +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import java.util.regex.Pattern + +class PlayerChatFormatter { + + private val loggerPlayerChat = LorenzLogger("chat/player") + + //§6[⌬57] §r§8[§r§b235§r§8] §r§6[MVP§r§c++§r§6] hannibal2§r§f: Hello World! + private val patternElitePrefix = Pattern.compile("§6\\[⌬(\\d+)] (.+)") + + //§8[§9109§8] §b[MVP§c+§b] 4Apex§f§r§f: omg selling + private val patternSkyBlockLevel = Pattern.compile("§8\\[§(.)(\\d+)§8] (.+)") + + //§dTo §r§b[MVP§r§3+§r§b] Skyfall55§r§7: §r§7hello :) + private var patternPrivateMessage: Pattern = Pattern.compile("§d(To|From) §r(.+)§r§7: §r§7(.+)") + + private val patternUrl = + Pattern.compile("^https?:\\/\\/(?:www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b(?:[-a-zA-Z0-9()@:%_\\+.~#?&\\/=]*)$") + + @SubscribeEvent + fun onChatMessage(event: LorenzChatEvent) { + if (!LorenzUtils.isOnHypixel) return + + if (shouldBlock(event.message)) { + event.blockedReason = "player_chat" + } + } + + private fun shouldBlock(originalMessage: String): Boolean { + if (handlePrivateMessage(originalMessage)) return true + + //since hypixel sends own chat messages really weird " §r§8[§r§d205§r§8] §r§6[MVP§r§c++§r§6] hannibal2" + var rawMessage = originalMessage.replace("§r", "").trim() + + val matcherElite = patternElitePrefix.matcher(rawMessage) + val elitePrefix = if (matcherElite.matches()) { + val elitePosition = matcherElite.group(1).toInt() + rawMessage = matcherElite.group(2) + when (SkyHanniMod.feature.chat.eliteFormat) { + 0 -> "§6[⌬$elitePosition] " + 1 -> "§6§l⌬$elitePosition " + 2 -> "" + else -> "" + } + } else { + "" + } + + + val level: Int + val levelColor: String + val matcher = patternSkyBlockLevel.matcher(rawMessage) + if (matcher.matches()) { + levelColor = matcher.group(1) + level = matcher.group(2).toInt() + rawMessage = matcher.group(3) + } else { + level = -1 + levelColor = "" + } + + val split = if (rawMessage.contains("§7§7: ")) { + rawMessage.split("§7§7: ") + } else if (rawMessage.contains("§f: ")) { + rawMessage.split("§f: ") + } else { + return false + } + + var rawName = split[0] + val channel = grabChannel(rawName) + + rawName = rawName.substring(channel.originalPrefix.length) + val name = grabName(rawName) ?: return false + + val message = split[1] + callEvent(channel, name, message.removeColor(), level, levelColor, elitePrefix) + return true + } + + private fun handlePrivateMessage(originalMessage: String): Boolean { + val matcher = patternPrivateMessage.matcher(originalMessage) + if (!matcher.matches()) return false + val direction = matcher.group(1) + val rawName = matcher.group(2) + val name = grabName(rawName) ?: return false + + val message = matcher.group(3) + val colon = if (SkyHanniMod.feature.chat.playerColonHider) "" else ":" + LorenzUtils.chat("§d$direction $name§f$colon $message") + loggerPlayerChat.log("[Msg_$direction] $name: $message") + return true + } + + private fun grabChannel(name: String): PlayerMessageChannel { + return PlayerMessageChannel.values() + .find { it != PlayerMessageChannel.ALL && name.startsWith(it.originalPrefix) } + ?: PlayerMessageChannel.ALL + } + + private fun grabName(rawName: String): String? { + val nameSplit = rawName.removeColor().split(" ") + val last = nameSplit.last() + val cleanName = if (last.endsWith("]")) { + nameSplit[nameSplit.size - 2] + } else { + last + } + + val first = nameSplit[0] + if (first != cleanName) { + if (!first.contains("VIP") && !first.contains("MVP")) { + //TODO support yt + admin + return null + } + } + return if (SkyHanniMod.feature.chat.playerRankHider) { + "§b$cleanName" + } else { + rawName + } + } + + private fun callEvent( + channel: PlayerMessageChannel, + name: String, + message: String, + level: Int, + levelColor: String, + elitePrefix: String, + ) { + loggerPlayerChat.log("[$channel] ${name.removeColor()}: $message") + val event = PlayerSendChatEvent(channel, name, message) + event.postAndCatch() + + if (event.cancelledReason != "") { + loggerPlayerChat.log("cancelled: " + event.cancelledReason) + return + } + + val channelPrefix = getChannelPrefix(channel) + val colon = if (SkyHanniMod.feature.chat.playerColonHider) "" else ":" + val levelFormat = getLevelFormat(name, level, levelColor) + + sendWithLink("$channelPrefix$elitePrefix$levelFormat§f$colon", event.message) + } + + private fun sendWithLink(prefix: String, message: String) { + val fullText = ChatComponentText(prefix) + + for (lines in message.split(" ")) { + fullText.appendSibling(ChatComponentText(" ")) + if (patternUrl.matcher(lines).matches()) { + val oneWord = ChatComponentText(lines) + oneWord.chatStyle.chatClickEvent = ClickEvent(ClickEvent.Action.OPEN_URL, lines) + fullText.appendSibling(oneWord) + } else { + fullText.appendSibling(ChatComponentText(lines)) + } + } + + Minecraft.getMinecraft().thePlayer.addChatMessage(fullText) + } + + private fun getLevelFormat(name: String, level: Int, levelColor: String): String { + if (level == -1) return name + + return when (SkyHanniMod.feature.chat.skyblockLevelDesign) { + 0 -> "§8[§${levelColor}${level}§8] $name" + 1 -> "§${levelColor}§l${level} $name" + 2 -> "$name §8[§${levelColor}${level}§8]" + 3 -> name + else -> "§8[§${levelColor}${level}§8] $name" + } + } + + private fun getChannelPrefix(channel: PlayerMessageChannel): String { + if (channel == PlayerMessageChannel.ALL && !SkyHanniMod.feature.chat.allChannelPrefix) return "" + + val color = channel.prefixColor + val small = channel.prefixSmall + val large = channel.prefixLarge + return when (SkyHanniMod.feature.chat.channelDesign) { + 0 -> "$color$large §8> " + 1 -> "$color$small> " + 2 -> "§8<$color$small§8> " + 3 -> "§8[$color$small§8] " + 4 -> "§8($color$small§8) " + else -> "$color$large §8> " + } + } + + companion object { + + fun testAllChat() { + val name = Minecraft.getMinecraft().thePlayer.name + val message = + "§6[⌬499] §8[§b123§8] §6[MVP§c++§6] $name§f: This is a all chat test message and will not be sent to hypixel." + LorenzChatEvent(message, ChatComponentText(message)).postAndCatch() + } + + fun testGuildChat() { + val name = Minecraft.getMinecraft().thePlayer.name + val message = + "§2Guild > §6[MVP§f++§6] $name §2[GuildRank]§f: This is a guild chat test message and will not be sent to hypixel." + LorenzChatEvent(message, ChatComponentText(message)).postAndCatch() + } + } +} \ No newline at end of file diff --git a/src/main/java/at/hannibal2/skyhanni/features/chat/SkyBlockLevelChatMessage.kt b/src/main/java/at/hannibal2/skyhanni/features/chat/SkyBlockLevelChatMessage.kt deleted file mode 100644 index 8a0e3628b..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/chat/SkyBlockLevelChatMessage.kt +++ /dev/null @@ -1,39 +0,0 @@ -package at.hannibal2.skyhanni.features.chat - -import at.hannibal2.skyhanni.SkyHanniMod -import at.hannibal2.skyhanni.events.PlayerSendChatEvent -import at.hannibal2.skyhanni.utils.LorenzUtils -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent - -class SkyBlockLevelChatMessage { - - companion object { - var level = -1 - var levelColor = "" - var elitePrefix = "" - } - - @SubscribeEvent - fun onChatMessage(event: PlayerSendChatEvent) { - if (level == -1) return - event.cancelledReason = "skyblock level" - - val message = event.message - val name = event.formattedName - val channelPrefix = PlayerChatFilter.getChannelPrefix(event.channel) - - val colon = if (SkyHanniMod.feature.chat.playerColonHider) "" else ":" - - val levelFormat = getLevelFormat(name) - LorenzUtils.chat("$channelPrefix$elitePrefix$levelFormat§f$colon $message") - level = -1 - } - - private fun getLevelFormat(name: String) = when (SkyHanniMod.feature.chat.skyblockLevelDesign) { - 0 -> "§8[§$levelColor${level}§8] $name" - 1 -> "§${levelColor}§l$level $name" - 2 -> "$name §8[§$levelColor${level}§8]" - 3 -> name - else -> "§8[§$levelColor${level}§8] $name" - } -} \ No newline at end of file diff --git a/src/main/java/at/hannibal2/skyhanni/test/LorenzTest.kt b/src/main/java/at/hannibal2/skyhanni/test/LorenzTest.kt index e39b62d28..2e931b97a 100644 --- a/src/main/java/at/hannibal2/skyhanni/test/LorenzTest.kt +++ b/src/main/java/at/hannibal2/skyhanni/test/LorenzTest.kt @@ -10,7 +10,9 @@ import at.hannibal2.skyhanni.utils.LorenzLogger import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.RenderUtils.renderString import net.minecraft.client.Minecraft +import net.minecraft.event.HoverEvent import net.minecraft.nbt.NBTTagCompound +import net.minecraft.util.ChatComponentText import net.minecraftforge.client.event.RenderGameOverlayEvent import net.minecraftforge.event.entity.living.EnderTeleportEvent import net.minecraftforge.event.entity.player.ItemTooltipEvent @@ -43,9 +45,23 @@ class LorenzTest { fun testCommand(args: Array) { - a = args[0].toDouble() - b = args[1].toDouble() - c = args[2].toDouble() + + val textA = ChatComponentText("a") + + textA.chatStyle.chatHoverEvent = HoverEvent(HoverEvent.Action.SHOW_TEXT, ChatComponentText("hey :)")) + + val textB = ChatComponentText("b") + val text1 = ChatComponentText("1") + text1.appendSibling(textA) + text1.appendSibling(textB) + + Minecraft.getMinecraft().thePlayer.addChatMessage(text1) + + + +// a = args[0].toDouble() +// b = args[1].toDouble() +// c = args[2].toDouble() // for (line in (Minecraft.getMinecraft().ingameGUI.tabList as AccessorGuiPlayerTabOverlay).footer.unformattedText // .split("\n")) { -- cgit