fix: TAB hex format and chat color codes support

This commit is contained in:
loki5512344 2025-12-30 13:43:12 +01:00
parent ed796a4264
commit 5c1230bc16
3 changed files with 41 additions and 13 deletions

View file

@ -88,7 +88,12 @@ public final class GradientUtil {
private static String formatHex(String hex, boolean useLegacyFormat) { private static String formatHex(String hex, boolean useLegacyFormat) {
hex = hex.replace("#", "").toLowerCase(); hex = hex.replace("#", "").toLowerCase();
if (useLegacyFormat) { if (useLegacyFormat) {
return "&#" + hex; // Формат §x§R§R§G§G§B§B для TAB и других плагинов
StringBuilder sb = new StringBuilder("§x");
for (char c : hex.toCharArray()) {
sb.append("§").append(c);
}
return sb.toString();
} else { } else {
return "<#" + hex + ">"; return "<#" + hex + ">";
} }

View file

@ -18,31 +18,52 @@ public class ChatFormatter {
private static final Pattern HEX_PATTERN = Pattern.compile("&#([A-Fa-f0-9]{6})"); 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 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_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 static final Pattern MINIMESSAGE_HEX_PATTERN = Pattern.compile("<#([A-Fa-f0-9]{6})>");
private ChatFormatter() {} private ChatFormatter() {}
/** /**
* Конвертирует все форматы цветов в MiniMessage * Конвертирует все форматы цветов в MiniMessage
* Поддерживает: &коды, §коды, &#HEX, MiniMessage теги * Поддерживает: &коды, §коды, &#HEX, §x§...HEX, MiniMessage теги
*/ */
public static String convertAllColors(String message) { public static String convertAllColors(String message) {
if (message == null) return ""; if (message == null) return "";
String result = message; String result = message;
// 1. Конвертируем §коды -> &коды (для унификации) // 1. Конвертируем §x§R§R§G§G§B§B -> <#RRGGBB>
result = convertSectionHexColors(result);
// 2. Конвертируем §коды -> &коды (для унификации)
result = convertSectionToAmpersand(result); result = convertSectionToAmpersand(result);
// 2. Конвертируем &#RRGGBB -> <#RRGGBB> (только если еще не в MiniMessage формате) // 3. Конвертируем &#RRGGBB -> <#RRGGBB> (только если еще не в MiniMessage формате)
result = convertHexColors(result); result = convertHexColors(result);
// 3. Конвертируем &коды -> MiniMessage теги // 4. Конвертируем &коды -> MiniMessage теги
result = convertLegacyColors(result); result = convertLegacyColors(result);
return 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();
}
/** /**
* Конвертирует §коды в &коды * Конвертирует §коды в &коды
*/ */
@ -251,7 +272,9 @@ public class ChatFormatter {
private static String getPlayerDisplay(Player player) { private static String getPlayerDisplay(Player player) {
LoChat plugin = LoChat.getInstance(); LoChat plugin = LoChat.getInstance();
if (plugin != null && plugin.getGradientModule() != null && plugin.getGradientModule().isEnabled()) { if (plugin != null && plugin.getGradientModule() != null && plugin.getGradientModule().isEnabled()) {
return plugin.getGradientModule().getFormattedName(player); String name = plugin.getGradientModule().getFormattedName(player);
// Конвертируем §x§... формат в MiniMessage
return convertAllColors(name);
} }
return player.getName(); return player.getName();
} }

View file

@ -35,8 +35,8 @@ class GradientUtilTest {
void applyGradient_singleColor_legacy() { void applyGradient_singleColor_legacy() {
String result = GradientUtil.applyGradient("Hi", List.of("#FF0000"), true); String result = GradientUtil.applyGradient("Hi", List.of("#FF0000"), true);
assertNotNull(result); assertNotNull(result);
assertTrue(result.contains("&#ff0000")); // Формат §x§f§f§0§0§0§0
assertEquals("&#ff0000H&#ff0000i", result); assertTrue(result.contains("§x§f§f§0§0§0§0"));
} }
@Test @Test
@ -51,8 +51,8 @@ class GradientUtilTest {
String result = GradientUtil.applyGradient("AB", List.of("#FF0000", "#0000FF"), true); String result = GradientUtil.applyGradient("AB", List.of("#FF0000", "#0000FF"), true);
assertNotNull(result); assertNotNull(result);
// Первый символ должен быть красным, последний синим // Первый символ должен быть красным, последний синим
assertTrue(result.startsWith("&#ff0000A")); assertTrue(result.contains("§x§f§f§0§0§0§0")); // красный
assertTrue(result.contains("&#0000ffB")); assertTrue(result.contains("§x§0§0§0§0§f§f")); // синий
} }
@Test @Test
@ -105,7 +105,7 @@ class GradientUtilTest {
void buildDisplayName_noPrefix_withColors() { void buildDisplayName_noPrefix_withColors() {
String result = GradientUtil.buildDisplayName(null, "AB", List.of("#FF0000", "#0000FF"), true, true, "[{prefix}] ", true); String result = GradientUtil.buildDisplayName(null, "AB", List.of("#FF0000", "#0000FF"), true, true, "[{prefix}] ", true);
assertNotNull(result); assertNotNull(result);
assertTrue(result.contains("&#")); assertTrue(result.contains("§x"));
} }
@Test @Test
@ -113,7 +113,7 @@ class GradientUtilTest {
String result = GradientUtil.buildDisplayName("V", "AB", List.of("#FF0000", "#0000FF"), true, true, "[{prefix}] ", true); String result = GradientUtil.buildDisplayName("V", "AB", List.of("#FF0000", "#0000FF"), true, true, "[{prefix}] ", true);
assertNotNull(result); assertNotNull(result);
// Единый градиент на всё // Единый градиент на всё
assertTrue(result.contains("&#")); assertTrue(result.contains("§x"));
} }
@Test @Test
@ -121,7 +121,7 @@ class GradientUtilTest {
String result = GradientUtil.buildDisplayName("V", "AB", List.of("#FF0000", "#0000FF"), true, false, "[{prefix}] ", true); String result = GradientUtil.buildDisplayName("V", "AB", List.of("#FF0000", "#0000FF"), true, false, "[{prefix}] ", true);
assertNotNull(result); assertNotNull(result);
// Отдельные градиенты // Отдельные градиенты
assertTrue(result.contains("&#")); assertTrue(result.contains("§x"));
} }
@Test @Test