Переделал настройки цветов: /chatcolor теперь принимает &b формат, добавлена поддержка #RRGGBB в конфигах
This commit is contained in:
parent
c6442bc88f
commit
ee67dcc12a
4 changed files with 99 additions and 34 deletions
|
|
@ -11,12 +11,13 @@ import org.jetbrains.annotations.NotNull;
|
|||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
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;
|
||||
|
|
@ -36,51 +37,51 @@ public class ChatColorCommand implements CommandExecutor, TabCompleter {
|
|||
|
||||
if (args.length == 0) {
|
||||
player.sendMessage(ChatFormatter.parse(plugin.getMessageConfig().getInvalidUsage("/chatcolor <цвет>")));
|
||||
player.sendMessage(ChatFormatter.parse("<gray>Доступные цвета: <red>red</red>, <blue>blue</blue>, <green>green</green>, <yellow>yellow</yellow>, <gold>gold</gold>, <aqua>aqua</aqua>, <light_purple>light_purple</light_purple>, <white>white</white>, <gray>gray</gray>, <dark_gray>dark_gray</dark_gray>"));
|
||||
player.sendMessage(ChatFormatter.parse("<gray>Используйте Minecraft color codes: &a, &b, &c, &d, &e, &f, &0-&9, &k, &l, &m, &n, &o, &r</gray>"));
|
||||
player.sendMessage(ChatFormatter.parse("<gray>Пример: /chatcolor &b</gray>"));
|
||||
return true;
|
||||
}
|
||||
|
||||
String color = args[0].toLowerCase();
|
||||
String color = args[0];
|
||||
|
||||
// Проверяем валидность цвета
|
||||
// Проверяем валидность цвета (формат &X где X - это цветовой код)
|
||||
if (!isValidColor(color)) {
|
||||
player.sendMessage(ChatFormatter.parse("<red>Неверный цвет! Используйте один из доступных цветов.</red>"));
|
||||
player.sendMessage(ChatFormatter.parse("<red>Неверный формат цвета! Используйте формат &X, например: &b, &a, &c</red>"));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Сохраняем цвет чата игрока
|
||||
plugin.getChatColorManager().setChatColor(player.getUniqueId(), color);
|
||||
player.sendMessage(ChatFormatter.parse("<green>Цвет чата установлен на <" + color + ">" + color + "</color>!"));
|
||||
|
||||
// Показываем пример с примененным цветом
|
||||
String preview = ChatFormatter.convertAllColors(color + "Пример текста");
|
||||
player.sendMessage(ChatFormatter.parse("<green>Цвет чата установлен! Пример: " + preview));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isValidColor(String color) {
|
||||
List<String> validColors = Arrays.asList(
|
||||
"red", "blue", "green", "yellow", "gold", "aqua",
|
||||
"light_purple", "white", "gray", "dark_gray", "black",
|
||||
"dark_red", "dark_green", "dark_blue", "dark_aqua", "dark_purple"
|
||||
);
|
||||
return validColors.contains(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) {
|
||||
if (args.length == 1) {
|
||||
List<String> colors = Arrays.asList(
|
||||
"red", "blue", "green", "yellow", "gold", "aqua",
|
||||
"light_purple", "white", "gray", "dark_gray"
|
||||
);
|
||||
List<String> completions = new ArrayList<>();
|
||||
String input = args[0].toLowerCase();
|
||||
|
||||
for (String color : colors) {
|
||||
if (color.startsWith(input)) {
|
||||
completions.add(color);
|
||||
}
|
||||
}
|
||||
return completions;
|
||||
}
|
||||
// Убираем автодополнение, так как теперь пользователь сам вводит цвет
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
|
@ -82,12 +82,59 @@ public class ChatColorManager {
|
|||
|
||||
/**
|
||||
* Применяет цвет чата к сообщению
|
||||
* Поддерживает формат &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 -> "";
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@ public class ChatFormatter {
|
|||
|
||||
// Паттерны для цветов
|
||||
private static final Pattern HEX_PATTERN = Pattern.compile("&#([A-Fa-f0-9]{6})");
|
||||
private static final Pattern HEX_PATTERN_NO_AMPERSAND = 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}");
|
||||
|
|
@ -73,16 +74,28 @@ public class ChatFormatter {
|
|||
}
|
||||
|
||||
/**
|
||||
* Конвертирует &#RRGGBB в MiniMessage формат <#RRGGBB>
|
||||
* Конвертирует &#RRGGBB и #RRGGBB в MiniMessage формат <#RRGGBB>
|
||||
*/
|
||||
public static String convertHexColors(String message) {
|
||||
Matcher matcher = HEX_PATTERN.matcher(message);
|
||||
StringBuilder result = new StringBuilder();
|
||||
String result = message;
|
||||
|
||||
// Конвертируем &#RRGGBB
|
||||
Matcher matcher = HEX_PATTERN.matcher(result);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
while (matcher.find()) {
|
||||
matcher.appendReplacement(result, "<#" + matcher.group(1) + ">");
|
||||
matcher.appendReplacement(sb, "<#" + matcher.group(1) + ">");
|
||||
}
|
||||
matcher.appendTail(result);
|
||||
return result.toString();
|
||||
matcher.appendTail(sb);
|
||||
result = sb.toString();
|
||||
|
||||
// Конвертируем #RRGGBB (без &, но не если это часть &#RRGGBB)
|
||||
matcher = HEX_PATTERN_NO_AMPERSAND.matcher(result);
|
||||
sb = new StringBuilder();
|
||||
while (matcher.find()) {
|
||||
matcher.appendReplacement(sb, "<#" + matcher.group(1) + ">");
|
||||
}
|
||||
matcher.appendTail(sb);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -171,6 +184,7 @@ public class ChatFormatter {
|
|||
boolean hasColorCodes = LEGACY_COLOR_PATTERN.matcher(result).find()
|
||||
|| SECTION_COLOR_PATTERN.matcher(result).find()
|
||||
|| HEX_PATTERN.matcher(result).find()
|
||||
|| HEX_PATTERN_NO_AMPERSAND.matcher(result).find()
|
||||
|| MINIMESSAGE_HEX_PATTERN.matcher(result).find();
|
||||
|
||||
// Если есть право на цвета И есть цветовые коды - конвертируем
|
||||
|
|
@ -239,6 +253,9 @@ public class ChatFormatter {
|
|||
// Убираем &#RRGGBB
|
||||
result = HEX_PATTERN.matcher(result).replaceAll("");
|
||||
|
||||
// Убираем #RRGGBB (без &)
|
||||
result = HEX_PATTERN_NO_AMPERSAND.matcher(result).replaceAll("");
|
||||
|
||||
// Убираем &коды
|
||||
result = stripLegacyColors(result);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue