From 4abf64f6257ff0e1232b96531339bcfa28a8112e Mon Sep 17 00:00:00 2001 From: nossr50 Date: Fri, 6 Nov 2020 15:16:26 -0800 Subject: [PATCH] Full hex color support in admin/party chat --- Changelog.txt | 12 +++++-- .../nossr50/chat/mailer/AdminChatMailer.java | 4 ++- .../nossr50/chat/mailer/PartyChatMailer.java | 16 ++++++---- .../chat/message/PartyChatMessage.java | 2 +- .../nossr50/commands/CommandManager.java | 1 + .../commands/chat/AdminChatCommand.java | 3 ++ .../gmail/nossr50/locale/LocaleLoader.java | 29 +++++++++++++++++ .../gmail/nossr50/util/text/TextUtils.java | 31 +++++++++++++++++++ 8 files changed, 88 insertions(+), 10 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 8d64f63cd..0e4573159 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -1,6 +1,9 @@ Version 2.1.154 - Fixed a bug where Tree Feller was not dropping stuff like saplings - Fixed a bug where player names that used hex color codes weren't working in party or admin chat + Hex colors are now supported in Party & Admin chat + Added support for &#RRGGBB color codes (hex colors) in chat and nicknames for party and admin chat + Added hex colored nickname support to admin/party chat + Fixed a bug where Tree Feller was not dropping some items like saplings + Fixed a bug where using admin chat would in some circumstances throw a NPE (API) Author class has been reworked (API) McMMOChatEvent::getSender removed (use getDisplayName() instead) (API) McMMMOChatEvent::setDisplayName() removed (you can set author names in Author) @@ -8,6 +11,11 @@ Version 2.1.154 (API) Modified Author::getAuthoredName signature to -> Author::getAuthoredName(ChatChannel) (API) Added Author::getAuthoredComponentName(ChatChannel) (API) PartyAuthor and AdminAuthor removed, replaced by PlayerAuthor + (API) Probably some more undocumented changes that I'm forgetting... + +Notes: + For example '/p &#ccFF33hi guys' will send a message colored in hex colors + You'll see ~§x in console when hex color codes are used, this is a quirk of how the 'adventure' library we are using is handling some bungee component related things, so it's outside of my hands for now Version 2.1.153 Fixed a bug where most sub-skills were not being displayed when using a skills command (for example /taming) diff --git a/src/main/java/com/gmail/nossr50/chat/mailer/AdminChatMailer.java b/src/main/java/com/gmail/nossr50/chat/mailer/AdminChatMailer.java index 7886bc5cc..a238d4e63 100644 --- a/src/main/java/com/gmail/nossr50/chat/mailer/AdminChatMailer.java +++ b/src/main/java/com/gmail/nossr50/chat/mailer/AdminChatMailer.java @@ -54,7 +54,7 @@ public class AdminChatMailer extends AbstractChatMailer { */ public @NotNull TextComponent addStyle(@NotNull Author author, @NotNull String message, boolean canColor) { if(canColor) { - return TextUtils.ofLegacyTextRaw(LocaleLoader.getString("Chat.Style.Admin", author.getAuthoredName(ChatChannel.ADMIN), LocaleLoader.addColors(message))); + return LocaleLoader.getTextComponent("Chat.Style.Admin", TextUtils.sanitizeAuthorName(author, ChatChannel.ADMIN), message); } else { return TextUtils.ofLegacyTextRaw(LocaleLoader.getString("Chat.Style.Admin", author.getAuthoredName(ChatChannel.ADMIN), message)); } @@ -75,4 +75,6 @@ public class AdminChatMailer extends AbstractChatMailer { sendMail(chatMessage); } } + + } diff --git a/src/main/java/com/gmail/nossr50/chat/mailer/PartyChatMailer.java b/src/main/java/com/gmail/nossr50/chat/mailer/PartyChatMailer.java index 603934ee1..37c02f144 100644 --- a/src/main/java/com/gmail/nossr50/chat/mailer/PartyChatMailer.java +++ b/src/main/java/com/gmail/nossr50/chat/mailer/PartyChatMailer.java @@ -46,13 +46,17 @@ public class PartyChatMailer extends AbstractChatMailer { */ public @NotNull TextComponent addStyle(@NotNull Author author, @NotNull String message, boolean canColor, boolean isLeader) { if(canColor) { - message = LocaleLoader.addColors(message); - } - - if(isLeader) { - return TextUtils.ofLegacyTextRaw(LocaleLoader.getString("Chat.Style.Party.Leader", author.getAuthoredName(ChatChannel.PARTY), message)); + if(isLeader) { + return LocaleLoader.getTextComponent("Chat.Style.Party.Leader", TextUtils.sanitizeAuthorName(author, ChatChannel.PARTY), message); + } else { + return LocaleLoader.getTextComponent("Chat.Style.Party", author.getAuthoredName(ChatChannel.PARTY), message); + } } else { - return TextUtils.ofLegacyTextRaw(LocaleLoader.getString("Chat.Style.Party", author.getAuthoredName(ChatChannel.PARTY), message)); + if(isLeader) { + return TextUtils.ofLegacyTextRaw(LocaleLoader.getString("Chat.Style.Party.Leader", author.getAuthoredName(ChatChannel.PARTY), message)); + } else { + return TextUtils.ofLegacyTextRaw(LocaleLoader.getString("Chat.Style.Party", author.getAuthoredName(ChatChannel.PARTY), message)); + } } } diff --git a/src/main/java/com/gmail/nossr50/chat/message/PartyChatMessage.java b/src/main/java/com/gmail/nossr50/chat/message/PartyChatMessage.java index 3c957d483..c66644d6e 100644 --- a/src/main/java/com/gmail/nossr50/chat/message/PartyChatMessage.java +++ b/src/main/java/com/gmail/nossr50/chat/message/PartyChatMessage.java @@ -46,7 +46,7 @@ public class PartyChatMessage extends AbstractChatMessage { //Sends to everyone but console audience.sendMessage(author, componentMessage); - TextComponent spyMessage = TextUtils.ofLegacyTextRaw(LocaleLoader.getString("Chat.Spy.Party", author.getAuthoredName(ChatChannel.PARTY), rawMessage, party.getName())); + TextComponent spyMessage = LocaleLoader.getTextComponent("Chat.Spy.Party", TextUtils.sanitizeAuthorName(author, ChatChannel.PARTY), rawMessage, party.getName()); //Relay to spies messagePartyChatSpies(spyMessage); diff --git a/src/main/java/com/gmail/nossr50/commands/CommandManager.java b/src/main/java/com/gmail/nossr50/commands/CommandManager.java index 7182744b2..de5d4a7fd 100644 --- a/src/main/java/com/gmail/nossr50/commands/CommandManager.java +++ b/src/main/java/com/gmail/nossr50/commands/CommandManager.java @@ -59,6 +59,7 @@ public class CommandManager { BukkitCommandIssuer issuer = context.getIssuer(); if(issuer.getIssuer() instanceof Player) { + validateLoadedData(issuer.getPlayer()); validateAdmin(issuer.getPlayer()); } }); diff --git a/src/main/java/com/gmail/nossr50/commands/chat/AdminChatCommand.java b/src/main/java/com/gmail/nossr50/commands/chat/AdminChatCommand.java index f8547a4a0..e2b2aef79 100644 --- a/src/main/java/com/gmail/nossr50/commands/chat/AdminChatCommand.java +++ b/src/main/java/com/gmail/nossr50/commands/chat/AdminChatCommand.java @@ -36,6 +36,9 @@ public class AdminChatCommand extends BaseCommand { if(bukkitCommandIssuer.isPlayer()) { McMMOPlayer mmoPlayer = UserManager.getPlayer(bukkitCommandIssuer.getPlayer()); + if(mmoPlayer == null) + return; + //Message contains the original command so it needs to be passed to this method to trim it pluginRef.getChatManager().processPlayerMessage(mmoPlayer, args, ChatChannel.ADMIN); } else { diff --git a/src/main/java/com/gmail/nossr50/locale/LocaleLoader.java b/src/main/java/com/gmail/nossr50/locale/LocaleLoader.java index ac6f496ea..f4f57ceaf 100644 --- a/src/main/java/com/gmail/nossr50/locale/LocaleLoader.java +++ b/src/main/java/com/gmail/nossr50/locale/LocaleLoader.java @@ -2,6 +2,8 @@ package com.gmail.nossr50.locale; import com.gmail.nossr50.config.Config; import com.gmail.nossr50.mcMMO; +import com.gmail.nossr50.util.text.TextUtils; +import net.kyori.adventure.text.TextComponent; import org.bukkit.ChatColor; import java.io.IOException; @@ -42,6 +44,23 @@ public final class LocaleLoader { return formatString(rawMessage, messageArguments); } + //TODO: Remove this hacky crap with something better later + /** + * Gets the appropriate TextComponent representation of a formatted string from the Locale files. + * + * @param key The key to look up the string with + * @param messageArguments Any arguments to be added to the text component + * @return The properly formatted text component + */ + public static TextComponent getTextComponent(String key, Object... messageArguments) { + if (bundle == null) { + initialize(); + } + + String rawMessage = bundleCache.computeIfAbsent(key, LocaleLoader::getRawString); + return formatComponent(rawMessage, messageArguments); + } + /** * Reloads locale */ @@ -90,6 +109,16 @@ public final class LocaleLoader { return string; } + public static TextComponent formatComponent(String string, Object... messageArguments) { + if (messageArguments != null) { + MessageFormat formatter = new MessageFormat(""); + formatter.applyPattern(string.replace("'", "''")); + string = formatter.format(messageArguments); + } + + return TextUtils.colorizeText(string); + } + public static Locale getCurrentLocale() { if (bundle == null) { initialize(); diff --git a/src/main/java/com/gmail/nossr50/util/text/TextUtils.java b/src/main/java/com/gmail/nossr50/util/text/TextUtils.java index 865105eb1..231b7be69 100644 --- a/src/main/java/com/gmail/nossr50/util/text/TextUtils.java +++ b/src/main/java/com/gmail/nossr50/util/text/TextUtils.java @@ -1,5 +1,7 @@ package com.gmail.nossr50.util.text; +import com.gmail.nossr50.chat.author.Author; +import com.gmail.nossr50.datatypes.chat.ChatChannel; import com.gmail.nossr50.mcMMO; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.ComponentBuilder; @@ -14,6 +16,9 @@ import org.jetbrains.annotations.Nullable; import java.util.List; public class TextUtils { + + private static @Nullable LegacyComponentSerializer customLegacySerializer; + /** * Makes a single component from an array of components, can optionally add prefixes and suffixes to come before and after each component * @param componentsArray target array @@ -103,4 +108,30 @@ public class TextUtils { public static @NotNull TextComponent ofLegacyTextRaw(@NotNull String rawString) { return LegacyComponentSerializer.legacySection().deserialize(rawString); } + + public static @NotNull TextComponent colorizeText(String rawtext) { + if(customLegacySerializer == null) { + customLegacySerializer = getSerializer(); + } + + return customLegacySerializer.deserialize(rawtext); + } + + @NotNull + private static LegacyComponentSerializer getSerializer() { + return LegacyComponentSerializer.builder().hexColors().useUnusualXRepeatedCharacterHexFormat().character('&').hexCharacter('#').build(); + } + + public static @NotNull String sanitizeForSerializer(@NotNull String string) { + if(customLegacySerializer == null) { + customLegacySerializer = getSerializer(); + } + + TextComponent componentForm = ofLegacyTextRaw(string); + return customLegacySerializer.serialize(componentForm); + } + + public static @NotNull String sanitizeAuthorName(@NotNull Author author, @NotNull ChatChannel chatChannel) { + return sanitizeForSerializer(author.getAuthoredName(ChatChannel.ADMIN)); + } }