LoChat/src/main/java/com/loki/lochat/utils/ChatFormatter.java

351 lines
14 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.loki.lochat.utils;
import com.loki.lochat.LoChat;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import org.bukkit.entity.Player;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ChatFormatter {
private static final MiniMessage MINI_MESSAGE = MiniMessage.miniMessage();
// Паттерны для цветов
private static final Pattern HEX_PATTERN = Pattern.compile("&#([A-Fa-f0-9]{6})");
private static final Pattern LEGACY_COLOR_PATTERN = Pattern.compile("&([0-9a-fk-orA-FK-OR])");
private static final Pattern SECTION_COLOR_PATTERN = Pattern.compile("§([0-9a-fk-orA-FK-OR])");
private static final Pattern SECTION_HEX_PATTERN = Pattern.compile("§x(§[0-9A-Fa-f]){6}");
private static final Pattern MINIMESSAGE_HEX_PATTERN = Pattern.compile("<#([A-Fa-f0-9]{6})>");
private ChatFormatter() {}
/**
* Конвертирует все форматы цветов в MiniMessage
* Поддерживает: &коды, §коды, &#HEX, §x§...HEX, MiniMessage теги
*/
public static String convertAllColors(String message) {
if (message == null) return "";
String result = message;
// 1. Конвертируем §x§R§R§G§G§B§B -> <#RRGGBB>
result = convertSectionHexColors(result);
// 2. Конвертируем §коды -> &коды (для унификации)
result = convertSectionToAmpersand(result);
// 3. Конвертируем &#RRGGBB -> <#RRGGBB> (только если еще не в MiniMessage формате)
result = convertHexColors(result);
// 4. Конвертируем &коды -> MiniMessage теги
result = convertLegacyColors(result);
return result;
}
/**
* Конвертирует §x§R§R§G§G§B§B в <#RRGGBB>
*/
public static String convertSectionHexColors(String message) {
if (message == null) return "";
Matcher matcher = SECTION_HEX_PATTERN.matcher(message);
StringBuilder result = new StringBuilder();
while (matcher.find()) {
String match = matcher.group();
// §x§R§R§G§G§B§B -> RRGGBB
String hex = match.replace("§x", "").replace("§", "");
matcher.appendReplacement(result, "<#" + hex + ">");
}
matcher.appendTail(result);
return result.toString();
}
/**
* Конвертирует §коды в &коды
*/
public static String convertSectionToAmpersand(String message) {
if (message == null) return "";
return SECTION_COLOR_PATTERN.matcher(message).replaceAll("&$1");
}
/**
* Конвертирует &#RRGGBB в MiniMessage формат <#RRGGBB>
*/
public static String convertHexColors(String message) {
Matcher matcher = HEX_PATTERN.matcher(message);
StringBuilder result = new StringBuilder();
while (matcher.find()) {
matcher.appendReplacement(result, "<#" + matcher.group(1) + ">");
}
matcher.appendTail(result);
return result.toString();
}
/**
* Конвертирует &коды в MiniMessage теги
* &a -> <green>, &b -> <aqua>, &l -> <bold>, etc.
*/
public static String convertLegacyColors(String message) {
StringBuilder result = new StringBuilder();
Matcher matcher = LEGACY_COLOR_PATTERN.matcher(message);
while (matcher.find()) {
String code = matcher.group(1).toLowerCase();
String replacement = switch (code) {
case "0" -> "<black>";
case "1" -> "<dark_blue>";
case "2" -> "<dark_green>";
case "3" -> "<dark_aqua>";
case "4" -> "<dark_red>";
case "5" -> "<dark_purple>";
case "6" -> "<gold>";
case "7" -> "<gray>";
case "8" -> "<dark_gray>";
case "9" -> "<blue>";
case "a" -> "<green>";
case "b" -> "<aqua>";
case "c" -> "<red>";
case "d" -> "<light_purple>";
case "e" -> "<yellow>";
case "f" -> "<white>";
case "k" -> "<obfuscated>";
case "l" -> "<bold>";
case "m" -> "<strikethrough>";
case "n" -> "<underlined>";
case "o" -> "<italic>";
case "r" -> "<reset>";
default -> "&" + code;
};
matcher.appendReplacement(result, Matcher.quoteReplacement(replacement));
}
matcher.appendTail(result);
return result.toString();
}
/**
* Заменяет смайлики в сообщении
*/
public static String replaceEmojis(String message, Player player) {
LoChat plugin = LoChat.getInstance();
if (plugin != null && plugin.getEmojiManager() != null) {
return plugin.getEmojiManager().process(message, player);
}
return message;
}
/**
* Заменяет смайлики без проверки прав
*/
public static String replaceEmojis(String message) {
LoChat plugin = LoChat.getInstance();
if (plugin != null && plugin.getEmojiManager() != null) {
return plugin.getEmojiManager().process(message);
}
return message;
}
/**
* @deprecated Use replaceEmojis(String) instead
*/
@Deprecated
public static String replaceEmojis(String message, Map<String, String> emojis) {
return replaceEmojis(message);
}
/**
* Полная обработка сообщения игрока
* Цвета + смайлики + цвет чата
*/
public static String processPlayerMessage(String message, Player player, boolean hasColorPermission) {
String result = message;
// Заменяем смайлики
result = replaceEmojis(result, player);
// Если есть право на цвета - конвертируем
if (hasColorPermission) {
result = convertAllColors(result);
} else {
// Убираем цветовые коды
result = stripLegacyColors(result);
// Применяем цвет чата если установлен
LoChat plugin = LoChat.getInstance();
if (plugin != null && plugin.getChatColorManager() != null) {
result = plugin.getChatColorManager().applyChatColor(player.getUniqueId(), result);
}
}
return result;
}
/**
* Убирает &коды и §коды из сообщения
*/
public static String stripLegacyColors(String message) {
String result = LEGACY_COLOR_PATTERN.matcher(message).replaceAll("");
return SECTION_COLOR_PATTERN.matcher(result).replaceAll("");
}
public static Component parse(String message) {
return MINI_MESSAGE.deserialize(convertAllColors(message));
}
public static Component parse(String message, String... replacements) {
String result = message;
for (int i = 0; i < replacements.length - 1; i += 2) {
result = result.replace(replacements[i], replacements[i + 1]);
}
return MINI_MESSAGE.deserialize(convertAllColors(result));
}
public static String toPlain(Component component) {
return PlainTextComponentSerializer.plainText().serialize(component);
}
public static String stripTags(String message) {
if (message == null) return "";
// Убираем MiniMessage теги и legacy коды
String result = MINI_MESSAGE.stripTags(message);
result = stripLegacyColors(result);
result = HEX_PATTERN.matcher(result).replaceAll("");
result = MINIMESSAGE_HEX_PATTERN.matcher(result).replaceAll("");
return result;
}
/**
* Полностью очищает все цветовые коды из строки
*/
public static String stripAllColors(String message) {
if (message == null) return "";
String result = message;
// Убираем MiniMessage HEX теги <#RRGGBB>
result = MINIMESSAGE_HEX_PATTERN.matcher(result).replaceAll("");
// Убираем &#RRGGBB
result = HEX_PATTERN.matcher(result).replaceAll("");
// Убираем &коды
result = stripLegacyColors(result);
// Убираем MiniMessage теги
result = MINI_MESSAGE.stripTags(result);
return result;
}
/**
* Форматирует глобальное сообщение с поддержкой LoPreff
*/
public static Component formatGlobalMessage(String format, String prefix, Player player, String message, boolean hasColorPermission) {
String playerDisplay = getPlayerDisplay(player);
String finalMessage = processPlayerMessage(message, player, hasColorPermission);
String formatted = format
.replace("<prefix>", prefix)
.replace("<player>", playerDisplay)
.replace("<message>", finalMessage);
return parse(formatted);
}
/**
* Форматирует локальное сообщение с поддержкой LoPreff
*/
public static Component formatLocalMessage(String format, String prefix, Player player, String message, boolean hasColorPermission) {
String playerDisplay = getPlayerDisplay(player);
String finalMessage = processPlayerMessage(message, player, hasColorPermission);
String formatted = prefix + " " + format
.replace("<player>", playerDisplay)
.replace("<message>", finalMessage);
return parse(formatted);
}
private static String getPlayerDisplay(Player player) {
LoChat plugin = LoChat.getInstance();
if (plugin != null && plugin.getGradientModule() != null && plugin.getGradientModule().isEnabled()) {
String name = plugin.getGradientModule().getFormattedName(player);
// Конвертируем §x§... формат в MiniMessage
return convertAllColors(name);
}
return player.getName();
}
public static Component formatPmSent(String format, String targetName, String message) {
return parse(format
.replace("{player}", targetName)
.replace("{message}", message));
}
public static Component formatPmReceived(String format, String senderName, String message) {
return parse(format
.replace("{player}", senderName)
.replace("{message}", message));
}
/**
* Форматирует исходящее PM с поддержкой градиентных имён
*/
public static Component formatPmSentNew(String format, Player sender, Player receiver, String message) {
LoChat plugin = LoChat.getInstance();
String senderDisplay = sender.getName();
String receiverDisplay = receiver.getName();
// Используем градиентные имена если включено
if (plugin != null && plugin.getMessageConfig().isPmUseGradientNames()
&& plugin.getGradientModule() != null && plugin.getGradientModule().isEnabled()) {
senderDisplay = plugin.getGradientModule().getFormattedName(sender);
receiverDisplay = plugin.getGradientModule().getFormattedName(receiver);
// Конвертируем legacy коды в MiniMessage формат
senderDisplay = convertAllColors(senderDisplay);
receiverDisplay = convertAllColors(receiverDisplay);
}
return parse(format
.replace("{sender}", sender.getName())
.replace("{receiver}", receiver.getName())
.replace("{sender_display}", senderDisplay)
.replace("{receiver_display}", receiverDisplay)
.replace("{message}", message));
}
/**
* Форматирует входящее PM с поддержкой градиентных имён
*/
public static Component formatPmReceivedNew(String format, Player sender, Player receiver, String message) {
LoChat plugin = LoChat.getInstance();
String senderDisplay = sender.getName();
String receiverDisplay = receiver.getName();
// Используем градиентные имена если включено
if (plugin != null && plugin.getMessageConfig().isPmUseGradientNames()
&& plugin.getGradientModule() != null && plugin.getGradientModule().isEnabled()) {
senderDisplay = plugin.getGradientModule().getFormattedName(sender);
receiverDisplay = plugin.getGradientModule().getFormattedName(receiver);
// Конвертируем legacy коды в MiniMessage формат
senderDisplay = convertAllColors(senderDisplay);
receiverDisplay = convertAllColors(receiverDisplay);
}
return parse(format
.replace("{sender}", sender.getName())
.replace("{receiver}", receiver.getName())
.replace("{sender_display}", senderDisplay)
.replace("{receiver_display}", receiverDisplay)
.replace("{message}", message));
}
public static Component formatAnnouncement(String format, String message) {
return parse(format.replace("<message>", message));
}
}