aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/at/hannibal2
diff options
context:
space:
mode:
authorhannibal2 <24389977+hannibal002@users.noreply.github.com>2024-04-19 11:24:36 +0200
committerGitHub <noreply@github.com>2024-04-19 11:24:36 +0200
commitf8efe9effd27bee18bced64385fc1ad9b05b68bd (patch)
tree1429920226fc79af8bae814bb7596b9e65e0cf7e /src/main/java/at/hannibal2
parent7feb5c67fbc1c9f63118952f1bea649ada1dccd6 (diff)
downloadskyhanni-f8efe9effd27bee18bced64385fc1ad9b05b68bd.tar.gz
skyhanni-f8efe9effd27bee18bced64385fc1ad9b05b68bd.tar.bz2
skyhanni-f8efe9effd27bee18bced64385fc1ad9b05b68bd.zip
Feature + Fix: Player Chat Rework (#1483)
Co-authored-by: CalMWolfs <94038482+CalMWolfs@users.noreply.github.com> Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com>
Diffstat (limited to 'src/main/java/at/hannibal2')
-rw-r--r--src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt6
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/chat/ChatConfig.java7
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/chat/ChatSymbols.java54
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/chat/PlayerMessagesConfig.java65
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/PartyAPI.kt25
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/PlayerChatManager.kt220
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/PlayerNameFormatter.kt200
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/AbstractChatEvent.kt11
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/GuildChatEvent.kt11
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/NpcChatEvent.kt10
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/PartyChatEvent.kt10
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/PlayerAllChatEvent.kt15
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/PlayerShowItemChatEvent.kt14
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/PrivateMessageChatEvent.kt11
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/SystemMessageEvent.kt10
-rw-r--r--src/main/java/at/hannibal2/skyhanni/events/PartyChatEvent.kt7
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/bingo/BingoAPI.kt9
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/chat/Translator.kt1
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/chat/playerchat/PlayerChatModifier.kt61
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/commands/PartyChatCommands.kt6
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorFeatures.kt1
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/MarkedPlayerManager.kt11
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/PlayerChatSymbols.kt107
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/compacttablist/AdvancedPlayerList.kt109
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/compacttablist/TabListReader.kt1
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt55
27 files changed, 737 insertions, 302 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt
index c23149967..a91d6bcad 100644
--- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt
+++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt
@@ -54,6 +54,8 @@ import at.hannibal2.skyhanni.data.TitleData
import at.hannibal2.skyhanni.data.TitleManager
import at.hannibal2.skyhanni.data.ToolTipData
import at.hannibal2.skyhanni.data.TrackerManager
+import at.hannibal2.skyhanni.data.hypixel.chat.PlayerChatManager
+import at.hannibal2.skyhanni.data.hypixel.chat.PlayerNameFormatter
import at.hannibal2.skyhanni.data.jsonobjects.local.FriendsJson
import at.hannibal2.skyhanni.data.jsonobjects.local.JacobContestsJson
import at.hannibal2.skyhanni.data.jsonobjects.local.KnownFeaturesJson
@@ -319,7 +321,6 @@ import at.hannibal2.skyhanni.features.misc.PatcherSendCoordinates
import at.hannibal2.skyhanni.features.misc.PetCandyUsedDisplay
import at.hannibal2.skyhanni.features.misc.PetExpTooltip
import at.hannibal2.skyhanni.features.misc.PetItemDisplay
-import at.hannibal2.skyhanni.features.misc.PlayerChatSymbols
import at.hannibal2.skyhanni.features.misc.PocketSackInASackDisplay
import at.hannibal2.skyhanni.features.misc.PrivateIslandNoPickaxeAbility
import at.hannibal2.skyhanni.features.misc.QuickModMenuSwitch
@@ -465,6 +466,8 @@ class SkyHanniMod {
// data
loadModule(this)
loadModule(ChatManager)
+ loadModule(PlayerChatManager())
+ loadModule(PlayerNameFormatter())
loadModule(HypixelData())
loadModule(LocationFixData)
loadModule(DungeonAPI)
@@ -821,7 +824,6 @@ class SkyHanniMod {
loadModule(DungeonRankTabListColor())
loadModule(TerracottaPhase())
loadModule(VolcanoExplosivityDisplay())
- loadModule(PlayerChatSymbols())
loadModule(FixNEUHeavyPearls())
loadModule(QuickCraftFeatures())
loadModule(SkyBlockKickDuration())
diff --git a/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt b/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt
index 9f0b281ff..1e8a576e2 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt
+++ b/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt
@@ -12,7 +12,7 @@ import com.google.gson.JsonPrimitive
object ConfigUpdaterMigrator {
val logger = LorenzLogger("ConfigMigration")
- const val CONFIG_VERSION = 40
+ const val CONFIG_VERSION = 41
fun JsonElement.at(chain: List<String>, init: Boolean): JsonElement? {
if (chain.isEmpty()) return this
if (this !is JsonObject) return null
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/chat/ChatConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/chat/ChatConfig.java
index 72b21411b..f2d187687 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/chat/ChatConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/chat/ChatConfig.java
@@ -22,20 +22,17 @@ public class ChatConfig {
@Expose
@ConfigOption(name = "Chat Filter Types", desc = "")
@Accordion
+ // TODO move into own sub category
public FilterTypesConfig filterType = new FilterTypesConfig();
@Expose
@ConfigOption(name = "Player Messages", desc = "")
@Accordion
+ // TODO move into own sub category
public PlayerMessagesConfig playerMessage = new PlayerMessagesConfig();
@Expose
- @ConfigOption(name = "Player Chat Symbols", desc = "")
- @Accordion
- public ChatSymbols chatSymbols = new ChatSymbols();
-
- @Expose
@ConfigOption(name = "Dungeon Filter", desc = "Hide specific message types in Dungeons.")
@ConfigEditorDraggableList
public List<DungeonMessageTypes> dungeonFilteredMessageTypes = new ArrayList<>();
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/chat/ChatSymbols.java b/src/main/java/at/hannibal2/skyhanni/config/features/chat/ChatSymbols.java
deleted file mode 100644
index ccead7f7b..000000000
--- a/src/main/java/at/hannibal2/skyhanni/config/features/chat/ChatSymbols.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package at.hannibal2.skyhanni.config.features.chat;
-
-import at.hannibal2.skyhanni.config.FeatureToggle;
-import at.hannibal2.skyhanni.config.HasLegacyId;
-import com.google.gson.annotations.Expose;
-import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean;
-import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorDropdown;
-import io.github.notenoughupdates.moulconfig.annotations.ConfigOption;
-
-public class ChatSymbols {
-
- @Expose
- @ConfigOption(name = "Enabled", desc = "Adds extra symbols to the chat such as those from ironman, " +
- "stranded, bingo or nether factions and places them next to your regular player emblems. " +
- "§cDoes not work with hide rank hider!")
- @ConfigEditorBoolean
- @FeatureToggle
- public boolean enabled = true;
-
- @Expose
- @ConfigOption(name = "Chat Symbol Location", desc = "Determines where the symbols should go in chat in relation to the " +
- "player's name. Hidden will hide all emblems from the chat. §eRequires above setting to be on to hide the symbols.")
- @ConfigEditorDropdown
- public SymbolLocationEntry symbolLocation = SymbolLocationEntry.LEFT;
-
- public enum SymbolLocationEntry implements HasLegacyId {
- LEFT("Left", 0),
- RIGHT("Right", 1),
- HIDDEN("Hidden", 2);
-
- private final String str;
- private final int legacyId;
-
- SymbolLocationEntry(String str, int legacyId) {
- this.str = str;
- this.legacyId = legacyId;
- }
-
- // Constructor if new enum elements are added post-migration
- SymbolLocationEntry(String str) {
- this(str, -1);
- }
-
- @Override
- public int getLegacyId() {
- return legacyId;
- }
-
- @Override
- public String toString() {
- return str;
- }
- }
-}
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/chat/PlayerMessagesConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/chat/PlayerMessagesConfig.java
index 5ebad3d0c..a8903f4f1 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/chat/PlayerMessagesConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/chat/PlayerMessagesConfig.java
@@ -3,19 +3,84 @@ package at.hannibal2.skyhanni.config.features.chat;
import at.hannibal2.skyhanni.config.FeatureToggle;
import com.google.gson.annotations.Expose;
import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorDraggableList;
import io.github.notenoughupdates.moulconfig.annotations.ConfigOption;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
public class PlayerMessagesConfig {
@Expose
+ @ConfigOption(
+ name = "Part Order",
+ desc = "Drag text to change the chat message format order for chat messages."
+ )
+ @ConfigEditorDraggableList
+ public List<MessagePart> partsOrder = new ArrayList<>(Arrays.asList(
+ MessagePart.SKYBLOCK_LEVEL,
+ MessagePart.PRIVATE_ISLAND_RANK,
+ MessagePart.PRIVATE_ISLAND_GUEST,
+ MessagePart.PLAYER_NAME,
+ MessagePart.GUILD_RANK,
+ MessagePart.EMBLEM
+ ));
+
+ public enum MessagePart {
+ SKYBLOCK_LEVEL("SkyBlock Level"),
+ EMBLEM("Emblem"),
+ PLAYER_NAME("§bPlayer Name"),
+ GUILD_RANK("Guild Rank"),
+ PRIVATE_ISLAND_RANK("Private Island Rank"),
+ PRIVATE_ISLAND_GUEST("Private Island Guest"),
+ CRIMSON_FACTION("Crimson Faction"),
+ MODE_IRONMAN("Ironman Mode"),
+ BINGO_LEVEL("Bingo Level"),
+ ;
+
+ private final String str;
+
+ MessagePart(String str) {
+ this.str = str;
+ }
+
+ @Override
+ public String toString() {
+ return str;
+ }
+ }
+
+ @Expose
+ @ConfigOption(name = "Hide Level Brackets", desc = "Hide the gray brackets in front of and behind the level numbers.")
+ @ConfigEditorBoolean
+ public boolean hideLevelBrackets = false;
+
+ @Expose
+ @ConfigOption(name = "Level Color As Name", desc = "Use the color of the SkyBlock level for the player color.")
+ @ConfigEditorBoolean
+ public boolean useLevelColorForName = false;
+
+ @Expose
@ConfigOption(name = "Player Rank Hider", desc = "Hide player ranks in all chat messages.")
@ConfigEditorBoolean
@FeatureToggle
public boolean playerRankHider = false;
@Expose
+ @ConfigOption(name = "Ignore YouTube", desc = "Do not remove the rank for YouTubers in chat.")
+ @ConfigEditorBoolean
+ public boolean ignoreYouTube = false;
+
+ @Expose
@ConfigOption(name = "Chat Filter", desc = "Scan messages sent by players for blacklisted words and gray out the message if any are found.")
@ConfigEditorBoolean
@FeatureToggle
public boolean chatFilter = false;
+
+ @Expose
+ @ConfigOption(name = "Same Chat Color", desc = "All players, also those with ranks, write with the same, white chat color.")
+ @ConfigEditorBoolean
+ @FeatureToggle
+ public boolean sameChatColor = true;
}
diff --git a/src/main/java/at/hannibal2/skyhanni/data/PartyAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/PartyAPI.kt
index 44a778292..3bd3967be 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/PartyAPI.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/PartyAPI.kt
@@ -1,7 +1,7 @@
package at.hannibal2.skyhanni.data
+import at.hannibal2.skyhanni.data.hypixel.chat.event.PartyChatEvent
import at.hannibal2.skyhanni.events.LorenzChatEvent
-import at.hannibal2.skyhanni.events.PartyChatEvent
import at.hannibal2.skyhanni.utils.ChatUtils
import at.hannibal2.skyhanni.utils.LorenzUtils
import at.hannibal2.skyhanni.utils.OSUtils
@@ -78,16 +78,6 @@ object PartyAPI {
"§dParty Finder §f> (?<name>.*?) §ejoined the dungeon group! \\(§[a-fA-F0-9].* Level \\d+§[a-fA-F0-9]\\)"
)
- /**
- * REGEX-TEST: §9Party §8> §b§l⚛ §b[MVP§f+§b] Dankbarkeit§f: §rx: -190, y: 5, z: -163
- * REGEX-TEST: §9Party §8> §6⚔ §6[MVP§3++§6] RealBacklight§f: §r!warp
- * REGEX-TEST: §9Party §8> §b[MVP§3+§b] Eisengolem§f: §r!pt
- */
- private val partyChatMessagePattern by patternGroup.pattern(
- "chat.message",
- "§9Party §8> (?<name>[^:]*): §r(?<message>.*)"
- )
-
val partyMembers = mutableListOf<String>()
var partyLeader: String? = null
@@ -114,16 +104,15 @@ object PartyAPI {
}
@SubscribeEvent
+ fun onPartyChat(event: PartyChatEvent) {
+ val name = event.author.cleanPlayerName()
+ addPlayer(name)
+ }
+
+ @SubscribeEvent
fun onChat(event: LorenzChatEvent) {
val message = event.message.trimWhiteSpace().removeResets()
- partyChatMessagePattern.matchMatcher(event.message) {
- val name = group("name").cleanPlayerName()
- val message = group("message")
- addPlayer(name)
- PartyChatEvent(name, message, event).postAndCatch()
- }
-
// new member joined
youJoinedPartyPattern.matchMatcher(message) {
val name = group("name").cleanPlayerName()
diff --git a/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/PlayerChatManager.kt b/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/PlayerChatManager.kt
new file mode 100644
index 000000000..2b3efb6aa
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/PlayerChatManager.kt
@@ -0,0 +1,220 @@
+package at.hannibal2.skyhanni.data.hypixel.chat
+
+import at.hannibal2.skyhanni.data.IslandType
+import at.hannibal2.skyhanni.data.hypixel.chat.event.AbstractChatEvent
+import at.hannibal2.skyhanni.data.hypixel.chat.event.GuildChatEvent
+import at.hannibal2.skyhanni.data.hypixel.chat.event.NpcChatEvent
+import at.hannibal2.skyhanni.data.hypixel.chat.event.PartyChatEvent
+import at.hannibal2.skyhanni.data.hypixel.chat.event.PlayerAllChatEvent
+import at.hannibal2.skyhanni.data.hypixel.chat.event.PlayerShowItemChatEvent
+import at.hannibal2.skyhanni.data.hypixel.chat.event.PrivateMessageChatEvent
+import at.hannibal2.skyhanni.data.hypixel.chat.event.SystemMessageEvent
+import at.hannibal2.skyhanni.events.LorenzChatEvent
+import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.LorenzUtils.groupOrNull
+import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland
+import at.hannibal2.skyhanni.utils.NumberUtil.formatInt
+import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher
+import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern
+import net.minecraft.util.IChatComponent
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import java.util.regex.Matcher
+
+/**
+ * Reading normal chat events, and splitting them up into many different player chat events, with all avaliable extra information
+ */
+class PlayerChatManager {
+
+ private val patternGroup = RepoPattern.group("data.chat.player")
+
+ /**
+ * REGEX-TEST: §8[§r§6428§r§8] §r§b[MVP§5+§b] Alea1337§f: t
+ * REGEX-TEST: §8[§r§e102§r§8] §r§7☠ §r§b[MVP§d+§b] cobyjoey§f§r§f: first person to type "halo0011 is my favorite player on the game I love halo0011!!!"
+ * REGEX-TEST: §8[§r§5396§r§8] §r§7☢ §r§b[MVP§c+§b] hannibal2§f: hello
+ * REGEX-TEST: §8[§r§e97§r§8] §r§7☃ §r§7Tambaloo§7§r§7: i did capital i
+ * REGEX-TEST: §8[§r§f76§r§8] §r§7❂ §r§a[VIP] Asymmetrically§f§r§f: i need to put on my necron
+ * REGEX-TEST: §8[§r§c446§r§8] §r§b§l⚛ §r§6[MVP§1++§6] XueRuu§f§r§f: TROPHY FISH! You caught a Lavahorse DIAMOND.
+ * REGEX-TEST: §b[MVP§c+§b] hannibal2§f: test
+ */
+ private val globalPattern by patternGroup.pattern(
+ "global",
+ "(?:§8\\[§r(?<levelColor>§.)(?<level>\\d+)§r§8] §r)?(?<author>§.+)(?<chatColor>§f|§7§r§7): (?<message>.*)"
+ )
+
+ /**
+ * REGEX-TEST: §9Party §8> §b§l⚛ §b[MVP§f+§b] Dankbarkeit§f: §rx: -190, y: 5, z: -163
+ * REGEX-TEST: §9Party §8> §6⚔ §6[MVP§3++§6] RealBacklight§f: §r!warp
+ * REGEX-TEST: §9Party §8> §b[MVP§3+§b] Eisengolem§f: §r!pt
+ */
+ private val partyPattern by patternGroup.pattern(
+ "party",
+ "§9Party §8> (?<author>[^:]*): §r(?<message>.*)"
+ )
+
+ /**
+ * REGEX-TEST: §2Guild > §b§l⚛ §b[MVP§f+§b] Dankbarkeit§f: §rx: -190, y: 5, z: -163
+ * REGEX-TEST: §2Guild > §6⚔ §6[MVP§3++§6] RealBacklight§f: §r!warp
+ * REGEX-TEST: §2Guild > §b[MVP§3+§b] Eisengolem§f: §r!pt
+ * REGEX-TEST: §2Guild > §b[MVP§d+§b] zunoff §e[VET]§f: §rwas löuft
+ */
+ private val guildPattern by patternGroup.pattern(
+ "guild",
+ "§2Guild > (?<author>§.+?)(?<guildRank> §e\\[\\w*])?§f: §r(?<message>.*)"
+ )
+
+ /**
+ * REGEX-TEST: §dFrom §r§b[MVP§r§3+§r§b] Eisengolem§r§7: §r§7Baum
+ * REGEX-TEST: §dTo §r§b[MVP§r§3+§r§b] Eisengolem§r§7: §r§7hey
+ * REGEX-TEST: §dTo §r§b[MVP§r§5+§r§b] Alea1337§r§7: §r§d§lBoop!
+ */
+ private val privateMessagePattern by patternGroup.pattern(
+ "privatemessage",
+ "§d(?<direction>From|To) §r(?<author>[^:]*)§7: §r(?<message>.*)"
+ )
+
+ /**
+ * REGEX-TEST: §b[MVP§c+§b] hannibal2§f§7 is holding §r§8[§6Heroic Aspect of the Void§8]
+ * REGEX-TEST: §b[MVP§c+§b] hannibal2§f§7 is holding §r§8[§7[Lvl 2] §dSpider§8]
+ * REGEX-TEST: §b[MVP§c+§b] hannibal2§f§7 is friends with a §r§8[§7[Lvl 200] §8[§6103§8§4✦§8] §6Golden Dragon§8]
+ * REGEX-TEST: §b[MVP§c+§b] hannibal2§f§7 is wearing §r§8[§5Glistening Implosion Belt§8]
+ * REGEX-TEST: §b[MVP§c+§b] hannibal2§f§7 is friends with a §r§8[§7[Lvl 100] §dEnderman§8]
+ * REGEX-TEST: §b[MVP§c+§b] hannibal2§f§7 has §r§8[§6Heroic Aspect of the Void§8]
+ * REGEX-TEST: §8[§5396§8] §7☢ §r§b[MVP§c+§b] hannibal2§f§7 is holding §r§8[§6Buzzing InfiniVacuum™ Hooverius§8]
+ */
+ private val itemShowPattern by patternGroup.pattern(
+ "itemshow",
+ "(?:§8\\[(?<levelColor>§.)(?<level>\\d+)§8] )?(?<author>.*)§f§7 (?<action>is (?:holding|friends with a|wearing)|has) §r(?<itemName>.*)"
+ )
+
+ /**
+ * REGEX-TEST: §c[Tiffany] §b[MVP§c+§b] hannibal2
+ * REGEX-TEST: §b[MVP§c+§b] hannibal2
+ * REGEX-TEST: §6§l℻ §r§f[Gamer] §b[MVP§f+§b] SchrankLP§f§r
+ */
+ private val privateIslandRankPattern by patternGroup.pattern(
+ "privateislandrank",
+ ".*(?<privateIslandRank>§.\\[\\w+]).*"
+ )
+
+ /**
+ * REGEX-TEST: §8[§r§5396§r§8] §r§7☢ §r§a[✌] §b[MVP§c+§b] hannibal2§f: hey
+ * REGEX-TEST: §b[MVP§c+§b] hannibal2
+ * REGEX-TEST: §6§l℻ §r§f[Gamer] §b[MVP§f+§b] SchrankLP§f§r
+ * REGEX-TEST: §7☢ §r§a[✌] §b[MVP§c+§b] hannibal2
+ */
+ private val prrivateIslandGuestPattern by patternGroup.pattern(
+ "privateislandguest",
+ ".*(?<guest>§r§a\\[✌]).*"
+ )
+
+ @SubscribeEvent
+ fun onChat(event: LorenzChatEvent) {
+ val chatComponent = event.chatComponent
+ globalPattern.matchMatcher(event.message) {
+ if (isGlobalChat(event)) return
+ }
+ partyPattern.matchMatcher(event.message) {
+ val author = group("author")
+ val message = group("message")
+ PartyChatEvent(author, message, chatComponent).postChat(event)
+ return
+ }
+ guildPattern.matchMatcher(event.message) {
+ val author = group("author")
+ val message = group("message")
+ val guildRank = groupOrNull("guildRank")
+ GuildChatEvent(author, message, guildRank, chatComponent).postChat(event)
+ return
+ }
+ privateMessagePattern.matchMatcher(event.message) {
+ val direction = group("direction")
+ val author = group("author")
+ val message = group("message")
+ PrivateMessageChatEvent(direction, author, message, chatComponent).postChat(event)
+ return
+ }
+ itemShowPattern.matchMatcher(event.message) {
+ val levelColor = groupOrNull("levelColor")
+ val level = groupOrNull("level")?.formatInt()
+ val author = group("author")
+ val action = group("action")
+ val itemName = group("itemName")
+
+ // for consistency
+ val message = "§7$action §r$itemName"
+ PlayerShowItemChatEvent(levelColor, level, author, message, action, itemName, chatComponent).postChat(event)
+ }
+
+ sendSystemMessage(event)
+ }
+
+ private fun Matcher.isGlobalChat(event: LorenzChatEvent): Boolean {
+ var author = group("author")
+ // TODO move into regex
+ val isGuild = author.startsWith("§2Guild >")
+ val isParty = author.startsWith("§9Party")
+ if (isGuild || isParty) return false
+
+ val message = LorenzUtils.stripVanillaMessage(group("message"))
+ if (author.contains("[NPC]")) {
+ NpcChatEvent(author, message.removePrefix("§f"), event.chatComponent).postChat(event)
+ return true
+ }
+
+ var privateIslandRank: String? = null
+ var isAGuest = false
+ if (IslandType.PRIVATE_ISLAND.isInIsland() || IslandType.PRIVATE_ISLAND_GUEST.isInIsland()) {
+ privateIslandRankPattern.matchMatcher(author) {
+ val rank = group("privateIslandRank")
+ privateIslandRank = rank
+ author = author.replace(rank, "")
+ }
+ prrivateIslandGuestPattern.matchMatcher(author) {
+ val guest = group("guest")
+ isAGuest = true
+ author = author.replace(guest, "")
+ }
+ }
+
+ val chatColor = group("chatColor")
+ val levelColor = groupOrNull("levelColor")
+ val level = groupOrNull("level")?.formatInt()
+ PlayerAllChatEvent(
+ levelColor = levelColor,
+ level = level,
+ privateIslandRank = privateIslandRank,
+ isAGuest = isAGuest,
+ author = author,
+ chatColor = chatColor,
+ message = message,
+ chatComponent = event.chatComponent,
+ ).postChat(event)
+ return true
+ }
+
+ private fun sendSystemMessage(event: LorenzChatEvent) {
+ with(SystemMessageEvent(event.message, event.chatComponent)) {
+ val cancelled = postAndCatch()
+ event.handleChat(cancelled, blockedReason, chatComponent)
+ }
+ }
+
+ private fun AbstractChatEvent.postChat(event: LorenzChatEvent) {
+ val cancelled = postAndCatch()
+ event.handleChat(cancelled, blockedReason, chatComponent)
+ }
+
+ private fun LorenzChatEvent.handleChat(
+ cancelled: Boolean,
+ blockedReason: String?,
+ chatComponent: IChatComponent,
+ ) {
+ if (cancelled) {
+ this.cancel()
+ }
+ blockedReason?.let {
+ this.blockedReason = it
+ }
+ this.chatComponent = chatComponent
+ }
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/PlayerNameFormatter.kt b/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/PlayerNameFormatter.kt
new file mode 100644
index 000000000..4463270b3
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/PlayerNameFormatter.kt
@@ -0,0 +1,200 @@
+package at.hannibal2.skyhanni.data.hypixel.chat
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator
+import at.hannibal2.skyhanni.config.features.chat.PlayerMessagesConfig
+import at.hannibal2.skyhanni.data.hypixel.chat.event.GuildChatEvent
+import at.hannibal2.skyhanni.data.hypixel.chat.event.PartyChatEvent
+import at.hannibal2.skyhanni.data.hypixel.chat.event.PlayerAllChatEvent
+import at.hannibal2.skyhanni.data.hypixel.chat.event.PlayerShowItemChatEvent
+import at.hannibal2.skyhanni.data.hypixel.chat.event.PrivateMessageChatEvent
+import at.hannibal2.skyhanni.features.bingo.BingoAPI
+import at.hannibal2.skyhanni.features.chat.playerchat.PlayerChatFilter
+import at.hannibal2.skyhanni.features.misc.MarkedPlayerManager
+import at.hannibal2.skyhanni.features.misc.compacttablist.AdvancedPlayerList
+import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.StringUtils
+import at.hannibal2.skyhanni.utils.StringUtils.cleanPlayerName
+import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher
+import at.hannibal2.skyhanni.utils.StringUtils.replaceAll
+import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern
+import com.google.gson.JsonArray
+import com.google.gson.JsonNull
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+
+/**
+ * Listening to the player chat events, and applying custom chat options to them.
+ * E.g. part order, rank hider, etc
+ */
+class PlayerNameFormatter {
+ private val config get() = SkyHanniMod.feature.chat.playerMessage
+
+ private val patternGroup = RepoPattern.group("data.chat.player.name")
+
+ /**
+ * REGEX-TEST: §7☢ §r§b[MVP§d+§b] hannibal2
+ * REGEX-TEST: §7☢ §r§b[MVP§d+§b] hannibal2
+ * REGEX-TEST: §7☢ §r§bhannibal2
+ * REGEX-TEST: §7☢ §rhannibal2
+ * REGEX-TEST: §7☢ §b[MVP§c+§b] hannibal2
+ */
+ private val emblemPattern by patternGroup.pattern(
+ "emblem",
+ "(?<emblem>(?:§.){1,2}.) (?<author>.*)"
+ )
+
+ @SubscribeEvent
+ fun onPlayerAllChat(event: PlayerAllChatEvent) {
+ if (!isEnabled()) return
+ val levelColor = event.levelColor
+ val level = event.level
+ val message = event.message
+ val author = event.author
+ val privateIslandRank = event.privateIslandRank
+ val isAGuest = event.isAGuest
+
+ val shouldFilter = config.chatFilter && PlayerChatFilter.shouldChatFilter(message)
+ val chatColor = if (shouldFilter) "§7" else if (config.sameChatColor) "§f" else event.chatColor
+
+ val name = nameFormat(author, levelColor, level, privateIslandRank = privateIslandRank, isAGuest = isAGuest)
+ val newMessage = "$name$chatColor: $message"
+
+ event.chatComponent = StringUtils.replaceIfNeeded(event.chatComponent, newMessage) ?: return
+ }
+
+ @SubscribeEvent
+ fun onPartyChat(event: PartyChatEvent) {
+ if (!isEnabled()) return
+ val message = event.message
+ val author = event.author
+ val name = nameFormat(author)
+ val newMessage = "§9Party §8> $name§f: $message"
+
+ event.chatComponent = StringUtils.replaceIfNeeded(event.chatComponent, newMessage) ?: return
+ }
+
+ @SubscribeEvent
+ fun onGuildChat(event: GuildChatEvent) {
+ if (!isEnabled()) return
+ val message = event.message
+ val author = event.author
+ val guildRank = event.guildRank
+ val name = nameFormat(author, guildRank = guildRank)
+ val newMessage = "§2Guild > $name§f: $message"
+
+ event.chatComponent = StringUtils.replaceIfNeeded(event.chatComponent, newMessage) ?: return
+ }
+
+ @SubscribeEvent
+ fun onPrivateMessageChat(event: PrivateMessageChatEvent) {
+ if (!isEnabled()) return
+ val direction = event.direction
+ val message = event.message
+ val author = event.author
+ val name = nameFormat(author)
+ val newMessage = "§d$direction §f$name§7: §f$message"
+
+ event.chatComponent = StringUtils.replaceIfNeeded(event.chatComponent, newMessage) ?: return
+ }
+
+ @SubscribeEvent
+ fun onPlayerShowItemChat(event: PlayerShowItemChatEvent) {
+ if (!isEnabled()) return
+ val author = event.author
+ val action = event.action
+ val itemName = event.itemName
+ val levelColor = event.levelColor
+ val level = event.level
+ val name = nameFormat(author, levelColor = levelColor, level = level)
+ val newMessage = "$name §7$action §r$itemName"
+
+ event.chatComponent = StringUtils.replaceIfNeeded(event.chatComponent, newMessage) ?: return
+ }
+
+ private fun nameFormat(
+ author: String,
+ levelColor: String? = null,
+ level: Int? = null,
+ guildRank: String? = null,
+ privateIslandRank: String? = null,
+ isAGuest: Boolean = false,
+ ): String {
+ var cleanAuthor = cleanAuthor(author)
+
+ var emblemFormat = ""
+ emblemPattern.matchMatcher(author) {
+ emblemFormat = group("emblem")
+ cleanAuthor = LorenzUtils.stripVanillaMessage(group("author"))
+ }
+
+ val name = formatAuthor(cleanAuthor, levelColor)
+ val levelFormat = formatLevel(levelColor, level)
+ val guildRankFormat = guildRank ?: ""
+ val privateIslandRankFormat = privateIslandRank ?: ""
+ val privateIslandGuestFormat = if (isAGuest) "§a[✌]" else ""
+
+ val cleanName = cleanAuthor.cleanPlayerName()
+ val (faction, ironman, bingo) = AdvancedPlayerList.tabPlayerData[cleanName]?.let {
+ val faction = it.faction.icon
+ val ironman = if (it.ironman) "§7♲" else ""
+ val bingo = it.bingoLevel?.let { level -> BingoAPI.getBingoIcon(level) } ?: ""
+ listOf(faction, ironman, bingo)
+ } ?: listOf("", "", "")
+
+ val map = mutableMapOf<PlayerMessagesConfig.MessagePart, String>()
+ map[PlayerMessagesConfig.MessagePart.SKYBLOCK_LEVEL] = levelFormat
+ map[PlayerMessagesConfig.MessagePart.EMBLEM] = emblemFormat
+ map[PlayerMessagesConfig.MessagePart.PLAYER_NAME] = name
+ map[PlayerMessagesConfig.MessagePart.CRIMSON_FACTION] = faction
+ map[PlayerMessagesConfig.MessagePart.MODE_IRONMAN] = ironman
+ map[PlayerMessagesConfig.MessagePart.BINGO_LEVEL] = bingo
+ map[PlayerMessagesConfig.MessagePart.GUILD_RANK] = guildRankFormat
+ map[PlayerMessagesConfig.MessagePart.PRIVATE_ISLAND_RANK] = privateIslandRankFormat
+ map[PlayerMessagesConfig.MessagePart.PRIVATE_ISLAND_GUEST] = privateIslandGuestFormat
+
+ return config.partsOrder.map { map[it] }.joinToString(" ").replaceAll(" ", " ").trim()
+ }
+
+ private fun formatLevel(rawColor: String?, rawLevel: Int?): String {
+ val color = rawColor ?: return ""
+ val level = rawLevel ?: error("level is null, color is not null")
+ val levelData = "$color$level"
+ return if (config.hideLevelBrackets) levelData else "§8[${levelData}§8]"
+ }
+
+ private fun cleanAuthor(author: String): String {
+ val text = LorenzUtils.stripVanillaMessage(author)
+ return text.removeSuffix("§f")
+ }
+
+ private fun formatAuthor(author: String, levelColor: String?): String {
+ if (author.contains("ADMIN")) return author
+ if (config.ignoreYouTube && author.contains("YOUTUBE")) return author
+
+ var result = author.cleanPlayerName(displayName = true)
+ levelColor?.let {
+ if (config.useLevelColorForName) {
+ val cleanPlayerName = author.cleanPlayerName()
+ result = result.replace(cleanPlayerName, it + cleanPlayerName)
+ }
+ }
+
+ return MarkedPlayerManager.replaceInChat(result)
+ }
+
+ fun isEnabled() = LorenzUtils.inSkyBlock && (config.playerRankHider || config.chatFilter || config.sameChatColor)
+
+ @SubscribeEvent
+ fun onConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) {
+ event.transform(41, "chat.PlayerMessagesConfig.partsOrder") { element ->
+ val newList = JsonArray()
+ for (entry in element.asJsonArray) {
+ if (entry is JsonNull) continue
+ if (entry.asString != "EMPTY_CHAR") {
+ newList.add(entry)
+ }
+ }
+ newList
+ }
+ }
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/AbstractChatEvent.kt b/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/AbstractChatEvent.kt
new file mode 100644
index 000000000..cd0a8f92b
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/AbstractChatEvent.kt
@@ -0,0 +1,11 @@
+package at.hannibal2.skyhanni.data.hypixel.chat.event
+
+import at.hannibal2.skyhanni.events.LorenzEvent
+import net.minecraft.util.IChatComponent
+
+open class AbstractChatEvent(
+ val author: String,
+ val message: String,
+ var chatComponent: IChatComponent,
+ var blockedReason: String? = null,
+) : LorenzEvent()
diff --git a/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/GuildChatEvent.kt b/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/GuildChatEvent.kt
new file mode 100644
index 000000000..dd3867106
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/GuildChatEvent.kt
@@ -0,0 +1,11 @@
+package at.hannibal2.skyhanni.data.hypixel.chat.event
+
+import net.minecraft.util.IChatComponent
+
+class GuildChatEvent(
+ author: String,
+ message: String,
+ val guildRank: String? = null,
+ chatComponent: IChatComponent,
+ blockedReason: String? = null,
+) : AbstractChatEvent(author, message, chatComponent, blockedReason)
diff --git a/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/NpcChatEvent.kt b/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/NpcChatEvent.kt
new file mode 100644
index 000000000..574324520
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/NpcChatEvent.kt
@@ -0,0 +1,10 @@
+package at.hannibal2.skyhanni.data.hypixel.chat.event
+
+import net.minecraft.util.IChatComponent
+
+class NpcChatEvent(
+ author: String,
+ message: String,
+ chatComponent: IChatComponent,
+ blockedReason: String? = null,
+) : AbstractChatEvent(author, message, chatComponent, blockedReason)
diff --git a/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/PartyChatEvent.kt b/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/PartyChatEvent.kt
new file mode 100644
index 000000000..dc9e921cc
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/PartyChatEvent.kt
@@ -0,0 +1,10 @@
+package at.hannibal2.skyhanni.data.hypixel.chat.event
+
+import net.minecraft.util.IChatComponent
+
+class PartyChatEvent(
+ author: String,
+ message: String,
+ chatComponent: IChatComponent,
+ blockedReason: String? = null,
+) : AbstractChatEvent(author, message, chatComponent, blockedReason)
diff --git a/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/PlayerAllChatEvent.kt b/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/PlayerAllChatEvent.kt
new file mode 100644
index 000000000..56ea15a64
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/PlayerAllChatEvent.kt
@@ -0,0 +1,15 @@
+package at.hannibal2.skyhanni.data.hypixel.chat.event
+
+import net.minecraft.util.IChatComponent
+
+class PlayerAllChatEvent(
+ val levelColor: String?,
+ val level: Int?,
+ val privateIslandRank: String? = null,
+ val isAGuest: Boolean,
+ author: String,
+ val chatColor: String?,
+ message: String,
+ chatComponent: IChatComponent,
+ blockedReason: String? = null,
+) : AbstractChatEvent(author, message, chatComponent, blockedReason)
diff --git a/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/PlayerShowItemChatEvent.kt b/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/PlayerShowItemChatEvent.kt
new file mode 100644
index 000000000..229264b27
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/PlayerShowItemChatEvent.kt
@@ -0,0 +1,14 @@
+package at.hannibal2.skyhanni.data.hypixel.chat.event
+
+import net.minecraft.util.IChatComponent
+
+class PlayerShowItemChatEvent(
+ val levelColor: String?,
+ val level: Int?,
+ author: String,
+ message: String,
+ val action: String,
+ val itemName: String,
+ chatComponent: IChatComponent,
+ blockedReason: String? = null,
+) : AbstractChatEvent(author, message, chatComponent, blockedReason)
diff --git a/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/PrivateMessageChatEvent.kt b/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/PrivateMessageChatEvent.kt
new file mode 100644
index 000000000..f23b1d0b0
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/PrivateMessageChatEvent.kt
@@ -0,0 +1,11 @@
+package at.hannibal2.skyhanni.data.hypixel.chat.event
+
+import net.minecraft.util.IChatComponent
+
+class PrivateMessageChatEvent(
+ val direction: String?,
+ author: String,
+ message: String,
+ chatComponent: IChatComponent,
+ blockedReason: String? = null,
+) : AbstractChatEvent(author, message, chatComponent, blockedReason)
diff --git a/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/SystemMessageEvent.kt b/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/SystemMessageEvent.kt
new file mode 100644
index 000000000..82c53d0b1
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/SystemMessageEvent.kt
@@ -0,0 +1,10 @@
+package at.hannibal2.skyhanni.data.hypixel.chat.event
+
+import at.hannibal2.skyhanni.events.LorenzEvent
+import net.minecraft.util.IChatComponent
+
+class SystemMessageEvent(
+ val message: String,
+ var chatComponent: IChatComponent,
+ var blockedReason: String? = null,
+) : LorenzEvent()
diff --git a/src/main/java/at/hannibal2/skyhanni/events/PartyChatEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/PartyChatEvent.kt
deleted file mode 100644
index 76630583e..000000000
--- a/src/main/java/at/hannibal2/skyhanni/events/PartyChatEvent.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package at.hannibal2.skyhanni.events
-
-data class PartyChatEvent(
- val author: String,
- val text: String,
- val trigger: LorenzChatEvent,
-) : LorenzEvent()
diff --git a/src/main/java/at/hannibal2/skyhanni/features/bingo/BingoAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/bingo/BingoAPI.kt
index f5361e09a..ccfd85ef7 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/bingo/BingoAPI.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/bingo/BingoAPI.kt
@@ -106,4 +106,13 @@ object BingoAPI {
else -> "§c"
} + LorenzUtils.formatPercentage(percentage)
+
+ fun getBingoIcon(rank: Int): String {
+ val rankIcon = getIcon(rank) ?: ""
+ return if (rank != -1) {
+ "$rankIcon $rank"
+ } else {
+ rankIcon
+ }
+ }
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/chat/Translator.kt b/src/main/java/at/hannibal2/skyhanni/features/chat/Translator.kt
index 4e02f89f3..8e61f4b6c 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/chat/Translator.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/chat/Translator.kt
@@ -31,6 +31,7 @@ class Translator {
if (!isEnabled()) return
val message = event.message
+ // TODO use PlayerAllChatEvent and other player chat events
if (message.getPlayerNameFromChatMessage() == null) return
val editedComponent = event.chatComponent.transformIf({ siblings.isNotEmpty() }) { siblings.last() }
diff --git a/src/main/java/at/hannibal2/skyhanni/features/chat/playerchat/PlayerChatModifier.kt b/src/main/java/at/hannibal2/skyhanni/features/chat/playerchat/PlayerChatModifier.kt
index 087769645..4aabeaf6c 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/chat/playerchat/PlayerChatModifier.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/chat/playerchat/PlayerChatModifier.kt
@@ -2,12 +2,9 @@ package at.hannibal2.skyhanni.features.chat.playerchat
import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator
-import at.hannibal2.skyhanni.events.LorenzChatEvent
-import at.hannibal2.skyhanni.features.dungeon.DungeonMilestonesDisplay
+import at.hannibal2.skyhanni.data.hypixel.chat.event.SystemMessageEvent
import at.hannibal2.skyhanni.features.misc.MarkedPlayerManager
-import at.hannibal2.skyhanni.utils.StringUtils.matches
-import net.minecraft.util.ChatComponentText
-import net.minecraft.util.IChatComponent
+import at.hannibal2.skyhanni.utils.StringUtils
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
class PlayerChatModifier {
@@ -18,44 +15,13 @@ class PlayerChatModifier {
init {
patterns.add("§[ab6]\\[(?:VIP|MVP)(?:§.|\\+)*] {1,2}(?:§[7ab6])?(\\w{2,16})".toRegex()) // ranked player with prefix everywhere
patterns.add("§[7ab6](\\w{2,16})§r(?!§7x)(?!\$)".toRegex()) // all players without rank prefix in notification messages
- patterns.add("(?:§7 )?§7(\\w{2,16})§7§r".toRegex()) // nons user chat
}
@SubscribeEvent
- fun onChat(event: LorenzChatEvent) {
- val foundCommands = mutableListOf<IChatComponent>()
- val message = event.chatComponent
+ fun onChat(event: SystemMessageEvent) {
+ val newMessage = cutMessage(event.chatComponent.formattedText)
- addComponent(foundCommands, event.chatComponent)
- for (sibling in message.siblings) {
- addComponent(foundCommands, sibling)
- }
-
- val size = foundCommands.size
- if (size > 1) {
- return
- }
- val original = event.chatComponent.formattedText
- val newText = cutMessage(original)
- if (original == newText) return
-
- val text = ChatComponentText(newText)
- if (size == 1) {
- val chatStyle = foundCommands[0].chatStyle
- text.chatStyle.chatClickEvent = chatStyle.chatClickEvent
- text.chatStyle.chatHoverEvent = chatStyle.chatHoverEvent
- }
- event.chatComponent = text
- }
-
- private fun addComponent(foundCommands: MutableList<IChatComponent>, message: IChatComponent) {
- val clickEvent = message.chatStyle.chatClickEvent
- if (clickEvent != null) {
- if (foundCommands.size == 1 && foundCommands[0].chatStyle.chatClickEvent.value == clickEvent.value) {
- return
- }
- foundCommands.add(message)
- }
+ event.chatComponent = StringUtils.replaceIfNeeded(event.chatComponent, newMessage) ?: return
}
private fun cutMessage(input: String): String {
@@ -67,24 +33,9 @@ class PlayerChatModifier {
}
string = string.replace("§[7ab6]((?:\\w+){2,16})'s", "§b$1's")
string = string.replace("§[7ab6]((?:\\w+){2,16}) (§.)", "§b$1 $2")
-
- // TODO remove workaround
- if (!DungeonMilestonesDisplay.milestonePattern.matches(input)) {
- // all players same color in chat
- string = string.replace("§r§7: ", "§r§f: ")
- }
}
- if (config.chatFilter && string.contains("§r§f: ") && PlayerChatFilter.shouldChatFilter(string)) {
- string = string.replace("§r§f: ", "§r§7: ")
- }
-
- if (MarkedPlayerManager.config.highlightInChat) {
- val color = MarkedPlayerManager.config.chatColor.getChatColor()
- for (markedPlayer in MarkedPlayerManager.playerNamesToMark) {
- string = string.replace(markedPlayer, "$color$markedPlayer§r")
- }
- }
+ string = MarkedPlayerManager.replaceInChat(string)
return string
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/commands/PartyChatCommands.kt b/src/main/java/at/hannibal2/skyhanni/features/commands/PartyChatCommands.kt
index b2de36a7a..8ead93fcf 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/commands/PartyChatCommands.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/commands/PartyChatCommands.kt
@@ -4,7 +4,7 @@ import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.config.features.misc.PartyCommandsConfig
import at.hannibal2.skyhanni.data.FriendAPI
import at.hannibal2.skyhanni.data.PartyAPI
-import at.hannibal2.skyhanni.events.PartyChatEvent
+import at.hannibal2.skyhanni.data.hypixel.chat.event.PartyChatEvent
import at.hannibal2.skyhanni.utils.ChatUtils
import at.hannibal2.skyhanni.utils.LorenzUtils
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
@@ -60,9 +60,9 @@ object PartyChatCommands {
@SubscribeEvent
fun onPartyCommand(event: PartyChatEvent) {
- if (event.text.firstOrNull() !in commandBeginChars)
+ if (event.message.firstOrNull() !in commandBeginChars)
return
- val commandLabel = event.text.substring(1).substringBefore(' ')
+ val commandLabel = event.message.substring(1).substringBefore(' ')
val command = indexedPartyChatCommands[commandLabel.lowercase()] ?: return
if (event.author == LorenzUtils.getPlayerName()) {
return
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorFeatures.kt
index b86e580aa..56bb8396c 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorFeatures.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorFeatures.kt
@@ -462,6 +462,7 @@ object GardenVisitorFeatures {
event.blockedReason = "new_visitor_arrived"
}
+ // TODO use NpcChatEvent
if (GardenAPI.inGarden() && config.hideChat && hideVisitorMessage(event.message)) {
event.blockedReason = "garden_visitor_message"
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/MarkedPlayerManager.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/MarkedPlayerManager.kt
index 0adf1d5ec..5edabcbb1 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/misc/MarkedPlayerManager.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/MarkedPlayerManager.kt
@@ -80,6 +80,17 @@ class MarkedPlayerManager {
private fun isEnabled() = (LorenzUtils.inSkyBlock || OutsideSbFeature.MARKED_PLAYERS.isSelected())
&& config.highlightInWorld
+
+ fun replaceInChat(string: String): String {
+ if (!config.highlightInChat) return string
+
+ val color = config.chatColor.getChatColor()
+ var text = string
+ for (markedPlayer in playerNamesToMark) {
+ text = text.replace(markedPlayer, "$color$markedPlayer§r")
+ }
+ return text
+ }
}
@SubscribeEvent
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/PlayerChatSymbols.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/PlayerChatSymbols.kt
deleted file mode 100644
index 56c6b8bfe..000000000
--- a/src/main/java/at/hannibal2/skyhanni/features/misc/PlayerChatSymbols.kt
+++ /dev/null
@@ -1,107 +0,0 @@
-package at.hannibal2.skyhanni.features.misc
-
-import at.hannibal2.skyhanni.SkyHanniMod
-import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator
-import at.hannibal2.skyhanni.config.features.chat.ChatSymbols.SymbolLocationEntry
-import at.hannibal2.skyhanni.events.LorenzChatEvent
-import at.hannibal2.skyhanni.features.misc.compacttablist.TabStringType
-import at.hannibal2.skyhanni.mixins.transformers.AccessorChatComponentText
-import at.hannibal2.skyhanni.utils.ConfigUtils
-import at.hannibal2.skyhanni.utils.LorenzUtils
-import at.hannibal2.skyhanni.utils.StringUtils
-import at.hannibal2.skyhanni.utils.StringUtils.getPlayerNameAndRankFromChatMessage
-import at.hannibal2.skyhanni.utils.StringUtils.getPlayerNameFromChatMessage
-import at.hannibal2.skyhanni.utils.StringUtils.removeResets
-import at.hannibal2.skyhanni.utils.TabListData
-import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern
-import net.minecraft.util.ChatComponentText
-import net.minecraft.util.IChatComponent
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
-
-// code inspired by SBA but heavily modified to be more functional and actually work
-class PlayerChatSymbols {
-
- private val config get() = SkyHanniMod.feature.chat.chatSymbols
- private val nameSymbols = mutableMapOf<String, String>()
-
- private val patternGroup = RepoPattern.group("misc.chatsymbols")
- private val symbolsPattern by patternGroup.pattern(
- "symbols",
- "^(?<symbols>(?:(?:§\\w)+\\S)+) "
- )
- private val symbolPattern by patternGroup.pattern(
- "symbol",
- "(?:§.)+(\\S)"
- )
-
- @SubscribeEvent
- fun onChat(event: LorenzChatEvent) {
- if (!LorenzUtils.inSkyBlock) return
- if (!config.enabled) return
-
- val username = event.message.getPlayerNameFromChatMessage() ?: return
-
- var usernameWithSymbols = TabListData.getTabList()
- .find { playerName -> TabStringType.usernameFromLine(playerName) == username }
-
- if (usernameWithSymbols != null) {
- nameSymbols[username] = usernameWithSymbols
- }
-
- usernameWithSymbols = nameSymbols[username] ?: return
-
- val split = usernameWithSymbols.split("$username ")
- var emblemText = if (split.size > 1) split[1].removeResets() else ""
-
- var matcher = symbolsPattern.matcher("$emblemText ")
- emblemText = if (matcher.find()) {
- matcher.group("symbols")
- } else ""
-
- if (emblemText == "") {
- return
- }
-
- val emblems = mutableListOf<String>()
- matcher = symbolPattern.matcher(emblemText)
- while (matcher.find()) {
- emblems.add(matcher.group(1))
- }
-
- for (emblem in emblems) {
- event.chatComponent = StringUtils.replaceFirstChatText(event.chatComponent, "$emblem ", "")
- }
-
- val rankAndName = event.message.getPlayerNameAndRankFromChatMessage() ?: return
-
- StringUtils.modifyFirstChatComponent(event.chatComponent) { component ->
- modify(component, emblemText, rankAndName)
- }
- }
-
- private fun modify(component: IChatComponent, emblemText: String, rankAndName: String): Boolean {
- if (component !is ChatComponentText) return false
- component as AccessorChatComponentText
- if (!component.text_skyhanni().contains(rankAndName)) return false
- val oldText = component.text_skyhanni()
-
- val newText = getNewText(emblemText, oldText, rankAndName)
- component.setText_skyhanni(component.text_skyhanni().replace(oldText, newText))
- return true
- }
-
- private fun getNewText(emblemText: String, oldText: String, rankAndName: String): String =
- when (config.symbolLocation) {
- SymbolLocationEntry.LEFT -> oldText.replace(rankAndName, "$emblemText $rankAndName")
- SymbolLocationEntry.RIGHT -> oldText.replace(rankAndName, "$rankAndName $emblemText ")
- SymbolLocationEntry.HIDDEN -> oldText
- else -> oldText
- }
-
- @SubscribeEvent
- fun onConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) {
- event.transform(15, "chat.chatSymbols.symbolLocation") { element ->
- ConfigUtils.migrateIntToEnum(element, SymbolLocationEntry::class.java)
- }
- }
-}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/compacttablist/AdvancedPlayerList.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/compacttablist/AdvancedPlayerList.kt
index f5bd15750..273942287 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/misc/compacttablist/AdvancedPlayerList.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/compacttablist/AdvancedPlayerList.kt
@@ -23,11 +23,14 @@ import at.hannibal2.skyhanni.utils.StringUtils.removeColor
import at.hannibal2.skyhanni.utils.TimeLimitedCache
import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import java.util.regex.Matcher
import kotlin.random.Random
import kotlin.time.Duration.Companion.minutes
object AdvancedPlayerList {
+ val tabPlayerData = mutableMapOf<String, PlayerData>()
+
private val config get() = SkyHanniMod.feature.gui.compactTabList.advancedPlayerList
private val levelPattern by RepoPattern.pattern(
@@ -62,48 +65,12 @@ object AdvancedPlayerList {
extraTitles++
continue
}
- levelPattern.matchMatcher(line) {
+ val playerData: PlayerData? = levelPattern.matchMatcher(line) {
val levelText = group("level")
val removeColor = levelText.removeColor()
try {
- val playerData = PlayerData(removeColor.toInt())
- currentData[line] = playerData
-
- var index = 0
- val fullName = group("name")
- if (fullName.contains("[")) index++
- val name = fullName.split(" ")
- val coloredName = name[index]
- if (index == 1) {
- playerData.coloredName = name[0] + " " + coloredName
- } else {
- playerData.coloredName = coloredName
- }
- playerData.name = coloredName.removeColor()
- playerData.levelText = levelText
- index++
- if (name.size > index) {
- var nameSuffix = name.drop(index).joinToString(" ")
- if (nameSuffix.contains("♲")) {
- playerData.ironman = true
- } else {
- playerData.bingoLevel = BingoAPI.getRank(line)
- }
- if (IslandType.CRIMSON_ISLE.isInIsland()) {
- playerData.faction = if (line.contains("§c⚒")) {
- nameSuffix = nameSuffix.replace("§c⚒", "")
- CrimsonIsleFaction.BARBARIAN
- } else if (line.contains("§5ቾ")) {
- nameSuffix = nameSuffix.replace("§5ቾ", "")
- CrimsonIsleFaction.MAGE
- } else {
- CrimsonIsleFaction.NONE
- }
- }
- playerData.nameSuffix = nameSuffix
- } else {
- playerData.nameSuffix = ""
- }
+ val sbLevel = removeColor.toInt()
+ readPlayerData(sbLevel, levelText, line)
} catch (e: NumberFormatException) {
ErrorManager.logErrorWithData(
e, "Advanced Player List failed to parse user name",
@@ -111,7 +78,15 @@ object AdvancedPlayerList {
"i" to i,
"original" to original,
)
+ null
+ }
+ }
+ playerData?.let {
+ val name = it.name
+ if (name != "?") {
+ tabPlayerData[name] = it
}
+ currentData[line] = it
}
}
playerDatas = currentData
@@ -156,6 +131,50 @@ object AdvancedPlayerList {
return newList
}
+ private fun Matcher.readPlayerData(
+ sbLevel: Int,
+ levelText: String,
+ line: String,
+ ): PlayerData {
+ val playerData = PlayerData(sbLevel)
+ var index = 0
+ val fullName = group("name")
+ if (fullName.contains("[")) index++
+ val name = fullName.split(" ")
+ val coloredName = name[index]
+ if (index == 1) {
+ playerData.coloredName = name[0] + " " + coloredName
+ } else {
+ playerData.coloredName = coloredName
+ }
+ playerData.name = coloredName.removeColor()
+ playerData.levelText = levelText
+ index++
+ if (name.size > index) {
+ var nameSuffix = name.drop(index).joinToString(" ")
+ if (nameSuffix.contains("♲")) {
+ playerData.ironman = true
+ } else {
+ playerData.bingoLevel = BingoAPI.getRank(line)
+ }
+ if (IslandType.CRIMSON_ISLE.isInIsland()) {
+ playerData.faction = if (line.contains("§c⚒")) {
+ nameSuffix = nameSuffix.replace("§c⚒", "")
+ CrimsonIsleFaction.BARBARIAN
+ } else if (line.contains("§5ቾ")) {
+ nameSuffix = nameSuffix.replace("§5ቾ", "")
+ CrimsonIsleFaction.MAGE
+ } else {
+ CrimsonIsleFaction.NONE
+ }
+ }
+ playerData.nameSuffix = nameSuffix
+ } else {
+ playerData.nameSuffix = ""
+ }
+ return playerData
+ }
+
fun ignoreCustomTabList(): Boolean {
val denyKeyPressed = SkyHanniMod.feature.dev.debug.bypassAdvancedPlayerTabList.isKeyHeld()
return denyKeyPressed || !SkyHanniDebugsAndTests.globalRender
@@ -169,6 +188,7 @@ object AdvancedPlayerList {
}
private fun createCustomName(data: PlayerData): String {
+
val playerName = if (config.useLevelColorForName) {
val c = data.levelText[3]
"§$c" + data.name
@@ -179,7 +199,7 @@ object AdvancedPlayerList {
} else ""
var suffix = if (config.hideEmblem) {
- if (data.ironman) "§7♲" else data.bingoLevel?.let { getBingoIcon(it) } ?: ""
+ if (data.ironman) "§7♲" else data.bingoLevel?.let { BingoAPI.getBingoIcon(it) } ?: ""
} else data.nameSuffix
if (config.markSpecialPersons) {
@@ -230,15 +250,6 @@ object AdvancedPlayerList {
else -> ""
}
- private fun getBingoIcon(rank: Int): String {
- val rankIcon = BingoAPI.getIcon(rank) ?: ""
- return if (config.showBingoRankNumber && rank != -1) {
- "$rankIcon $rank"
- } else {
- rankIcon
- }
- }
-
class PlayerData(val sbLevel: Int) {
var name: String = "?"
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/compacttablist/TabListReader.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/compacttablist/TabListReader.kt
index 9d21c7421..18bdede44 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/misc/compacttablist/TabListReader.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/compacttablist/TabListReader.kt
@@ -59,7 +59,6 @@ object TabListReader {
private fun updateTablistData(tablist: List<String>? = null) {
if (!LorenzUtils.inSkyBlock) return
- if (!config.enabled.get()) return
var tabLines = tablist ?: TabListData.getTabList()
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt
index 59b82cd8c..68c92f7a7 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt
@@ -127,6 +127,7 @@ object StringUtils {
fun String.cleanPlayerName(displayName: Boolean = false): String {
return if (displayName) {
if (SkyHanniMod.feature.chat.playerMessage.playerRankHider) {
+ // TODO custom color
"§b" + internalCleanPlayerName()
} else this
} else {
@@ -317,4 +318,58 @@ object StringUtils {
fun isEmpty(message: String): Boolean = message.removeColor().trimWhiteSpaceAndResets().isEmpty()
fun generateRandomId() = UUID.randomUUID().toString()
+
+ fun replaceIfNeeded(
+ original: IChatComponent,
+ newText: String,
+ ): ChatComponentText? {
+ val foundCommands = mutableListOf<IChatComponent>()
+
+ addComponent(foundCommands, original)
+ for (sibling in original.siblings) {
+ addComponent(foundCommands, sibling)
+ }
+
+ val size = foundCommands.size
+ if (size > 1) {
+ return null
+ }
+
+ if (LorenzUtils.stripVanillaMessage(original.formattedText) == newText) return null
+ // TODO remove debug
+// println("replaceIfNeeded!")
+// println("original: ${original.formattedText}")
+// println("newText: $newText")
+// println(" ")
+
+ val text = ChatComponentText(newText)
+ if (size == 1) {
+ val chatStyle = foundCommands[0].chatStyle
+ text.chatStyle.chatClickEvent = chatStyle.chatClickEvent
+ text.chatStyle.chatHoverEvent = chatStyle.chatHoverEvent
+ }
+
+ return text
+ }
+
+ private fun addComponent(foundCommands: MutableList<IChatComponent>, message: IChatComponent) {
+ val clickEvent = message.chatStyle.chatClickEvent
+ if (clickEvent != null) {
+ if (foundCommands.size == 1 && foundCommands[0].chatStyle.chatClickEvent.value == clickEvent.value) {
+ return
+ }
+ foundCommands.add(message)
+ }
+ }
+
+ fun String.replaceAll(oldValue: String, newValue: String, ignoreCase: Boolean = false): String {
+ var text = this
+ while (true) {
+ val newText = text.replace(oldValue, newValue, ignoreCase = ignoreCase)
+ if (newText == text) {
+ return text
+ }
+ text = newText
+ }
+ }
}