diff --git a/build.gradle.kts b/build.gradle.kts index 6a5a9ce..e303950 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,6 +1,5 @@ plugins { java - checkstyle } group = "com.loki" @@ -53,17 +52,3 @@ tasks.jar { from(configurations.runtimeClasspath.get().map { if (it.isDirectory) it else zipTree(it) }) duplicatesStrategy = DuplicatesStrategy.EXCLUDE } - -checkstyle { - toolVersion = "10.12.5" - configFile = file("${rootDir}/config/checkstyle/checkstyle.xml") - isIgnoreFailures = true - maxWarnings = 999 -} - -tasks.withType { - reports { - xml.required.set(false) - html.required.set(true) - } -} diff --git a/src/main/java/com/loki/lochat/commands/CustomCommandManager.java b/src/main/java/com/loki/lochat/commands/CustomCommandManager.java index 71be886..64405c0 100644 --- a/src/main/java/com/loki/lochat/commands/CustomCommandManager.java +++ b/src/main/java/com/loki/lochat/commands/CustomCommandManager.java @@ -28,7 +28,6 @@ public class CustomCommandManager { // Информационные команды commands.put("help", new HelpCommand(plugin)); commands.put("rules", new RulesCommand(plugin)); - commands.put("discord", new DiscordCommand(plugin)); // Утилиты commands.put("coords", new CoordsCommand(plugin)); diff --git a/src/main/java/com/loki/lochat/integrations/DiscordWebhook.java b/src/main/java/com/loki/lochat/integrations/DiscordWebhook.java index ec57896..045d2ac 100644 --- a/src/main/java/com/loki/lochat/integrations/DiscordWebhook.java +++ b/src/main/java/com/loki/lochat/integrations/DiscordWebhook.java @@ -8,6 +8,7 @@ import org.bukkit.plugin.java.JavaPlugin; import java.io.IOException; import java.io.OutputStream; import java.net.HttpURLConnection; +import java.net.URI; import java.net.URL; import java.nio.charset.StandardCharsets; import java.util.concurrent.CompletableFuture; @@ -141,7 +142,7 @@ public class DiscordWebhook { * Синхронная отправка в вебхук */ private boolean sendWebhookSync(String jsonPayload) throws IOException { - URL url = new URL(webhookUrl); + URL url = URI.create(webhookUrl).toURL(); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); try { diff --git a/src/main/java/com/loki/lochat/listener/DiscordEventListener.java b/src/main/java/com/loki/lochat/listener/DiscordEventListener.java index cb1c478..4df46d1 100644 --- a/src/main/java/com/loki/lochat/listener/DiscordEventListener.java +++ b/src/main/java/com/loki/lochat/listener/DiscordEventListener.java @@ -72,8 +72,8 @@ public class DiscordEventListener implements Listener { if (!discord.isEnabled()) return; Player player = event.getEntity(); - String deathMessage = event.getDeathMessage() != null ? - PlainTextComponentSerializer.plainText().serialize(event.getDeathMessage()) : + String deathMessage = event.deathMessage() != null ? + PlainTextComponentSerializer.plainText().serialize(event.deathMessage()) : "умер"; discord.sendPlayerDeath(player, deathMessage); diff --git a/src/main/java/com/loki/lochat/renderer/EnhancedChatRenderer.java b/src/main/java/com/loki/lochat/renderer/EnhancedChatRenderer.java index e42cd7a..a126356 100644 --- a/src/main/java/com/loki/lochat/renderer/EnhancedChatRenderer.java +++ b/src/main/java/com/loki/lochat/renderer/EnhancedChatRenderer.java @@ -33,20 +33,25 @@ public class EnhancedChatRenderer implements ChatRenderer { @Override public Component render(Player source, Component sourceDisplayName, Component message, Audience viewer) { - // Префикс в зависимости от типа чата + // Красивые префиксы с градиентами и эмодзи Component prefixComponent; if (isGlobal) { - // [G] с желтой буквой G - prefixComponent = Component.text("[") - .color(net.kyori.adventure.text.format.NamedTextColor.GRAY) - .append(Component.text("G").color(net.kyori.adventure.text.format.NamedTextColor.GOLD)) - .append(Component.text("]").color(net.kyori.adventure.text.format.NamedTextColor.GRAY)); + // 🌍 GLOBAL с градиентом от золотого к оранжевому + prefixComponent = Component.text("🌍 ") + .append(Component.text("G").color(net.kyori.adventure.text.format.TextColor.fromHexString("#FFD700"))) + .append(Component.text("L").color(net.kyori.adventure.text.format.TextColor.fromHexString("#FFA500"))) + .append(Component.text("O").color(net.kyori.adventure.text.format.TextColor.fromHexString("#FF8C00"))) + .append(Component.text("B").color(net.kyori.adventure.text.format.TextColor.fromHexString("#FF7F50"))) + .append(Component.text("A").color(net.kyori.adventure.text.format.TextColor.fromHexString("#FF6347"))) + .append(Component.text("L").color(net.kyori.adventure.text.format.TextColor.fromHexString("#FF4500"))); } else { - // [L] с голубой буквой L - prefixComponent = Component.text("[") - .color(net.kyori.adventure.text.format.NamedTextColor.GRAY) - .append(Component.text("L").color(net.kyori.adventure.text.format.NamedTextColor.AQUA)) - .append(Component.text("]").color(net.kyori.adventure.text.format.NamedTextColor.GRAY)); + // 📍 LOCAL с градиентом от голубого к синему + prefixComponent = Component.text("📍 ") + .append(Component.text("L").color(net.kyori.adventure.text.format.TextColor.fromHexString("#87CEEB"))) + .append(Component.text("O").color(net.kyori.adventure.text.format.TextColor.fromHexString("#87CEFA"))) + .append(Component.text("C").color(net.kyori.adventure.text.format.TextColor.fromHexString("#00BFFF"))) + .append(Component.text("A").color(net.kyori.adventure.text.format.TextColor.fromHexString("#1E90FF"))) + .append(Component.text("L").color(net.kyori.adventure.text.format.TextColor.fromHexString("#4169E1"))); } Component playerComponent = createPlayerComponent(source, sourceDisplayName); @@ -60,10 +65,15 @@ public class EnhancedChatRenderer implements ChatRenderer { processedMessage = mentionHandler.processMentions(processedMessage, source, viewerPlayer); } + // Красивое разделение с градиентными стрелками + Component separator = isGlobal ? + Component.text(" ▶ ").color(net.kyori.adventure.text.format.TextColor.fromHexString("#FFD700")) : + Component.text(" ▶ ").color(net.kyori.adventure.text.format.TextColor.fromHexString("#87CEEB")); + return prefixComponent - .append(Component.text(" ")) + .append(separator) .append(playerComponent) - .append(Component.text(": ").color(net.kyori.adventure.text.format.NamedTextColor.GRAY)) + .append(Component.text(": ").color(net.kyori.adventure.text.format.NamedTextColor.DARK_GRAY)) .append(processedMessage); } @@ -75,10 +85,16 @@ public class EnhancedChatRenderer implements ChatRenderer { java.util.List hoverLines = plugin.getConfig().getStringList("chat.hover.format"); if (hoverLines.isEmpty()) { hoverLines = java.util.Arrays.asList( - "Игрок: {player}", - "Мир: {world}", + "▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬", + "👤 Информация об игроке", "", - "▶ Клик: написать ЛС" + "🏷️ Имя: {player}", + "📶 Пинг: {ping}ms", + "❤️ Здоровье: {health}/20", + "🍖 Голод: {food}/20", + "", + "▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬", + "💬 Клик: написать личное сообщение" ); } @@ -89,7 +105,7 @@ public class EnhancedChatRenderer implements ChatRenderer { line = line.replace("{player}", player.getName()) .replace("{world}", player.getWorld().getName()) .replace("{ping}", String.valueOf(player.getPing())) - .replace("{gamemode}", player.getGameMode().name()) + .replace("{gamemode}", getGameModeDisplay(player.getGameMode())) .replace("{health}", String.valueOf(Math.round(player.getHealth()))) .replace("{food}", String.valueOf(player.getFoodLevel())); @@ -106,6 +122,18 @@ public class EnhancedChatRenderer implements ChatRenderer { .clickEvent(ClickEvent.suggestCommand("/msg " + player.getName() + " ")); } + /** + * Получить красивое отображение игрового режима + */ + private String getGameModeDisplay(org.bukkit.GameMode gameMode) { + return switch (gameMode) { + case SURVIVAL -> "Выживание"; + case CREATIVE -> "Творчество"; + case ADVENTURE -> "Приключение"; + case SPECTATOR -> "Наблюдатель"; + }; + } + private Component processUrls(Component message) { String plainText = PlainTextComponentSerializer.plainText().serialize(message); // Fixed regex: escape the dash in character class to avoid illegal range @@ -130,26 +158,50 @@ public class EnhancedChatRenderer implements ChatRenderer { private Component processEmojis(Component message) { Component result = message; - result = result.replaceText(builder -> builder.matchLiteral(":heart:").replacement("❤")); + + // Основные символы + result = result.replaceText(builder -> builder.matchLiteral(":heart:").replacement("♥")); result = result.replaceText(builder -> builder.matchLiteral(":star:").replacement("★")); - result = result.replaceText(builder -> builder.matchLiteral(":check:").replacement("✔")); - result = result.replaceText(builder -> builder.matchLiteral(":cross:").replacement("✖")); + result = result.replaceText(builder -> builder.matchLiteral(":check:").replacement("✓")); + result = result.replaceText(builder -> builder.matchLiteral(":cross:").replacement("✗")); result = result.replaceText(builder -> builder.matchLiteral(":arrow:").replacement("→")); result = result.replaceText(builder -> builder.matchLiteral(":skull:").replacement("☠")); result = result.replaceText(builder -> builder.matchLiteral(":note:").replacement("♪")); result = result.replaceText(builder -> builder.matchLiteral(":sun:").replacement("☀")); result = result.replaceText(builder -> builder.matchLiteral(":moon:").replacement("☽")); result = result.replaceText(builder -> builder.matchLiteral(":snowflake:").replacement("❄")); - result = result.replaceText(builder -> builder.matchLiteral(":fire:").replacement("🔥")); + result = result.replaceText(builder -> builder.matchLiteral(":fire:").replacement("▲")); + + // Minecraft символы result = result.replaceText(builder -> builder.matchLiteral(":diamond:").replacement("◆")); result = result.replaceText(builder -> builder.matchLiteral(":sword:").replacement("⚔")); result = result.replaceText(builder -> builder.matchLiteral(":pickaxe:").replacement("⛏")); - result = result.replaceText(builder -> builder.matchLiteral(":bow:").replacement("🏹")); - result = result.replaceText(builder -> builder.matchLiteral(":shield:").replacement("🛡")); - result = result.replaceText(builder -> builder.matchLiteral(":potion:").replacement("🧪")); - result = result.replaceText(builder -> builder.matchLiteral(":book:").replacement("📖")); - result = result.replaceText(builder -> builder.matchLiteral(":crown:").replacement("👑")); - result = result.replaceText(builder -> builder.matchLiteral(":gem:").replacement("💎")); + result = result.replaceText(builder -> builder.matchLiteral(":bow:").replacement("⌐")); + result = result.replaceText(builder -> builder.matchLiteral(":shield:").replacement("▣")); + result = result.replaceText(builder -> builder.matchLiteral(":potion:").replacement("⚗")); + result = result.replaceText(builder -> builder.matchLiteral(":book:").replacement("▤")); + result = result.replaceText(builder -> builder.matchLiteral(":crown:").replacement("♔")); + result = result.replaceText(builder -> builder.matchLiteral(":gem:").replacement("◊")); + result = result.replaceText(builder -> builder.matchLiteral(":emerald:").replacement("◈")); + result = result.replaceText(builder -> builder.matchLiteral(":gold:").replacement("◉")); + result = result.replaceText(builder -> builder.matchLiteral(":iron:").replacement("◎")); + + // Дополнительные символы + result = result.replaceText(builder -> builder.matchLiteral(":thumbsup:").replacement("▲")); + result = result.replaceText(builder -> builder.matchLiteral(":thumbsdown:").replacement("▼")); + result = result.replaceText(builder -> builder.matchLiteral(":clap:").replacement("※")); + result = result.replaceText(builder -> builder.matchLiteral(":wave:").replacement("~")); + result = result.replaceText(builder -> builder.matchLiteral(":peace:").replacement("✌")); + result = result.replaceText(builder -> builder.matchLiteral(":ok:").replacement("◯")); + result = result.replaceText(builder -> builder.matchLiteral(":facepalm:").replacement("⌐_⌐")); + result = result.replaceText(builder -> builder.matchLiteral(":shrug:").replacement("¯\\_(ツ)_/¯")); + result = result.replaceText(builder -> builder.matchLiteral(":thinking:").replacement("?")); + result = result.replaceText(builder -> builder.matchLiteral(":laugh:").replacement("xD")); + result = result.replaceText(builder -> builder.matchLiteral(":cry:").replacement(":'(")); + result = result.replaceText(builder -> builder.matchLiteral(":rage:").replacement(">:(")); + result = result.replaceText(builder -> builder.matchLiteral(":cool:").replacement("B)")); + result = result.replaceText(builder -> builder.matchLiteral(":wink:").replacement(";)")); + return result; } } \ No newline at end of file diff --git a/src/main/resources/config/chat-formats.yml b/src/main/resources/config/chat-formats.yml index 6cb9b01..374a090 100644 --- a/src/main/resources/config/chat-formats.yml +++ b/src/main/resources/config/chat-formats.yml @@ -1,85 +1,141 @@ # ╔══════════════════════════════════════════════════════════════════════════════╗ -# ║ LoChat Chat Formats ║ -# ║ Форматы чата ║ +# ║ LoChat Beautiful Chat Formats ║ +# ║ Красивые форматы чата ║ # ║ Версия: 1.5.5-1.20.1 ║ # ╚══════════════════════════════════════════════════════════════════════════════╝ # ┌─────────────────────────────────────────────────────────────────────────────┐ -# │ ФОРМАТЫ ЧАТА │ +# │ КРАСИВЫЕ ФОРМАТЫ ЧАТА │ # └─────────────────────────────────────────────────────────────────────────────┘ -# Доступные плейсхолдеры: -# {player} - имя игрока -# {display_name} - отображаемое имя с градиентом -# {prefix} - префикс игрока -# {suffix} - суффикс игрока -# {world} - мир игрока -# {message} - сообщение -# {time} - время -# {date} - дата -# Все плейсхолдеры PlaceholderAPI +# Настройки отображения чата +chat: + # Включить красивые префиксы + beautiful_prefixes: true + + # Включить hover эффекты на никах + hover: + enabled: true + # Формат hover подсказки (поддерживает MiniMessage) + format: + - "▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬" + - "👤 Информация об игроке" + - "" + - "🏷️ Имя: {player}" + - "📶 Пинг: {ping}ms" + - "❤️ Здоровье: {health}/20" + - "🍖 Голод: {food}/20" + - "" + - "▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬" + - "💬 Клик: написать личное сообщение" -formats: - # Глобальный чат - global: - enabled: true - format: "&#FFD700[G] {prefix}{display_name}&r: {message}" - hover: - - "Игрок: {player}" - - "Мир: {world}" - - "Пинг: %player_ping%ms" - - "" - - "▶ Клик: написать ЛС" - click: - action: "suggest_command" - value: "/msg {player} " +# Настройки глобального чата +global: + # Префикс глобального чата + prefix: + # Использовать эмодзи + emoji: "🌍" + # Текст с градиентом + text: "GLOBAL" + # Цвета градиента (от -> к) + gradient: + from: "#FFD700" + to: "#FF4500" - # Локальный чат - local: - enabled: true - format: "WCEEB[L] {prefix}{display_name}&r: {message}" - hover: - - "Игрок: {player}" - - "Координаты: {x}, {y}, {z}" - - "Расстояние: %distance%м" - - "" - - "▶ Клик: написать ЛС" - click: - action: "suggest_command" - value: "/msg {player} " + # Разделитель между префиксом и ником + separator: + text: " ▶ " + color: "#FFD700" + +# Настройки локального чата +local: + # Префикс локального чата + prefix: + # Использовать эмодзи + emoji: "📍" + # Текст с градиентом + text: "LOCAL" + # Цвета градиента (от -> к) + gradient: + from: "#87CEEB" + to: "#4169E1" - # Личные сообщения - private: - sent: "&7[→] WCEEBВы &7→ {display_name}&7: {message}" - received: "&7[←] {display_name} &7→ WCEEBВы&7: {message}" - hover: - - "Отправлено: %time%" - - "" - - "▶ Клик: ответить" - click: - action: "suggest_command" - value: "/reply " - - # Объявления - announcement: - format: "&#FF6B6B[ОБЪЯВЛЕНИЕ] " - title: - enabled: true - title: "&#FF6B6BОБЪЯВЛЕНИЕ" - subtitle: "{message}" - fade-in: 10 - stay: 60 - fade-out: 10 - actionbar: - enabled: true - format: "&#FF6B6B[ОБЪЯВЛЕНИЕ] {message}" - - # Системные сообщения - system: - join: "BCB77+ {display_name} BCB77присоединился к игре" - quit: "&#FF6B6B- {display_name} &#FF6B6Bпокинул игру" - death: "&#FF6B6B☠ {display_name} &#FF6B6B{death_message}" + # Разделитель между префиксом и ником + separator: + text: " ▶ " + color: "#87CEEB" + # Радиус локального чата (блоки) + radius: 100 + +# Настройки эмодзи +emojis: + # Включить обработку эмодзи + enabled: true + + # Список доступных эмодзи (символы для Minecraft) + list: + # Основные + ":heart:": "♥" + ":star:": "★" + ":check:": "✓" + ":cross:": "✗" + ":arrow:": "→" + ":fire:": "▲" + ":snowflake:": "❄" + ":sun:": "☀" + ":moon:": "☽" + + # Minecraft + ":diamond:": "◆" + ":sword:": "⚔" + ":pickaxe:": "⛏" + ":bow:": "⌐" + ":shield:": "▣" + ":potion:": "⚗" + ":book:": "▤" + ":crown:": "♔" + ":emerald:": "◈" + ":gold:": "◉" + ":iron:": "◎" + + # Эмоции (текстовые) + ":thumbsup:": "▲" + ":thumbsdown:": "▼" + ":clap:": "※" + ":wave:": "~" + ":ok:": "◯" + ":thinking:": "?" + ":laugh:": "xD" + ":cry:": ":'(" + ":rage:": ">:(" + ":cool:": "B)" + ":wink:": ";)" + +# Настройки URL обработки +urls: + # Включить кликабельные ссылки + enabled: true + # Цвет ссылок + color: "#00BFFF" + # Подчеркивание + underlined: true + # Hover текст + hover_text: "🔗 Открыть ссылку: {url}" + +# Настройки упоминаний (@player) +mentions: + # Включить упоминания + enabled: true + # Цвет упоминания + color: "#FFD700" + # Звук при упоминании + sound: + enabled: true + type: "BLOCK_NOTE_BLOCK_PLING" + volume: 1.0 + pitch: 2.0 + # ┌─────────────────────────────────────────────────────────────────────────────┐ # │ ФОРМАТЫ ПО ГРУППАМ │ # └─────────────────────────────────────────────────────────────────────────────┘ @@ -89,49 +145,42 @@ groups: priority: 1000 prefix: "&#FF0000[OWNER]" suffix: "" - format: "{prefix} {display_name}&r: {message}" name-color: "&#FF0000" admin: priority: 900 prefix: "&#FF6B6B[ADMIN]" suffix: "" - format: "{prefix} {display_name}&r: {message}" name-color: "&#FF6B6B" moderator: priority: 800 prefix: "&#FFA726[MOD]" suffix: "" - format: "{prefix} {display_name}&r: {message}" name-color: "&#FFA726" helper: priority: 700 prefix: "WCEEB[HELPER]" suffix: "" - format: "{prefix} {display_name}&r: {message}" name-color: "WCEEB" vip: priority: 600 prefix: "&#FFD700[VIP]" suffix: "" - format: "{prefix} {display_name}&r: {message}" name-color: "&#FFD700" premium: priority: 500 prefix: "BCB77[PREMIUM]" suffix: "" - format: "{prefix} {display_name}&r: {message}" name-color: "BCB77" default: priority: 0 prefix: "" suffix: "" - format: "{display_name}&r: {message}" name-color: "&#FFFFFF" # ┌─────────────────────────────────────────────────────────────────────────────┐ @@ -151,14 +200,9 @@ special: volume: 1.0 pitch: 1.0 - # Формат для эмодзи голов - head-emoji: - format: ":head_{player}:" - max-per-message: 3 - # Формат для ссылок url: - format: "Открыть ссылку'>{url}" + format: "🔗 Открыть ссылку'><#00BFFF>{url}" # ┌─────────────────────────────────────────────────────────────────────────────┐ # │ НАСТРОЙКИ ОТОБРАЖЕНИЯ │ @@ -183,33 +227,4 @@ display: word-wrap: true # Цвет сообщений по умолчанию - default-message-color: "&#FFFFFF" - -# ┌─────────────────────────────────────────────────────────────────────────────┐ -# │ ИНТЕГРАЦИИ │ -# └─────────────────────────────────────────────────────────────────────────────┘ - -integrations: - # PlaceholderAPI - placeholderapi: - enabled: true - - # LuckPerms - luckperms: - enabled: true - use-prefix: true - use-suffix: true - - # Vault - vault: - enabled: true - - # DiscordSRV - discordsrv: - enabled: false - format: "**{player}**: {message}" - - # Dynmap - dynmap: - enabled: false - format: "{player}: {message}" \ No newline at end of file + default-message-color: "&#FFFFFF" \ No newline at end of file