Fix GUI colors and TAB placeholder format - applyGradient uses &#RRGGBB for GUI (LegacyComponentSerializer) - Added applyGradientTabFormat for TAB plugin (§x§R§R§G§G§B§B) - PlaceholderAPIHook now uses TAB format for %lochat_full% - Updated tests to match new formats

This commit is contained in:
loki5512344 2025-12-30 21:54:34 +01:00
parent 036382b71a
commit 29ae373554
5 changed files with 127 additions and 26 deletions

View file

@ -116,8 +116,25 @@ public class GradientModule {
/**
* Получает отформатированное имя игрока с градиентом и LuckPerms префиксом
* Градиент применяется на всю строку целиком (префикс + ник)
* Использует формат &#RRGGBB
*/
public String getFormattedName(Player player) {
return getFormattedName(player, false);
}
/**
* Получает отформатированное имя для TAB плагина
* Использует формат §x§R§R§G§G§B§B
*/
public String getFormattedNameForTab(Player player) {
return getFormattedName(player, true);
}
/**
* Получает отформатированное имя игрока с градиентом и LuckPerms префиксом
* @param useTabFormat true для §x§... формата (TAB), false для &#RRGGBB
*/
private String getFormattedName(Player player, boolean useTabFormat) {
if (!enabled) return player.getName();
GradientPlayerData data = dataManager.getPlayerData(player.getUniqueId());
@ -142,7 +159,7 @@ public class GradientModule {
} else {
// LP префикс со своими цветами, ник отдельно
String nick = data.hasColors() && data.isColorEnabled()
? GradientUtil.applyGradient(player.getName(), data.getColors(), config.isUseLegacyRgbFormat())
? applyGradientWithFormat(player.getName(), data.getColors(), useTabFormat)
: player.getName();
return lpPrefix + nick;
}
@ -153,12 +170,25 @@ public class GradientModule {
// Применяем единый градиент на всю строку
if (data.hasColors() && data.isColorEnabled()) {
return GradientUtil.applyGradient(fullText.toString(), data.getColors(), config.isUseLegacyRgbFormat());
return applyGradientWithFormat(fullText.toString(), data.getColors(), useTabFormat);
}
return fullText.toString();
}
/**
* Применяет градиент с нужным форматом
*/
private String applyGradientWithFormat(String text, java.util.List<String> colors, boolean useTabFormat) {
if (useTabFormat) {
// Формат §x§R§R§G§G§B§B для TAB
return GradientUtil.applyGradientTabFormat(text, colors);
} else {
// Формат &#RRGGBB для GUI и чата
return GradientUtil.applyGradient(text, colors, true);
}
}
/**
* Убирает цветовые коды из строки
*/

View file

@ -68,8 +68,8 @@ public class GradientConfirmGUI implements InventoryHolder {
skullMeta.setOwningPlayer(player);
String preview = buildPreview();
// Preview уже в MiniMessage формате, просто парсим
Component previewComponent = ChatFormatter.parse(preview);
// Для GUI используем LegacyComponentSerializer с поддержкой HEX
Component previewComponent = SERIALIZER.deserialize(preview);
skullMeta.displayName(previewComponent.decoration(TextDecoration.ITALIC, false));
List<Component> lore = new ArrayList<>();
@ -126,22 +126,22 @@ public class GradientConfirmGUI implements InventoryHolder {
}
}
// Для GUI всегда используем MiniMessage формат (false) для правильного отображения градиента
boolean useLegacyForPreview = false;
// Для GUI используем legacy формат &#RRGGBB который LegacyComponentSerializer понимает
boolean useLegacyForPreview = true;
// Если нет кастомного префикса - используем LuckPerms префикс
if ((prefixToUse == null || prefixToUse.isEmpty()) && module.getLuckPermsHook().isEnabled()) {
String lpPrefix = module.getLuckPermsHook().getActivePrefix(player);
if (lpPrefix != null && !lpPrefix.isEmpty()) {
// Для превью показываем LP префикс
// Конвертируем LP префикс в legacy формат
lpPrefix = convertToLegacy(lpPrefix);
// Если градиент на LP префикс включен - применяем градиент на всю строку
if (colorsToUse != null && !colorsToUse.isEmpty() && module.getConfig().isGradientOnLuckPermsPrefix()) {
// Убираем цвета из LP префикса и применяем градиент на всё
String cleanLpPrefix = stripColors(lpPrefix);
String fullText = cleanLpPrefix + nick;
return GradientUtil.applyGradient(fullText, colorsToUse, useLegacyForPreview);
} else {
// LP префикс со своими цветами + градиентный ник
if (colorsToUse != null && !colorsToUse.isEmpty()) {
return lpPrefix + GradientUtil.applyGradient(nick, colorsToUse, useLegacyForPreview);
}
@ -161,6 +161,15 @@ public class GradientConfirmGUI implements InventoryHolder {
);
}
/**
* Конвертирует MiniMessage теги в legacy формат
*/
private String convertToLegacy(String text) {
if (text == null) return "";
// Конвертируем <#RRGGBB> в &#RRGGBB
return text.replaceAll("<#([A-Fa-f0-9]{6})>", "&#$1");
}
/**
* Убирает цветовые коды из строки
*/

View file

@ -98,17 +98,59 @@ public final class GradientUtil {
private static String formatHex(String hex, boolean useLegacyFormat) {
hex = hex.replace("#", "").toLowerCase();
if (useLegacyFormat) {
// Формат §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();
// Формат &#RRGGBB для LegacyComponentSerializer
return "&#" + hex;
} else {
return "<#" + hex + ">";
}
}
/**
* Конвертирует HEX в формат §x§R§R§G§G§B§B для TAB плагина
*/
private static String formatHexForTab(String hex) {
hex = hex.replace("#", "").toLowerCase();
StringBuilder sb = new StringBuilder("§x");
for (char c : hex.toCharArray()) {
sb.append("§").append(c);
}
return sb.toString();
}
/**
* Применяет градиент в формате §x§R§R§G§G§B§B для TAB плагина
*/
public static String applyGradientTabFormat(String text, List<String> hexColors) {
if (text == null || text.isEmpty() || hexColors == null || hexColors.isEmpty()) {
return text;
}
char[] chars = text.toCharArray();
int length = chars.length;
if (length == 0) return text;
StringBuilder result = new StringBuilder();
if (hexColors.size() == 1) {
String colorCode = formatHexForTab(hexColors.get(0));
result.append(colorCode).append(text);
} else {
Color[] colors = hexColors.stream()
.map(GradientUtil::parseHex)
.toArray(Color[]::new);
for (int i = 0; i < length; i++) {
double ratio = length > 1 ? (double) i / (length - 1) : 0.0;
Color interpolated = interpolateMultiColor(colors, ratio);
String hex = String.format("#%02x%02x%02x",
interpolated.getRed(), interpolated.getGreen(), interpolated.getBlue());
result.append(formatHexForTab(hex)).append(chars[i]);
}
}
return result.toString();
}
public static String buildDisplayName(String prefix, String nick, List<String> colors,
boolean gradientOnPrefix, boolean continuousGradient,
String prefixFormat, boolean useLegacyFormat) {

View file

@ -69,6 +69,7 @@ public class PlaceholderAPIHook extends PlaceholderExpansion {
}
// Gradient placeholders (совместимость с LoPreff)
// Используем TAB формат §x§R§R§G§G§B§B для совместимости с TAB плагином
case "gradient_full", "full" -> {
Player onlinePlayer = player.getPlayer();
if (onlinePlayer == null) yield player.getName() != null ? player.getName() : "";
@ -78,7 +79,8 @@ public class PlaceholderAPIHook extends PlaceholderExpansion {
yield player.getName() != null ? player.getName() : "";
}
yield gradient.getFormattedName(onlinePlayer);
// Используем TAB формат для плейсхолдеров
yield gradient.getFormattedNameForTab(onlinePlayer);
}
case "gradient_name", "name" -> {
Player onlinePlayer = player.getPlayer();