This commit is contained in:
loki5512344 2026-03-11 14:35:00 +01:00
parent 5ece2192a2
commit 6b6605a2b0
6 changed files with 212 additions and 160 deletions

View file

@ -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));

View file

@ -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 {

View file

@ -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);

View file

@ -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<String> hoverLines = plugin.getConfig().getStringList("chat.hover.format");
if (hoverLines.isEmpty()) {
hoverLines = java.util.Arrays.asList(
"<gray>Игрок: <white>{player}",
"<gray>Мир: <green>{world}",
"<gradient:#FFD700:#FFA500><bold>▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬</bold></gradient>",
"<gradient:#87CEEB:#4169E1><bold>👤 Информация об игроке</bold></gradient>",
"",
"<yellow>▶ Клик: написать ЛС"
"<gray>🏷️ Имя: <white><bold>{player}</bold>",
"<gray>📶 Пинг: <yellow><bold>{ping}ms</bold>",
"<gray>❤️ Здоровье: <red><bold>{health}/20</bold>",
"<gray>🍖 Голод: <gold><bold>{food}/20</bold>",
"",
"<gradient:#FFD700:#FFA500><bold>▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬</bold></gradient>",
"<yellow>💬 <bold>Клик:</bold> <gray>написать личное сообщение"
);
}
@ -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;
}
}