Remove ChatColor system - unified all color handling in GradientModule + fix color formats
This commit is contained in:
parent
dbb6a61351
commit
d8721138d9
9 changed files with 16 additions and 441 deletions
|
|
@ -26,11 +26,9 @@ public final class LoChat extends JavaPlugin {
|
||||||
private MentionManager mentionManager;
|
private MentionManager mentionManager;
|
||||||
private SpyManager spyManager;
|
private SpyManager spyManager;
|
||||||
private EmojiManager emojiManager;
|
private EmojiManager emojiManager;
|
||||||
private ChatColorManager chatColorManager;
|
|
||||||
private CustomCommandManager customCommandManager;
|
private CustomCommandManager customCommandManager;
|
||||||
private MuteManager muteManager;
|
private MuteManager muteManager;
|
||||||
private GradientModule gradientModule;
|
private GradientModule gradientModule;
|
||||||
private com.loki.lochat.listeners.DisplayNameListener displayNameListener;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
|
|
@ -49,7 +47,6 @@ public final class LoChat extends JavaPlugin {
|
||||||
cooldownManager = new CooldownManager();
|
cooldownManager = new CooldownManager();
|
||||||
mentionManager = new MentionManager(this);
|
mentionManager = new MentionManager(this);
|
||||||
spyManager = new SpyManager(this);
|
spyManager = new SpyManager(this);
|
||||||
chatColorManager = new ChatColorManager(this);
|
|
||||||
customCommandManager = new CustomCommandManager(this);
|
customCommandManager = new CustomCommandManager(this);
|
||||||
muteManager = new MuteManager(this);
|
muteManager = new MuteManager(this);
|
||||||
chatManager = new ChatManager(this);
|
chatManager = new ChatManager(this);
|
||||||
|
|
@ -66,8 +63,6 @@ public final class LoChat extends JavaPlugin {
|
||||||
|
|
||||||
// Регистрация листенеров
|
// Регистрация листенеров
|
||||||
getServer().getPluginManager().registerEvents(new ChatListener(this), this);
|
getServer().getPluginManager().registerEvents(new ChatListener(this), this);
|
||||||
displayNameListener = new com.loki.lochat.listeners.DisplayNameListener(this);
|
|
||||||
getServer().getPluginManager().registerEvents(displayNameListener, this);
|
|
||||||
|
|
||||||
// Запуск автосообщений
|
// Запуск автосообщений
|
||||||
autoMessageManager.start();
|
autoMessageManager.start();
|
||||||
|
|
@ -89,9 +84,6 @@ public final class LoChat extends JavaPlugin {
|
||||||
if (ignoreManager != null) {
|
if (ignoreManager != null) {
|
||||||
ignoreManager.save();
|
ignoreManager.save();
|
||||||
}
|
}
|
||||||
if (chatColorManager != null) {
|
|
||||||
chatColorManager.saveData();
|
|
||||||
}
|
|
||||||
if (muteManager != null) {
|
if (muteManager != null) {
|
||||||
muteManager.saveData();
|
muteManager.saveData();
|
||||||
}
|
}
|
||||||
|
|
@ -114,7 +106,6 @@ public final class LoChat extends JavaPlugin {
|
||||||
getCommand("clearchat").setExecutor(new ClearChatCommand(this));
|
getCommand("clearchat").setExecutor(new ClearChatCommand(this));
|
||||||
getCommand("mute").setExecutor(new MuteCommand(this));
|
getCommand("mute").setExecutor(new MuteCommand(this));
|
||||||
getCommand("unmute").setExecutor(new UnmuteCommand(this));
|
getCommand("unmute").setExecutor(new UnmuteCommand(this));
|
||||||
getCommand("chatcolor").setExecutor(new ChatColorCommand(this));
|
|
||||||
|
|
||||||
LoChatCommand loChatCommand = new LoChatCommand(this);
|
LoChatCommand loChatCommand = new LoChatCommand(this);
|
||||||
getCommand("lochat").setExecutor(loChatCommand);
|
getCommand("lochat").setExecutor(loChatCommand);
|
||||||
|
|
@ -194,10 +185,6 @@ public final class LoChat extends JavaPlugin {
|
||||||
return gradientModule;
|
return gradientModule;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChatColorManager getChatColorManager() {
|
|
||||||
return chatColorManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CustomCommandManager getCustomCommandManager() {
|
public CustomCommandManager getCustomCommandManager() {
|
||||||
return customCommandManager;
|
return customCommandManager;
|
||||||
}
|
}
|
||||||
|
|
@ -205,8 +192,4 @@ public final class LoChat extends JavaPlugin {
|
||||||
public MuteManager getMuteManager() {
|
public MuteManager getMuteManager() {
|
||||||
return muteManager;
|
return muteManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public com.loki.lochat.listeners.DisplayNameListener getDisplayNameListener() {
|
|
||||||
return displayNameListener;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,94 +0,0 @@
|
||||||
package com.loki.lochat.commands;
|
|
||||||
|
|
||||||
import com.loki.lochat.LoChat;
|
|
||||||
import com.loki.lochat.utils.ChatFormatter;
|
|
||||||
import org.bukkit.command.Command;
|
|
||||||
import org.bukkit.command.CommandExecutor;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.command.TabCompleter;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
public class ChatColorCommand implements CommandExecutor, TabCompleter {
|
|
||||||
|
|
||||||
private final LoChat plugin;
|
|
||||||
private static final Pattern LEGACY_COLOR_PATTERN = Pattern.compile("^&([0-9a-fk-orA-FK-OR])$");
|
|
||||||
|
|
||||||
public ChatColorCommand(LoChat plugin) {
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
|
||||||
if (!(sender instanceof Player player)) {
|
|
||||||
sender.sendMessage("Только для игроков!");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!player.hasPermission("lochat.chatcolor")) {
|
|
||||||
player.sendMessage(ChatFormatter.parse(plugin.getMessageConfig().getNoPermission()));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.length == 0) {
|
|
||||||
player.sendMessage(ChatFormatter.parse(plugin.getMessageConfig().getInvalidUsage("/chatcolor <цвет>")));
|
|
||||||
player.sendMessage(ChatFormatter.parse("󅒐Используйте Minecraft color codes: &a, &b, &c, &d, &e, &f, &0-&9, &k, &l, &m, &n, &o, &r"));
|
|
||||||
player.sendMessage(ChatFormatter.parse("󅒐Пример: /chatcolor &b"));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
String color = args[0];
|
|
||||||
|
|
||||||
// Проверяем валидность цвета (формат &X где X - это цветовой код)
|
|
||||||
if (!isValidColor(color)) {
|
|
||||||
player.sendMessage(ChatFormatter.parse("&#FF0000Неверный формат цвета! Используйте формат &X, например: &b, &a, &c"));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Сохраняем цвет чата игрока
|
|
||||||
plugin.getChatColorManager().setChatColor(player.getUniqueId(), color);
|
|
||||||
|
|
||||||
// Обновляем display name игрока
|
|
||||||
player.getScheduler().run(plugin, task -> {
|
|
||||||
if (plugin.getDisplayNameListener() != null) {
|
|
||||||
plugin.getDisplayNameListener().updatePlayerDisplayName(player);
|
|
||||||
}
|
|
||||||
}, null);
|
|
||||||
|
|
||||||
// Показываем пример с примененным цветом
|
|
||||||
String preview = ChatFormatter.convertAllColors(color + "Пример текста");
|
|
||||||
player.sendMessage(ChatFormatter.parse("�FF00Цвет чата установлен! Пример: " + preview));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isValidColor(String color) {
|
|
||||||
if (color == null || color.length() != 2) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!color.startsWith("&")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
char code = color.charAt(1);
|
|
||||||
return (code >= '0' && code <= '9') ||
|
|
||||||
(code >= 'a' && code <= 'f') ||
|
|
||||||
(code >= 'A' && code <= 'F') ||
|
|
||||||
code == 'k' || code == 'K' ||
|
|
||||||
code == 'l' || code == 'L' ||
|
|
||||||
code == 'm' || code == 'M' ||
|
|
||||||
code == 'n' || code == 'N' ||
|
|
||||||
code == 'o' || code == 'O' ||
|
|
||||||
code == 'r' || code == 'R';
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) {
|
|
||||||
// Убираем автодополнение, так как теперь пользователь сам вводит цвет
|
|
||||||
return new ArrayList<>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -20,8 +20,6 @@ public final class DisplayNameUtil {
|
||||||
.hexCharacter('#')
|
.hexCharacter('#')
|
||||||
.hexColors()
|
.hexColors()
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
private static final Pattern HEX_PATTERN = Pattern.compile("&#([0-9a-fA-F]{6})");
|
|
||||||
|
|
||||||
private DisplayNameUtil() {}
|
private DisplayNameUtil() {}
|
||||||
|
|
||||||
|
|
@ -52,8 +50,8 @@ public final class DisplayNameUtil {
|
||||||
cfg.isUseLegacyRgbFormat(),
|
cfg.isUseLegacyRgbFormat(),
|
||||||
cfg.isContinuousGradient()
|
cfg.isContinuousGradient()
|
||||||
);
|
);
|
||||||
// Конвертируем &#RRGGBB в §x§R§R§G§G§B§B для display name
|
// Для display name нужен §x формат, конвертируем MiniMessage в legacy
|
||||||
displayName = convertToLegacyFormat(displayName);
|
displayName = convertMiniMessageToLegacy(displayName);
|
||||||
var component = SERIALIZER.deserialize(displayName);
|
var component = SERIALIZER.deserialize(displayName);
|
||||||
player.displayName(component);
|
player.displayName(component);
|
||||||
player.playerListName(component);
|
player.playerListName(component);
|
||||||
|
|
@ -72,20 +70,22 @@ public final class DisplayNameUtil {
|
||||||
cfg.isUseLegacyRgbFormat()
|
cfg.isUseLegacyRgbFormat()
|
||||||
);
|
);
|
||||||
|
|
||||||
// Конвертируем &#RRGGBB в §x§R§R§G§G§B§B для display name
|
// Для display name нужен §x формат, конвертируем MiniMessage в legacy
|
||||||
displayName = convertToLegacyFormat(displayName);
|
displayName = convertMiniMessageToLegacy(displayName);
|
||||||
var component = SERIALIZER.deserialize(displayName);
|
var component = SERIALIZER.deserialize(displayName);
|
||||||
player.displayName(component);
|
player.displayName(component);
|
||||||
player.playerListName(component);
|
player.playerListName(component);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Конвертирует &#RRGGBB формат в §x§R§R§G§G§B§B для display name
|
* Конвертирует MiniMessage <#RRGGBB> формат в §x§R§R§G§G§B§B для display name
|
||||||
*/
|
*/
|
||||||
private static String convertToLegacyFormat(String text) {
|
private static String convertMiniMessageToLegacy(String text) {
|
||||||
if (text == null) return "";
|
if (text == null) return "";
|
||||||
|
|
||||||
Matcher matcher = HEX_PATTERN.matcher(text);
|
// Конвертируем <#RRGGBB> в §x§R§R§G§G§B§B
|
||||||
|
Pattern pattern = Pattern.compile("<#([0-9a-fA-F]{6})>");
|
||||||
|
Matcher matcher = pattern.matcher(text);
|
||||||
StringBuffer sb = new StringBuffer();
|
StringBuffer sb = new StringBuffer();
|
||||||
|
|
||||||
while (matcher.find()) {
|
while (matcher.find()) {
|
||||||
|
|
|
||||||
|
|
@ -150,18 +150,15 @@ public class TextDisplayManager {
|
||||||
boolean useLegacyFormat,
|
boolean useLegacyFormat,
|
||||||
boolean continuousGradient) {
|
boolean continuousGradient) {
|
||||||
if (colors == null || colors.isEmpty()) {
|
if (colors == null || colors.isEmpty()) {
|
||||||
return convertToMiniMessageFormat(lpPrefix + nick);
|
return lpPrefix + nick;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (continuousGradient) {
|
if (continuousGradient) {
|
||||||
String cleanPrefix = stripColors(lpPrefix);
|
String cleanPrefix = stripColors(lpPrefix);
|
||||||
String fullText = cleanPrefix + nick;
|
String fullText = cleanPrefix + nick;
|
||||||
String result = GradientUtil.applyGradient(fullText, colors, false); // MiniMessage формат
|
return GradientUtil.applyGradient(fullText, colors, false); // Всегда MiniMessage формат для TextDisplay
|
||||||
return convertToMiniMessageFormat(result);
|
|
||||||
} else {
|
} else {
|
||||||
String result = convertToMiniMessageFormat(lpPrefix) +
|
return lpPrefix + GradientUtil.applyGradient(nick, colors, false); // Всегда MiniMessage формат для TextDisplay
|
||||||
convertToMiniMessageFormat(GradientUtil.applyGradient(nick, colors, false));
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -174,25 +171,10 @@ public class TextDisplayManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Конвертирует &#RRGGBB в <#RRGGBB> для MiniMessage
|
* Возвращает текст как есть, так как градиенты уже в MiniMessage формате
|
||||||
*/
|
*/
|
||||||
private String convertToMiniMessageFormat(String text) {
|
private String convertToMiniMessageFormat(String text) {
|
||||||
if (text == null) return "";
|
if (text == null) return "";
|
||||||
// Конвертируем &#RRGGBB в <#RRGGBB>
|
|
||||||
text = text.replaceAll("&#([0-9a-fA-F]{6})", "<#$1>");
|
|
||||||
// Конвертируем §x§R§R§G§G§B§B в <#RRGGBB> (используем Pattern и Matcher)
|
|
||||||
java.util.regex.Pattern pattern = java.util.regex.Pattern.compile("§x(§[0-9a-fA-F]){6}");
|
|
||||||
java.util.regex.Matcher matcher = pattern.matcher(text);
|
|
||||||
StringBuffer sb = new StringBuffer();
|
|
||||||
while (matcher.find()) {
|
|
||||||
String hex = matcher.group().replaceAll("§", "").substring(1); // Убираем все § и x
|
|
||||||
matcher.appendReplacement(sb, "<#" + hex + ">");
|
|
||||||
}
|
|
||||||
matcher.appendTail(sb);
|
|
||||||
text = sb.toString();
|
|
||||||
|
|
||||||
// Конвертируем обычные цветовые коды §a в <green> и т.д.
|
|
||||||
text = text.replaceAll("§([0-9a-fk-or])", "<$1>");
|
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,139 +0,0 @@
|
||||||
package com.loki.lochat.listeners;
|
|
||||||
|
|
||||||
import com.loki.lochat.LoChat;
|
|
||||||
import com.loki.lochat.managers.ChatColorManager;
|
|
||||||
import net.kyori.adventure.text.Component;
|
|
||||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.event.EventHandler;
|
|
||||||
import org.bukkit.event.EventPriority;
|
|
||||||
import org.bukkit.event.Listener;
|
|
||||||
import org.bukkit.event.player.PlayerJoinEvent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Слушатель для обновления display name игроков с префиксом и цветом ника
|
|
||||||
*/
|
|
||||||
public class DisplayNameListener implements Listener {
|
|
||||||
|
|
||||||
private final LoChat plugin;
|
|
||||||
private static final MiniMessage MINI_MESSAGE = MiniMessage.miniMessage();
|
|
||||||
|
|
||||||
public DisplayNameListener(LoChat plugin) {
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.MONITOR)
|
|
||||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
|
||||||
Player player = event.getPlayer();
|
|
||||||
|
|
||||||
// Обновляем display name через RegionScheduler для Folia
|
|
||||||
player.getScheduler().run(plugin, task -> {
|
|
||||||
updatePlayerDisplayName(player);
|
|
||||||
}, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Обновляет display name игрока с префиксом и цветом ника
|
|
||||||
*/
|
|
||||||
public void updatePlayerDisplayName(Player player) {
|
|
||||||
// Если градиентный модуль включен и обновляет display name, не дублируем
|
|
||||||
if (plugin.getGradientModule() != null && plugin.getGradientModule().isEnabled()) {
|
|
||||||
if (plugin.getGradientModule().getConfig().isUpdateDisplayName()) {
|
|
||||||
// Градиентный модуль сам обновляет display name
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String displayName = buildDisplayName(player);
|
|
||||||
Component component = MINI_MESSAGE.deserialize(displayName);
|
|
||||||
player.displayName(component);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Строит display name с префиксом и цветом ника
|
|
||||||
*/
|
|
||||||
private String buildDisplayName(Player player) {
|
|
||||||
StringBuilder result = new StringBuilder();
|
|
||||||
|
|
||||||
// Получаем префикс из градиентного модуля (если есть)
|
|
||||||
String prefix = null;
|
|
||||||
if (plugin.getGradientModule() != null && plugin.getGradientModule().isEnabled()) {
|
|
||||||
var data = plugin.getGradientModule().getDataManager().getPlayerData(player.getUniqueId());
|
|
||||||
if (data != null && data.isPrefixEnabled() && data.hasPrefix()) {
|
|
||||||
prefix = plugin.getGradientModule().getConfig().getPrefixFormat()
|
|
||||||
.replace("{prefix}", data.getPrefix());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Добавляем префикс если есть
|
|
||||||
if (prefix != null && !prefix.isEmpty()) {
|
|
||||||
result.append(prefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Получаем цвет чата
|
|
||||||
ChatColorManager colorManager = plugin.getChatColorManager();
|
|
||||||
String chatColor = colorManager.getChatColor(player.getUniqueId());
|
|
||||||
|
|
||||||
// Получаем имя игрока
|
|
||||||
String playerName = player.getName();
|
|
||||||
|
|
||||||
// Применяем цвет к нику
|
|
||||||
if (chatColor != null) {
|
|
||||||
// Если цвет в формате &X, конвертируем его в MiniMessage
|
|
||||||
if (chatColor.startsWith("&") && chatColor.length() == 2) {
|
|
||||||
String miniMessageColor = convertLegacyColorToMiniMessage(chatColor);
|
|
||||||
if (!miniMessageColor.isEmpty()) {
|
|
||||||
String tagName = miniMessageColor.substring(1, miniMessageColor.length() - 1);
|
|
||||||
result.append(miniMessageColor).append(playerName).append("</").append(tagName).append(">");
|
|
||||||
} else {
|
|
||||||
result.append(playerName);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Если уже в формате MiniMessage
|
|
||||||
result.append("<").append(chatColor).append(">").append(playerName).append("</").append(chatColor).append(">");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Нет цвета, просто имя
|
|
||||||
result.append(playerName);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Конвертирует &X код в MiniMessage формат
|
|
||||||
*/
|
|
||||||
private String convertLegacyColorToMiniMessage(String legacyColor) {
|
|
||||||
if (legacyColor == null || legacyColor.length() != 2 || !legacyColor.startsWith("&")) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
char code = legacyColor.charAt(1);
|
|
||||||
return switch (Character.toLowerCase(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 -> "";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,148 +0,0 @@
|
||||||
package com.loki.lochat.managers;
|
|
||||||
|
|
||||||
import com.loki.lochat.LoChat;
|
|
||||||
import com.loki.lochat.gradient.util.FoliaUtil;
|
|
||||||
import org.bukkit.configuration.file.FileConfiguration;
|
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class ChatColorManager {
|
|
||||||
|
|
||||||
private final LoChat plugin;
|
|
||||||
private final Map<UUID, String> chatColors;
|
|
||||||
private File dataFile;
|
|
||||||
private FileConfiguration dataConfig;
|
|
||||||
|
|
||||||
public ChatColorManager(LoChat plugin) {
|
|
||||||
this.plugin = plugin;
|
|
||||||
this.chatColors = new HashMap<>();
|
|
||||||
loadData();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadData() {
|
|
||||||
dataFile = new File(plugin.getDataFolder(), "chatcolors.yml");
|
|
||||||
if (!dataFile.exists()) {
|
|
||||||
try {
|
|
||||||
dataFile.createNewFile();
|
|
||||||
} catch (IOException e) {
|
|
||||||
plugin.getLogger().severe("Не удалось создать файл chatcolors.yml: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dataConfig = YamlConfiguration.loadConfiguration(dataFile);
|
|
||||||
|
|
||||||
// Загружаем цвета из файла
|
|
||||||
for (String key : dataConfig.getKeys(false)) {
|
|
||||||
try {
|
|
||||||
UUID uuid = UUID.fromString(key);
|
|
||||||
String color = dataConfig.getString(key);
|
|
||||||
if (color != null) {
|
|
||||||
chatColors.put(uuid, color);
|
|
||||||
}
|
|
||||||
} catch (IllegalArgumentException ignored) {
|
|
||||||
// Неверный UUID, пропускаем
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void saveData() {
|
|
||||||
for (Map.Entry<UUID, String> entry : chatColors.entrySet()) {
|
|
||||||
dataConfig.set(entry.getKey().toString(), entry.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
dataConfig.save(dataFile);
|
|
||||||
} catch (IOException e) {
|
|
||||||
plugin.getLogger().severe("Не удалось сохранить chatcolors.yml: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Асинхронное сохранение данных (для Folia совместимости)
|
|
||||||
*/
|
|
||||||
private void saveDataAsync() {
|
|
||||||
FoliaUtil.runAsync(plugin, this::saveData);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setChatColor(UUID playerId, String color) {
|
|
||||||
chatColors.put(playerId, color);
|
|
||||||
saveDataAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getChatColor(UUID playerId) {
|
|
||||||
return chatColors.get(playerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasChatColor(UUID playerId) {
|
|
||||||
return chatColors.containsKey(playerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeChatColor(UUID playerId) {
|
|
||||||
chatColors.remove(playerId);
|
|
||||||
dataConfig.set(playerId.toString(), null);
|
|
||||||
saveDataAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Применяет цвет чата к сообщению
|
|
||||||
* Поддерживает формат &X (Minecraft color codes)
|
|
||||||
*/
|
|
||||||
public String applyChatColor(UUID playerId, String message) {
|
|
||||||
String color = getChatColor(playerId);
|
|
||||||
if (color != null) {
|
|
||||||
// Если цвет в формате &X, конвертируем его в MiniMessage
|
|
||||||
if (color.startsWith("&") && color.length() == 2) {
|
|
||||||
String miniMessageColor = convertLegacyColorToMiniMessage(color);
|
|
||||||
if (!miniMessageColor.isEmpty()) {
|
|
||||||
// Извлекаем имя тега из <tag> для закрывающего тега
|
|
||||||
String tagName = miniMessageColor.substring(1, miniMessageColor.length() - 1);
|
|
||||||
return miniMessageColor + message + "</" + tagName + ">";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Если уже в формате MiniMessage, используем как есть
|
|
||||||
return "<" + color + ">" + message + "</" + color + ">";
|
|
||||||
}
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Конвертирует &X код в MiniMessage формат
|
|
||||||
*/
|
|
||||||
private String convertLegacyColorToMiniMessage(String legacyColor) {
|
|
||||||
if (legacyColor == null || legacyColor.length() != 2 || !legacyColor.startsWith("&")) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
char code = legacyColor.charAt(1);
|
|
||||||
return switch (Character.toLowerCase(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 -> "";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -41,12 +41,11 @@ public final class ChatFormatter {
|
||||||
/* ===================== COLORS ===================== */
|
/* ===================== COLORS ===================== */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Конвертирует &#RRGGBB формат в MiniMessage <#RRGGBB> формат
|
* Возвращает строку как есть, так как теперь градиенты генерируются в MiniMessage формате
|
||||||
*/
|
*/
|
||||||
public static String convertAllColors(String message) {
|
public static String convertAllColors(String message) {
|
||||||
if (message == null) return "";
|
if (message == null) return "";
|
||||||
// Конвертируем &#RRGGBB в <#RRGGBB> для MiniMessage
|
return message;
|
||||||
return message.replaceAll("&#([0-9a-fA-F]{6})", "<#$1>");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ===================== EMOJIS ===================== */
|
/* ===================== EMOJIS ===================== */
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ gradient-on-luckperms-prefix: true
|
||||||
continuous-gradient: true
|
continuous-gradient: true
|
||||||
|
|
||||||
# Использовать &#RRGGBB формат (true) или <#RRGGBB> (false)
|
# Использовать &#RRGGBB формат (true) или <#RRGGBB> (false)
|
||||||
use-legacy-rgb-format: true
|
use-legacy-rgb-format: false
|
||||||
|
|
||||||
# Отображение над игроком
|
# Отображение над игроком
|
||||||
display:
|
display:
|
||||||
|
|
|
||||||
|
|
@ -84,12 +84,6 @@ commands:
|
||||||
permission: chat.mute
|
permission: chat.mute
|
||||||
aliases: [размут, гтьгеу]
|
aliases: [размут, гтьгеу]
|
||||||
|
|
||||||
chatcolor:
|
|
||||||
description: Set chat color
|
|
||||||
usage: /chatcolor <color>
|
|
||||||
permission: lochat.chatcolor
|
|
||||||
aliases: [цветчата, chatcolour, сrfnсщдщк, сrfnсщдщгк]
|
|
||||||
|
|
||||||
lochat:
|
lochat:
|
||||||
description: LoChat admin command
|
description: LoChat admin command
|
||||||
usage: /lochat [reload]
|
usage: /lochat [reload]
|
||||||
|
|
@ -147,8 +141,6 @@ permissions:
|
||||||
default: op
|
default: op
|
||||||
chat.mention.use:
|
chat.mention.use:
|
||||||
default: true
|
default: true
|
||||||
lochat.chatcolor:
|
|
||||||
default: true
|
|
||||||
gradient.color:
|
gradient.color:
|
||||||
default: true
|
default: true
|
||||||
gradient.prefix:
|
gradient.prefix:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue