diff --git a/pom.xml b/pom.xml index 8ef54144cd..d9f6925bdc 100644 --- a/pom.xml +++ b/pom.xml @@ -454,18 +454,6 @@ com.alessiodp.libby fr.xephi.authme.libs.com.alessiodp.libby - - net.kyori.adventure - fr.xephi.authme.libs.net.kyori.adventure - - - net.kyori.examination - fr.xephi.authme.libs.net.kyori.examination - - - net.kyori.option - fr.xephi.authme.libs.net.kyori.option - @@ -903,11 +891,6 @@ adventure-platform-bukkit 4.3.3 - - net.kyori - adventure-text-serializer-gson - 4.17.0 - diff --git a/src/main/java/fr/xephi/authme/AuthMe.java b/src/main/java/fr/xephi/authme/AuthMe.java index fd51e70fe3..bad299b65c 100644 --- a/src/main/java/fr/xephi/authme/AuthMe.java +++ b/src/main/java/fr/xephi/authme/AuthMe.java @@ -31,6 +31,7 @@ import fr.xephi.authme.mail.EmailService; import fr.xephi.authme.output.ConsoleLoggerFactory; import fr.xephi.authme.security.crypts.Sha256; +import fr.xephi.authme.service.AdventureService; import fr.xephi.authme.service.BackupService; import fr.xephi.authme.service.BukkitService; import fr.xephi.authme.service.MigrationService; @@ -81,6 +82,7 @@ public class AuthMe extends JavaPlugin { private EmailService emailService; private CommandHandler commandHandler; private static TaskScheduler scheduler; + private static AdventureService adventureService; @Inject public static Settings settings; private DataSource database; @@ -139,6 +141,13 @@ public static TaskScheduler getScheduler() { return scheduler; } + /** + * Get the AdventureService + */ + public static AdventureService getAdventureService() { + return adventureService; + } + /** * The library manager */ @@ -153,6 +162,8 @@ public void onEnable() { loadPluginInfo(getDescription().getVersion()); scheduler = UniversalScheduler.getScheduler(this); libraryManager = new BukkitLibraryManager(this); + adventureService = new AdventureService(this); + adventureService.init(); // Set the Logger instance and log file path ConsoleLogger.initialize(getLogger(), new File(getDataFolder(), LOG_FILENAME)); @@ -403,6 +414,11 @@ public void onDisable() { // Wait for tasks and close data source new TaskCloser(database).run(); + // Close AdventureService + if (adventureService != null) { + adventureService.close(); + } + // Disabled correctly Consumer infoLogMethod = logger == null ? getLogger()::info : logger::info; infoLogMethod.accept("AuthMe " + this.getDescription().getVersion() + " is unloaded successfully!"); diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/RegisterAdminCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/RegisterAdminCommand.java index 7b2847f79b..1c3857e9eb 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/RegisterAdminCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/RegisterAdminCommand.java @@ -12,6 +12,7 @@ import fr.xephi.authme.service.CommonService; import fr.xephi.authme.service.ValidationService; import fr.xephi.authme.service.ValidationService.ValidationResult; +import fr.xephi.authme.util.message.MiniMessageUtils; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -79,7 +80,7 @@ public void executeCommand(final CommandSender sender, List arguments) { if (player != null) { bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(() -> // AuthMeReReloaded - Folia compatibility - bukkitService.runTaskIfFolia(player, () -> player.kickPlayer(commonService.retrieveSingleMessage(player, MessageKey.KICK_FOR_ADMIN_REGISTER)))); + bukkitService.runTaskIfFolia(player, () -> MiniMessageUtils.kickPlayer(player, MiniMessageUtils.parseMiniMessage(commonService.retrieveSingleMessage(player, MessageKey.KICK_FOR_ADMIN_REGISTER))))); } }); } diff --git a/src/main/java/fr/xephi/authme/data/TempbanManager.java b/src/main/java/fr/xephi/authme/data/TempbanManager.java index 2a767874db..0ffd9e4b2e 100644 --- a/src/main/java/fr/xephi/authme/data/TempbanManager.java +++ b/src/main/java/fr/xephi/authme/data/TempbanManager.java @@ -9,6 +9,7 @@ import fr.xephi.authme.settings.properties.SecuritySettings; import fr.xephi.authme.util.PlayerUtils; import fr.xephi.authme.util.expiring.TimedCounter; +import fr.xephi.authme.util.message.MiniMessageUtils; import org.bukkit.entity.Player; import javax.inject.Inject; @@ -106,7 +107,7 @@ public void tempbanPlayer(final Player player) { bukkitService.runTask(player,() -> { // AuthMeReReloaded - Folia compatibility if (customCommand.isEmpty()) { bukkitService.banIp(ip, reason, expires, "AuthMe"); - player.kickPlayer(reason); + MiniMessageUtils.kickPlayer(player, MiniMessageUtils.parseMiniMessage(reason)); } else { String command = customCommand .replace("%player%", name) diff --git a/src/main/java/fr/xephi/authme/listener/DoubleLoginFixListener.java b/src/main/java/fr/xephi/authme/listener/DoubleLoginFixListener.java index 2c0370a433..c6e3bbd8b2 100644 --- a/src/main/java/fr/xephi/authme/listener/DoubleLoginFixListener.java +++ b/src/main/java/fr/xephi/authme/listener/DoubleLoginFixListener.java @@ -3,6 +3,7 @@ import fr.xephi.authme.message.MessageKey; import fr.xephi.authme.service.CommonService; +import fr.xephi.authme.util.message.MiniMessageUtils; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -26,7 +27,7 @@ public void onPlayerJoin(PlayerJoinEvent event) { HashSet PlayerSet = new HashSet(); for (Player ep : PlayerList) { if (PlayerSet.contains(ep.getName().toLowerCase())) { - ep.kickPlayer(service.retrieveSingleMessage(ep.getPlayer(), MessageKey.DOUBLE_LOGIN_FIX)); + MiniMessageUtils.kickPlayer(ep, MiniMessageUtils.parseMiniMessage(service.retrieveSingleMessage(ep.getPlayer(), MessageKey.DOUBLE_LOGIN_FIX))); break; } PlayerSet.add(ep.getName().toLowerCase()); diff --git a/src/main/java/fr/xephi/authme/listener/OnJoinVerifier.java b/src/main/java/fr/xephi/authme/listener/OnJoinVerifier.java index a617c2fa88..db2f53820b 100644 --- a/src/main/java/fr/xephi/authme/listener/OnJoinVerifier.java +++ b/src/main/java/fr/xephi/authme/listener/OnJoinVerifier.java @@ -18,6 +18,7 @@ import fr.xephi.authme.settings.properties.RestrictionSettings; import fr.xephi.authme.util.StringUtils; import fr.xephi.authme.util.Utils; +import fr.xephi.authme.util.message.MiniMessageUtils; import org.bukkit.Server; import org.bukkit.entity.Player; import org.bukkit.event.player.PlayerLoginEvent; @@ -140,7 +141,7 @@ public boolean refusePlayerForFullServer(PlayerLoginEvent event) { Player nonVipPlayer = generateKickPlayer(onlinePlayers); if (nonVipPlayer != null) { // AuthMeReReloaded - Folia compatibility - bukkitService.runTaskIfFolia(nonVipPlayer, () -> nonVipPlayer.kickPlayer(messages.retrieveSingle(player, MessageKey.KICK_FOR_VIP))); + bukkitService.runTaskIfFolia(nonVipPlayer, () -> MiniMessageUtils.kickPlayer(nonVipPlayer, MiniMessageUtils.parseMiniMessage(messages.retrieveSingle(player, MessageKey.KICK_FOR_VIP)))); event.allow(); return false; } else { diff --git a/src/main/java/fr/xephi/authme/listener/PlayerListener.java b/src/main/java/fr/xephi/authme/listener/PlayerListener.java index b24da9da2f..001a23132b 100644 --- a/src/main/java/fr/xephi/authme/listener/PlayerListener.java +++ b/src/main/java/fr/xephi/authme/listener/PlayerListener.java @@ -219,7 +219,7 @@ public void onJoinMessage(PlayerJoinEvent event) { String customJoinMessage = settings.getProperty(RegistrationSettings.CUSTOM_JOIN_MESSAGE); if (!customJoinMessage.isEmpty()) { - customJoinMessage = ChatColor.translateAlternateColorCodes('&', MiniMessageUtils.parseMiniMessageToLegacy(customJoinMessage)); + customJoinMessage = ChatColor.translateAlternateColorCodes('&', customJoinMessage); event.setJoinMessage(customJoinMessage .replace("{PLAYERNAME}", player.getName()) .replace("{DISPLAYNAME}", player.getDisplayName()) @@ -324,7 +324,7 @@ public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) { final Player player = event.getPlayer(); if (!quickCommandsProtectionManager.isAllowed(player.getName())) { event.setCancelled(true); - bukkitService.runTaskIfFolia(player, () -> player.kickPlayer(messages.retrieveSingle(player, MessageKey.QUICK_COMMAND_PROTECTION_KICK))); + bukkitService.runTaskIfFolia(player, () -> MiniMessageUtils.kickPlayer(player, MiniMessageUtils.parseMiniMessage(messages.retrieveSingle(player, MessageKey.QUICK_COMMAND_PROTECTION_KICK)))); // AuthMeReReloaded - Folia compatibility return; } diff --git a/src/main/java/fr/xephi/authme/message/Messages.java b/src/main/java/fr/xephi/authme/message/Messages.java index 0d7ec317e4..4ae0e8f2c2 100644 --- a/src/main/java/fr/xephi/authme/message/Messages.java +++ b/src/main/java/fr/xephi/authme/message/Messages.java @@ -1,9 +1,11 @@ package fr.xephi.authme.message; import com.google.common.collect.ImmutableMap; +import fr.xephi.authme.AuthMe; import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.mail.EmailService; import fr.xephi.authme.output.ConsoleLoggerFactory; +import fr.xephi.authme.service.AdventureService; import fr.xephi.authme.util.expiring.Duration; import fr.xephi.authme.util.message.I18NUtils; import fr.xephi.authme.util.message.MiniMessageUtils; @@ -44,6 +46,7 @@ public class Messages { private final ConsoleLogger logger = ConsoleLoggerFactory.get(EmailService.class); private MessagesFileHandler messagesFileHandler; + private static final AdventureService adventureService = AuthMe.getAdventureService(); /* * Constructor. @@ -62,7 +65,7 @@ public class Messages { public void send(CommandSender sender, MessageKey key) { String[] lines = retrieve(key, sender); for (String line : lines) { - sender.sendMessage(line); + adventureService.send(sender, MiniMessageUtils.parseMiniMessage(line)); } } @@ -78,7 +81,7 @@ public void send(CommandSender sender, MessageKey key) { public void send(CommandSender sender, MessageKey key, String... replacements) { String message = retrieveSingle(sender, key, replacements); for (String line : message.split("\n")) { - sender.sendMessage(line); + adventureService.send(sender, MiniMessageUtils.parseMiniMessage(line)); } } @@ -131,7 +134,7 @@ private String retrieveMessage(MessageKey key, CommandSender sender) { displayName = ((Player) sender).getDisplayName(); } - return ChatColor.translateAlternateColorCodes('&', MiniMessageUtils.parseMiniMessageToLegacy(message)) + return ChatColor.translateAlternateColorCodes('&', message) .replace(NEWLINE_TAG, "\n") .replace(USERNAME_TAG, sender.getName()) .replace(DISPLAYNAME_TAG, displayName); @@ -147,7 +150,7 @@ private String retrieveMessage(MessageKey key, CommandSender sender) { private String retrieveMessage(MessageKey key, String name) { String message = messagesFileHandler.getMessage(key.getKey()); - return ChatColor.translateAlternateColorCodes('&', MiniMessageUtils.parseMiniMessageToLegacy(message)) + return ChatColor.translateAlternateColorCodes('&', message) .replace(NEWLINE_TAG, "\n") .replace(USERNAME_TAG, name) .replace(DISPLAYNAME_TAG, name); diff --git a/src/main/java/fr/xephi/authme/process/join/AsynchronousJoin.java b/src/main/java/fr/xephi/authme/process/join/AsynchronousJoin.java index 424c49896b..6d8fc11dc1 100644 --- a/src/main/java/fr/xephi/authme/process/join/AsynchronousJoin.java +++ b/src/main/java/fr/xephi/authme/process/join/AsynchronousJoin.java @@ -26,6 +26,7 @@ import fr.xephi.authme.settings.properties.RestrictionSettings; import fr.xephi.authme.util.InternetProtocolUtils; import fr.xephi.authme.util.PlayerUtils; +import fr.xephi.authme.util.message.MiniMessageUtils; import org.bukkit.GameMode; import org.bukkit.Server; import org.bukkit.entity.Player; @@ -177,7 +178,7 @@ public void processJoin(Player player) { private void handlePlayerWithUnmetNameRestriction(Player player, String ip) { bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(() -> { - player.kickPlayer(service.retrieveSingleMessage(player, MessageKey.NOT_OWNER_ERROR)); + MiniMessageUtils.kickPlayer(player, MiniMessageUtils.parseMiniMessage(service.retrieveSingleMessage(player, MessageKey.NOT_OWNER_ERROR))); if (service.getProperty(RestrictionSettings.BAN_UNKNOWN_IP)) { server.banIP(ip); } @@ -228,7 +229,7 @@ private boolean validatePlayerCountForIp(Player player, String ip) { && countOnlinePlayersByIp(ip) > service.getProperty(RestrictionSettings.MAX_JOIN_PER_IP)) { bukkitService.scheduleSyncTaskFromOptionallyAsyncTask( - () -> player.kickPlayer(service.retrieveSingleMessage(player, MessageKey.SAME_IP_ONLINE))); + () -> MiniMessageUtils.kickPlayer(player, MiniMessageUtils.parseMiniMessage(service.retrieveSingleMessage(player, MessageKey.SAME_IP_ONLINE)))); return false; } return true; diff --git a/src/main/java/fr/xephi/authme/process/login/AsynchronousLogin.java b/src/main/java/fr/xephi/authme/process/login/AsynchronousLogin.java index 988124d9a4..913a8fcfc6 100644 --- a/src/main/java/fr/xephi/authme/process/login/AsynchronousLogin.java +++ b/src/main/java/fr/xephi/authme/process/login/AsynchronousLogin.java @@ -36,6 +36,7 @@ import fr.xephi.authme.util.InternetProtocolUtils; import fr.xephi.authme.util.PlayerUtils; import fr.xephi.authme.util.Utils; +import fr.xephi.authme.util.message.MiniMessageUtils; import org.bukkit.ChatColor; import org.bukkit.entity.Player; @@ -249,7 +250,7 @@ private void handleWrongPassword(Player player, PlayerAuth auth, String ip) { tempbanManager.tempbanPlayer(player); } else if (service.getProperty(RestrictionSettings.KICK_ON_WRONG_PASSWORD)) { bukkitService.scheduleSyncTaskFromOptionallyAsyncTask( - () -> player.kickPlayer(service.retrieveSingleMessage(player, MessageKey.WRONG_PASSWORD))); + () -> MiniMessageUtils.kickPlayer(player, MiniMessageUtils.parseMiniMessage(service.retrieveSingleMessage(player, MessageKey.WRONG_PASSWORD)))); } else { service.send(player, MessageKey.WRONG_PASSWORD); diff --git a/src/main/java/fr/xephi/authme/process/register/ProcessSyncPasswordRegister.java b/src/main/java/fr/xephi/authme/process/register/ProcessSyncPasswordRegister.java index f68ba015dd..9bba0f6a80 100644 --- a/src/main/java/fr/xephi/authme/process/register/ProcessSyncPasswordRegister.java +++ b/src/main/java/fr/xephi/authme/process/register/ProcessSyncPasswordRegister.java @@ -15,6 +15,7 @@ import fr.xephi.authme.settings.properties.EmailSettings; import fr.xephi.authme.settings.properties.RegistrationSettings; import fr.xephi.authme.util.PlayerUtils; +import fr.xephi.authme.util.message.MiniMessageUtils; import org.bukkit.entity.Player; import javax.inject.Inject; @@ -77,7 +78,7 @@ public void processPasswordRegister(Player player) { // Kick Player after Registration is enabled, kick the player if (service.getProperty(RegistrationSettings.FORCE_KICK_AFTER_REGISTER)) { - player.kickPlayer(service.retrieveSingleMessage(player, MessageKey.REGISTER_SUCCESS)); + MiniMessageUtils.kickPlayer(player, MiniMessageUtils.parseMiniMessage(service.retrieveSingleMessage(player, MessageKey.REGISTER_SUCCESS))); return; } diff --git a/src/main/java/fr/xephi/authme/service/AdventureService.java b/src/main/java/fr/xephi/authme/service/AdventureService.java new file mode 100644 index 0000000000..ddb7c6333a --- /dev/null +++ b/src/main/java/fr/xephi/authme/service/AdventureService.java @@ -0,0 +1,35 @@ +package fr.xephi.authme.service; + +import fr.xephi.authme.AuthMe; +import net.kyori.adventure.platform.bukkit.BukkitAudiences; +import net.kyori.adventure.text.Component; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class AdventureService { + private final AuthMe plugin; + public BukkitAudiences adventure; + public AdventureService(AuthMe plugin) { + this.plugin = plugin; + } + + public void init() { + adventure = BukkitAudiences.create(plugin); + } + + public void close() { + if (adventure != null) { + adventure.close(); + adventure = null; + } + } + + public void send(CommandSender sender, Component component) { + adventure.sender(sender).sendMessage(component); + } + + public void send(Player player, Component component) { + adventure.player(player).sendMessage(component); + } + +} diff --git a/src/main/java/fr/xephi/authme/task/TimeoutTask.java b/src/main/java/fr/xephi/authme/task/TimeoutTask.java index 60aac74143..1d441cff11 100644 --- a/src/main/java/fr/xephi/authme/task/TimeoutTask.java +++ b/src/main/java/fr/xephi/authme/task/TimeoutTask.java @@ -1,6 +1,7 @@ package fr.xephi.authme.task; import fr.xephi.authme.data.auth.PlayerCache; +import fr.xephi.authme.util.message.MiniMessageUtils; import org.bukkit.entity.Player; /** @@ -28,7 +29,7 @@ public TimeoutTask(Player player, String message, PlayerCache playerCache) { @Override public void run() { if (!playerCache.isAuthenticated(player.getName())) { - player.kickPlayer(message); + MiniMessageUtils.kickPlayer(player, MiniMessageUtils.parseMiniMessage(message)); } } } diff --git a/src/main/java/fr/xephi/authme/util/message/MiniMessageUtils.java b/src/main/java/fr/xephi/authme/util/message/MiniMessageUtils.java index 36756c6207..0cc4ffc913 100644 --- a/src/main/java/fr/xephi/authme/util/message/MiniMessageUtils.java +++ b/src/main/java/fr/xephi/authme/util/message/MiniMessageUtils.java @@ -1,12 +1,36 @@ package fr.xephi.authme.util.message; +import fr.xephi.authme.util.Utils; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import org.bukkit.entity.Player; +import org.bukkit.event.player.AsyncPlayerPreLoginEvent; + +import java.lang.reflect.Method; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class MiniMessageUtils { private static final MiniMessage miniMessage = MiniMessage.miniMessage(); + private static final char SECTION_CHAR = 'ยง'; + private static final char AMPERSAND_CHAR = '&'; + private static final boolean HEX_SUPPORTED = Utils.MAJOR_VERSION >= 16; + private static Method methodDisallow; + private static Method methodKick; + static { + try { + methodDisallow = AsyncPlayerPreLoginEvent.class.getMethod("disallow", AsyncPlayerPreLoginEvent.Result.class, Component.class); + } catch (Exception e) { + methodDisallow = null; + } + try { + methodKick = Player.class.getMethod("kick", Component.class); + } catch (Exception e) { + methodKick = null; + } + } /** * Parse a MiniMessage string into a legacy string. * @@ -17,6 +41,98 @@ public static String parseMiniMessageToLegacy(String message) { Component component = miniMessage.deserialize(message); return LegacyComponentSerializer.legacyAmpersand().serialize(component); } + + /** + * Parse a MiniMessage string into a component. + * + * @param message The message to parse. + * @return The parsed message. + */ + public static Component parseMiniMessage(String message) { + return miniMessage.deserialize(convertLegacyToMiniMessage(message, false, SECTION_CHAR, HEX_SUPPORTED)); + } + + /** + * Kicks a player with the given message. + * + * @param player the player to kick + * @param message the message to send + */ + public static void kickPlayer(Player player, Component message) { + if (methodKick != null) { + try { + methodKick.invoke(player, message); + } catch (Exception e) { + player.kickPlayer(LegacyComponentSerializer.legacySection().serialize(message)); + } + } else { + player.kickPlayer(LegacyComponentSerializer.legacySection().serialize(message)); + } + } + + /** + * Disallows the login event with the given result and reason. + * + * @param event the event + * @param result the event result to set + * @param message the denial message + */ + public static void disallowPreLoginEvent(AsyncPlayerPreLoginEvent event, + AsyncPlayerPreLoginEvent.Result result, Component message) { + if (methodDisallow != null) { + try { + methodDisallow.invoke(event, result, message); + } catch (Exception e) { + event.disallow(result, LegacyComponentSerializer.legacySection().serialize(message)); + } + } else { + event.disallow(result, LegacyComponentSerializer.legacySection().serialize(message)); + } + } + + @SuppressWarnings("all") + private static String convertLegacyToMiniMessage(String legacy, boolean concise, char charCode, boolean rgb) { + String miniMessage = legacy.replaceAll(Pattern.quote(String.valueOf(charCode)) + "0", "") + .replaceAll(Pattern.quote(String.valueOf(charCode)) + "1", "") + .replaceAll(Pattern.quote(String.valueOf(charCode)) + "2", "") + .replaceAll(Pattern.quote(String.valueOf(charCode)) + "3", "") + .replaceAll(Pattern.quote(String.valueOf(charCode)) + "4", "") + .replaceAll(Pattern.quote(String.valueOf(charCode)) + "5", "") + .replaceAll(Pattern.quote(String.valueOf(charCode)) + "6", "") + .replaceAll(Pattern.quote(String.valueOf(charCode)) + "7", "") + .replaceAll(Pattern.quote(String.valueOf(charCode)) + "8", "") + .replaceAll(Pattern.quote(String.valueOf(charCode)) + "9", "") + .replaceAll(Pattern.quote(String.valueOf(charCode)) + "a", "") + .replaceAll(Pattern.quote(String.valueOf(charCode)) + "b", "") + .replaceAll(Pattern.quote(String.valueOf(charCode)) + "c", "") + .replaceAll(Pattern.quote(String.valueOf(charCode)) + "d", "") + .replaceAll(Pattern.quote(String.valueOf(charCode)) + "e", "") + .replaceAll(Pattern.quote(String.valueOf(charCode)) + "f", ""); + + if (concise) { + miniMessage = miniMessage.replaceAll(Pattern.quote(String.valueOf(charCode)) + "n", "") + .replaceAll(Pattern.quote(String.valueOf(charCode)) + "m", "") + .replaceAll(Pattern.quote(String.valueOf(charCode)) + "k", "") + .replaceAll(Pattern.quote(String.valueOf(charCode)) + "o", "") + .replaceAll(Pattern.quote(String.valueOf(charCode)) + "l", "") + .replaceAll(Pattern.quote(String.valueOf(charCode)) + "r", ""); + } else { + miniMessage = miniMessage.replaceAll(Pattern.quote(String.valueOf(charCode)) + "n", "") + .replaceAll(Pattern.quote(String.valueOf(charCode)) + "m", "") + .replaceAll(Pattern.quote(String.valueOf(charCode)) + "k", "") + .replaceAll(Pattern.quote(String.valueOf(charCode)) + "o", "") + .replaceAll(Pattern.quote(String.valueOf(charCode)) + "l", "") + .replaceAll(Pattern.quote(String.valueOf(charCode)) + "r", ""); + } + + if (rgb) { + Pattern pattern = Pattern.compile(Pattern.quote(String.valueOf(charCode)) + "#([0-9a-fA-F]{6})"); + Matcher matcher = pattern.matcher(miniMessage); + miniMessage = matcher.replaceAll("<#$1>"); + } + + return miniMessage; + } private MiniMessageUtils() { } }