fix command and refactoring config

This commit is contained in:
loki5512344 2026-03-10 16:58:10 +01:00
parent b922f588d0
commit fe64b3d51f
109 changed files with 4103 additions and 5403 deletions

View file

@ -59,6 +59,7 @@ public final class LoChat extends JavaPlugin {
// Команды и слушатели
registerCommands();
registerListeners();
registerPluginChannels();
// Автосообщения
autoMessageManager.start();
@ -108,9 +109,11 @@ public final class LoChat extends JavaPlugin {
getCommand("reply").setExecutor(new ReplyCommand(this));
getCommand("ignore").setExecutor(new IgnoreCommand(this));
getCommand("unignore").setExecutor(new UnignoreCommand(this));
getCommand("ignorelist").setExecutor(new IgnoreListCommand(this));
getCommand("announce").setExecutor(new AnnounceCommand(this));
getCommand("chatspy").setExecutor(new ChatSpyCommand(this));
getCommand("clearchat").setExecutor(new ClearChatCommand(this));
getCommand("hub").setExecutor(new HubCommand(this));
NickCommand nickCmd = new NickCommand(this);
getCommand("nick").setExecutor(nickCmd);
@ -149,6 +152,11 @@ public final class LoChat extends JavaPlugin {
getLogger().info("Слушатели зарегистрированы (новая архитектура)");
}
private void registerPluginChannels() {
getServer().getMessenger().registerOutgoingPluginChannel(this, "BungeeCord");
getLogger().info("BungeeCord plugin messaging channel registered");
}
public void reload() {
configManager.reload();
messageConfig.reload();

View file

@ -0,0 +1,107 @@
package com.loki.lochat.commands;
import com.loki.lochat.LoChat;
import com.loki.lochat.commands.custom.*;
import org.bukkit.command.CommandExecutor;
import java.util.HashMap;
import java.util.Map;
/**
* Менеджер кастомных команд
*/
public class CustomCommandManager {
private final LoChat plugin;
private final Map<String, CommandExecutor> commands;
public CustomCommandManager(LoChat plugin) {
this.plugin = plugin;
this.commands = new HashMap<>();
registerCommands();
}
/**
* Регистрирует все кастомные команды
*/
private void registerCommands() {
// Информационные команды
commands.put("help", new HelpCommand(plugin));
commands.put("rules", new RulesCommand(plugin));
commands.put("discord", new DiscordCommand(plugin));
// Утилиты
commands.put("coords", new CoordsCommand(plugin));
commands.put("ping", new PingCommand(plugin));
commands.put("stats", new StatsCommand(plugin));
// Чат команды
commands.put("me", new MeCommand(plugin));
commands.put("sounds", new SoundsCommand(plugin));
// TODO: Добавить остальные команды
// commands.put("website", new WebsiteCommand(plugin));
// commands.put("time", new TimeCommand(plugin));
// commands.put("list", new ListCommand(plugin));
// commands.put("top", new TopCommand(plugin));
// commands.put("afk", new AfkCommand(plugin));
// commands.put("back", new BackCommand(plugin));
// commands.put("broadcast", new BroadcastCommand(plugin));
// commands.put("maintenance", new MaintenanceCommand(plugin));
// commands.put("motd", new MotdCommand(plugin));
// commands.put("tps", new TpsCommand(plugin));
// commands.put("memory", new MemoryCommand(plugin));
// commands.put("version", new VersionCommand(plugin));
// commands.put("reload", new ReloadCommand(plugin));
// commands.put("automessage", new AutoMessageCommand(plugin));
}
/**
* Регистрирует команды в Bukkit
*/
public void registerBukkitCommands() {
for (Map.Entry<String, CommandExecutor> entry : commands.entrySet()) {
String commandName = entry.getKey();
CommandExecutor executor = entry.getValue();
if (plugin.getCommand(commandName) != null) {
plugin.getCommand(commandName).setExecutor(executor);
plugin.getLogger().info("Зарегистрирована кастомная команда: /" + commandName);
} else {
plugin.getLogger().warning("Не удалось зарегистрировать команду: /" + commandName +
" (не найдена в plugin.yml)");
}
}
}
/**
* Получить исполнителя команды
*/
public CommandExecutor getCommandExecutor(String command) {
return commands.get(command.toLowerCase());
}
/**
* Проверить, является ли команда кастомной
*/
public boolean isCustomCommand(String command) {
return commands.containsKey(command.toLowerCase());
}
/**
* Получить все зарегистрированные команды
*/
public Map<String, CommandExecutor> getCommands() {
return new HashMap<>(commands);
}
/**
* Перезагрузить команды
*/
public void reload() {
commands.clear();
registerCommands();
registerBukkitCommands();
plugin.getLogger().info("Кастомные команды перезагружены!");
}
}

View file

@ -0,0 +1,52 @@
package com.loki.lochat.commands;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
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.entity.Player;
public class HubCommand implements CommandExecutor {
private final LoChat plugin;
public HubCommand(LoChat plugin) {
this.plugin = plugin;
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (!(sender instanceof Player player)) {
sender.sendMessage(ChatFormatter.parse(plugin.getMessageConfig().get("general.players-only")));
return true;
}
// Check if hub command is enabled
if (!plugin.getConfigManager().getBoolean("hub_command.enabled", true)) {
player.sendMessage(ChatFormatter.parse(plugin.getMessageConfig().get("general.command-disabled")));
return true;
}
String hubServer = plugin.getConfigManager().getString("hub_command.server", "hub");
// Send player to hub server via BungeeCord
sendToServer(player, hubServer);
String message = plugin.getMessageConfig().get("hub.connecting")
.replace("%server%", hubServer);
player.sendMessage(ChatFormatter.parse(message));
return true;
}
private void sendToServer(Player player, String server) {
ByteArrayDataOutput out = ByteStreams.newDataOutput();
out.writeUTF("Connect");
out.writeUTF(server);
player.sendPluginMessage(plugin, "BungeeCord", out.toByteArray());
}
}

View file

@ -0,0 +1,60 @@
package com.loki.lochat.commands;
import com.loki.lochat.LoChat;
import com.loki.lochat.api.service.IgnoreService;
import com.loki.lochat.utils.ChatFormatter;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.Set;
import java.util.UUID;
/**
* Команда /ignorelist - показывает список игнорируемых игроков
*/
public class IgnoreListCommand implements CommandExecutor {
private final LoChat plugin;
private final IgnoreService ignoreService;
public IgnoreListCommand(LoChat plugin) {
this.plugin = plugin;
this.ignoreService = plugin.getServiceRegistry().get(IgnoreService.class);
}
@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;
}
Set<UUID> ignoredPlayers = ignoreService.getIgnoredPlayers(player.getUniqueId());
if (ignoredPlayers.isEmpty()) {
player.sendMessage(ChatFormatter.parse(plugin.getMessageConfig().get("ignore.list-empty")));
return true;
}
player.sendMessage(ChatFormatter.parse(plugin.getMessageConfig().get("ignore.list-header")));
for (UUID ignoredUuid : ignoredPlayers) {
String playerName = com.loki.lochat.utils.PlayerUtil.getPlayerName(ignoredUuid);
if (playerName != null) {
player.sendMessage(ChatFormatter.parse("&#87CEEB• &#FFFFFF" + playerName));
}
}
player.sendMessage(ChatFormatter.parse(
plugin.getMessageConfig().get("ignore.list-footer")
.replace("{count}", String.valueOf(ignoredPlayers.size()))
));
return true;
}
}

View file

@ -0,0 +1,45 @@
package com.loki.lochat.commands.custom;
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.entity.Player;
import org.jetbrains.annotations.NotNull;
/**
* Команда координат игрока
*/
public class CoordsCommand implements CommandExecutor {
private final LoChat plugin;
public CoordsCommand(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(ChatFormatter.parse("<red>Эта команда только для игроков!</red>"));
return true;
}
int x = (int) player.getLocation().getX();
int y = (int) player.getLocation().getY();
int z = (int) player.getLocation().getZ();
String world = player.getWorld().getName();
String message = String.format("""
<gradient:#FFA726:#FF9800>Ваши координаты:</gradient>
<gradient:#87CEEB:#4682B4>X:</gradient> <white>%d</white>
<gradient:#87CEEB:#4682B4>Y:</gradient> <white>%d</white>
<gradient:#87CEEB:#4682B4>Z:</gradient> <white>%d</white>
<gradient:#87CEEB:#4682B4>Мир:</gradient> <white>%s</white>
""", x, y, z, world);
player.sendMessage(ChatFormatter.parse(message));
return true;
}
}

View file

@ -0,0 +1,41 @@
package com.loki.lochat.commands.custom;
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.jetbrains.annotations.NotNull;
/**
* Команда Discord сервера
*/
public class DiscordCommand implements CommandExecutor {
private final LoChat plugin;
public DiscordCommand(LoChat plugin) {
this.plugin = plugin;
}
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
String discordLink = plugin.getConfig().getString("discord.invite-link", "discord.gg/example");
String message = String.format("""
<gradient:#7289DA:#5865F2>═══════ Наш Discord ═══════</gradient>
<gray>Присоединяйтесь к нашему сообществу!</gray>
<click:open_url:'https://%s'><gradient:#87CEEB:#4682B4>🔗 %s</gradient></click>
<gray>В Discord вы можете:</gray>
<white>•</white> <gray>Общаться с игроками</gray>
<white>•</white> <gray>Получать новости сервера</gray>
<white>•</white> <gray>Участвовать в событиях</gray>
<white>•</white> <gray>Получать поддержку</gray>
""", discordLink, discordLink);
sender.sendMessage(ChatFormatter.parse(message));
return true;
}
}

View file

@ -0,0 +1,44 @@
package com.loki.lochat.commands.custom;
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.entity.Player;
import org.jetbrains.annotations.NotNull;
/**
* Команда помощи сервера
*/
public class HelpCommand implements CommandExecutor {
private final LoChat plugin;
public HelpCommand(LoChat plugin) {
this.plugin = plugin;
}
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
String message = """
<gradient:#FFD700:#FFA500>═══════ Помощь по серверу ═══════</gradient>
<gradient:#87CEEB:#4682B4>/rules</gradient> <gray>- правила сервера</gray>
<gradient:#87CEEB:#4682B4>/discord</gradient> <gray>- наш Discord</gray>
<gradient:#87CEEB:#4682B4>/website</gradient> <gray>- официальный сайт</gray>
<gradient:#87CEEB:#4682B4>/coords</gradient> <gray>- ваши координаты</gray>
<gradient:#87CEEB:#4682B4>/time</gradient> <gray>- время на сервере</gray>
<gradient:#87CEEB:#4682B4>/ping</gradient> <gray>- ваш пинг</gray>
<gradient:#87CEEB:#4682B4>/list</gradient> <gray>- список игроков</gray>
<gradient:#87CEEB:#4682B4>/me <действие></gradient> <gray>- действие от третьего лица</gray>
<gradient:#87CEEB:#4682B4>/msg <игрок> <сообщение></gradient> <gray>- личное сообщение</gray>
<gradient:#87CEEB:#4682B4>/reply <сообщение></gradient> <gray>- ответить на ЛС</gray>
<gradient:#87CEEB:#4682B4>/ignore <игрок></gradient> <gray>- игнорировать игрока</gray>
<gradient:#87CEEB:#4682B4>/color <цвета></gradient> <gray>- градиентный ник</gray>
<gradient:#87CEEB:#4682B4>/prefix <текст></gradient> <gray>- кастомный префикс</gray>
""";
sender.sendMessage(ChatFormatter.parse(message));
return true;
}
}

View file

@ -0,0 +1,75 @@
package com.loki.lochat.commands.custom;
import com.loki.lochat.LoChat;
import com.loki.lochat.utils.ChatFormatter;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
/**
* Команда действия от третьего лица
*/
public class MeCommand implements CommandExecutor {
private final LoChat plugin;
public MeCommand(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(ChatFormatter.parse("<red>Эта команда только для игроков!</red>"));
return true;
}
if (!player.hasPermission("chat.me")) {
player.sendMessage(ChatFormatter.parse("<red>У вас нет прав для использования этой команды!</red>"));
return true;
}
if (args.length == 0) {
player.sendMessage(ChatFormatter.parse("<red>Использование: /me <действие></red>"));
return true;
}
// Проверяем мут
if (plugin.getMuteService() != null && plugin.getMuteService().isMuted(player.getUniqueId())) {
String muteMessage = plugin.getMessagesConfig().getString("mute.you-muted",
"<red>Вы замучены!</red>");
player.sendMessage(ChatFormatter.parse(muteMessage));
return true;
}
// Собираем действие из аргументов
String action = String.join(" ", args);
// Получаем отображаемое имя игрока (с градиентом если есть)
String displayName = player.getDisplayName();
if (plugin.getGradientModule() != null) {
displayName = plugin.getGradientModule().getFormattedName(player);
}
// Форматируем сообщение действия
String message = String.format("<gray>* %s %s</gray>", displayName, action);
// Отправляем всем игрокам в радиусе (как локальный чат)
int radius = plugin.getConfig().getInt("chat.local.radius", 100);
for (Player onlinePlayer : Bukkit.getOnlinePlayers()) {
if (onlinePlayer.getWorld().equals(player.getWorld()) &&
onlinePlayer.getLocation().distance(player.getLocation()) <= radius) {
onlinePlayer.sendMessage(ChatFormatter.parse(message));
}
}
// Логируем действие
plugin.getLogger().info(String.format("[ME] %s: %s", player.getName(), action));
return true;
}
}

View file

@ -0,0 +1,74 @@
package com.loki.lochat.commands.custom;
import com.loki.lochat.LoChat;
import com.loki.lochat.utils.ChatFormatter;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
/**
* Команда пинга игрока
*/
public class PingCommand implements CommandExecutor {
private final LoChat plugin;
public PingCommand(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(ChatFormatter.parse("<red>Эта команда только для игроков!</red>"));
return true;
}
// Если указан аргумент - показать пинг другого игрока
if (args.length > 0) {
if (!player.hasPermission("lochat.ping.others")) {
player.sendMessage(ChatFormatter.parse("<red>У вас нет прав для просмотра пинга других игроков!</red>"));
return true;
}
Player target = Bukkit.getPlayer(args[0]);
if (target == null || !target.isOnline()) {
player.sendMessage(ChatFormatter.parse("<red>Игрок не найден или не в сети!</red>"));
return true;
}
int ping = target.getPing();
String color = getPingColor(ping);
String message = String.format(
"<gradient:#87CEEB:#4682B4>Пинг игрока %s:</gradient> <%s>%dмс</%s>",
target.getName(), color, ping, color
);
player.sendMessage(ChatFormatter.parse(message));
} else {
// Показать свой пинг
int ping = player.getPing();
String color = getPingColor(ping);
String message = String.format(
"<gradient:#87CEEB:#4682B4>Ваш пинг:</gradient> <%s>%dмс</%s>",
color, ping, color
);
player.sendMessage(ChatFormatter.parse(message));
}
return true;
}
private String getPingColor(int ping) {
if (ping < 50) return "green";
if (ping < 100) return "yellow";
if (ping < 200) return "gold";
return "red";
}
}

View file

@ -0,0 +1,41 @@
package com.loki.lochat.commands.custom;
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.jetbrains.annotations.NotNull;
/**
* Команда правил сервера
*/
public class RulesCommand implements CommandExecutor {
private final LoChat plugin;
public RulesCommand(LoChat plugin) {
this.plugin = plugin;
}
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
String message = """
<gradient:#FF6B6B:#FF4757>═══════ Правила сервера ═══════</gradient>
<white>1.</white> <gray>Не используйте читы и моды</gray>
<white>2.</white> <gray>Уважайте других игроков</gray>
<white>3.</white> <gray>Не спамьте в чате</gray>
<white>4.</white> <gray>Не стройте рядом с чужими постройками</gray>
<white>5.</white> <gray>Не используйте мат и оскорбления</gray>
<white>6.</white> <gray>Не рекламируйте другие серверы</gray>
<white>7.</white> <gray>Слушайтесь администрацию</gray>
<white>8.</white> <gray>Не злоупотребляйте багами</gray>
<gradient:#FFA726:#FF9800>Нарушение правил карается мутом или баном!</gradient>
<gradient:#87CEEB:#4682B4>За помощью обращайтесь к администрации</gradient>
""";
sender.sendMessage(ChatFormatter.parse(message));
return true;
}
}

View file

@ -0,0 +1,79 @@
package com.loki.lochat.commands.custom;
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.entity.Player;
import org.jetbrains.annotations.NotNull;
/**
* Команда управления звуками
*/
public class SoundsCommand implements CommandExecutor {
private final LoChat plugin;
public SoundsCommand(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(ChatFormatter.parse("<red>Эта команда только для игроков!</red>"));
return true;
}
String playerUUID = player.getUniqueId().toString();
boolean currentState = plugin.getPlayerData().getBoolean("players." + playerUUID + ".settings.sounds-enabled", true);
if (args.length == 0) {
// Показать текущее состояние
String status = currentState ? "<green>включены</green>" : "<red>отключены</red>";
String message = String.format(
"<gradient:#87CEEB:#4682B4>Звуки сейчас %s</gradient>\n" +
"<gray>Используйте /sounds on или /sounds off для изменения</gray>",
status
);
player.sendMessage(ChatFormatter.parse(message));
return true;
}
String action = args[0].toLowerCase();
boolean newState;
switch (action) {
case "on", "включить", "вкл" -> {
newState = true;
player.sendMessage(ChatFormatter.parse("<green>Звуки включены!</green>"));
}
case "off", "отключить", "выкл" -> {
newState = false;
player.sendMessage(ChatFormatter.parse("<red>Звуки отключены!</red>"));
}
case "toggle", "переключить" -> {
newState = !currentState;
String status = newState ? "<green>включены</green>" : "<red>отключены</red>";
player.sendMessage(ChatFormatter.parse(String.format("Звуки %s!", status)));
}
default -> {
player.sendMessage(ChatFormatter.parse("""
<red>Неверное использование!</red>
<gray>Доступные команды:</gray>
<white>/sounds on</white> <gray>- включить звуки</gray>
<white>/sounds off</white> <gray>- отключить звуки</gray>
<white>/sounds toggle</white> <gray>- переключить</gray>
"""));
return true;
}
}
// Сохраняем настройку
plugin.getPlayerData().set("players." + playerUUID + ".settings.sounds-enabled", newState);
plugin.savePlayerData();
return true;
}
}

View file

@ -0,0 +1,114 @@
package com.loki.lochat.commands.custom;
import com.loki.lochat.LoChat;
import com.loki.lochat.utils.ChatFormatter;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
/**
* Команда статистики чата
*/
public class StatsCommand implements CommandExecutor {
private final LoChat plugin;
public StatsCommand(LoChat plugin) {
this.plugin = plugin;
}
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (!sender.hasPermission("lochat.stats")) {
sender.sendMessage(ChatFormatter.parse("<red>У вас нет прав для просмотра статистики!</red>"));
return true;
}
if (args.length > 0) {
// Статистика конкретного игрока
Player target = Bukkit.getPlayer(args[0]);
if (target == null) {
sender.sendMessage(ChatFormatter.parse("<red>Игрок не найден!</red>"));
return true;
}
showPlayerStats(sender, target);
} else {
// Общая статистика сервера
showServerStats(sender);
}
return true;
}
private void showPlayerStats(CommandSender sender, Player target) {
// Получаем статистику игрока из конфига или базы данных
int messagesSent = plugin.getPlayerData().getInt("players." + target.getUniqueId() + ".messages-sent", 0);
int commandsUsed = plugin.getPlayerData().getInt("players." + target.getUniqueId() + ".commands-used", 0);
long playtime = plugin.getPlayerData().getLong("players." + target.getUniqueId() + ".total-playtime", 0);
String playtimeFormatted = formatTime(playtime);
String message = String.format("""
<gradient:#FFD700:#FFA500>═══ Статистика игрока %s ═══</gradient>
<gradient:#87CEEB:#4682B4>Сообщений отправлено:</gradient> <white>%d</white>
<gradient:#87CEEB:#4682B4>Команд использовано:</gradient> <white>%d</white>
<gradient:#87CEEB:#4682B4>Время в игре:</gradient> <white>%s</white>
<gradient:#87CEEB:#4682B4>Статус:</gradient> <green>В сети</green>
<gradient:#87CEEB:#4682B4>Пинг:</gradient> <yellow>%dмс</yellow>
""", target.getName(), messagesSent, commandsUsed, playtimeFormatted, target.getPing());
sender.sendMessage(ChatFormatter.parse(message));
}
private void showServerStats(CommandSender sender) {
// Получаем общую статистику сервера
int totalMessages = plugin.getStatisticsData().getInt("global.total-messages", 0);
int messagesToday = plugin.getStatisticsData().getInt("global.messages-today", 0);
int onlinePlayers = Bukkit.getOnlinePlayers().size();
int maxPlayers = Bukkit.getMaxPlayers();
String message = String.format("""
<gradient:#FFD700:#FFA500>═══ Статистика сервера ═══</gradient>
<gradient:#87CEEB:#4682B4>Всего сообщений:</gradient> <white>%d</white>
<gradient:#87CEEB:#4682B4>Сообщений сегодня:</gradient> <white>%d</white>
<gradient:#87CEEB:#4682B4>Игроков онлайн:</gradient> <white>%d/%d</white>
<gradient:#87CEEB:#4682B4>Активных мутов:</gradient> <white>%d</white>
<gradient:#87CEEB:#4682B4>TPS:</gradient> <green>%.1f</green>
""", totalMessages, messagesToday, onlinePlayers, maxPlayers,
getActiveMutesCount(), getCurrentTPS());
sender.sendMessage(ChatFormatter.parse(message));
}
private String formatTime(long milliseconds) {
long seconds = milliseconds / 1000;
long minutes = seconds / 60;
long hours = minutes / 60;
long days = hours / 24;
if (days > 0) {
return String.format("%dд %dч %dм", days, hours % 24, minutes % 60);
} else if (hours > 0) {
return String.format("%dч %dм", hours, minutes % 60);
} else {
return String.format("%dм", minutes);
}
}
private int getActiveMutesCount() {
return plugin.getMuteData().getConfigurationSection("active-mutes") != null ?
plugin.getMuteData().getConfigurationSection("active-mutes").getKeys(false).size() : 0;
}
private double getCurrentTPS() {
try {
return Bukkit.getTPS()[0];
} catch (Exception e) {
return 20.0;
}
}
}

View file

@ -22,25 +22,69 @@ public class AdvancedMessageFilter {
"(.)\\1{3,}"
);
// Паттерн для скрытых ссылок (h t t p, w w w и т.д.)
private static final Pattern HIDDEN_URL_PATTERN = Pattern.compile(
"(?i)(h\\s*t\\s*t\\s*p|w\\s*w\\s*w|d\\s*o\\s*t\\s*c\\s*o\\s*m)",
Pattern.CASE_INSENSITIVE
);
// Паттерн для доменов без http
private static final Pattern DOMAIN_PATTERN = Pattern.compile(
"\\b([a-zA-Z0-9-]+\\.(com|net|org|ru|gg|me|io|xyz|tk|ml|ga|cf|gq))\\b",
Pattern.CASE_INSENSITIVE
);
private final FileConfiguration config;
private final List<String> whitelistedDomains;
private final List<String> blacklistedDomains;
private final CapsFilter capsFilter;
public AdvancedMessageFilter(FileConfiguration config) {
this.config = config;
this.whitelistedDomains = config.getStringList("filters.url.whitelist");
this.blacklistedDomains = config.getStringList("filters.url.blacklist");
this.whitelistedDomains = config.getStringList("filters.advertising.whitelist");
this.blacklistedDomains = config.getStringList("filters.advertising.blacklist");
// Инициализация капс фильтра
int maxCapsPercent = config.getInt("filters.caps.max-percent", 70);
int minLength = config.getInt("filters.caps.min-length", 5);
boolean autoLowercase = config.getBoolean("filters.caps.auto-lowercase", true);
boolean blockMessage = config.getBoolean("filters.caps.block", false);
this.capsFilter = new CapsFilter(maxCapsPercent, minLength, autoLowercase, blockMessage);
}
public FilterResult filterMessage(Player player, String message) {
if (config.getBoolean("filters.url.enabled", true)) {
// Капс фильтр
if (config.getBoolean("filters.caps.enabled", true)) {
String filtered = capsFilter.filter(player, message);
if (filtered == null) {
return new FilterResult(false, message, "&#FF6B6BНе кричите в чате!");
}
message = filtered;
}
// Анти-реклама (объединенная проверка)
if (config.getBoolean("filters.advertising.enabled", true)) {
// URL фильтр
FilterResult urlResult = filterUrls(player, message);
if (!urlResult.allowed()) {
return urlResult;
}
message = urlResult.filteredMessage();
// Скрытые ссылки
FilterResult hiddenResult = filterHiddenUrls(player, message);
if (!hiddenResult.allowed()) {
return hiddenResult;
}
// Домены без http
FilterResult domainResult = filterDomains(player, message);
if (!domainResult.allowed()) {
return domainResult;
}
}
// IP фильтр
if (config.getBoolean("filters.ip.enabled", true)) {
FilterResult ipResult = filterIPs(player, message);
if (!ipResult.allowed()) {
@ -49,6 +93,7 @@ public class AdvancedMessageFilter {
message = ipResult.filteredMessage();
}
// Повторяющиеся символы
if (config.getBoolean("filters.repeat.enabled", true)) {
message = filterRepeatingChars(message);
}
@ -138,6 +183,70 @@ public class AdvancedMessageFilter {
return url;
}
/**
* Фильтрует скрытые ссылки (h t t p, w w w и т.д.)
*/
private FilterResult filterHiddenUrls(Player player, String message) {
if (!config.getBoolean("filters.advertising.block-hidden-urls", true)) {
return new FilterResult(true, message, null);
}
if (player.hasPermission("lochat.bypass.hiddenurls")) {
return new FilterResult(true, message, null);
}
Matcher matcher = HIDDEN_URL_PATTERN.matcher(message);
if (matcher.find()) {
return new FilterResult(false, message,
config.getString("filters.advertising.blocked-message", "&#FF6B6BРеклама запрещена!"));
}
return new FilterResult(true, message, null);
}
/**
* Фильтрует домены без http (example.com, discord.gg и т.д.)
*/
private FilterResult filterDomains(Player player, String message) {
if (!config.getBoolean("filters.advertising.block-domains", true)) {
return new FilterResult(true, message, null);
}
if (player.hasPermission("lochat.bypass.domains")) {
return new FilterResult(true, message, null);
}
Matcher matcher = DOMAIN_PATTERN.matcher(message);
while (matcher.find()) {
String domain = matcher.group();
// Проверяем whitelist
if (!whitelistedDomains.isEmpty()) {
boolean isWhitelisted = whitelistedDomains.stream()
.anyMatch(d -> domain.toLowerCase().contains(d.toLowerCase()));
if (!isWhitelisted) {
return new FilterResult(false, message,
config.getString("filters.advertising.blocked-message", "&#FF6B6BРеклама запрещена!"));
}
}
// Проверяем blacklist
if (!blacklistedDomains.isEmpty()) {
boolean isBlacklisted = blacklistedDomains.stream()
.anyMatch(d -> domain.toLowerCase().contains(d.toLowerCase()));
if (isBlacklisted) {
return new FilterResult(false, message,
config.getString("filters.advertising.blocked-message", "&#FF6B6BРеклама запрещена!"));
}
}
}
return new FilterResult(true, message, null);
}
public record FilterResult(boolean allowed, String filteredMessage, String blockReason) {
}
}

View file

@ -0,0 +1,83 @@
package com.loki.lochat.core.filter;
import org.bukkit.entity.Player;
/**
* Фильтр капса (заглавных букв)
*/
public class CapsFilter {
private final int maxCapsPercent;
private final int minLength;
private final boolean autoLowercase;
private final boolean blockMessage;
public CapsFilter(int maxCapsPercent, int minLength, boolean autoLowercase, boolean blockMessage) {
this.maxCapsPercent = maxCapsPercent;
this.minLength = minLength;
this.autoLowercase = autoLowercase;
this.blockMessage = blockMessage;
}
/**
* Проверяет и обрабатывает сообщение с капсом
*
* @return обработанное сообщение или null если заблокировано
*/
public String filter(Player player, String message) {
// Bypass для админов
if (player.hasPermission("lochat.bypass.caps")) {
return message;
}
// Игнорируем короткие сообщения
if (message.length() < minLength) {
return message;
}
// Подсчитываем процент заглавных букв
int totalLetters = 0;
int capsLetters = 0;
for (char c : message.toCharArray()) {
if (Character.isLetter(c)) {
totalLetters++;
if (Character.isUpperCase(c)) {
capsLetters++;
}
}
}
// Если букв мало, пропускаем
if (totalLetters < 3) {
return message;
}
int capsPercent = (capsLetters * 100) / totalLetters;
// Если капса больше лимита
if (capsPercent > maxCapsPercent) {
if (blockMessage) {
return null; // Блокируем сообщение
} else if (autoLowercase) {
// Понижаем регистр (первая буква заглавная)
return capitalizeFirst(message.toLowerCase());
}
}
return message;
}
/**
* Делает первую букву заглавной
*/
private String capitalizeFirst(String text) {
if (text == null || text.isEmpty()) {
return text;
}
return Character.toUpperCase(text.charAt(0)) + text.substring(1);
}
public int getMaxCapsPercent() {
return maxCapsPercent;
}
}

View file

@ -32,20 +32,40 @@ public class MuteServiceImpl implements MuteService {
@Override
public void mute(UUID uuid, String playerName, long duration, String reason, String mutedBy) {
if (uuid == null) {
plugin.getLogger().warning("Attempted to mute player with null UUID");
return;
}
if (playerName == null || playerName.isEmpty()) {
plugin.getLogger().warning("Attempted to mute player with null or empty name");
return;
}
long endTime = duration > 0 ? System.currentTimeMillis() + duration : 0;
MuteData data = new MuteData(uuid, playerName, endTime, reason, mutedBy);
mutes.put(uuid, data);
historyManager.addEntry(uuid, playerName, duration, reason, mutedBy);
saveAsync();
plugin.getLogger().info("Player " + playerName + " muted by " + mutedBy +
" for " + (duration > 0 ? formatTime(duration) : "permanent") +
(reason != null ? " (reason: " + reason + ")" : ""));
}
@Override
public boolean unmute(UUID uuid, String unmutedBy) {
if (uuid == null) {
plugin.getLogger().warning("Attempted to unmute player with null UUID");
return false;
}
MuteData removed = mutes.remove(uuid);
if (removed != null) {
historyManager.updateUnmute(uuid, unmutedBy);
saveAsync();
plugin.getLogger().info("Player " + removed.getPlayerName() + " unmuted by " + unmutedBy);
return true;
}
return false;
@ -53,6 +73,10 @@ public class MuteServiceImpl implements MuteService {
@Override
public boolean isMuted(UUID uuid) {
if (uuid == null) {
return false;
}
MuteData data = mutes.get(uuid);
if (data == null) {
return false;
@ -61,6 +85,7 @@ public class MuteServiceImpl implements MuteService {
if (isExpired(data)) {
mutes.remove(uuid);
saveAsync();
plugin.getLogger().info("Mute expired for player " + data.getPlayerName());
return false;
}
return true;

View file

@ -19,9 +19,9 @@ public class ChatMessage {
}
public static ChatMessage create(Player sender, String rawMessage) {
// Определяем тип чата
boolean isGlobal = rawMessage.startsWith("!") &&
sender.hasPermission("chat.global.use");
// С "!" = глобальный чат
// Без "!" = локальный чат
boolean isGlobal = rawMessage.startsWith("!");
String content = isGlobal ?
rawMessage.substring(1).trim() :

View file

@ -28,100 +28,88 @@ public class GradientConfig {
}
private void loadConfig() {
configFile = new File(plugin.getDataFolder(), "gradient-config.yml");
if (!configFile.exists()) {
plugin.saveResource("gradient-config.yml", false);
}
config = YamlConfiguration.loadConfiguration(configFile);
// Загружаем дефолты
InputStream defStream = plugin.getResource("gradient-config.yml");
if (defStream != null) {
YamlConfiguration defConfig = YamlConfiguration.loadConfiguration(
new InputStreamReader(defStream, StandardCharsets.UTF_8));
config.setDefaults(defConfig);
}
// Читаем из главного config.yml вместо отдельного файла
config = plugin.getConfig();
plugin.getLogger().info("Gradient конфиг загружен из config.yml");
}
public void reload() {
plugin.reloadConfig();
this.mainConfig = plugin.getConfig();
loadConfig();
this.config = plugin.getConfig();
}
public void save() {
try {
config.save(configFile);
} catch (IOException e) {
plugin.getLogger().warning("Ошибка сохранения gradient-config.yml: " + e.getMessage());
}
// Сохранение не требуется, используем главный конфиг
plugin.saveConfig();
}
public boolean isEnabled() {
return config.getBoolean("enabled", true);
return config.getBoolean("gradient.enabled", true);
}
public int getMaxColors() {
return config.getInt("max-colors", 7);
return config.getInt("gradient.max-colors", 7);
}
public int getMinColors() {
return config.getInt("min-colors", 1);
return config.getInt("gradient.min-colors", 1);
}
public int getPricePerColor() {
return config.getInt("price-per-color", 50);
return config.getInt("gradient.price-per-color", 50);
}
public int getPrefixPrice() {
return config.getInt("prefix-price", 500);
return config.getInt("gradient.prefix-price", 500);
}
public boolean isPrefixOneTimePurchase() {
return config.getBoolean("prefix-one-time-purchase", true);
return config.getBoolean("gradient.prefix-one-time-purchase", true);
}
public int getColorCooldown() {
return config.getInt("color-cooldown", 60);
return config.getInt("gradient.color-cooldown", 60);
}
public int getPrefixCooldown() {
return config.getInt("prefix-cooldown", 300);
return config.getInt("gradient.prefix-cooldown", 120);
}
public int getMaxPrefixLength() {
return config.getInt("max-prefix-length", 7);
return config.getInt("gradient.max-prefix-length", 16);
}
public String getPrefixFormat() {
return config.getString("prefix-format", "[{prefix}] ");
return config.getString("gradient.prefix-format", "[{prefix}] ");
}
public boolean isGradientOnPrefix() {
return config.getBoolean("gradient-on-prefix", true);
return config.getBoolean("gradient.gradient-on-prefix", true);
}
public boolean isGradientOnLuckPermsPrefix() {
return config.getBoolean("gradient-on-luckperms-prefix", true);
return config.getBoolean("gradient.gradient-on-luckperms-prefix", true);
}
public boolean isContinuousGradient() {
return config.getBoolean("continuous-gradient", true);
return config.getBoolean("gradient.continuous-gradient", true);
}
public boolean isUseLegacyRgbFormat() {
return config.getBoolean("use-legacy-rgb-format", true);
return config.getBoolean("gradient.use-legacy-rgb-format", true);
}
public String getStorageType() {
return config.getString("storage-type", "YAML");
return config.getString("gradient.storage-type", "file");
}
public String getSqliteFile() {
return config.getString("sqlite-file", "gradient-data.db");
return config.getString("gradient.sqlite-file", "gradient-data.db");
}
public List<String> getPrefixBlacklist() {
return config.getStringList("prefix-blacklist");
return config.getStringList("gradient.prefix-blacklist");
}
public boolean isPrefixBlacklisted(String prefix) {

View file

@ -27,13 +27,13 @@ public class GradientMessages {
}
private void loadMessages() {
messagesFile = new File(plugin.getDataFolder(), "gradient-messages.yml");
messagesFile = new File(plugin.getDataFolder(), "messages.yml");
if (!messagesFile.exists()) {
plugin.saveResource("gradient-messages.yml", false);
plugin.saveResource("messages.yml", false);
}
messages = YamlConfiguration.loadConfiguration(messagesFile);
InputStream defStream = plugin.getResource("gradient-messages.yml");
InputStream defStream = plugin.getResource("messages.yml");
if (defStream != null) {
YamlConfiguration defConfig = YamlConfiguration.loadConfiguration(
new InputStreamReader(defStream, StandardCharsets.UTF_8));
@ -49,7 +49,7 @@ public class GradientMessages {
* Получает сообщение как строку с MiniMessage тегами
*/
public String get(String key) {
String message = messages.getString(key, "&#FF0000Сообщение не найдено: " + key);
String message = messages.getString("gradient." + key, "&#FF0000Сообщение не найдено: " + key);
return ChatFormatter.convertAllColors(message);
}
@ -57,7 +57,7 @@ public class GradientMessages {
* Получает сообщение как строку с заменами
*/
public String get(String key, String... replacements) {
String message = messages.getString(key, "&#FF0000Сообщение не найдено: " + key);
String message = messages.getString("gradient." + key, "&#FF0000Сообщение не найдено: " + key);
for (int i = 0; i < replacements.length; i += 2) {
if (i + 1 < replacements.length) {
message = message.replace("{" + replacements[i] + "}", replacements[i + 1]);

View file

@ -54,23 +54,44 @@ public class ChatEventListener implements Listener {
}
String filteredMessage = filterResult.filteredMessage();
event.message(Component.text(filteredMessage));
// Определяем тип чата
boolean isGlobal = message.startsWith("!");
event.message(com.loki.lochat.utils.ChatFormatter.parse(filteredMessage));
event.renderer(new EnhancedChatRenderer(sender, event.message()));
event.renderer(new EnhancedChatRenderer(sender, event.message(), isGlobal));
}
private class EnhancedChatRenderer implements ChatRenderer {
private final Player sender;
private final Component originalMessage;
private final boolean isGlobal;
public EnhancedChatRenderer(Player sender, Component originalMessage) {
public EnhancedChatRenderer(Player sender, Component originalMessage, boolean isGlobal) {
this.sender = sender;
this.originalMessage = originalMessage;
this.isGlobal = isGlobal;
}
@Override
public Component render(Player source, Component sourceDisplayName, Component message, Audience viewer) {
String prefix = plugin.getConfig().getString("chat.global.prefix", "[G]");
// Префикс в зависимости от типа чата
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));
} 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));
}
Component playerComponent = createPlayerComponent(source, sourceDisplayName);
Component processedMessage = message;
@ -82,9 +103,10 @@ public class ChatEventListener implements Listener {
processedMessage = mentionHandler.processMentions(processedMessage, source, viewerPlayer);
}
return Component.text(prefix + " ")
return prefixComponent
.append(Component.text(" "))
.append(playerComponent)
.append(Component.text(": "))
.append(Component.text(": ").color(net.kyori.adventure.text.format.NamedTextColor.GRAY))
.append(processedMessage);
}
@ -129,7 +151,8 @@ public class ChatEventListener implements Listener {
private Component processUrls(Component message) {
String plainText = PlainTextComponentSerializer.plainText().serialize(message);
String urlPattern = "(https?://[\\w\\-._~:/?#\\[\\]@!35538117-c5a8-4bfe-b9f2-b0dcf9374222'()*+,;=%]+)";
// Fixed regex: escape the dash in character class to avoid illegal range
String urlPattern = "(https?://[\\w\\-._~:/?#\\[\\]@!$&'()*+,;=%]+)";
java.util.regex.Pattern pattern = java.util.regex.Pattern.compile(urlPattern);
java.util.regex.Matcher matcher = pattern.matcher(plainText);

View file

@ -31,20 +31,15 @@ public class AutoMessageManager {
}
private void loadMessages() {
File file = new File(plugin.getDataFolder(), "automessages.yml");
if (!file.exists()) {
plugin.saveResource("automessages.yml", false);
}
FileConfiguration config = YamlConfiguration.loadConfiguration(file);
FileConfiguration config = plugin.getConfig();
// Настройки
prefix = config.getString("settings.prefix", "&6[&eINFO&6]&r");
mode = config.getString("settings.mode", "sequential").toLowerCase();
prefix = plugin.getConfigManager().getString("prefix", "&#00D4FF[LoChat]");
mode = "sequential"; // Всегда последовательно
// Загружаем сообщения
// Загружаем сообщения из config.yml
messages = new LinkedHashMap<>();
ConfigurationSection msgSection = config.getConfigurationSection("messages");
ConfigurationSection msgSection = config.getConfigurationSection("automessages-list");
if (msgSection != null) {
for (String key : msgSection.getKeys(false)) {
@ -65,32 +60,7 @@ public class AutoMessageManager {
}
}
// Определяем порядок
messageOrder = new ArrayList<>();
if (mode.equals("custom")) {
String orderStr = config.getString("settings.order", "");
for (String item : orderStr.split(",")) {
String trimmed = item.trim();
if (!trimmed.isEmpty()) {
try {
int index = Integer.parseInt(trimmed) - 1;
List<String> keys = new ArrayList<>(messages.keySet());
if (index >= 0 && index < keys.size()) {
messageOrder.add(keys.get(index));
}
} catch (NumberFormatException e) {
if (messages.containsKey(trimmed)) {
messageOrder.add(trimmed);
}
}
}
}
}
if (messageOrder.isEmpty()) {
messageOrder.addAll(messages.keySet());
}
messageOrder = new ArrayList<>(messages.keySet());
plugin.getLogger().info("Загружено " + messages.size() + " автосообщений");
}

View file

@ -1,51 +0,0 @@
package com.loki.lochat.util;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.bukkit.command.CommandSender;
/**
* Утилита для форматирования сообщений
*/
public class ChatFormatter {
private static final MiniMessage MINI_MESSAGE = MiniMessage.miniMessage();
private static final LegacyComponentSerializer LEGACY = LegacyComponentSerializer.legacyAmpersand();
public static Object parse(String message) {
try {
return MINI_MESSAGE.deserialize(message);
} catch (Exception e) {
return LEGACY.deserialize(message);
}
}
public static String toPlain(Object message) {
if (message instanceof Component component) {
return LegacyComponentSerializer.legacySection().serialize(component);
}
return message.toString();
}
public static void sendMessage(CommandSender sender, Object message) {
if (message instanceof Component component) {
sender.sendMessage(component);
} else {
sender.sendMessage(message.toString());
}
}
public static void broadcast(Object message) {
if (message instanceof Component component) {
org.bukkit.Bukkit.broadcast(component);
}
}
public static String stripTags(String message) {
return message.replaceAll("<[^>]+>", "").replaceAll("§[0-9a-fk-or]", "");
}
public static String convertAllColors(String message) {
return message.replace("&", "§");
}
}

View file

@ -40,24 +40,24 @@ public final class ChatFormatter {
private static String convertLegacyFormats(String message) {
if (message == null) return "";
// Конвертируем &#RRGGBB в <#RRGGBB>
// Конвертируем &#RRGGBB в <color:#RRGGBB>
java.util.regex.Pattern pattern1 = java.util.regex.Pattern.compile("&#([0-9a-fA-F]{6})");
java.util.regex.Matcher matcher1 = pattern1.matcher(message);
StringBuffer sb1 = new StringBuffer();
while (matcher1.find()) {
String hex = matcher1.group(1).toLowerCase();
matcher1.appendReplacement(sb1, "<#" + hex + ">");
matcher1.appendReplacement(sb1, "<color:#" + hex + ">");
}
matcher1.appendTail(sb1);
message = sb1.toString();
// Конвертируем #RRGGBB в <#RRGGBB> (только если не внутри тегов)
// Конвертируем #RRGGBB в <color:#RRGGBB> (только если не внутри тегов)
java.util.regex.Pattern pattern2 = java.util.regex.Pattern.compile("(?<!<)#([0-9a-fA-F]{6})(?![^<]*>)");
java.util.regex.Matcher matcher2 = pattern2.matcher(message);
StringBuffer sb2 = new StringBuffer();
while (matcher2.find()) {
String hex = matcher2.group(1).toLowerCase();
matcher2.appendReplacement(sb2, "<#" + hex + ">");
matcher2.appendReplacement(sb2, "<color:#" + hex + ">");
}
matcher2.appendTail(sb2);
message = sb2.toString();

View file

@ -17,20 +17,32 @@ public final class PlayerUtil {
/**
* Safely parses a sound name from config.
* Uses deprecated Sound.valueOf() for backward compatibility with string-based config values.
* Uses Registry API for modern sound parsing with fallback to reflection.
*
* @param soundName the sound name to parse
* @param defaultSound the default sound to return if parsing fails
* @return the parsed Sound or the default if invalid
*/
@SuppressWarnings("deprecation")
public static Sound parseSound(String soundName, Sound defaultSound) {
if (soundName == null || soundName.isEmpty()) {
return defaultSound;
}
try {
return Sound.valueOf(soundName.toUpperCase());
} catch (IllegalArgumentException e) {
// Try to get sound by key using Registry (modern way)
Sound sound = org.bukkit.Registry.SOUNDS.match(soundName);
if (sound != null) {
return sound;
}
} catch (Exception e) {
// Registry failed, try fallback
}
// Fallback: try direct field access via reflection
try {
java.lang.reflect.Field field = Sound.class.getField(soundName.toUpperCase().trim());
return (Sound) field.get(null);
} catch (Exception ex) {
return defaultSound;
}
}

View file

@ -6,9 +6,13 @@ public final class TimeFormatter {
}
public static String format(long millis) {
if (millis <= 0) {
if (millis < 0) {
return "0с";
}
if (millis == 0) {
return "навсегда";
}
long seconds = millis / 1000;
long minutes = seconds / 60;
@ -16,18 +20,21 @@ public final class TimeFormatter {
long days = hours / 24;
if (days > 0) {
return days + "д " + (hours % 24) + "ч";
long remainingHours = hours % 24;
return remainingHours > 0 ? days + "д " + remainingHours + "ч" : days + "д";
} else if (hours > 0) {
return hours + "ч " + (minutes % 60) + "м";
long remainingMinutes = minutes % 60;
return remainingMinutes > 0 ? hours + "ч " + remainingMinutes + "м" : hours + "ч";
} else if (minutes > 0) {
return minutes + "м " + (seconds % 60) + "с";
long remainingSeconds = seconds % 60;
return remainingSeconds > 0 ? minutes + "м " + remainingSeconds + "с" : minutes + "м";
} else {
return seconds + "с";
}
}
public static long parse(String timeStr) {
if (timeStr == null || timeStr.isEmpty()) {
if (timeStr == null || timeStr.trim().isEmpty()) {
return 0;
}
@ -38,8 +45,12 @@ public final class TimeFormatter {
if (Character.isDigit(c)) {
number.append(c);
} else if (number.length() > 0) {
long value = Long.parseLong(number.toString());
totalMillis += getMillisForUnit(c, value);
try {
long value = Long.parseLong(number.toString());
totalMillis += getMillisForUnit(c, value);
} catch (NumberFormatException e) {
// Skip invalid numbers
}
number.setLength(0);
}
}

View file

@ -1,90 +0,0 @@
# ╔══════════════════════════════════════════════════════════════════════════════╗
# ║ LoChat Auto Messages ║
# ║ Автосообщения чата ║
# ║ Версия: 1.5.5-1.20.1 ║
# ╚══════════════════════════════════════════════════════════════════════════════╝
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ НАСТРОЙКИ │
# └─────────────────────────────────────────────────────────────────────────────┘
settings:
# Префикс автосообщений
prefix: "&#00D4FF[&#00D4FFI&#00CAF7N&#00C0EEF&#00B7E6O&#0099CC]"
# Режим отправки: sequential (по порядку), random (случайно), custom (свой порядок)
mode: "sequential"
# Свой порядок сообщений (только для режима custom)
# Можно указывать номера или названия сообщений
order: "welcome, rules, discord, website"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ СООБЩЕНИЯ │
# └─────────────────────────────────────────────────────────────────────────────┘
messages:
# Приветственное сообщение
welcome:
- "<gradient:#FFD700:#FFA500>Добро пожаловать на наш сервер!</gradient>"
- "<gray>Используйте</gray> <gradient:#87CEEB:#4682B4>/help</gradient> <gray>для получения помощи</gray>"
# Правила сервера
rules:
- "<gradient:#FF6B6B:#FF4757>Соблюдайте правила сервера!</gradient>"
- "<gray>Подробнее:</gray> <gradient:#87CEEB:#4682B4>/rules</gradient>"
# Информация о Discord
discord:
- "<gradient:#7289DA:#5865F2>Присоединяйтесь к нашему Discord!</gradient>"
- "<gray>Ссылка:</gray> <click:open_url:'https://discord.gg/example'><gradient:#87CEEB:#4682B4>discord.gg/example</gradient></click>"
# Веб-сайт
website:
- "<gradient:#00FF88:#00CC66>Посетите наш сайт!</gradient>"
- "<gray>Адрес:</gray> <click:open_url:'https://example.com'><gradient:#87CEEB:#4682B4>example.com</gradient></click>"
# Донат информация
donate:
- "<gradient:#FFD700:#FFA500>Поддержите сервер!</gradient>"
- "<gray>Донат:</gray> <click:open_url:'https://donate.example.com'><gradient:#87CEEB:#4682B4>donate.example.com</gradient></click>"
# Градиентные ники
gradients:
- "<gradient:#9370DB:#8A2BE2>Создайте красивый ник!</gradient>"
- "<gray>Команда:</gray> <gradient:#87CEEB:#4682B4>/color</gradient> <gray>для градиентов</gray>"
# Чат команды
chat-commands:
- "<gradient:#FFA726:#FF9800>Полезные команды чата:</gradient>"
- "<gradient:#87CEEB:#4682B4>/msg <игрок> <сообщение></gradient> <gray>- личное сообщение</gray>"
- "<gradient:#87CEEB:#4682B4>/ignore <игрок></gradient> <gray>- игнорировать игрока</gray>"
# Онлайн статистика
online-stats:
- "<gradient:#6BCB77:#4ECDC4>Сейчас онлайн: {online} игроков</gradient>"
- "<gray>Максимум за день:</gray> <white>{max_online}</white>"
# Время на сервере
server-time:
- "<gradient:#87CEEB:#4682B4>Время на сервере:</gradient> <white>{time}</white>"
- "<gray>Дата:</gray> <white>{date}</white>"
# События
events:
- "<gradient:#FF69B4:#FF1493>Следите за событиями!</gradient>"
- "<gray>Расписание:</gray> <gradient:#87CEEB:#4682B4>/events</gradient>"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ПЛЕЙСХОЛДЕРЫ │
# └─────────────────────────────────────────────────────────────────────────────┘
# Доступные плейсхолдеры в сообщениях:
# {online} - количество игроков онлайн
# {max_online} - максимальное количество игроков (из server.properties)
# {time} - текущее время
# {date} - текущая дата
# {server_name} - название сервера
# {tps} - TPS сервера (если доступно)
#
# Также поддерживаются все плейсхолдеры PlaceholderAPI

View file

@ -1,3 +0,0 @@
formats:
global: "<gray>[G]</gray> {prefix}{name}<gray>:</gray> <white>{message}"
local: "{prefix}{name}<gray>:</gray> <white>{message}"

View file

@ -1,75 +1,122 @@
# ╔══════════════════════════════════════════════════════════════════════════════╗
# ║ LoChat Configuration ║
# ║ Продвинутый чат-плагин для Paper ║
# ║ Версия: 1.5.5-1.20.1 ║
# ║ Автор: loki ║
# ╚══════════════════════════════════════════════════════════════════════════════╝
config-version: 3
config-version: 4
prefix: "&#00D4FF[LoChat]"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ОСНОВНЫЕ НАСТРОЙКИ │
# │ ДОПОЛНИТЕЛЬНЫЕ КОНФИГИ │
# └─────────────────────────────────────────────────────────────────────────────┘
# Префикс плагина в сообщениях
prefix: "&#00D4FF[&#00D4FFL&#00CAF7o&#00C0EEC&#00B7E6h&#00ADDDa&#00A3D5t&#0099CC]"
# Загружать дополнительные конфигурационные файлы
load-additional-configs: true
# Список дополнительных конфигов для загрузки
additional-configs:
- "config/chat-formats.yml" # Форматы чата и сообщений
- "config/filters.yml" # Настройки фильтров
- "config/gradient-config.yml" # Конфигурация градиентов
- "config/automessages.yml" # Автосообщения
- "config/mute-config.yml" # Система мутов
- "config/sounds.yml" # Звуковые эффекты
- "config/database.yml" # База данных
- "config/integrations.yml" # Интеграции с другими плагинами
- "config/custom-commands.yml" # Кастомные команды
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ СТРУКТУРА ДАННЫХ │
# └─────────────────────────────────────────────────────────────────────────────┘
# Настройки хранения данных
data-storage:
# Основная папка для данных
data-folder: "data/"
# Использовать отдельные файлы для разных типов данных
separate-files: true
# Файлы данных
files:
main: "data.yml" # Основные данные (если separate-files: false)
players: "players.yml" # Данные игроков
gradients: "gradients.yml" # Градиентные ники
mutes: "mutes.yml" # Муты и история
ignores: "ignores.yml" # Игнорирование
statistics: "statistics.yml" # Статистика
filter-words: "filter-words.json" # Запрещенные слова
# Автосохранение (секунды)
auto-save-interval: 300
# Создавать резервные копии
backup:
enabled: true
interval: 3600 # Каждый час
max-backups: 24
folder: "backups/"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ HUB COMMAND │
# └─────────────────────────────────────────────────────────────────────────────┘
hub_command:
# Enable/disable /hub command
enabled: true
# Target server name for /hub command
# Sends player to this server via BungeeCord
server: "hub"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ КАСТОМНЫЕ КОМАНДЫ │
# └─────────────────────────────────────────────────────────────────────────────┘
custom-commands:
# Включить кастомные команды
enabled: true
# Настройки Discord команды
discord:
invite-link: "discord.gg/example"
# Настройки Website команды
website:
url: "https://example.com"
# Настройки координат
coords:
# Показывать координаты в actionbar
show-in-actionbar: true
# Время показа в actionbar (тики)
actionbar-duration: 60
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ НАСТРОЙКИ ЧАТА │
# └─────────────────────────────────────────────────────────────────────────────┘
chat:
# ═══════════════════════════════════════════════════════════════════════════
# ГЛОБАЛЬНЫЙ ЧАТ
# ═══════════════════════════════════════════════════════════════════════════
global:
# Включить глобальный чат
enabled: true
# Символ для отправки в глобальный чат
symbol: "!"
# Кулдаун между сообщениями (секунды)
cooldown: 3
# Префикс глобального чата
prefix: "&#FFD700[G]"
format: "{prefix} &#00FF88{player}&#555555: {message}"
# ═══════════════════════════════════════════════════════════════════════════
# ЛОКАЛЬНЫЙ ЧАТ
# ═══════════════════════════════════════════════════════════════════════════
local:
# Включить локальный чат
enabled: true
# Радиус локального чата (блоки)
radius: 100
# Кулдаун между сообщениями (секунды)
cooldown: 1
# Префикс локального чата
prefix: "&#87CEEB[L]"
format: "{prefix} &#00FF88{player}&#555555: {message}"
# ═══════════════════════════════════════════════════════════════════════════
# ЛИЧНЫЕ СООБЩЕНИЯ
# ═══════════════════════════════════════════════════════════════════════════
pm:
# Включить личные сообщения
enabled: true
# Кулдаун между PM (секунды)
cooldown: 2
# Логировать PM в консоль
log: false
# Звук при получении PM
sound: true
sound-type: "BLOCK_NOTE_BLOCK_PLING"
# ═══════════════════════════════════════════════════════════════════════════
# HOVER TOOLTIP (наведение на ник)
# ═══════════════════════════════════════════════════════════════════════════
log: false
hover:
# Включить hover tooltip при наведении на ник
enabled: true
# Формат tooltip (список строк)
# Плейсхолдеры: {player}, {world}, {ping}, {gamemode}, {health}, {food}
# Поддержка PlaceholderAPI: %placeholder%
format:
- "<gray>Игрок: <white>{player}"
- "<gray>Мир: <green>{world}"
@ -81,87 +128,54 @@ chat:
# │ ГРАДИЕНТНЫЕ НИКИ │
# └─────────────────────────────────────────────────────────────────────────────┘
# Интеграция с градиентным модулем (встроенный LoPreff)
lopreff:
# Включить градиентные ники
enabled: true
# Использовать градиентный ник в чате
use-gradient-name: true
# Использовать кастомный префикс
use-custom-prefix: true
# Настройки отображения ника
display:
# Обновлять display name игрока (показывает префикс+ник над головой)
update-display-name: true
# Обновлять tab list
update-tab-list: true
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ УПОМИНАНИЯ │
# │ ДОПОЛНИТЕЛЬНЫЕ ФУНКЦИИ │
# └─────────────────────────────────────────────────────────────────────────────┘
mentions:
# Включить систему упоминаний (@nickname)
enabled: true
# Воспроизводить звук при упоминании
sound: true
# Тип звука
sound-type: "BLOCK_NOTE_BLOCK_PLING"
# Подсветка упоминания в чате
highlight: "&#FFFF00@{player}"
self-highlight: "&#FFD700{player}"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ АВТОСООБЩЕНИЯ │
# └─────────────────────────────────────────────────────────────────────────────┘
everyone:
enabled: true
permission: "lochat.mention.everyone"
here:
enabled: true
permission: "lochat.mention.here"
role:
enabled: true
permission: "lochat.mention.role"
automessages:
# Включить автосообщения
enabled: true
# Интервал между сообщениями (секунды)
interval: 300
# Случайный порядок сообщений
random: false
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ОБЪЯВЛЕНИЯ │
# └─────────────────────────────────────────────────────────────────────────────┘
announcements:
# Показывать title при объявлении
show-title: true
# Заголовок title
title-header: "&#FF6B6BОБЪЯВЛЕНИЕ"
# Показывать actionbar при объявлении
show-actionbar: true
# Время показа title (в секундах)
title-duration: 3
# Формат объявления
formats:
announcement: "&#FF6B6B[ОБЪЯВЛЕНИЕ] <message>"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ОЧИСТКА ЧАТА │
# └─────────────────────────────────────────────────────────────────────────────┘
clearchat:
message:
# Показывать сообщение после очистки чата
enabled: true
# Текст сообщения ({player} - имя администратора)
text: "&#FF6B6BЧат очищен администратором {player}"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ГОЛОВЫ ИГРОКОВ │
# └─────────────────────────────────────────────────────────────────────────────┘
head-emoji:
# Включить функцию голов игроков
enabled: true
# Разрешить использование @head команд
allow-player-heads: true
# Максимальное количество голов в одном сообщении
max-heads-per-message: 3
# ┌─────────────────────────────────────────────────────────────────────────────┐
@ -169,29 +183,8 @@ head-emoji:
# └─────────────────────────────────────────────────────────────────────────────┘
mute:
# Сообщения с плейсхолдерами:
# %duration% - время мута
# %reason% - причина
# %player% - замученный игрок
# %operator% - модератор
messages:
muted: "&#FF6B6B%player% &#888888был замучен на &#FF6B6B%duration% &#888888модератором &#FF6B6B%operator%&#888888. Причина: &#FF6B6B%reason%"
unmuted: "&#6BCB77%player% &#888888был размучен модератором &#6BCB77%operator%"
you-muted: "&#FF6B6BВы замучены на %duration%! Причина: %reason%"
you-muted-permanent: "&#FF6B6BВы замучены навсегда! Причина: %reason%"
cannot-chat: "&#FF6B6BВы замучены! Осталось: %duration%"
cannot-chat-permanent: "&#FF6B6BВы замучены навсегда!"
silent-muted: "&#888888[Тихо] &#FF6B6B%player% &#888888замучен на &#FF6B6B%duration% &#888888(%operator%). Причина: %reason%"
silent-unmuted: "&#888888[Тихо] &#6BCB77%player% &#888888размучен (%operator%)"
# Причина по умолчанию если не указана
default-reason: "Нарушение правил"
# Максимальное время мута по умолчанию (если не указано время)
default-duration: "7d"
# Доступные длительности для прав lochat.mute.dur.<время>
durations:
- "10m"
- "30m"
@ -210,8 +203,16 @@ mute:
# └─────────────────────────────────────────────────────────────────────────────┘
filters:
url:
caps:
enabled: true
max-percent: 70
min-length: 5
auto-lowercase: true
advertising:
enabled: true
block-hidden-urls: true
block-domains: true
whitelist:
- "youtube.com"
- "youtu.be"
@ -219,30 +220,59 @@ filters:
- "twitch.tv"
blacklist:
- "scam-site.com"
blocked-message: "&#FF6B6BС&#FF5F5Fс&#FF5353ы&#FF4747л&#FF3B3Bк&#FF2F2Fи &#FF2323з&#FF1717а&#FF0B0Bп&#FF0000р&#FF0000е&#FF0000щ&#FF0000е&#FF0000н&#FF0000ы!"
ip:
enabled: true
block: false
replacement: "[IP скрыт]"
blocked-message: "&#FF6B6BI&#FF5F5FP &#FF5353а&#FF4747д&#FF3B3Bр&#FF2F2Fе&#FF2323с&#FF1717а &#FF0B0Bз&#FF0000а&#FF0000п&#FF0000р&#FF0000е&#FF0000щ&#FF0000е&#FF0000н&#FF0000ы!"
repeat:
enabled: true
max-repeats: 3
# Форматы (не трогать)
formats:
announcement: "&#FF6B6B[ОБЪЯВЛЕНИЕ] <message>"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ УПОМИНАНИЯ │
# │ НАСТРОЙКИ ГРАДИЕНТОВ │
# └─────────────────────────────────────────────────────────────────────────────┘
advanced-mentions:
enabled: true
everyone:
enabled: true
permission: "lochat.mention.everyone"
here:
enabled: true
permission: "lochat.mention.here"
role:
enabled: true
permission: "lochat.mention.role"
gradient:
storage-type: "file"
min-colors: 1
max-colors: 7
price-per-color: 50
prefix-price: 500
prefix-one-time-purchase: true
max-prefix-length: 16
color-cooldown: 60
prefix-cooldown: 120
presets:
fire: [ "#FF4500", "#FF6347", "#FFD700" ]
ocean: [ "#00CED1", "#1E90FF", "#4169E1" ]
forest: [ "#228B22", "#32CD32", "#90EE90" ]
sunset: [ "#FF69B4", "#FF1493", "#DC143C" ]
rainbow: [ "#FF0000", "#FF7F00", "#FFFF00", "#00FF00", "#0000FF", "#4B0082", "#9400D3" ]
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ АВТОСООБЩЕНИЯ │
# └─────────────────────────────────────────────────────────────────────────────┘
automessages-list:
welcome:
- "&#FFD700Добро пожаловать на наш сервер!"
- "&#87CEEBИспользуйте /help для получения помощи"
rules:
- "&#FF6B6BСоблюдайте правила сервера!"
- "&#87CEEBПодробнее: /rules"
discord:
- "&#7289DAПрисоединяйтесь к нашему Discord!"
- "&#87CEEBСсылка: discord.gg/example"
website:
- "&#00FF88Посетите наш сайт!"
- "&#87CEEBАдрес: example.com"

View file

@ -0,0 +1,255 @@
# ╔══════════════════════════════════════════════════════════════════════════════╗
# ║ LoChat Auto Messages ║
# ║ Автосообщения ║
# ║ Версия: 1.5.5-1.20.1 ║
# ╚══════════════════════════════════════════════════════════════════════════════╝
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ОСНОВНЫЕ НАСТРОЙКИ │
# └─────────────────────────────────────────────────────────────────────────────┘
settings:
# Включить автосообщения
enabled: true
# Интервал между сообщениями (секунды)
interval: 300
# Случайный порядок сообщений
random: true
# Минимальное количество игроков для отправки
min-players: 1
# Префикс для автосообщений
prefix: "&#00D4FF[Авто]"
# Отправлять в определенные миры
worlds:
- "world"
- "world_nether"
- "world_the_end"
# Тип отправки: chat, actionbar, title, bossbar
type: "chat"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ СООБЩЕНИЯ │
# └─────────────────────────────────────────────────────────────────────────────┘
messages:
welcome:
enabled: true
weight: 10 # Вес для случайного выбора (больше = чаще)
permission: "" # Пустое = для всех
worlds: [] # Пустое = во всех мирах
content:
- "&#FFD700Добро пожаловать на наш сервер!"
- "&#87CEEBИспользуйте /help для получения помощи"
- "&#6BCB77Приятной игры!"
rules:
enabled: true
weight: 8
permission: ""
worlds: []
content:
- "&#FF6B6BСоблюдайте правила сервера!"
- "&#87CEEBПодробнее: /rules"
- "&#FFA726Нарушения караются мутом или баном"
discord:
enabled: true
weight: 7
permission: ""
worlds: []
content:
- "&#7289DAПрисоединяйтесь к нашему Discord!"
- "&#87CEEBСсылка: discord.gg/example"
- "&#6BCB77Общайтесь с игроками вне игры!"
website:
enabled: true
weight: 6
permission: ""
worlds: []
content:
- "&#00FF88Посетите наш сайт!"
- "&#87CEEBАдрес: example.com"
- "&#6BCB77Карта сервера, статистика и многое другое!"
donate:
enabled: true
weight: 5
permission: ""
worlds: []
content:
- "&#FFD700Поддержите сервер донатом!"
- "&#87CEEBПолучите VIP статус и привилегии"
- "&#6BCB77Подробнее: /donate"
tips:
enabled: true
weight: 9
permission: ""
worlds: []
content:
- "&#87CEEB💡 Совет: Используйте /coords для просмотра координат"
- "&#87CEEB💡 Совет: /ignore <игрок> - игнорировать игрока"
- "&#87CEEB💡 Совет: /msg <игрок> <сообщение> - личное сообщение"
- "&#87CEEB💡 Совет: /reply <сообщение> - ответить на ЛС"
- "&#87CEEB💡 Совет: /color <цвет> - изменить цвет ника"
events:
enabled: false
weight: 3
permission: ""
worlds: []
content:
- "&#FF69B4🎉 Скоро событие на сервере!"
- "&#87CEEBСледите за новостями в Discord"
- "&#6BCB77Участвуйте и получайте призы!"
economy:
enabled: false
weight: 4
permission: ""
worlds: []
content:
- "&#FFD700💰 Зарабатывайте деньги на сервере!"
- "&#87CEEBПродавайте ресурсы в магазине"
- "&#6BCB77Команды: /shop, /sell, /balance"
pvp:
enabled: false
weight: 2
permission: ""
worlds: ["world_pvp"]
content:
- "&#FF6B6B⚔️ Вы в PvP зоне!"
- "&#FFA726Будьте осторожны с другими игроками"
- "&#87CEEBИспользуйте /spawn для выхода"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ СПЕЦИАЛЬНЫЕ СООБЩЕНИЯ │
# └─────────────────────────────────────────────────────────────────────────────┘
special:
# Сообщения для новичков (первый вход)
newbie:
enabled: true
delay: 30 # Задержка после входа (секунды)
content:
- "&#6BCB77Добро пожаловать на сервер, {player}!"
- "&#87CEEBЭто ваш первый визит. Изучите /help"
- "&#FFD700Желаем приятной игры!"
# Сообщения при входе
join:
enabled: false
delay: 5
content:
- "&#6BCB77С возвращением, {player}!"
- "&#87CEEBНе забудьте проверить новости: /news"
# Сообщения при достижениях
achievement:
enabled: false
content:
- "&#FFD700🏆 Поздравляем с достижением!"
- "&#87CEEBПродолжайте исследовать мир"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ НАСТРОЙКИ ОТОБРАЖЕНИЯ │
# └─────────────────────────────────────────────────────────────────────────────┘
display:
# Настройки для title сообщений
title:
fade-in: 10
stay: 40
fade-out: 10
title: "&#FFD700Информация"
subtitle: "{message}"
# Настройки для actionbar сообщений
actionbar:
duration: 60 # Время показа (тики)
# Настройки для bossbar сообщений
bossbar:
color: "BLUE" # BLUE, GREEN, PINK, PURPLE, RED, WHITE, YELLOW
style: "SOLID" # SOLID, SEGMENTED_6, SEGMENTED_10, SEGMENTED_12, SEGMENTED_20
duration: 100 # Время показа (тики)
# Звуковые эффекты
sound:
enabled: false
type: "BLOCK_NOTE_BLOCK_PLING"
volume: 0.5
pitch: 1.0
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ УСЛОВИЯ ОТПРАВКИ │
# └─────────────────────────────────────────────────────────────────────────────┘
conditions:
# Время суток (24-часовой формат)
time:
enabled: false
start: "09:00"
end: "23:00"
# Дни недели (1-7, где 1 = понедельник)
days:
enabled: false
allowed: [1, 2, 3, 4, 5, 6, 7]
# Исключить игроков в AFK
exclude-afk: false
# Исключить игроков в творческом режиме
exclude-creative: false
# Исключить игроков с определенными правами
exclude-permissions:
- "lochat.automessage.ignore"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ПЕРСОНАЛИЗАЦИЯ │
# └─────────────────────────────────────────────────────────────────────────────┘
personalization:
# Использовать имя игрока в сообщениях
use-player-name: true
# Адаптировать сообщения под группу игрока
group-specific: false
# Сообщения для разных групп
groups:
vip:
prefix: "&#FFD700[VIP Авто]"
messages:
- "&#FFD700Спасибо за поддержку сервера, {player}!"
- "&#87CEEBВы получаете эксклюзивные привилегии"
newbie:
prefix: "&#6BCB77[Помощь]"
messages:
- "&#6BCB77Нужна помощь, {player}? Спросите в чате!"
- "&#87CEEBИспользуйте /help для списка команд"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ СТАТИСТИКА │
# └─────────────────────────────────────────────────────────────────────────────┘
statistics:
# Вести статистику отправленных сообщений
enabled: true
# Файл для сохранения статистики
file: "plugins/LoChat/automessage-stats.yml"
# Сбрасывать статистику каждый месяц
reset-monthly: true

View file

@ -0,0 +1,215 @@
# ╔══════════════════════════════════════════════════════════════════════════════╗
# ║ LoChat Chat Formats ║
# ║ Форматы чата ║
# ║ Версия: 1.5.5-1.20.1 ║
# ╚══════════════════════════════════════════════════════════════════════════════╝
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ФОРМАТЫ ЧАТА │
# └─────────────────────────────────────────────────────────────────────────────┘
# Доступные плейсхолдеры:
# {player} - имя игрока
# {display_name} - отображаемое имя с градиентом
# {prefix} - префикс игрока
# {suffix} - суффикс игрока
# {world} - мир игрока
# {message} - сообщение
# {time} - время
# {date} - дата
# Все плейсхолдеры PlaceholderAPI
formats:
# Глобальный чат
global:
enabled: true
format: "&#FFD700[G] {prefix}{display_name}&r: {message}"
hover:
- "<gray>Игрок: <white>{player}"
- "<gray>Мир: <green>{world}"
- "<gray>Пинг: <yellow>%player_ping%ms"
- ""
- "<yellow>▶ Клик: написать ЛС"
click:
action: "suggest_command"
value: "/msg {player} "
# Локальный чат
local:
enabled: true
format: "&#87CEEB[L] {prefix}{display_name}&r: {message}"
hover:
- "<gray>Игрок: <white>{player}"
- "<gray>Координаты: <yellow>{x}, {y}, {z}"
- "<gray>Расстояние: <green>%distance%м"
- ""
- "<yellow>▶ Клик: написать ЛС"
click:
action: "suggest_command"
value: "/msg {player} "
# Личные сообщения
private:
sent: "&7[→] &#87CEEBВы &7→ {display_name}&7: {message}"
received: "&7[←] {display_name} &7→ &#87CEEBВы&7: {message}"
hover:
- "<gray>Отправлено: <white>%time%"
- ""
- "<yellow>▶ Клик: ответить"
click:
action: "suggest_command"
value: "/reply "
# Объявления
announcement:
format: "&#FF6B6B[ОБЪЯВЛЕНИЕ] <message>"
title:
enabled: true
title: "&#FF6B6BОБЪЯВЛЕНИЕ"
subtitle: "{message}"
fade-in: 10
stay: 60
fade-out: 10
actionbar:
enabled: true
format: "&#FF6B6B[ОБЪЯВЛЕНИЕ] {message}"
# Системные сообщения
system:
join: "&#6BCB77+ {display_name} &#6BCB77присоединился к игре"
quit: "&#FF6B6B- {display_name} &#FF6B6Bпокинул игру"
death: "&#FF6B6B☠ {display_name} &#FF6B6B{death_message}"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ФОРМАТЫ ПО ГРУППАМ │
# └─────────────────────────────────────────────────────────────────────────────┘
groups:
owner:
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: "&#87CEEB[HELPER]"
suffix: ""
format: "{prefix} {display_name}&r: {message}"
name-color: "&#87CEEB"
vip:
priority: 600
prefix: "&#FFD700[VIP]"
suffix: ""
format: "{prefix} {display_name}&r: {message}"
name-color: "&#FFD700"
premium:
priority: 500
prefix: "&#6BCB77[PREMIUM]"
suffix: ""
format: "{prefix} {display_name}&r: {message}"
name-color: "&#6BCB77"
default:
priority: 0
prefix: ""
suffix: ""
format: "{display_name}&r: {message}"
name-color: "&#FFFFFF"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ СПЕЦИАЛЬНЫЕ ФОРМАТЫ │
# └─────────────────────────────────────────────────────────────────────────────┘
special:
# Формат для мутов
mute:
message: "&#FF6B6BВы замучены! Осталось: {time}"
permanent: "&#FF6B6BВы замучены навсегда!"
# Формат для упоминаний
mention:
format: "&#FFFF00@{player}"
sound: "BLOCK_NOTE_BLOCK_PLING"
volume: 1.0
pitch: 1.0
# Формат для эмодзи голов
head-emoji:
format: ":head_{player}:"
max-per-message: 3
# Формат для ссылок
url:
format: "<click:open_url:'{url}'><hover:show_text:'<gray>Открыть ссылку'><u>{url}</u></hover></click>"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ НАСТРОЙКИ ОТОБРАЖЕНИЯ │
# └─────────────────────────────────────────────────────────────────────────────┘
display:
# Максимальная длина сообщения
max-message-length: 256
# Показывать время в чате
show-time: false
time-format: "[HH:mm]"
# Показывать мир в чате
show-world: false
world-format: "[{world}]"
# Компактный режим (убирает лишние пробелы)
compact-mode: false
# Автоматически переносить длинные сообщения
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}"

View file

@ -5,7 +5,41 @@
# ╚══════════════════════════════════════════════════════════════════════════════╝
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ПРИМЕРЫ КОМАНД │
# │ НАСТРОЙКИ КОМАНД │
# └─────────────────────────────────────────────────────────────────────────────┘
settings:
# Включить кастомные команды
enabled: true
# Настройки Discord команды
discord:
invite-link: "discord.gg/example"
# Настройки Website команды
website:
url: "https://example.com"
# Настройки координат
coords:
show-in-actionbar: true
actionbar-duration: 60
# Настройки /me команды
me:
radius: 100 # Радиус для локального действия
# Настройки звуков
sounds:
allow-toggle: true
# Настройки статистики
stats:
show-server-stats: true
show-player-stats: true
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ТЕКСТОВЫЕ КОМАНДЫ │
# └─────────────────────────────────────────────────────────────────────────────┘
# Структура команды:

View file

@ -0,0 +1,346 @@
# ╔══════════════════════════════════════════════════════════════════════════════╗
# ║ LoChat Database Configuration ║
# ║ Конфигурация базы данных ║
# ║ Версия: 1.5.5-1.20.1 ║
# ╚══════════════════════════════════════════════════════════════════════════════╝
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ОСНОВНЫЕ НАСТРОЙКИ │
# └─────────────────────────────────────────────────────────────────────────────┘
settings:
# Тип базы данных: file, sqlite, mysql, postgresql
type: "file"
# Префикс для таблиц
table-prefix: "lochat_"
# Автоматически создавать таблицы
auto-create-tables: true
# Автоматически обновлять структуру таблиц
auto-update-tables: true
# Кодировка для MySQL
charset: "utf8mb4"
# Collation для MySQL
collation: "utf8mb4_unicode_ci"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ФАЙЛОВОЕ ХРАНЕНИЕ │
# └─────────────────────────────────────────────────────────────────────────────┘
file:
# Папка для хранения файлов данных
data-folder: "plugins/LoChat/data/"
# Формат файлов: yaml, json
format: "yaml"
# Автоматическое сохранение (секунды)
auto-save-interval: 300
# Создавать резервные копии
backup:
enabled: true
interval: 3600 # Каждый час
max-backups: 24 # Хранить 24 копии
folder: "plugins/LoChat/backups/"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ SQLITE │
# └─────────────────────────────────────────────────────────────────────────────┘
sqlite:
# Путь к файлу базы данных
file: "plugins/LoChat/database.db"
# Настройки соединения
connection:
# Таймаут соединения (миллисекунды)
timeout: 30000
# Включить WAL режим (Write-Ahead Logging)
wal-mode: true
# Размер кэша (KB)
cache-size: 2000
# Синхронизация: OFF, NORMAL, FULL
synchronous: "NORMAL"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ MYSQL │
# └─────────────────────────────────────────────────────────────────────────────┘
mysql:
# Хост базы данных
host: "localhost"
# Порт базы данных
port: 3306
# Имя базы данных
database: "lochat"
# Имя пользователя
username: "root"
# Пароль
password: "password"
# Дополнительные параметры подключения
properties:
useSSL: false
allowPublicKeyRetrieval: true
serverTimezone: "UTC"
characterEncoding: "utf8"
useUnicode: true
autoReconnect: true
failOverReadOnly: false
maxReconnects: 3
initialTimeout: 1
# Настройки пула соединений (HikariCP)
pool:
# Максимальное количество соединений
maximum-pool-size: 10
# Минимальное количество простаивающих соединений
minimum-idle: 2
# Таймаут получения соединения (миллисекунды)
connection-timeout: 30000
# Время жизни простаивающего соединения (миллисекунды)
idle-timeout: 600000
# Максимальное время жизни соединения (миллисекунды)
max-lifetime: 1800000
# Интервал проверки соединений (миллисекунды)
leak-detection-threshold: 60000
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ POSTGRESQL │
# └─────────────────────────────────────────────────────────────────────────────┘
postgresql:
# Хост базы данных
host: "localhost"
# Порт базы данных
port: 5432
# Имя базы данных
database: "lochat"
# Имя пользователя
username: "postgres"
# Пароль
password: "password"
# Схема базы данных
schema: "public"
# Дополнительные параметры подключения
properties:
ssl: false
sslmode: "disable"
serverTimezone: "UTC"
characterEncoding: "utf8"
autoReconnect: true
# Настройки пула соединений
pool:
maximum-pool-size: 10
minimum-idle: 2
connection-timeout: 30000
idle-timeout: 600000
max-lifetime: 1800000
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ СТРУКТУРА ТАБЛИЦ │
# └─────────────────────────────────────────────────────────────────────────────┘
tables:
# Таблица игроков
players:
name: "players"
columns:
uuid: "VARCHAR(36) PRIMARY KEY"
name: "VARCHAR(16) NOT NULL"
display_name: "TEXT"
first_join: "BIGINT NOT NULL"
last_join: "BIGINT NOT NULL"
last_quit: "BIGINT"
total_playtime: "BIGINT DEFAULT 0"
created_at: "TIMESTAMP DEFAULT CURRENT_TIMESTAMP"
updated_at: "TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP"
# Таблица градиентов
gradients:
name: "gradients"
columns:
uuid: "VARCHAR(36) PRIMARY KEY"
colors: "TEXT"
prefix: "TEXT"
enabled: "BOOLEAN DEFAULT TRUE"
created_at: "TIMESTAMP DEFAULT CURRENT_TIMESTAMP"
updated_at: "TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP"
# Таблица мутов
mutes:
name: "mutes"
columns:
id: "INT AUTO_INCREMENT PRIMARY KEY"
uuid: "VARCHAR(36) NOT NULL"
moderator_uuid: "VARCHAR(36)"
reason: "TEXT NOT NULL"
start_time: "BIGINT NOT NULL"
end_time: "BIGINT"
active: "BOOLEAN DEFAULT TRUE"
silent: "BOOLEAN DEFAULT FALSE"
created_at: "TIMESTAMP DEFAULT CURRENT_TIMESTAMP"
# История мутов
mute_history:
name: "mute_history"
columns:
id: "INT AUTO_INCREMENT PRIMARY KEY"
uuid: "VARCHAR(36) NOT NULL"
moderator_uuid: "VARCHAR(36)"
reason: "TEXT NOT NULL"
duration: "BIGINT NOT NULL"
start_time: "BIGINT NOT NULL"
end_time: "BIGINT"
unmute_reason: "TEXT"
unmute_moderator: "VARCHAR(36)"
created_at: "TIMESTAMP DEFAULT CURRENT_TIMESTAMP"
# Таблица игнорирования
ignores:
name: "ignores"
columns:
id: "INT AUTO_INCREMENT PRIMARY KEY"
player_uuid: "VARCHAR(36) NOT NULL"
ignored_uuid: "VARCHAR(36) NOT NULL"
created_at: "TIMESTAMP DEFAULT CURRENT_TIMESTAMP"
# Таблица сообщений (если включено логирование)
messages:
name: "messages"
columns:
id: "INT AUTO_INCREMENT PRIMARY KEY"
uuid: "VARCHAR(36) NOT NULL"
type: "VARCHAR(20) NOT NULL"
content: "TEXT NOT NULL"
server: "VARCHAR(50)"
world: "VARCHAR(50)"
created_at: "TIMESTAMP DEFAULT CURRENT_TIMESTAMP"
# Настройки игроков
player_settings:
name: "player_settings"
columns:
uuid: "VARCHAR(36) PRIMARY KEY"
sounds_enabled: "BOOLEAN DEFAULT TRUE"
sound_volume: "FLOAT DEFAULT 1.0"
auto_messages: "BOOLEAN DEFAULT TRUE"
mentions_enabled: "BOOLEAN DEFAULT TRUE"
pm_sounds: "BOOLEAN DEFAULT TRUE"
created_at: "TIMESTAMP DEFAULT CURRENT_TIMESTAMP"
updated_at: "TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ИНДЕКСЫ │
# └─────────────────────────────────────────────────────────────────────────────┘
indexes:
# Индексы для оптимизации запросов
players:
- "CREATE INDEX idx_players_name ON {prefix}players(name)"
- "CREATE INDEX idx_players_last_join ON {prefix}players(last_join)"
mutes:
- "CREATE INDEX idx_mutes_uuid ON {prefix}mutes(uuid)"
- "CREATE INDEX idx_mutes_active ON {prefix}mutes(active)"
- "CREATE INDEX idx_mutes_end_time ON {prefix}mutes(end_time)"
mute_history:
- "CREATE INDEX idx_mute_history_uuid ON {prefix}mute_history(uuid)"
- "CREATE INDEX idx_mute_history_moderator ON {prefix}mute_history(moderator_uuid)"
- "CREATE INDEX idx_mute_history_start_time ON {prefix}mute_history(start_time)"
ignores:
- "CREATE INDEX idx_ignores_player ON {prefix}ignores(player_uuid)"
- "CREATE INDEX idx_ignores_ignored ON {prefix}ignores(ignored_uuid)"
- "CREATE UNIQUE INDEX idx_ignores_unique ON {prefix}ignores(player_uuid, ignored_uuid)"
messages:
- "CREATE INDEX idx_messages_uuid ON {prefix}messages(uuid)"
- "CREATE INDEX idx_messages_type ON {prefix}messages(type)"
- "CREATE INDEX idx_messages_created_at ON {prefix}messages(created_at)"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ОЧИСТКА ДАННЫХ │
# └─────────────────────────────────────────────────────────────────────────────┘
cleanup:
# Автоматическая очистка старых данных
enabled: true
# Интервал очистки (секунды)
interval: 86400 # Раз в день
# Настройки очистки для каждой таблицы
tables:
mute_history:
# Удалять записи старше N дней
max-age-days: 90
# Оставлять минимум записей на игрока
min-records-per-player: 5
messages:
max-age-days: 30
# Максимальное количество записей
max-records: 100000
players:
# Удалять неактивных игроков (дни)
inactive-days: 365
# Не удалять игроков с определенными данными
keep-with-data: true
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ МИГРАЦИИ │
# └─────────────────────────────────────────────────────────────────────────────┘
migrations:
# Автоматически выполнять миграции
auto-migrate: true
# Создавать резервные копии перед миграцией
backup-before-migrate: true
# Версия схемы базы данных
schema-version: 1
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ОТЛАДКА │
# └─────────────────────────────────────────────────────────────────────────────┘
debug:
# Логировать SQL запросы
log-queries: false
# Логировать медленные запросы (миллисекунды)
slow-query-threshold: 1000
# Показывать статистику соединений
show-connection-stats: false
# Интервал вывода статистики (секунды)
stats-interval: 300

View file

@ -0,0 +1,286 @@
# ╔══════════════════════════════════════════════════════════════════════════════╗
# ║ LoChat Filters Configuration ║
# ║ Конфигурация фильтров ║
# ║ Версия: 1.5.5-1.20.1 ║
# ╚══════════════════════════════════════════════════════════════════════════════╝
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ФИЛЬТР ЗАГЛАВНЫХ БУКВ │
# └─────────────────────────────────────────────────────────────────────────────┘
caps:
# Включить фильтр заглавных букв
enabled: true
# Максимальный процент заглавных букв (0-100)
max-percent: 70
# Минимальная длина сообщения для проверки
min-length: 5
# Автоматически переводить в нижний регистр
auto-lowercase: true
# Действие при нарушении: block, warn, lowercase
action: "lowercase"
# Сообщение при блокировке
block-message: "&#FF6B6BСлишком много заглавных букв!"
# Сообщение-предупреждение
warn-message: "&#FFA726Не используйте слишком много заглавных букв"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ФИЛЬТР РЕКЛАМЫ │
# └─────────────────────────────────────────────────────────────────────────────┘
advertising:
# Включить фильтр рекламы
enabled: true
# Блокировать скрытые URL (bit.ly, tinyurl и т.д.)
block-hidden-urls: true
# Блокировать домены
block-domains: true
# Блокировать IP адреса
block-ips: true
# Действие при обнаружении: block, warn, replace
action: "block"
# Сообщение при блокировке
block-message: "&#FF6B6BРеклама запрещена!"
# Замена для заблокированного контента
replacement: "[РЕКЛАМА УДАЛЕНА]"
# Белый список доменов (разрешенные)
whitelist:
- "youtube.com"
- "youtu.be"
- "discord.gg"
- "twitch.tv"
- "imgur.com"
- "gyazo.com"
- "prntscr.com"
# Черный список доменов (запрещенные)
blacklist:
- "scam-site.com"
- "virus-site.ru"
- "fake-minecraft.net"
# Регулярные выражения для поиска рекламы
patterns:
- "(?i)\\b(?:[0-9]{1,3}\\.){3}[0-9]{1,3}(?::[0-9]{1,5})?\\b" # IP адреса
- "(?i)\\b[a-z0-9.-]+\\.(com|net|org|ru|de|uk)\\b" # Домены
- "(?i)\\b(server|сервер)\\s*[:-]?\\s*[a-z0-9.-]+\\b" # Серверы
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ФИЛЬТР IP АДРЕСОВ │
# └─────────────────────────────────────────────────────────────────────────────┘
ip:
# Включить фильтр IP адресов
enabled: true
# Блокировать сообщение или заменять IP
block: false
# Замена для IP адресов
replacement: "[IP СКРЫТ]"
# Сообщение при блокировке
block-message: "&#FF6B6BIP адреса запрещены!"
# Белый список IP (разрешенные)
whitelist:
- "127.0.0.1"
- "localhost"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ФИЛЬТР ПОВТОРОВ │
# └─────────────────────────────────────────────────────────────────────────────┘
repeat:
# Включить фильтр повторяющихся символов
enabled: true
# Максимальное количество повторов подряд
max-repeats: 3
# Действие: block, warn, replace
action: "replace"
# Сообщение при блокировке
block-message: "&#FF6B6BНе повторяйте символы!"
# Автоматически сокращать повторы
auto-reduce: true
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ФИЛЬТР СПАМА │
# └─────────────────────────────────────────────────────────────────────────────┘
spam:
# Включить антиспам
enabled: true
# Максимальное количество одинаковых сообщений
max-similar-messages: 3
# Время для сброса счетчика (секунды)
reset-time: 60
# Процент схожести сообщений (0-100)
similarity-threshold: 80
# Действие при спаме: block, warn, mute
action: "warn"
# Сообщение при блокировке
block-message: "&#FF6B6BНе спамьте!"
# Время мута за спам (секунды)
mute-duration: 300
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ФИЛЬТР МАТА │
# └─────────────────────────────────────────────────────────────────────────────┘
swear:
# Включить фильтр мата
enabled: true
# Использовать внешний файл со словами
use-external-file: true
# Файл со словами (относительно папки плагина)
words-file: "filter-words.json"
# Действие: block, warn, replace, mute
action: "replace"
# Символ для замены
replacement-char: "*"
# Сообщение при блокировке
block-message: "&#FF6B6BМат запрещен!"
# Время мута за мат (секунды)
mute-duration: 600
# Встроенный список слов (если не используется внешний файл)
words:
- "плохое_слово1"
- "плохое_слово2"
# Проверять фрагменты слов
check-fragments: true
# Игнорировать регистр
ignore-case: true
# Проверять транслитерацию
check-transliteration: true
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ФИЛЬТР ФЛУДА │
# └─────────────────────────────────────────────────────────────────────────────┘
flood:
# Включить антифлуд
enabled: true
# Максимальное количество сообщений в период
max-messages: 5
# Период времени (секунды)
time-period: 10
# Действие при флуде: block, warn, mute
action: "warn"
# Сообщение при блокировке
block-message: "&#FF6B6BНе флудите!"
# Время мута за флуд (секунды)
mute-duration: 180
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ДОПОЛНИТЕЛЬНЫЕ ФИЛЬТРЫ │
# └─────────────────────────────────────────────────────────────────────────────┘
additional:
# Фильтр эмодзи
emoji:
enabled: false
max-per-message: 5
block-message: "&#FF6B6BСлишком много эмодзи!"
# Фильтр длинных сообщений
length:
enabled: true
max-length: 256
action: "truncate" # truncate или block
block-message: "&#FF6B6BСообщение слишком длинное!"
# Фильтр пустых сообщений
empty:
enabled: true
block-message: "&#FF6B6BПустые сообщения запрещены!"
# Фильтр только пробелов
whitespace:
enabled: true
block-message: "&#FF6B6BСообщение не может состоять только из пробелов!"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ НАСТРОЙКИ ОБХОДА │
# └─────────────────────────────────────────────────────────────────────────────┘
bypass:
# Права для обхода фильтров
permissions:
caps: "lochat.bypass.caps"
advertising: "lochat.bypass.advertising"
ip: "lochat.bypass.ip"
repeat: "lochat.bypass.repeat"
spam: "lochat.bypass.spam"
swear: "lochat.bypass.swear"
flood: "lochat.bypass.flood"
all: "lochat.bypass.filter"
# Группы, которые обходят все фильтры
groups:
- "admin"
- "moderator"
# Миры, где фильтры отключены
worlds:
- "creative_world"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ЛОГИРОВАНИЕ │
# └─────────────────────────────────────────────────────────────────────────────┘
logging:
# Логировать заблокированные сообщения
enabled: true
# Файл для логов
file: "plugins/LoChat/logs/filter.log"
# Формат лога
format: "[{time}] {player} ({filter}): {message}"
# Логировать в консоль
console: true
# Уведомлять администраторов
notify-admins: true
# Право для получения уведомлений
notify-permission: "lochat.filter.notify"

View file

@ -0,0 +1,208 @@
# ╔══════════════════════════════════════════════════════════════════════════════╗
# ║ LoChat Gradient Configuration ║
# ║ Конфигурация градиентов ║
# ║ Версия: 1.5.5-1.20.1 ║
# ╚══════════════════════════════════════════════════════════════════════════════╝
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ОСНОВНЫЕ НАСТРОЙКИ │
# └─────────────────────────────────────────────────────────────────────────────┘
gradient:
# Тип хранения данных: file, mysql, sqlite
storage-type: "file"
# Минимальное количество цветов в градиенте
min-colors: 1
# Максимальное количество цветов в градиенте
max-colors: 7
# Стоимость за каждый цвет (PlayerPoints)
price-per-color: 50
# Стоимость префикса
prefix-price: 500
# Одноразовая покупка префикса (true) или за каждое изменение (false)
prefix-one-time-purchase: true
# Максимальная длина префикса
max-prefix-length: 16
# Кулдаун на смену цвета (секунды)
color-cooldown: 60
# Кулдаун на смену префикса (секунды)
prefix-cooldown: 120
# Автоматически применять градиент к нику
auto-apply-gradient: true
# Обновлять отображаемое имя
update-display-name: true
# Обновлять таб-лист
update-tab-list: true
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ГОТОВЫЕ ПРЕСЕТЫ │
# └─────────────────────────────────────────────────────────────────────────────┘
presets:
fire:
name: "Огонь"
colors: [ "#FF4500", "#FF6347", "#FFD700" ]
permission: "gradient.preset.fire"
price: 100
ocean:
name: "Океан"
colors: [ "#00CED1", "#1E90FF", "#4169E1" ]
permission: "gradient.preset.ocean"
price: 100
forest:
name: "Лес"
colors: [ "#228B22", "#32CD32", "#90EE90" ]
permission: "gradient.preset.forest"
price: 100
sunset:
name: "Закат"
colors: [ "#FF69B4", "#FF1493", "#DC143C" ]
permission: "gradient.preset.sunset"
price: 150
rainbow:
name: "Радуга"
colors: [ "#FF0000", "#FF7F00", "#FFFF00", "#00FF00", "#0000FF", "#4B0082", "#9400D3" ]
permission: "gradient.preset.rainbow"
price: 300
gold:
name: "Золото"
colors: [ "#FFD700", "#FFA500", "#FF8C00" ]
permission: "gradient.preset.gold"
price: 200
silver:
name: "Серебро"
colors: [ "#C0C0C0", "#A9A9A9", "#808080" ]
permission: "gradient.preset.silver"
price: 150
purple:
name: "Фиолетовый"
colors: [ "#9400D3", "#8A2BE2", "#DA70D6" ]
permission: "gradient.preset.purple"
price: 120
ice:
name: "Лёд"
colors: [ "#B0E0E6", "#87CEEB", "#4682B4" ]
permission: "gradient.preset.ice"
price: 120
lava:
name: "Лава"
colors: [ "#DC143C", "#B22222", "#8B0000" ]
permission: "gradient.preset.lava"
price: 150
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ НАСТРОЙКИ БАЗЫ ДАННЫХ │
# └─────────────────────────────────────────────────────────────────────────────┘
database:
mysql:
host: "localhost"
port: 3306
database: "lochat"
username: "root"
password: "password"
table-prefix: "lochat_"
# Настройки пула соединений
pool:
maximum-pool-size: 10
minimum-idle: 5
connection-timeout: 30000
idle-timeout: 600000
max-lifetime: 1800000
sqlite:
file: "plugins/LoChat/gradient-data.db"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ДОПОЛНИТЕЛЬНЫЕ ФУНКЦИИ │
# └─────────────────────────────────────────────────────────────────────────────┘
features:
# Анимированные градиенты
animated-gradients:
enabled: false
speed: 1000 # миллисекунды
# Случайные градиенты
random-gradients:
enabled: true
change-interval: 3600 # секунды (1 час)
# Градиенты в чате
chat-gradients:
enabled: true
apply-to-messages: true
# Градиенты в табе
tab-gradients:
enabled: true
update-interval: 20 # тики
# Сохранение градиентов при выходе
save-on-quit: true
# Восстановление градиентов при входе
restore-on-join: true
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ПРАВА ДОСТУПА │
# └─────────────────────────────────────────────────────────────────────────────┘
permissions:
# Базовые права
use-gradient: "gradient.use"
use-prefix: "gradient.prefix"
admin: "gradient.admin"
# Обход ограничений
bypass-cooldown: "gradient.bypass.cooldown"
bypass-cost: "gradient.bypass.cost"
bypass-length: "gradient.bypass.length"
# Дополнительные цвета
extra-colors:
"gradient.colors.5": 5
"gradient.colors.10": 10
"gradient.colors.15": 15
"gradient.colors.unlimited": 999
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ФОРМАТИРОВАНИЕ │
# └─────────────────────────────────────────────────────────────────────────────┘
formatting:
# Формат ника с градиентом
nick-format: "{gradient}{nick}"
# Формат префикса с градиентом
prefix-format: "{gradient}{prefix}"
# Формат в табе
tab-format: "{prefix} {gradient}{nick}"
# Формат в чате
chat-format: "{prefix} {gradient}{nick}&r: {message}"
# Разделитель между префиксом и ником
separator: " "

View file

@ -0,0 +1,380 @@
# ╔══════════════════════════════════════════════════════════════════════════════╗
# ║ LoChat Integrations ║
# ║ Интеграции ║
# ║ Версия: 1.5.5-1.20.1 ║
# ╚══════════════════════════════════════════════════════════════════════════════╝
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ PLACEHOLDERAPI │
# └─────────────────────────────────────────────────────────────────────────────┘
placeholderapi:
# Включить интеграцию с PlaceholderAPI
enabled: true
# Регистрировать собственные плейсхолдеры
register-placeholders: true
# Доступные плейсхолдеры LoChat:
# %lochat_player_muted% - замучен ли игрок (true/false)
# %lochat_player_mute_time% - оставшееся время мута
# %lochat_player_mute_reason% - причина мута
# %lochat_player_gradient% - градиентный ник
# %lochat_player_prefix% - кастомный префикс
# %lochat_player_ignored_count% - количество игнорируемых игроков
# %lochat_player_messages_sent% - отправлено сообщений
# %lochat_player_last_message% - последнее сообщение
# %lochat_server_muted_count% - количество замученных игроков
# %lochat_server_messages_today% - сообщений сегодня
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ LUCKPERMS │
# └─────────────────────────────────────────────────────────────────────────────┘
luckperms:
# Включить интеграцию с LuckPerms
enabled: true
# Использовать префиксы из LuckPerms
use-prefix: true
# Использовать суффиксы из LuckPerms
use-suffix: true
# Использовать мета-данные из LuckPerms
use-meta: true
# Приоритет групп для форматирования чата
group-priority: true
# Кэшировать данные LuckPerms
cache-data: true
# Время кэширования (секунды)
cache-duration: 300
# Синхронизировать изменения прав
sync-changes: true
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ VAULT │
# └─────────────────────────────────────────────────────────────────────────────┘
vault:
# Включить интеграцию с Vault
enabled: true
# Использовать Vault для прав
use-permissions: true
# Использовать Vault для экономики
use-economy: true
# Использовать Vault для чата (префиксы/суффиксы)
use-chat: true
# Приоритет Vault над другими системами
priority: 1
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ PLAYERPOINTS │
# └─────────────────────────────────────────────────────────────────────────────┘
playerpoints:
# Включить интеграцию с PlayerPoints
enabled: true
# Использовать поинты для покупки градиентов
use-for-gradients: true
# Использовать поинты для покупки префиксов
use-for-prefixes: true
# Автоматически списывать поинты
auto-deduct: true
# Уведомлять о списании поинтов
notify-deduction: true
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ LIBERTYBANS │
# └─────────────────────────────────────────────────────────────────────────────┘
libertybans:
# Включить интеграцию с LibertyBans
enabled: false
# Синхронизировать муты с LibertyBans
sync-mutes: true
# Использовать LibertyBans для мутов вместо встроенной системы
use-for-mutes: false
# Импортировать существующие муты из LibertyBans
import-existing: false
# Экспортировать муты в LibertyBans
export-mutes: true
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ SKINSRESTORER │
# └─────────────────────────────────────────────────────────────────────────────┘
skinsrestorer:
# Включить интеграцию с SkinsRestorer
enabled: true
# Обновлять отображение при смене скина
update-on-skin-change: true
# Использовать скины в head emoji
use-in-head-emoji: true
# Кэшировать данные скинов
cache-skins: true
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ DISCORDSRV │
# └─────────────────────────────────────────────────────────────────────────────┘
discordsrv:
# Включить интеграцию с DiscordSRV
enabled: false
# Отправлять сообщения чата в Discord
send-chat-to-discord: true
# Отправлять сообщения из Discord в игру
send-discord-to-chat: true
# Канал для глобального чата
global-chat-channel: "global-chat"
# Канал для локального чата
local-chat-channel: "local-chat"
# Канал для объявлений
announcement-channel: "announcements"
# Формат сообщений в Discord
discord-format: "**{player}**: {message}"
# Формат сообщений из Discord
minecraft-format: "&7[Discord] &b{user}&7: {message}"
# Использовать градиентные ники в Discord
use-gradients-in-discord: false
# Webhook для отправки сообщений
webhook:
enabled: false
url: ""
username: "LoChat"
avatar-url: ""
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ DYNMAP │
# └─────────────────────────────────────────────────────────────────────────────┘
dynmap:
# Включить интеграцию с Dynmap
enabled: false
# Отправлять сообщения чата на веб-карту
send-chat-to-web: true
# Отправлять сообщения с веб-карты в игру
send-web-to-chat: true
# Формат сообщений на веб-карте
web-format: "{player}: {message}"
# Формат сообщений с веб-карты
minecraft-format: "&7[Web] &a{player}&7: {message}"
# Использовать градиентные ники на веб-карте
use-gradients-on-web: false
# Фильтровать сообщения для веб-карты
filter-messages: true
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ BLUEMAP │
# └─────────────────────────────────────────────────────────────────────────────┘
bluemap:
# Включить интеграцию с BlueMap
enabled: false
# Отправлять сообщения чата на карту
send-chat-to-map: true
# Формат сообщений на карте
map-format: "{player}: {message}"
# Использовать градиентные ники на карте
use-gradients-on-map: false
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ PLAN │
# └─────────────────────────────────────────────────────────────────────────────┘
plan:
# Включить интеграцию с Plan
enabled: false
# Отправлять статистику чата в Plan
send-chat-stats: true
# Отправлять статистику мутов в Plan
send-mute-stats: true
# Интервал отправки статистики (секунды)
stats-interval: 300
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ COREPROTECT │
# └─────────────────────────────────────────────────────────────────────────────┘
coreprotect:
# Включить интеграцию с CoreProtect
enabled: false
# Логировать сообщения чата
log-chat-messages: true
# Логировать команды
log-commands: true
# Логировать муты
log-mutes: true
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ AUTHME │
# └─────────────────────────────────────────────────────────────────────────────┘
authme:
# Включить интеграцию с AuthMe
enabled: false
# Блокировать чат для неавторизованных игроков
block-chat-for-unregistered: true
# Сообщение для неавторизованных игроков
unregistered-message: "&#FF6B6BВойдите в аккаунт для использования чата!"
# Разрешенные команды для неавторизованных
allowed-commands:
- "/login"
- "/register"
- "/l"
- "/reg"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ TOWNY │
# └─────────────────────────────────────────────────────────────────────────────┘
towny:
# Включить интеграцию с Towny
enabled: false
# Чат города
town-chat:
enabled: true
format: "&6[Town] {prefix}{player}&r: {message}"
command: "/tc"
# Чат нации
nation-chat:
enabled: true
format: "&5[Nation] {prefix}{player}&r: {message}"
command: "/nc"
# Показывать город в чате
show-town-in-chat: true
# Формат города в чате
town-format: "&7[{town}]"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ FACTIONS │
# └─────────────────────────────────────────────────────────────────────────────┘
factions:
# Включить интеграцию с Factions
enabled: false
# Чат фракции
faction-chat:
enabled: true
format: "&c[Faction] {prefix}{player}&r: {message}"
command: "/fc"
# Чат альянса
alliance-chat:
enabled: true
format: "&a[Alliance] {prefix}{player}&r: {message}"
command: "/ac"
# Показывать фракцию в чате
show-faction-in-chat: true
# Формат фракции в чате
faction-format: "&7[{faction}]"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ MULTIVERSE │
# └─────────────────────────────────────────────────────────────────────────────┘
multiverse:
# Включить интеграцию с Multiverse
enabled: false
# Разделять чат по мирам
separate-chat-by-world: false
# Показывать мир в чате
show-world-in-chat: true
# Формат мира в чате
world-format: "&7[{world}]"
# Настройки чата для конкретных миров
world-settings:
world_nether:
chat-color: "&c"
prefix: "&4[Nether]"
world_the_end:
chat-color: "&5"
prefix: "&d[End]"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ОБЩИЕ НАСТРОЙКИ │
# └─────────────────────────────────────────────────────────────────────────────┘
general:
# Автоматически определять доступные плагины
auto-detect-plugins: true
# Интервал проверки плагинов (секунды)
plugin-check-interval: 60
# Логировать интеграции
log-integrations: true
# Уведомлять о подключении/отключении интеграций
notify-integration-changes: true
# Приоритет интеграций (чем выше число, тем выше приоритет)
integration-priority:
luckperms: 100
vault: 90
placeholderapi: 80
playerpoints: 70
libertybans: 60
skinsrestorer: 50
discordsrv: 40
dynmap: 30
plan: 20
coreprotect: 10

View file

@ -0,0 +1,336 @@
# ╔══════════════════════════════════════════════════════════════════════════════╗
# ║ LoChat Mute Configuration ║
# ║ Конфигурация мутов ║
# ║ Версия: 1.5.5-1.20.1 ║
# ╚══════════════════════════════════════════════════════════════════════════════╝
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ОСНОВНЫЕ НАСТРОЙКИ │
# └─────────────────────────────────────────────────────────────────────────────┘
settings:
# Причина мута по умолчанию
default-reason: "Нарушение правил чата"
# Длительность мута по умолчанию
default-duration: "1h"
# Максимальная длина причины мута
max-reason-length: 100
# Показывать причину мута игроку
show-reason: true
# Показывать оставшееся время мута
show-remaining-time: true
# Автоматически размучивать при истечении времени
auto-unmute: true
# Сохранять историю мутов
save-history: true
# Максимальное количество записей в истории на игрока
max-history-entries: 50
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ДОСТУПНЫЕ ДЛИТЕЛЬНОСТИ │
# └─────────────────────────────────────────────────────────────────────────────┘
durations:
# Формат: "время": "право для использования"
"5m":
permission: "lochat.mute.dur.5m"
display: "5 минут"
"10m":
permission: "lochat.mute.dur.10m"
display: "10 минут"
"30m":
permission: "lochat.mute.dur.30m"
display: "30 минут"
"1h":
permission: "lochat.mute.dur.1h"
display: "1 час"
"3h":
permission: "lochat.mute.dur.3h"
display: "3 часа"
"6h":
permission: "lochat.mute.dur.6h"
display: "6 часов"
"12h":
permission: "lochat.mute.dur.12h"
display: "12 часов"
"1d":
permission: "lochat.mute.dur.1d"
display: "1 день"
"3d":
permission: "lochat.mute.dur.3d"
display: "3 дня"
"7d":
permission: "lochat.mute.dur.7d"
display: "7 дней"
"14d":
permission: "lochat.mute.dur.14d"
display: "14 дней"
"30d":
permission: "lochat.mute.dur.30d"
display: "30 дней"
"perm":
permission: "lochat.mute.dur.perm"
display: "Навсегда"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ГОТОВЫЕ ПРИЧИНЫ │
# └─────────────────────────────────────────────────────────────────────────────┘
reasons:
spam:
text: "Спам в чате"
duration: "30m"
permission: "lochat.mute.reason.spam"
caps:
text: "Злоупотребление заглавными буквами"
duration: "15m"
permission: "lochat.mute.reason.caps"
swear:
text: "Использование нецензурной лексики"
duration: "1h"
permission: "lochat.mute.reason.swear"
flood:
text: "Флуд в чате"
duration: "20m"
permission: "lochat.mute.reason.flood"
advertising:
text: "Реклама"
duration: "3h"
permission: "lochat.mute.reason.advertising"
insult:
text: "Оскорбления игроков"
duration: "2h"
permission: "lochat.mute.reason.insult"
toxicity:
text: "Токсичное поведение"
duration: "6h"
permission: "lochat.mute.reason.toxicity"
politics:
text: "Обсуждение политики"
duration: "1h"
permission: "lochat.mute.reason.politics"
religion:
text: "Религиозные споры"
duration: "1h"
permission: "lochat.mute.reason.religion"
begging:
text: "Попрошайничество"
duration: "30m"
permission: "lochat.mute.reason.begging"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ АВТОМАТИЧЕСКИЕ МУТЫ │
# └─────────────────────────────────────────────────────────────────────────────┘
auto-mute:
# Включить автоматические муты
enabled: true
# Мут за спам
spam:
enabled: true
threshold: 5 # Количество сообщений
time-window: 10 # За какое время (секунды)
duration: "10m"
reason: "Автомут: спам в чате"
# Мут за мат
swear:
enabled: true
threshold: 3 # Количество нарушений
duration: "30m"
reason: "Автомут: использование мата"
# Мут за заглавные буквы
caps:
enabled: true
threshold: 5 # Количество нарушений
duration: "5m"
reason: "Автомут: злоупотребление CAPS"
# Мут за рекламу
advertising:
enabled: true
threshold: 1 # Одно нарушение
duration: "1h"
reason: "Автомут: реклама"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ЭСКАЛАЦИЯ НАКАЗАНИЙ │
# └─────────────────────────────────────────────────────────────────────────────┘
escalation:
# Включить эскалацию наказаний
enabled: true
# Период для подсчета нарушений (дни)
period: 30
# Уровни наказаний
levels:
1:
duration: "30m"
reason: "Первое нарушение"
2:
duration: "2h"
reason: "Повторное нарушение"
3:
duration: "12h"
reason: "Третье нарушение"
4:
duration: "3d"
reason: "Четвертое нарушение"
5:
duration: "7d"
reason: "Пятое нарушение"
6:
duration: "perm"
reason: "Систематические нарушения"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ УВЕДОМЛЕНИЯ │
# └─────────────────────────────────────────────────────────────────────────────┘
notifications:
# Уведомлять администраторов о мутах
notify-staff: true
# Право для получения уведомлений
staff-permission: "lochat.mute.notify"
# Публичные уведомления о мутах
public-mute: false
# Публичные уведомления о размутах
public-unmute: false
# Скрытые муты (с флагом -s)
silent-mute:
enabled: true
permission: "lochat.mute.silent"
notify-permission: "lochat.mute.see-silent"
# Формат уведомлений
formats:
mute: "&#FF6B6B{moderator} замутил {player} на {duration}. Причина: {reason}"
unmute: "&#6BCB77{moderator} размутил {player}"
silent-mute: "&#FFA726[ТИХО] {moderator} замутил {player} на {duration}. Причина: {reason}"
auto-mute: "&#FF6B6B[АВТО] {player} замучен на {duration}. Причина: {reason}"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ИНТЕГРАЦИИ │
# └─────────────────────────────────────────────────────────────────────────────┘
integrations:
# LibertyBans
libertybans:
enabled: false
sync-mutes: true
# AdvancedBan
advancedban:
enabled: false
sync-mutes: true
# LiteBans
litebans:
enabled: false
sync-mutes: true
# Discord уведомления
discord:
enabled: false
webhook-url: ""
format: "**{moderator}** замутил **{player}** на **{duration}**\nПричина: {reason}"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ХРАНЕНИЕ ДАННЫХ │
# └─────────────────────────────────────────────────────────────────────────────┘
storage:
# Тип хранения: file, mysql, sqlite
type: "file"
# Настройки MySQL
mysql:
host: "localhost"
port: 3306
database: "lochat"
username: "root"
password: "password"
table-prefix: "lochat_"
# Настройки SQLite
sqlite:
file: "plugins/LoChat/mutes.db"
# Автоматическая очистка старых записей
cleanup:
enabled: true
days: 90 # Удалять записи старше N дней
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ДОПОЛНИТЕЛЬНЫЕ ФУНКЦИИ │
# └─────────────────────────────────────────────────────────────────────────────┘
features:
# Временные муты (автоматически снимаются)
temporary-mutes: true
# IP муты (мутить по IP адресу)
ip-mutes:
enabled: false
permission: "lochat.mute.ip"
# Мут команд (блокировать определенные команды)
command-mute:
enabled: false
blocked-commands:
- "me"
- "say"
- "tell"
# Предупреждения перед мутом
warnings:
enabled: true
max-warnings: 3
reset-time: 3600 # Сброс предупреждений (секунды)
# Апелляции на муты
appeals:
enabled: false
command: "/appeal"
permission: "lochat.appeal"

View file

@ -0,0 +1,313 @@
# ╔══════════════════════════════════════════════════════════════════════════════╗
# ║ LoChat Sounds Configuration ║
# ║ Конфигурация звуков ║
# ║ Версия: 1.5.5-1.20.1 ║
# ╚══════════════════════════════════════════════════════════════════════════════╝
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ОСНОВНЫЕ НАСТРОЙКИ │
# └─────────────────────────────────────────────────────────────────────────────┘
settings:
# Включить звуки
enabled: true
# Глобальная громкость (0.0 - 1.0)
global-volume: 0.5
# Глобальная высота тона (0.5 - 2.0)
global-pitch: 1.0
# Разрешить игрокам отключать звуки
allow-disable: true
# Команда для управления звуками
toggle-command: "/sounds"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ЗВУКИ СООБЩЕНИЙ │
# └─────────────────────────────────────────────────────────────────────────────┘
messages:
# Личные сообщения
private-message:
enabled: true
sound: "BLOCK_NOTE_BLOCK_PLING"
volume: 0.8
pitch: 1.2
# Играть только получателю
receiver-only: true
# Упоминания в чате
mention:
enabled: true
sound: "BLOCK_NOTE_BLOCK_BELL"
volume: 0.7
pitch: 1.5
# Дополнительный звук для @everyone
everyone-sound: "BLOCK_NOTE_BLOCK_CHIME"
# Глобальный чат
global-chat:
enabled: false
sound: "UI_BUTTON_CLICK"
volume: 0.3
pitch: 1.0
# Локальный чат
local-chat:
enabled: false
sound: "UI_BUTTON_CLICK"
volume: 0.2
pitch: 0.8
# Объявления
announcement:
enabled: true
sound: "BLOCK_NOTE_BLOCK_CHIME"
volume: 1.0
pitch: 1.0
# Дополнительные звуки для важных объявлений
important-sound: "ENTITY_ENDER_DRAGON_GROWL"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ЗВУКИ СИСТЕМЫ │
# └─────────────────────────────────────────────────────────────────────────────┘
system:
# Подключение к серверу
join:
enabled: false
sound: "ENTITY_PLAYER_LEVELUP"
volume: 0.5
pitch: 1.0
# Играть только подключившемуся игроку
self-only: true
# Отключение от сервера
quit:
enabled: false
sound: "BLOCK_NOTE_BLOCK_BASS"
volume: 0.3
pitch: 0.8
# Мут игрока
mute:
enabled: true
sound: "BLOCK_ANVIL_LAND"
volume: 0.6
pitch: 0.5
# Играть замученному игроку
target-sound: "ENTITY_VILLAGER_NO"
# Размут игрока
unmute:
enabled: true
sound: "ENTITY_PLAYER_LEVELUP"
volume: 0.7
pitch: 1.2
# Играть размученному игроку
target-sound: "ENTITY_VILLAGER_YES"
# Очистка чата
clear-chat:
enabled: true
sound: "ITEM_BUCKET_EMPTY"
volume: 0.5
pitch: 1.5
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ЗВУКИ ГРАДИЕНТОВ │
# └─────────────────────────────────────────────────────────────────────────────┘
gradient:
# Установка градиента
color-set:
enabled: true
sound: "BLOCK_NOTE_BLOCK_HARP"
volume: 0.6
pitch: 1.3
# Сброс градиента
color-reset:
enabled: true
sound: "BLOCK_NOTE_BLOCK_BASS"
volume: 0.4
pitch: 0.7
# Установка префикса
prefix-set:
enabled: true
sound: "BLOCK_NOTE_BLOCK_CHIME"
volume: 0.7
pitch: 1.4
# Ошибка (недостаточно средств, кулдаун и т.д.)
error:
enabled: true
sound: "ENTITY_VILLAGER_NO"
volume: 0.5
pitch: 0.8
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ЗВУКИ КОМАНД │
# └─────────────────────────────────────────────────────────────────────────────┘
commands:
# Успешное выполнение команды
success:
enabled: false
sound: "ENTITY_EXPERIENCE_ORB_PICKUP"
volume: 0.4
pitch: 1.2
# Ошибка выполнения команды
error:
enabled: true
sound: "ENTITY_VILLAGER_NO"
volume: 0.5
pitch: 0.8
# Недостаточно прав
no-permission:
enabled: true
sound: "BLOCK_NOTE_BLOCK_BASS"
volume: 0.6
pitch: 0.5
# Игрок не найден
player-not-found:
enabled: true
sound: "ENTITY_ITEM_BREAK"
volume: 0.4
pitch: 0.6
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ЗВУКИ ФИЛЬТРОВ │
# └─────────────────────────────────────────────────────────────────────────────┘
filters:
# Сообщение заблокировано фильтром
blocked:
enabled: true
sound: "ENTITY_VILLAGER_NO"
volume: 0.6
pitch: 0.7
# Предупреждение от фильтра
warning:
enabled: true
sound: "BLOCK_NOTE_BLOCK_PLING"
volume: 0.5
pitch: 0.9
# Автоматическое исправление (например, caps)
auto-fix:
enabled: false
sound: "UI_BUTTON_CLICK"
volume: 0.3
pitch: 1.1
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ КАСТОМНЫЕ ЗВУКИ │
# └─────────────────────────────────────────────────────────────────────────────┘
custom:
# Звуки для VIP игроков
vip:
enabled: false
join-sound: "ENTITY_PLAYER_LEVELUP"
message-sound: "BLOCK_NOTE_BLOCK_HARP"
volume: 0.8
pitch: 1.3
# Звуки для администраторов
admin:
enabled: false
join-sound: "ENTITY_ENDER_DRAGON_GROWL"
command-sound: "BLOCK_ANVIL_USE"
volume: 0.7
pitch: 1.0
# Праздничные звуки
holiday:
enabled: false
christmas:
sound: "BLOCK_NOTE_BLOCK_CHIME"
volume: 0.6
pitch: 1.5
new-year:
sound: "ENTITY_FIREWORK_ROCKET_BLAST"
volume: 0.8
pitch: 1.2
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ЗВУКОВЫЕ СХЕМЫ │
# └─────────────────────────────────────────────────────────────────────────────┘
schemes:
# Классическая схема
classic:
name: "Классическая"
description: "Стандартные звуки Minecraft"
sounds:
private-message: "BLOCK_NOTE_BLOCK_PLING"
mention: "BLOCK_NOTE_BLOCK_BELL"
announcement: "BLOCK_NOTE_BLOCK_CHIME"
# Минималистичная схема
minimal:
name: "Минимальная"
description: "Только важные звуки"
sounds:
private-message: "UI_BUTTON_CLICK"
mention: "BLOCK_NOTE_BLOCK_PLING"
announcement: "ENTITY_EXPERIENCE_ORB_PICKUP"
# Отключенная схема
silent:
name: "Тишина"
description: "Все звуки отключены"
sounds: {}
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ НАСТРОЙКИ ПО МИРАМ │
# └─────────────────────────────────────────────────────────────────────────────┘
worlds:
# Настройки для конкретных миров
world_nether:
volume-modifier: 0.7 # Уменьшить громкость на 30%
pitch-modifier: 0.8 # Понизить тон
world_the_end:
volume-modifier: 0.5
pitch-modifier: 1.2
# Отключить определенные звуки
disabled-sounds:
- "global-chat"
- "local-chat"
creative_world:
volume-modifier: 1.2
# Включить дополнительные звуки
extra-sounds:
build: "BLOCK_STONE_PLACE"
fly: "ENTITY_BAT_TAKEOFF"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ПЕРСОНАЛЬНЫЕ НАСТРОЙКИ │
# └─────────────────────────────────────────────────────────────────────────────┘
personal:
# Разрешить игрокам настраивать громкость
allow-volume-control: true
# Разрешить игрокам выбирать звуковые схемы
allow-scheme-selection: true
# Сохранять настройки игроков
save-preferences: true
# Файл для сохранения настроек
preferences-file: "plugins/LoChat/sound-preferences.yml"

View file

@ -0,0 +1,91 @@
# ╔══════════════════════════════════════════════════════════════════════════════╗
# ║ LoChat Data Storage ║
# ║ Хранилище данных LoChat ║
# ║ Версия: 1.5.5-1.20.1 ║
# ╚══════════════════════════════════════════════════════════════════════════════╝
# Этот файл содержит основные данные плагина
# НЕ РЕДАКТИРУЙТЕ ЭТОТ ФАЙЛ ВРУЧНУЮ!
data-version: 1
last-updated: 0
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ДАННЫЕ ИГРОКОВ │
# └─────────────────────────────────────────────────────────────────────────────┘
players: {}
# Структура:
# uuid:
# name: "PlayerName"
# display-name: "GradientName"
# first-join: 1234567890
# last-join: 1234567890
# total-playtime: 3600000
# settings:
# sounds-enabled: true
# auto-messages: true
# mentions-enabled: true
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ГРАДИЕНТНЫЕ НИКИ │
# └─────────────────────────────────────────────────────────────────────────────┘
gradients: {}
# Структура:
# uuid:
# colors: ["#FF0000", "#00FF00", "#0000FF"]
# prefix: "[CUSTOM]"
# enabled: true
# created: 1234567890
# last-updated: 1234567890
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ АКТИВНЫЕ МУТЫ │
# └─────────────────────────────────────────────────────────────────────────────┘
mutes: {}
# Структура:
# uuid:
# moderator: "ModeratorUUID"
# reason: "Причина мута"
# start-time: 1234567890
# end-time: 1234567890
# silent: false
# active: true
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ИГНОРИРОВАНИЕ │
# └─────────────────────────────────────────────────────────────────────────────┘
ignores: {}
# Структура:
# player-uuid:
# - "ignored-uuid-1"
# - "ignored-uuid-2"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ СТАТИСТИКА │
# └─────────────────────────────────────────────────────────────────────────────┘
statistics:
total-messages: 0
messages-today: 0
last-reset: 0
top-chatters: {}
# uuid: message-count
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ КЭШИРОВАННЫЕ ДАННЫЕ │
# └─────────────────────────────────────────────────────────────────────────────┘
cache:
last-messages: {}
# uuid: "last message"
cooldowns: {}
# uuid:
# global: 1234567890
# local: 1234567890
# pm: 1234567890
# gradient: 1234567890

View file

@ -0,0 +1,22 @@
# ╔══════════════════════════════════════════════════════════════════════════════╗
# ║ Gradient Data ║
# ║ Данные градиентов ║
# ╚══════════════════════════════════════════════════════════════════════════════╝
# НЕ РЕДАКТИРУЙТЕ ЭТОТ ФАЙЛ ВРУЧНУЮ!
data-version: 1
gradients: {}
# Пример структуры:
# 550e8400-e29b-41d4-a716-446655440000:
# colors:
# - "#FF0000"
# - "#00FF00"
# - "#0000FF"
# prefix: "[VIP]"
# enabled: true
# created: 1640995200000
# last-updated: 1640995200000
# preset-used: "rainbow"
# cost-paid: 300

View file

@ -0,0 +1,19 @@
# ╔══════════════════════════════════════════════════════════════════════════════╗
# ║ Ignore Data ║
# ║ Данные игнорирования ║
# ╚══════════════════════════════════════════════════════════════════════════════╝
# НЕ РЕДАКТИРУЙТЕ ЭТОТ ФАЙЛ ВРУЧНУЮ!
data-version: 1
ignores: {}
# Пример структуры:
# 550e8400-e29b-41d4-a716-446655440000:
# ignored-players:
# - uuid: "ignored-player-uuid-1"
# name: "IgnoredPlayer1"
# added: 1640995200000
# - uuid: "ignored-player-uuid-2"
# name: "IgnoredPlayer2"
# added: 1640995300000

View file

@ -0,0 +1,39 @@
# ╔══════════════════════════════════════════════════════════════════════════════╗
# ║ Mute Data ║
# ║ Данные мутов ║
# ╚══════════════════════════════════════════════════════════════════════════════╝
# НЕ РЕДАКТИРУЙТЕ ЭТОТ ФАЙЛ ВРУЧНУЮ!
data-version: 1
active-mutes: {}
mute-history: {}
# Пример структуры активных мутов:
# active-mutes:
# 550e8400-e29b-41d4-a716-446655440000:
# id: 1
# moderator: "admin-uuid"
# moderator-name: "AdminName"
# reason: "Спам в чате"
# start-time: 1640995200000
# end-time: 1640998800000
# duration: 3600000
# silent: false
# active: true
# server: "lobby"
# Пример истории мутов:
# mute-history:
# 550e8400-e29b-41d4-a716-446655440000:
# - id: 1
# moderator: "admin-uuid"
# moderator-name: "AdminName"
# reason: "Первое нарушение"
# start-time: 1640995200000
# end-time: 1640998800000
# duration: 3600000
# unmute-reason: "Время истекло"
# unmute-moderator: null
# silent: false
# server: "lobby"

View file

@ -0,0 +1,30 @@
# ╔══════════════════════════════════════════════════════════════════════════════╗
# ║ Player Data ║
# ║ Данные игроков ║
# ╚══════════════════════════════════════════════════════════════════════════════╝
# НЕ РЕДАКТИРУЙТЕ ЭТОТ ФАЙЛ ВРУЧНУЮ!
data-version: 1
players: {}
# Пример структуры:
# 550e8400-e29b-41d4-a716-446655440000:
# name: "PlayerName"
# display-name: "&#FF0000P&#FF3300l&#FF6600a&#FF9900y&#FFcc00e&#FFff00r"
# first-join: 1640995200000
# last-join: 1640995200000
# last-quit: 1640995200000
# total-playtime: 3600000
# settings:
# sounds-enabled: true
# sound-volume: 1.0
# auto-messages: true
# mentions-enabled: true
# pm-sounds: true
# statistics:
# messages-sent: 150
# commands-used: 45
# mutes-received: 2
# last-message: "Привет всем!"
# join-count: 25

View file

@ -0,0 +1,76 @@
# ╔══════════════════════════════════════════════════════════════════════════════╗
# ║ Statistics Data ║
# ║ Статистика ║
# ╚══════════════════════════════════════════════════════════════════════════════╝
# НЕ РЕДАКТИРУЙТЕ ЭТОТ ФАЙЛ ВРУЧНУЮ!
data-version: 1
last-updated: 0
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ОБЩАЯ СТАТИСТИКА │
# └─────────────────────────────────────────────────────────────────────────────┘
global:
total-messages: 0
messages-today: 0
messages-this-week: 0
messages-this-month: 0
last-reset: 0
peak-online: 0
peak-online-time: 0
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ СТАТИСТИКА ПО ТИПАМ │
# └─────────────────────────────────────────────────────────────────────────────┘
by-type:
global-chat: 0
local-chat: 0
private-messages: 0
announcements: 0
commands: 0
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ТОП ИГРОКОВ │
# └─────────────────────────────────────────────────────────────────────────────┘
top-players:
by-messages: {}
by-playtime: {}
by-commands: {}
# Пример:
# by-messages:
# 550e8400-e29b-41d4-a716-446655440000:
# name: "PlayerName"
# count: 1500
# last-updated: 1640995200000
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ СТАТИСТИКА МУТОВ │
# └─────────────────────────────────────────────────────────────────────────────┘
mute-stats:
total-mutes: 0
active-mutes: 0
mutes-today: 0
mutes-this-week: 0
mutes-this-month: 0
top-reasons: {}
top-moderators: {}
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ СТАТИСТИКА ФИЛЬТРОВ │
# └─────────────────────────────────────────────────────────────────────────────┘
filter-stats:
total-blocked: 0
blocked-today: 0
by-filter:
caps: 0
swear: 0
spam: 0
advertising: 0
flood: 0

View file

@ -1,141 +0,0 @@
# ╔══════════════════════════════════════════════════════════════════════════════╗
# ║ LoChat Gradient Config ║
# ║ Настройки градиентных ников ║
# ║ Версия: 1.5.5-1.20.1 ║
# ╚══════════════════════════════════════════════════════════════════════════════╝
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ОСНОВНЫЕ НАСТРОЙКИ │
# └─────────────────────────────────────────────────────────────────────────────┘
# Включить градиентные ники
enabled: true
# Тип хранения данных: file или sqlite
storage-type: "file"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ НАСТРОЙКИ ЦВЕТОВ │
# └─────────────────────────────────────────────────────────────────────────────┘
# Минимальное количество цветов в градиенте
min-colors: 1
# Максимальное количество цветов в градиенте
max-colors: 7
# Цена за каждый цвет (PlayerPoints)
price-per-color: 50
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ НАСТРОЙКИ ПРЕФИКСОВ │
# └─────────────────────────────────────────────────────────────────────────────┘
# Цена за префикс (PlayerPoints)
prefix-price: 500
# Одноразовая покупка префикса (true) или за каждое изменение (false)
prefix-one-time-purchase: true
# Максимальная длина префикса (символы)
max-prefix-length: 16
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ КУЛДАУНЫ │
# └─────────────────────────────────────────────────────────────────────────────┘
# Кулдаун на изменение цвета (секунды)
color-cooldown: 60
# Кулдаун на изменение префикса (секунды)
prefix-cooldown: 120
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ИНТЕГРАЦИИ │
# └─────────────────────────────────────────────────────────────────────────────┘
# Интеграция с LuckPerms
luckperms:
# Включить интеграцию
enabled: true
# Приоритет префикса в LuckPerms
prefix-priority: 100
# Обновлять префикс в LuckPerms при изменении
update-prefix: true
# Интеграция с PlayerPoints
playerpoints:
# Включить интеграцию (покупки за поинты)
enabled: true
# Показывать баланс в GUI
show-balance: true
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ПРЕДУСТАНОВКИ │
# └─────────────────────────────────────────────────────────────────────────────┘
# Предустановленные градиенты
presets:
fire: [ "#FF4500", "#FF6347", "#FFD700" ]
ocean: [ "#00CED1", "#1E90FF", "#4169E1" ]
forest: [ "#228B22", "#32CD32", "#90EE90" ]
sunset: [ "#FF69B4", "#FF1493", "#DC143C" ]
rainbow: [ "#FF0000", "#FF7F00", "#FFFF00", "#00FF00", "#0000FF", "#4B0082", "#9400D3" ]
ice: [ "#B0E0E6", "#87CEEB", "#4682B4" ]
gold: [ "#FFD700", "#FFA500", "#FF8C00" ]
purple: [ "#9370DB", "#8A2BE2", "#4B0082" ]
pink: [ "#FFB6C1", "#FF69B4", "#FF1493" ]
green: [ "#00FF7F", "#00FA9A", "#98FB98" ]
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ GUI НАСТРОЙКИ │
# └─────────────────────────────────────────────────────────────────────────────┘
gui:
# Название GUI подтверждения
confirm-title: "<gradient:#FFD700:#FFA500>Подтверждение покупки</gradient>"
# Размер GUI (9, 18, 27, 36, 45, 54)
size: 27
# Предметы в GUI
items:
confirm:
material: "GREEN_WOOL"
name: "<gradient:#6BCB77:#4ECDC4>✓ Подтвердить</gradient>"
lore:
- "<gray>Нажмите для подтверждения"
- "<gray>покупки градиента"
cancel:
material: "RED_WOOL"
name: "<gradient:#FF6B6B:#FF4757>✗ Отменить</gradient>"
lore:
- "<gray>Нажмите для отмены"
- "<gray>покупки"
info:
material: "PAPER"
name: "<gradient:#FFA726:#FF9800>Информация</gradient>"
lore:
- "<gray>Цена: <yellow>{price} поинтов</yellow>"
- "<gray>Цвета: <white>{colors}</white>"
- ""
- "<gray>Ваш баланс: <yellow>{balance}</yellow>"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ РАЗРЕШЕНИЯ │
# └─────────────────────────────────────────────────────────────────────────────┘
# Автоматические разрешения для групп
permissions:
# Группы, которые получают бесплатные градиенты
free-groups:
- "vip"
- "premium"
- "admin"
# Группы, которые могут использовать любые цвета
unlimited-colors:
- "admin"
- "owner"

View file

@ -1,157 +0,0 @@
#file: noinspection YAMLDuplicatedKeys,YAMLDuplicatedKeys
# ╔══════════════════════════════════════════════════════════════════════════════╗
# ║ LoChat Gradient Messages ║
# ║ Сообщения градиентного модуля ║
# ║ Версия: 1.5.5-1.20.1 ║
# ╚══════════════════════════════════════════════════════════════════════════════╝
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ОСНОВНЫЕ СООБЩЕНИЯ │
# └─────────────────────────────────────────────────────────────────────────────┘
# Префикс градиентного модуля
prefix: "&#9370DB[&#9370DBG&#8E6CD9r&#896AD7a&#8467D5d&#7F65D3i&#7A62D1e&#7560CFn&#705DCDt&#6B5BCB]"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ КОМАНДА /color │
# └─────────────────────────────────────────────────────────────────────────────┘
color:
# Успешные действия
set: "<gradient:#6BCB77:#4ECDC4>Градиент установлен!</gradient>"
enabled: "<gradient:#6BCB77:#4ECDC4>Градиентный ник включен</gradient>"
disabled: "<gradient:#FF6B6B:#FF4757>Градиентный ник отключен</gradient>"
reset: "<gradient:#FFA726:#FF9800>Градиент сброшен</gradient>"
copied: "<gradient:#6BCB77:#4ECDC4>Градиент скопирован с игрока {player}</gradient>"
# Ошибки
invalid-hex: "<gradient:#FF6B6B:#FF4757>Неверный HEX цвет: {color}</gradient>"
too-many-colors: "<gradient:#FF6B6B:#FF4757>Слишком много цветов! Максимум: {max}</gradient>"
too-few-colors: "<gradient:#FF6B6B:#FF4757>Слишком мало цветов! Минимум: {min}</gradient>"
no-permission: "<gradient:#FF6B6B:#FF4757>Нет прав на использование градиентов</gradient>"
cooldown: "<gradient:#FFA726:#FF9800>Подождите {time} сек перед изменением цвета</gradient>"
not-enough-points: "<gradient:#FF6B6B:#FF4757>Недостаточно поинтов! Нужно: {price}, у вас: {balance}</gradient>"
player-not-found: "<gradient:#FF6B6B:#FF4757>Игрок не найден</gradient>"
no-gradient: "<gradient:#FFA726:#FF9800>У игрока нет градиента для копирования</gradient>"
# Помощь
help:
- "<gradient:#FFD700:#FFA500>═══════ Команды градиента ═══════</gradient>"
- "<gradient:#87CEEB:#4682B4>/color <hex1> [hex2] ...</gradient> <gray>- установить градиент</gray>"
- "<gradient:#87CEEB:#4682B4>/color on/off</gradient> <gray>- включить/выключить градиент</gray>"
- "<gradient:#87CEEB:#4682B4>/color reset</gradient> <gray>- сбросить градиент</gray>"
- "<gradient:#87CEEB:#4682B4>/color copy <игрок></gradient> <gray>- скопировать градиент</gray>"
- "<gradient:#87CEEB:#4682B4>/color preset <название></gradient> <gray>- использовать предустановку</gray>"
- ""
- "<gradient:#FFA726:#FF9800>Предустановки:</gradient> <white>fire, ocean, forest, sunset, rainbow, ice, gold, purple, pink, green</white>"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ КОМАНДА /prefix │
# └─────────────────────────────────────────────────────────────────────────────┘
prefix:
# Успешные действия
set: "<gradient:#6BCB77:#4ECDC4>Префикс установлен!</gradient>"
enabled: "<gradient:#6BCB77:#4ECDC4>Префикс включен</gradient>"
disabled: "<gradient:#FF6B6B:#FF4757>Префикс отключен</gradient>"
reset: "<gradient:#FFA726:#FF9800>Префикс сброшен</gradient>"
# Ошибки
too-long: "<gradient:#FF6B6B:#FF4757>Префикс слишком длинный! Максимум: {max} символов</gradient>"
no-permission: "<gradient:#FF6B6B:#FF4757>Нет прав на использование префиксов</gradient>"
cooldown: "<gradient:#FFA726:#FF9800>Подождите {time} сек перед изменением префикса</gradient>"
not-enough-points: "<gradient:#FF6B6B:#FF4757>Недостаточно поинтов! Нужно: {price}, у вас: {balance}</gradient>"
# Помощь
help:
- "<gradient:#FFD700:#FFA500>═══════ Команды префикса ═══════</gradient>"
- "<gradient:#87CEEB:#4682B4>/prefix <текст></gradient> <gray>- установить префикс</gray>"
- "<gradient:#87CEEB:#4682B4>/prefix on/off</gradient> <gray>- включить/выключить префикс</gray>"
- "<gradient:#87CEEB:#4682B4>/prefix reset</gradient> <gray>- сбросить префикс</gray>"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ АДМИНСКИЕ КОМАНДЫ │
# └─────────────────────────────────────────────────────────────────────────────┘
admin:
# Успешные действия
reloaded: "<gradient:#6BCB77:#4ECDC4>Конфигурация градиентов перезагружена</gradient>"
color-set: "<gradient:#6BCB77:#4ECDC4>Градиент установлен игроку {player}</gradient>"
prefix-set: "<gradient:#6BCB77:#4ECDC4>Префикс установлен игроку {player}</gradient>"
color-enabled: "<gradient:#6BCB77:#4ECDC4>Градиент включен для {player}</gradient>"
color-disabled: "<gradient:#FF6B6B:#FF4757>Градиент отключен для {player}</gradient>"
prefix-enabled: "<gradient:#6BCB77:#4ECDC4>Префикс включен для {player}</gradient>"
prefix-disabled: "<gradient:#FF6B6B:#FF4757>Префикс отключен для {player}</gradient>"
color-reset: "<gradient:#FFA726:#FF9800>Градиент сброшен для {player}</gradient>"
prefix-reset: "<gradient:#FFA726:#FF9800>Префикс сброшен для {player}</gradient>"
updated-all: "<gradient:#6BCB77:#4ECDC4>Обновлены все игроки ({count})</gradient>"
# Информация об игроке
info:
- "<gradient:#FFD700:#FFA500>═══════ Информация о {player} ═══════</gradient>"
- "<gradient:#87CEEB:#4682B4>Градиент:</gradient> <white>{gradient_status}</white>"
- "<gradient:#87CEEB:#4682B4>Цвета:</gradient> <white>{colors}</white>"
- "<gradient:#87CEEB:#4682B4>Префикс:</gradient> <white>{prefix_status}</white>"
- "<gradient:#87CEEB:#4682B4>Текст префикса:</gradient> <white>{prefix_text}</white>"
- "<gradient:#87CEEB:#4682B4>Отображаемое имя:</gradient> {display_name}"
# Ошибки
player-not-found: "<gradient:#FF6B6B:#FF4757>Игрок не найден</gradient>"
invalid-hex: "<gradient:#FF6B6B:#FF4757>Неверный HEX цвет: {color}</gradient>"
# Помощь
help:
- "<gradient:#FFD700:#FFA500>═══════ Админские команды ═══════</gradient>"
- "<gradient:#87CEEB:#4682B4>/aprefix reload</gradient> <gray>- перезагрузить конфиг</gray>"
- "<gradient:#87CEEB:#4682B4>/aprefix info <игрок></gradient> <gray>- информация об игроке</gray>"
- "<gradient:#87CEEB:#4682B4>/aprefix setcolor <игрок> <цвета></gradient> <gray>- установить градиент</gray>"
- "<gradient:#87CEEB:#4682B4>/aprefix setprefix <игрок> <текст></gradient> <gray>- установить префикс</gray>"
- "<gradient:#87CEEB:#4682B4>/aprefix coloron/coloroff <игрок></gradient> <gray>- вкл/выкл градиент</gray>"
- "<gradient:#87CEEB:#4682B4>/aprefix prefixon/prefixoff <игрок></gradient> <gray>- вкл/выкл префикс</gray>"
- "<gradient:#87CEEB:#4682B4>/aprefix resetcolor <игрок></gradient> <gray>- сбросить градиент</gray>"
- "<gradient:#87CEEB:#4682B4>/aprefix resetprefix <игрок></gradient> <gray>- сбросить префикс</gray>"
- "<gradient:#87CEEB:#4682B4>/aprefix updateall</gradient> <gray>- обновить всех игроков</gray>"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ GUI СООБЩЕНИЯ │
# └─────────────────────────────────────────────────────────────────────────────┘
gui:
# Заголовки
confirm-title: "<gradient:#FFD700:#FFA500>Подтверждение покупки</gradient>"
# Кнопки
confirm-button: "<gradient:#6BCB77:#4ECDC4>✓ Подтвердить покупку</gradient>"
cancel-button: "<gradient:#FF6B6B:#FF4757>✗ Отменить</gradient>"
# Описания
confirm-lore:
- "<gray>Цена: <yellow>{price} поинтов</yellow>"
- "<gray>Цвета: <white>{colors}</white>"
- ""
- "<gray>Ваш баланс: <yellow>{balance}</yellow>"
- ""
- "<gradient:#6BCB77:#4ECDC4>Нажмите для подтверждения</gradient>"
cancel-lore:
- "<gradient:#FF6B6B:#FF4757>Нажмите для отмены</gradient>"
# Результаты
purchase-success: "<gradient:#6BCB77:#4ECDC4>Градиент успешно куплен!</gradient>"
purchase-cancelled: "<gradient:#FFA726:#FF9800>Покупка отменена</gradient>"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ОБЩИЕ СООБЩЕНИЯ │
# └─────────────────────────────────────────────────────────────────────────────┘
general:
# Статусы
enabled: "<gradient:#6BCB77:#4ECDC4>Включено</gradient>"
disabled: "<gradient:#FF6B6B:#FF4757>Отключено</gradient>"
none: "<gray>Нет</gray>"
# Единицы времени
seconds: "сек"
minutes: "мин"
hours: "ч"
days: "д"

View file

@ -35,16 +35,16 @@ pm:
# Форматы личных сообщений
# {sender} - ник отправителя, {receiver} - ник получателя
# {sender_display} - отправитель с градиентом, {receiver_display} - получатель с градиентом
# {message} - текст сообщения
format-sent: "<gray>[PM]</gray> <gradient:#87CEEB:#4682B4>Ты</gradient> <gray>→</gray> {receiver_display}<gray>:</gray> {message}"
format-received: "<gray>[PM]</gray> {sender_display} <gray>→</gray> <gradient:#87CEEB:#4682B4>Ты</gradient><gray>:</gray> {message}"
# {message} - текст сообщение
format-sent: "&7[→] &#87CEEBВы &7→ {receiver_display}&7: {message}"
format-received: "&7[←] {sender_display} &7→ &#87CEEBВы&7: {message}"
# Использовать градиентные ники в PM
use-gradient-names: true
# Старые форматы (для совместимости)
sent: "<gray>[PM]</gray> <gradient:#87CEEB:#4682B4>Ты</gradient> <gray>→</gray> <white>{player}</white><gray>:</gray> {message}"
received: "<gray>[PM]</gray> <white>{player}</white> <gray>→</gray> <gradient:#87CEEB:#4682B4>Ты</gradient><gray>:</gray> {message}"
sent: "&7[→] &#87CEEBВы &7→ &f{player}&7: {message}"
received: "&7[←] &f{player} &7→ &#87CEEBВы&7: {message}"
# Ошибки PM
no-reply: "&#FF6B6BН&#FF5F5Fе&#FF5353к&#FF4747о&#FF3B3Bм&#FF2F2Fу &#FF2323о&#FF1717т&#FF0B0Bв&#FF0000е&#FF0000т&#FF0000и&#FF0000т&#FF0000ь"
@ -62,6 +62,9 @@ ignore:
already-ignored: "&#FFA726И&#FFA322г&#FF9F1Eр&#FF9B1Aо&#FF9716к &#FF9312у&#FF8F0Eж&#FF8B0Aе &#FF8706в &#FF8302и&#FF8000г&#FF8000н&#FF8000о&#FF8000р&#FF8000е"
not-ignored: "&#FFA726И&#FFA322г&#FF9F1Eр&#FF9B1Aо&#FF9716к &#FF9312н&#FF8F0Eе &#FF8B0Aв &#FF8706и&#FF8302г&#FF8000н&#FF8000о&#FF8000р&#FF8000е"
self: "&#FF6B6BН&#FF5F5Fе&#FF5353л&#FF4747ь&#FF3B3Bз&#FF2F2Fя &#FF2323и&#FF1717г&#FF0B0Bн&#FF0000о&#FF0000р&#FF0000и&#FF0000р&#FF0000о&#FF0000в&#FF0000а&#FF0000т&#FF0000ь &#FF0000с&#FF0000е&#FF0000б&#FF0000я"
list-empty: "&#87CEEBВ&#85CBE9а&#83C8E7ш &#81C5E5с&#7FC2E3п&#7DBFE1и&#7BBCDFс&#799BDDо&#7798DBк &#7595D9и&#7392D7г&#7190D5н&#6F8DD3о&#6D8AD1р&#6B87CFа &#6984CDп&#6782CBу&#6580C9с&#637DC7т"
list-header: "&#FFD700═&#FFC900═&#FFBB00═ &#FFAD00И&#FF9F00г&#FF9100н&#FF8300о&#FF7500р&#FF6700и&#FF5900р&#FF4B00у&#FF3D00е&#FF2F00м&#FF2100ы&#FF1300е &#FF0500и&#FF0000г&#FF0000р&#FF0000о&#FF0000к&#FF0000и &#FFD700═&#FFC900═&#FFBB00═"
list-footer: "&#87CEEBВ&#85CBE9с&#83C8E7е&#81C5E5г&#7FC2E3о&#7DBFE1: &#7BBCDFi&#799BDD{&#7798DBc&#7595D9o&#7392D7u&#7190D5n&#6F8DD3t&#6D8AD1}&#6B87CF &#6984CDи&#6782CBг&#6580C9р&#637DC7о&#6B7AC5к&#697CC3о&#6779C1в"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ОБЪЯВЛЕНИЯ │
@ -77,8 +80,8 @@ announce:
spy:
enabled: "&#6BCB77Ш&#62C973п&#5AC76Fи&#51C56Bо&#49C367н &#40C163р&#38BF5Fе&#2FBD5Bж&#27BB57и&#1EB953м &#16B74Fв&#0DB54Bк&#05B347л&#05B347ю&#05B347ч&#05B347е&#05B347н"
disabled: "&#FF6B6BШ&#FF5F5Fп&#FF5353и&#FF4747о&#FF3B3Bн &#FF2F2Fр&#FF2323е&#FF1717ж&#FF0B0Bи&#FF0000м &#FF0000в&#FF0000ы&#FF0000к&#FF0000л&#FF0000ю&#FF0000ч&#FF0000е&#FF0000н"
format: "<gray>[SPY]</gray> <gradient:#FFD700:#FFA500>{sender}</gradient> <gray>→</gray> <gradient:#87CEEB:#4682B4>{receiver}</gradient><gray>:</gray> <white>{message}</white>"
chat-format: "<gray>[SPY]</gray> <gradient:#FFA726:#FF9800>{type}</gradient> <gradient:#00FF88:#00CC66>{sender}</gradient><gray>:</gray> <white>{message}</white>"
format: "&7[SPY] &#FFD700{&#FFC900s&#FFBB00e&#FFAD00n&#FF9F00d&#FF9100e&#FF8300r&#FF7500} &7→ &#87CEEB{&#85CBE9r&#83C8E7e&#81C5E5c&#7FC2E3e&#7DBFE1i&#7BBCDFv&#799BDDe&#7798DBr&#7595D9}&7: &f{message}"
chat-format: "&7[SPY] &#FFA726{&#FFA322t&#FF9F1Ey&#FF9B1Ap&#FF9716e&#FF9312} &#00FF88{&#00F582s&#00EB7Ce&#00E176n&#00D770d&#00CD6Ae&#00C364r&#00B95E}&7: &f{message}"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ФИЛЬТР МАТА │
@ -120,6 +123,25 @@ errors:
player-not-found: "&#FF6B6BИ&#FF5F5Fг&#FF5353р&#FF4747о&#FF3B3Bк &#FF2F2Fн&#FF2323е &#FF1717н&#FF0B0Bа&#FF0000й&#FF0000д&#FF0000е&#FF0000н"
invalid-usage: "&#FFA726И&#FFA322с&#FF9F1Eп&#FF9B1Aо&#FF9716л&#FF9312ь&#FF8F0Eз&#FF8B0Aо&#FF8706в&#FF8302а&#FF8000н&#FF8000и&#FF8000е&#FF8000: &#FF8000{&#FF8000u&#FF8000s&#FF8000a&#FF8000g&#FF8000e&#FF8000}"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ОБЩИЕ СООБЩЕНИЯ │
# └─────────────────────────────────────────────────────────────────────────────┘
general:
no-permission: "{prefix} &#FF6B6BУ вас нет прав!"
players-only: "{prefix} &#FF6B6BТолько для игроков!"
config-reloaded: "{prefix} &#6BCB77Конфиг перезагружен!"
invalid-player: "{prefix} &#FF6B6BИгрок %player% не найден!"
cooldown-active: "{prefix} &#FF6B6BПодождите %time%с перед повторным использованием!"
command-disabled: "{prefix} &#FF6B6BЭта команда отключена!"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ HUB COMMAND │
# └─────────────────────────────────────────────────────────────────────────────┘
hub:
connecting: "{prefix} &#6BCB77Подключение к серверу %server%..."
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ СИСТЕМА МУТОВ │
# └─────────────────────────────────────────────────────────────────────────────┘
@ -130,4 +152,22 @@ mute:
already-muted: "&#FFA726И&#FFA322г&#FF9F1Eр&#FF9B1Aо&#FF9716к &#FF9312у&#FF8F0Eж&#FF8B0Aе &#FF8706з&#FF8302а&#FF8000м&#FF8000у&#FF8000ч&#FF8000е&#FF8000н"
not-muted: "&#FFA726И&#FFA322г&#FF9F1Eр&#FF9B1Aо&#FF9716к &#FF9312н&#FF8F0Eе &#FF8B0Aз&#FF8706а&#FF8302м&#FF8000у&#FF8000ч&#FF8000е&#FF8000н"
you-muted: "&#FF6B6BВ&#FF5F5Fы &#FF5353з&#FF4747а&#FF3B3Bм&#FF2F2Fу&#FF2323ч&#FF1717е&#FF0B0Bн&#FF0000ы&#FF0000! &#FF0000О&#FF0000с&#FF0000т&#FF0000а&#FF0000л&#FF0000о&#FF0000с&#FF0000ь&#FF0000: &#FF0000{&#FF0000t&#FF0000i&#FF0000m&#FF0000e&#FF0000}"
permanent: "&#FF6B6BВ&#FF5F5Fы &#FF5353з&#FF4747а&#FF3B3Bм&#FF2F2Fу&#FF2323ч&#FF1717е&#FF0B0Bн&#FF0000ы &#FF0000н&#FF0000а&#FF0000в&#FF0000с&#FF0000е&#FF0000г&#FF0000д&#FF0000а&#FF0000!"
permanent: "&#FF6B6BВ&#FF5F5Fы &#FF5353з&#FF4747а&#FF3B3Bм&#FF2F2Fу&#FF2323ч&#FF1717е&#FF0B0Bн&#FF0000ы &#FF0000н&#FF0000а&#FF0000в&#FF0000с&#FF0000е&#FF0000г&#FF0000д&#FF0000а&#FF0000!"
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ ГРАДИЕНТНЫЕ НИКИ │
# └─────────────────────────────────────────────────────────────────────────────┘
gradient:
color-set: "&#6BCB77Градиент установлен!"
color-enabled: "&#6BCB77Градиентный ник включен"
color-disabled: "&#FF6B6BГрадиентный ник отключен"
color-reset: "&#FFA726Градиент сброшен"
prefix-set: "&#6BCB77Префикс установлен!"
prefix-reset: "&#FFA726Префикс сброшен"
invalid-hex: "&#FF6B6BНеверный HEX цвет: {color}"
too-many-colors: "&#FF6B6BСлишком много цветов! Максимум: {max}"
too-few-colors: "&#FF6B6BСлишком мало цветов! Минимум: {min}"
cooldown: "&#FFA726Подождите {time} сек"
not-enough-points: "&#FF6B6BНедостаточно поинтов! Нужно: {price}"
player-not-found: "&#FF6B6BИгрок не найден"

View file

@ -56,6 +56,12 @@ commands:
permission: chat.pm.ignore
aliases: [ разигнор, гтшптщку ]
ignorelist:
description: List ignored players
usage: /ignorelist
permission: chat.pm.ignore
aliases: [ игнорлист, шптщкудшые ]
announce:
description: Send announcement
usage: /announce <message>
@ -86,6 +92,11 @@ commands:
permission: lochat.clearchat.config
aliases: [ ccc, настройкаочистки ]
hub:
description: Connect to hub server
usage: /hub
aliases: [ lobby, хаб, рги ]
lochat:
description: LoChat admin command
usage: /lochat [reload]
@ -140,6 +151,134 @@ commands:
permission: lochat.muteblame
aliases: [ muteblame, мутблейм, ьгеуидфьу ]
# ═══════════════════════════════════════════════════════════════════════════════
# КАСТОМНЫЕ КОМАНДЫ
# ═══════════════════════════════════════════════════════════════════════════════
help:
description: Show server help
usage: /help
aliases: [ помощь, хелп ]
rules:
description: Show server rules
usage: /rules
aliases: [ правила, rule ]
discord:
description: Show Discord invite
usage: /discord
aliases: [ дискорд, ds ]
website:
description: Show website link
usage: /website
aliases: [ сайт, site ]
coords:
description: Show your coordinates
usage: /coords
aliases: [ координаты, pos, position ]
time:
description: Show server time
usage: /time
aliases: [ время, дата ]
playerinfo:
description: Show player information
usage: /playerinfo [player]
permission: lochat.playerinfo
aliases: [ pinfo, инфо, info ]
sounds:
description: Toggle sound effects
usage: /sounds [on|off]
aliases: [ звуки, sound ]
automessage:
description: Toggle auto messages
usage: /automessage [on|off]
aliases: [ автосообщения, am ]
stats:
description: Show chat statistics
usage: /stats [player]
permission: lochat.stats
aliases: [ статистика, статы ]
top:
description: Show top chatters
usage: /top [messages|playtime]
aliases: [ топ, рейтинг ]
me:
description: Send action message
usage: /me <action>
permission: chat.me
aliases: [ action, действие ]
broadcast:
description: Broadcast message to all players
usage: /broadcast <message>
permission: lochat.broadcast
aliases: [ bc, объявить ]
maintenance:
description: Toggle maintenance mode
usage: /maintenance [on|off] [reason]
permission: lochat.maintenance
aliases: [ тех-работы, техработы ]
motd:
description: Show message of the day
usage: /motd
aliases: [ сообщение-дня, мотд ]
ping:
description: Show your ping
usage: /ping [player]
aliases: [ пинг ]
list:
description: Show online players
usage: /list
aliases: [ онлайн, online, who ]
afk:
description: Toggle AFK status
usage: /afk [reason]
aliases: [ афк, away ]
back:
description: Return from AFK
usage: /back
aliases: [ назад, return ]
tps:
description: Show server TPS
usage: /tps
permission: lochat.tps
aliases: [ тпс, performance ]
memory:
description: Show server memory usage
usage: /memory
permission: lochat.memory
aliases: [ mem, память, ram ]
version:
description: Show plugin version
usage: /version
permission: lochat.version
aliases: [ ver, версия ]
reload:
description: Reload plugin configuration
usage: /reload
permission: lochat.reload
aliases: [ rl, перезагрузить ]
permissions:
chat.global.use:
default: true
@ -256,3 +395,50 @@ permissions:
lochat.bypass.ipfilter:
description: Bypass IP filter
default: op
lochat.bypass.caps:
description: Bypass caps filter
default: op
lochat.bypass.hiddenurls:
description: Bypass hidden URLs filter
default: op
lochat.bypass.domains:
description: Bypass domains filter
default: op
# ═══════════════════════════════════════════════════════════════════════════════
# ПРАВА КАСТОМНЫХ КОМАНД
# ═══════════════════════════════════════════════════════════════════════════════
lochat.playerinfo:
description: Can view player information
default: op
lochat.stats:
description: Can view chat statistics
default: op
chat.me:
description: Can use /me command
default: true
lochat.broadcast:
description: Can broadcast messages
default: op
lochat.maintenance:
description: Can toggle maintenance mode
default: op
lochat.tps:
description: Can view server TPS
default: op
lochat.memory:
description: Can view server memory
default: op
lochat.version:
description: Can view plugin version
default: true
lochat.reload:
description: Can reload plugin
default: op
lochat.afk:
description: Can use AFK commands
default: true
lochat.ping.others:
description: Can view other players' ping
default: op