Рефакторинг: KISS принципы, разбиение god-классов, реорганизация

- Создан RatConfig.java с централизованными константами
- MuteServiceImpl: 261→170 строк (Strategy pattern)
- MessagingServiceImpl: 219→124 строк (3 отдельных сервиса)
- ServiceFactory для создания сервисов
- Реорганизованы директории: utils/, commands/moderation/, commands/admin/
- Все директории теперь ≤6 файлов
This commit is contained in:
loki5512344 2026-04-07 12:48:23 +02:00
parent 6119feafcf
commit f45786c6af
83 changed files with 747 additions and 514 deletions

View file

@ -1,10 +1,14 @@
package com.loki.lochat.commands;
import com.loki.lochat.LoChat;
import com.loki.lochat.commands.admin.*;
import com.loki.lochat.commands.admin.chat.*;
import com.loki.lochat.commands.admin.system.*;
import com.loki.lochat.commands.admin.broadcast.*;
import com.loki.lochat.commands.chat.*;
import com.loki.lochat.commands.messaging.*;
import com.loki.lochat.commands.moderation.*;
import com.loki.lochat.commands.moderation.ban.*;
import com.loki.lochat.commands.moderation.mute.*;
import com.loki.lochat.commands.moderation.warn.*;
import com.loki.lochat.commands.nick.*;
import com.loki.lochat.commands.rp.*;
import org.bukkit.command.PluginCommand;

View file

@ -2,7 +2,7 @@ package com.loki.lochat.commands;
import com.loki.lochat.LoChat;
import com.loki.lochat.managers.CustomCommandManager;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.format.ChatFormatter;
import net.kyori.adventure.text.Component;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;

View file

@ -1,7 +1,7 @@
package com.loki.lochat.commands.admin;
package com.loki.lochat.commands.admin.broadcast;
import com.loki.lochat.LoChat;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.format.ChatFormatter;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.title.Title;
import org.bukkit.Bukkit;

View file

@ -1,8 +1,8 @@
package com.loki.lochat.commands.admin;
package com.loki.lochat.commands.admin.broadcast;
import com.loki.lochat.LoChat;
import com.loki.lochat.integrations.DiscordIntegration;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.format.ChatFormatter;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;

View file

@ -1,8 +1,8 @@
package com.loki.lochat.commands.admin;
package com.loki.lochat.commands.admin.chat;
import com.loki.lochat.LoChat;
import com.loki.lochat.api.service.MessagingService;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.format.ChatFormatter;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;

View file

@ -1,7 +1,7 @@
package com.loki.lochat.commands.admin;
package com.loki.lochat.commands.admin.chat;
import com.loki.lochat.LoChat;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.format.ChatFormatter;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;

View file

@ -1,7 +1,7 @@
package com.loki.lochat.commands.admin;
package com.loki.lochat.commands.admin.chat;
import com.loki.lochat.LoChat;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.format.ChatFormatter;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;

View file

@ -1,9 +1,9 @@
package com.loki.lochat.commands.admin;
package com.loki.lochat.commands.admin.system;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import com.loki.lochat.LoChat;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.format.ChatFormatter;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;

View file

@ -1,7 +1,7 @@
package com.loki.lochat.commands.admin;
package com.loki.lochat.commands.admin.system;
import com.loki.lochat.LoChat;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.format.ChatFormatter;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;

View file

@ -1,7 +1,7 @@
package com.loki.lochat.commands.admin;
package com.loki.lochat.commands.admin.system;
import com.loki.lochat.LoChat;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.format.ChatFormatter;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;

View file

@ -2,7 +2,7 @@ package com.loki.lochat.commands.chat;
import com.loki.lochat.LoChat;
import com.loki.lochat.api.service.ChatService;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.format.ChatFormatter;
import net.kyori.adventure.text.minimessage.MiniMessage;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;

View file

@ -2,7 +2,7 @@ package com.loki.lochat.commands.chat;
import com.loki.lochat.LoChat;
import com.loki.lochat.api.service.ChatService;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.format.ChatFormatter;
import net.kyori.adventure.text.minimessage.MiniMessage;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;

View file

@ -2,7 +2,7 @@ package com.loki.lochat.commands.messaging;
import com.loki.lochat.LoChat;
import com.loki.lochat.api.service.MessagingService;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.format.ChatFormatter;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;

View file

@ -2,8 +2,8 @@ package com.loki.lochat.commands.messaging;
import com.loki.lochat.LoChat;
import com.loki.lochat.api.service.MessagingService;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.PlayerUtil;
import com.loki.lochat.utils.format.ChatFormatter;
import com.loki.lochat.utils.player.PlayerUtil;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;

View file

@ -2,8 +2,8 @@ package com.loki.lochat.commands.messaging;
import com.loki.lochat.LoChat;
import com.loki.lochat.api.service.MessagingService;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.PlayerUtil;
import com.loki.lochat.utils.format.ChatFormatter;
import com.loki.lochat.utils.player.PlayerUtil;
import org.bukkit.Bukkit;
import org.bukkit.Sound;
import org.bukkit.command.Command;

View file

@ -2,8 +2,8 @@ package com.loki.lochat.commands.messaging;
import com.loki.lochat.LoChat;
import com.loki.lochat.api.service.MessagingService;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.PlayerUtil;
import com.loki.lochat.utils.format.ChatFormatter;
import com.loki.lochat.utils.player.PlayerUtil;
import org.bukkit.Bukkit;
import org.bukkit.Sound;
import org.bukkit.command.Command;

View file

@ -2,7 +2,7 @@ package com.loki.lochat.commands.messaging;
import com.loki.lochat.LoChat;
import com.loki.lochat.api.service.MessagingService;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.format.ChatFormatter;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;

View file

@ -1,12 +1,12 @@
package com.loki.lochat.commands.moderation;
package com.loki.lochat.commands.moderation.ban;
import com.loki.lochat.LoChat;
import com.loki.lochat.api.service.MuteService;
import com.loki.lochat.api.service.PunishmentService;
import com.loki.lochat.config.MessagesConfig;
import com.loki.lochat.data.model.BanRecord;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.PlayerUtil;
import com.loki.lochat.utils.format.ChatFormatter;
import com.loki.lochat.utils.player.PlayerUtil;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;

View file

@ -1,10 +1,10 @@
package com.loki.lochat.commands.moderation;
package com.loki.lochat.commands.moderation.ban;
import com.loki.lochat.LoChat;
import com.loki.lochat.api.service.PunishmentService;
import com.loki.lochat.config.MessagesConfig;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.PlayerUtil;
import com.loki.lochat.utils.format.ChatFormatter;
import com.loki.lochat.utils.player.PlayerUtil;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;

View file

@ -1,4 +1,4 @@
package com.loki.lochat.commands.moderation;
package com.loki.lochat.commands.moderation.mute;
import com.loki.lochat.LoChat;
import com.loki.lochat.api.service.MuteService;

View file

@ -1,9 +1,9 @@
package com.loki.lochat.commands.moderation;
package com.loki.lochat.commands.moderation.mute;
import com.loki.lochat.LoChat;
import com.loki.lochat.api.service.MuteService;
import com.loki.lochat.config.MessagesConfig;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.format.ChatFormatter;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
@ -93,12 +93,12 @@ public class MuteCommand implements CommandExecutor, TabCompleter {
return true;
}
UUID targetUUID = com.loki.lochat.utils.PlayerUtil.findPlayerUUID(targetName);
UUID targetUUID = com.loki.lochat.utils.player.PlayerUtil.findPlayerUUID(targetName);
if (targetUUID == null) { sender.sendMessage(plugin.getMessageConfig().getComponent("errors.player-not-found")); return true; }
if (muteService.isMuted(targetUUID)) { sender.sendMessage(ChatFormatter.parse("&#CF6679Игрок уже замучен!")); return true; }
Player target = Bukkit.getPlayer(targetUUID);
String finalName = com.loki.lochat.utils.PlayerUtil.getPlayerName(targetUUID);
String finalName = com.loki.lochat.utils.player.PlayerUtil.getPlayerName(targetUUID);
String op = sender.getName();
muteService.mute(targetUUID, finalName, duration, reason, op);

View file

@ -1,4 +1,4 @@
package com.loki.lochat.commands.moderation;
package com.loki.lochat.commands.moderation.mute;
import com.loki.lochat.LoChat;
import com.loki.lochat.api.service.MuteService;
@ -34,7 +34,7 @@ public class MuteHistoryCommand implements CommandExecutor, TabCompleter {
if (!sender.hasPermission("lochat.mutehistory")) { sender.sendMessage(plugin.getMessageConfig().getComponent("errors.no-permission")); return true; }
if (args.length < 1) { sender.sendMessage("&#CF6679Использование: /lmutehistory <ник>"); return true; }
UUID uuid = com.loki.lochat.utils.PlayerUtil.findPlayerUUID(args[0]);
UUID uuid = com.loki.lochat.utils.player.PlayerUtil.findPlayerUUID(args[0]);
if (uuid == null) uuid = muteService.getUUIDByName(args[0]);
if (uuid == null) { sender.sendMessage(plugin.getMessageConfig().getComponent("errors.player-not-found")); return true; }

View file

@ -1,4 +1,4 @@
package com.loki.lochat.commands.moderation;
package com.loki.lochat.commands.moderation.mute;
import com.loki.lochat.LoChat;
import com.loki.lochat.api.service.MuteService;

View file

@ -1,8 +1,8 @@
package com.loki.lochat.commands.moderation;
package com.loki.lochat.commands.moderation.mute;
import com.loki.lochat.LoChat;
import com.loki.lochat.api.service.MuteService;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.format.ChatFormatter;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
@ -42,10 +42,10 @@ public class UnmuteCommand implements CommandExecutor, TabCompleter {
return true;
}
UUID uuid = com.loki.lochat.utils.PlayerUtil.findPlayerUUID(targetName);
UUID uuid = com.loki.lochat.utils.player.PlayerUtil.findPlayerUUID(targetName);
if (uuid == null) { sender.sendMessage(plugin.getMessageConfig().getComponent("errors.player-not-found")); return true; }
String name = com.loki.lochat.utils.PlayerUtil.getPlayerName(uuid);
String name = com.loki.lochat.utils.player.PlayerUtil.getPlayerName(uuid);
Player target = Bukkit.getPlayer(uuid);
String op = sender.getName();

View file

@ -1,10 +1,10 @@
package com.loki.lochat.commands.moderation;
package com.loki.lochat.commands.moderation.warn;
import com.loki.lochat.LoChat;
import com.loki.lochat.api.service.PunishmentService;
import com.loki.lochat.config.MessagesConfig;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.PlayerUtil;
import com.loki.lochat.utils.format.ChatFormatter;
import com.loki.lochat.utils.player.PlayerUtil;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;

View file

@ -1,10 +1,10 @@
package com.loki.lochat.commands.moderation;
package com.loki.lochat.commands.moderation.warn;
import com.loki.lochat.LoChat;
import com.loki.lochat.api.service.PunishmentService;
import com.loki.lochat.config.MessagesConfig;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.PlayerUtil;
import com.loki.lochat.utils.format.ChatFormatter;
import com.loki.lochat.utils.player.PlayerUtil;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;

View file

@ -2,7 +2,7 @@ package com.loki.lochat.commands.nick;
import com.loki.lochat.LoChat;
import com.loki.lochat.api.service.NickService;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.format.ChatFormatter;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.command.Command;

View file

@ -6,8 +6,8 @@ import com.loki.lochat.api.service.PunishmentService;
import com.loki.lochat.data.model.BanRecord;
import com.loki.lochat.data.model.MuteData;
import com.loki.lochat.data.model.WarnEntry;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.PlayerUtil;
import com.loki.lochat.utils.format.ChatFormatter;
import com.loki.lochat.utils.player.PlayerUtil;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;

View file

@ -3,7 +3,7 @@ package com.loki.lochat.commands.rp;
import com.loki.lochat.LoChat;
import com.loki.lochat.api.service.PlayerService;
import com.loki.lochat.commands.base.PlayerCommand;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.format.ChatFormatter;
import net.kyori.adventure.text.Component;
import org.bukkit.command.Command;
import org.bukkit.entity.Player;

View file

@ -3,7 +3,7 @@ package com.loki.lochat.commands.rp;
import com.loki.lochat.LoChat;
import com.loki.lochat.api.service.PlayerService;
import com.loki.lochat.commands.base.PlayerCommand;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.format.ChatFormatter;
import net.kyori.adventure.text.Component;
import org.bukkit.command.Command;
import org.bukkit.entity.Player;

View file

@ -2,7 +2,8 @@ package com.loki.lochat.commands.rp;
import com.loki.lochat.LoChat;
import com.loki.lochat.commands.base.PlayerCommand;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.config.RatConfig;
import com.loki.lochat.utils.format.ChatFormatter;
import net.kyori.adventure.text.Component;
import org.bukkit.command.Command;
import org.bukkit.entity.Player;
@ -20,8 +21,6 @@ import java.util.Random;
public class RollCommand extends PlayerCommand {
private static final Random RANDOM = new Random();
private static final int DEFAULT_MAX = 100;
private static final int ABSOLUTE_MAX = 1_000_000;
public RollCommand(LoChat plugin) {
super(plugin);
@ -32,7 +31,7 @@ public class RollCommand extends PlayerCommand {
@NotNull String label, @NotNull String[] args) {
if (!requirePermission(player, "lochat.rp.roll")) return true;
int max = DEFAULT_MAX;
int max = RatConfig.ROLL_DEFAULT_MAX;
if (args.length >= 1) {
try {
@ -43,7 +42,7 @@ public class RollCommand extends PlayerCommand {
"<red>Минимальное значение кубика: 2</red>")));
return true;
}
if (max > ABSOLUTE_MAX) {
if (max > RatConfig.ROLL_ABSOLUTE_MAX) {
player.sendMessage(ChatFormatter.parse(
plugin.getConfigManager().getString("rp.roll-max-error",
"<red>Максимальное значение кубика: 1000000</red>")));

View file

@ -1,7 +1,7 @@
package com.loki.lochat.commands.rp;
import com.loki.lochat.LoChat;
import com.loki.lochat.utils.DistanceUtil;
import com.loki.lochat.utils.player.DistanceUtil;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import org.bukkit.Bukkit;

View file

@ -3,7 +3,7 @@ package com.loki.lochat.commands.rp;
import com.loki.lochat.LoChat;
import com.loki.lochat.api.service.PlayerService;
import com.loki.lochat.commands.base.PlayerCommand;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.format.ChatFormatter;
import net.kyori.adventure.text.Component;
import org.bukkit.command.Command;
import org.bukkit.entity.Player;

View file

@ -1,7 +1,7 @@
package com.loki.lochat.config;
import com.loki.lochat.LoChat;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.format.ChatFormatter;
import org.bukkit.configuration.file.FileConfiguration;
import java.util.List;

View file

@ -1,7 +1,7 @@
package com.loki.lochat.config;
import com.loki.lochat.LoChat;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.format.ChatFormatter;
import net.kyori.adventure.text.Component;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.FileConfiguration;

View file

@ -0,0 +1,67 @@
package com.loki.lochat.config;
import java.util.List;
/**
* Централизованная конфигурация констант с поддержкой переменных окружения
* KISS: все хардкод значения в одном месте
*/
public final class RatConfig {
// ========== Nick validation ==========
public static final int NICK_MIN_LENGTH = getEnvOrDefault("LOCHAT_NICK_MIN", 3);
public static final int NICK_MAX_LENGTH = getEnvOrDefault("LOCHAT_NICK_MAX", 16);
// ========== Roll limits ==========
public static final int ROLL_DEFAULT_MAX = getEnvOrDefault("LOCHAT_ROLL_DEFAULT", 100);
public static final int ROLL_ABSOLUTE_MAX = getEnvOrDefault("LOCHAT_ROLL_MAX", 1_000_000);
// ========== Mute history ==========
public static final int MAX_HISTORY_PER_PLAYER = getEnvOrDefault("LOCHAT_MUTE_HISTORY", 50);
// ========== Time constants ==========
public static final long MILLIS_PER_SECOND = 1000L;
public static final int SECONDS_IN_MINUTE = 60;
public static final int MINUTES_IN_HOUR = 60;
public static final int HOURS_IN_DAY = 24;
// ========== Folia/Paper compatibility ==========
public static final int TICKS_PER_SECOND = 20;
public static final int MILLIS_PER_TICK = 50;
// ========== Math constants ==========
public static final int PERCENTAGE_MULTIPLIER = 100;
// ========== GUI slots ==========
public static final int GUI_CONFIRM_SLOT = 11;
public static final int GUI_CANCEL_SLOT = 15;
public static final int GUI_PREVIEW_SLOT = 13;
// ========== LuckPerms ==========
public static final int LUCKPERMS_PREFIX_PRIORITY = 100;
// ========== Gradient presets ==========
public static final List<String> PRESET_COLORS = List.of(
"#FF0000", "#FF7F00", "#FFFF00", "#00FF00",
"#0000FF", "#4B0082", "#9400D3", "#FF69B4",
"#00FFFF", "#FFD700", "#FFFFFF", "#000000"
);
private RatConfig() {
}
/**
* Получить значение из переменной окружения или вернуть дефолт
*/
private static int getEnvOrDefault(String envKey, int defaultValue) {
String envValue = System.getenv(envKey);
if (envValue != null) {
try {
return Integer.parseInt(envValue);
} catch (NumberFormatException e) {
return defaultValue;
}
}
return defaultValue;
}
}

View file

@ -0,0 +1,42 @@
package com.loki.lochat.core.factory;
import com.loki.lochat.api.service.MuteService;
import com.loki.lochat.core.service.MuteServiceImpl;
import com.loki.lochat.core.service.mute.MuteDataStorage;
import com.loki.lochat.core.service.mute.MuteHistoryManager;
import com.loki.lochat.core.service.mute.strategies.ChatMuteStrategy;
import com.loki.lochat.core.service.mute.strategies.MuteStrategy;
import com.loki.lochat.core.service.mute.strategies.VoiceMuteStrategy;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.File;
import java.util.List;
/**
* Фабрика для создания сервисов
* Factory pattern для инициализации сложных объектов
*/
public class ServiceFactory {
/**
* Создать MuteService со всеми зависимостями
*/
public static MuteService createMuteService(JavaPlugin plugin) {
// Создаем стратегии
List<MuteStrategy> strategies = List.of(
new ChatMuteStrategy(),
new VoiceMuteStrategy(plugin)
);
// Создаем хранилище данных
MuteDataStorage storage = new MuteDataStorage(plugin);
storage.load();
// Создаем менеджер истории
File historyFile = new File(plugin.getDataFolder(), "mute-history.json");
MuteHistoryManager historyManager = new MuteHistoryManager(historyFile);
// Собираем сервис
return new MuteServiceImpl(plugin, strategies, storage, historyManager);
}
}

View file

@ -4,7 +4,7 @@ import com.loki.lochat.api.filter.MessageFilter;
import com.loki.lochat.api.service.MuteService;
import com.loki.lochat.config.MessagesConfig;
import com.loki.lochat.data.model.ChatMessage;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.format.ChatFormatter;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;

View file

@ -3,6 +3,7 @@ package com.loki.lochat.core.registry;
import com.loki.lochat.api.service.*;
import com.loki.lochat.config.ConfigManager;
import com.loki.lochat.config.MessageConfig;
import com.loki.lochat.core.factory.ServiceFactory;
import com.loki.lochat.core.service.*;
import org.bukkit.plugin.java.JavaPlugin;
@ -25,7 +26,7 @@ public class ServiceRegistry {
private void registerServicesWithDeps(ConfigManager configManager, MessageConfig messageConfig) {
register(ChatService.class, new ChatServiceImpl(plugin, this));
register(MuteService.class, new MuteServiceImpl(plugin));
register(MuteService.class, ServiceFactory.createMuteService(plugin));
// ✅ NEW: Объединённый PlayerService (Cooldown + PlayerData)
PlayerService playerService = new PlayerServiceImpl(plugin);
@ -36,7 +37,7 @@ public class ServiceRegistry {
// ✅ NEW: Объединённый MessagingService (PM + Spy + Ignore)
MessagingService messagingService = new MessagingServiceImpl(plugin, messageConfig);
register(MessagingService.class, messagingService);
register(MentionService.class, new MentionServiceImpl(configManager));
register(NickService.class, new NickServiceImpl(plugin));
register(PunishmentService.class, new PunishmentServiceImpl(plugin, configManager.getMessagesConfig()));

View file

@ -3,9 +3,9 @@ package com.loki.lochat.core.service;
import com.loki.lochat.api.service.ChatService;
import com.loki.lochat.core.registry.ServiceRegistry;
import com.loki.lochat.renderer.EnhancedChatRenderer;
import com.loki.lochat.utils.DistanceUtil;
import com.loki.lochat.utils.FoliaUtil;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.player.DistanceUtil;
import com.loki.lochat.utils.platform.FoliaUtil;
import com.loki.lochat.utils.format.ChatFormatter;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.YamlConfiguration;

View file

@ -2,7 +2,7 @@ package com.loki.lochat.core.service;
import com.loki.lochat.api.service.MentionService;
import com.loki.lochat.config.ConfigManager;
import com.loki.lochat.utils.PlayerUtil;
import com.loki.lochat.utils.player.PlayerUtil;
import org.bukkit.Bukkit;
import org.bukkit.Sound;
import org.bukkit.entity.Player;

View file

@ -2,218 +2,123 @@ package com.loki.lochat.core.service;
import com.loki.lochat.api.service.MessagingService;
import com.loki.lochat.config.MessageConfig;
import com.loki.lochat.utils.FoliaUtil;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.core.service.messaging.IgnoreService;
import com.loki.lochat.core.service.messaging.PrivateMessageService;
import com.loki.lochat.core.service.messaging.SpyService;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
/**
* Объединённая реализация сервиса общения
* Включает: PM, Spy, Ignore
* Фасад для сервисов общения
* Делегирует вызовы: PrivateMessageService, SpyService, IgnoreService
*/
public class MessagingServiceImpl implements MessagingService {
private final JavaPlugin plugin;
private final MessageConfig messageConfig;
private final File ignoreFile;
// PM state
private final Map<UUID, UUID> lastConversation = new ConcurrentHashMap<>();
// Spy state
private final Set<UUID> spyEnabled = ConcurrentHashMap.newKeySet();
// Ignore state
private final Map<UUID, Set<UUID>> ignoreMap = new ConcurrentHashMap<>();
private final PrivateMessageService pmService;
private final SpyService spyService;
private final IgnoreService ignoreService;
public MessagingServiceImpl(JavaPlugin plugin, MessageConfig messageConfig) {
this.plugin = plugin;
this.messageConfig = messageConfig;
this.ignoreFile = new File(plugin.getDataFolder(), "ignores.yml");
load();
this.pmService = new PrivateMessageService();
this.spyService = new SpyService(messageConfig);
this.ignoreService = new IgnoreService(plugin);
}
// ========== PM Implementation ==========
// ========== PM Delegation ==========
@Override
public void setLastConversation(UUID player, UUID target) {
lastConversation.put(player, target);
pmService.setLastConversation(player, target);
}
@Override
public Optional<UUID> getLastConversation(UUID player) {
return Optional.ofNullable(lastConversation.get(player));
return pmService.getLastConversation(player);
}
@Override
public void removeConversation(UUID player) {
lastConversation.remove(player);
pmService.removeConversation(player);
}
@Override
public boolean hasConversation(UUID player) {
return lastConversation.containsKey(player);
return pmService.hasConversation(player);
}
// ========== Spy Implementation ==========
// ========== Spy Delegation ==========
@Override
public boolean toggleSpy(UUID player) {
if (spyEnabled.contains(player)) {
spyEnabled.remove(player);
return false;
} else {
spyEnabled.add(player);
return true;
}
return spyService.toggleSpy(player);
}
@Override
public boolean isSpying(UUID player) {
return spyEnabled.contains(player);
return spyService.isSpying(player);
}
@Override
public void broadcastPM(Player sender, Player receiver, String message) {
String format = messageConfig.get("spy.format");
for (UUID spyUuid : spyEnabled) {
Player spy = Bukkit.getPlayer(spyUuid);
if (spy != null && spy.isOnline() && !spy.equals(sender) && !spy.equals(receiver)) {
spy.sendMessage(ChatFormatter.parse(format
.replace("{sender}", sender.getName())
.replace("{receiver}", receiver.getName())
.replace("{message}", message)));
}
}
spyService.broadcastPM(sender, receiver, message);
}
@Override
public void sendToSpies(Player sender, Component message, boolean isGlobal) {
if (spyEnabled.isEmpty()) return;
String chatType = isGlobal ? "Global" : "Local";
String plainMessage = PlainTextComponentSerializer.plainText().serialize(message);
String format = messageConfig.get("spy.chat-format",
"§7[SPY] §e{type} §7{sender}: §f{message}");
for (UUID spyUuid : spyEnabled) {
Player spy = Bukkit.getPlayer(spyUuid);
if (spy != null && spy.isOnline() && !spy.equals(sender)) {
spy.sendMessage(ChatFormatter.parse(format
.replace("{type}", chatType)
.replace("{sender}", sender.getName())
.replace("{message}", plainMessage)));
}
}
spyService.sendToSpies(sender, message, isGlobal);
}
@Override
public void removeSpy(UUID player) {
spyEnabled.remove(player);
spyService.removeSpy(player);
}
// ========== Ignore Implementation ==========
// ========== Ignore Delegation ==========
@Override
public boolean isIgnoring(UUID player, UUID target) {
Set<UUID> ignored = ignoreMap.get(player);
return ignored != null && ignored.contains(target);
return ignoreService.isIgnoring(player, target);
}
@Override
public boolean addIgnore(UUID player, UUID target) {
Set<UUID> ignored = ignoreMap.computeIfAbsent(player, k -> ConcurrentHashMap.newKeySet());
boolean added = ignored.add(target);
if (added) saveAsync();
return added;
return ignoreService.addIgnore(player, target);
}
@Override
public boolean removeIgnore(UUID player, UUID target) {
Set<UUID> ignored = ignoreMap.get(player);
if (ignored == null) return false;
boolean removed = ignored.remove(target);
if (removed) saveAsync();
return removed;
return ignoreService.removeIgnore(player, target);
}
@Override
public Set<UUID> getIgnoredPlayers(UUID player) {
return ignoreMap.getOrDefault(player, Collections.emptySet());
return ignoreService.getIgnoredPlayers(player);
}
@Override
public int getIgnoredCount(UUID player) {
Set<UUID> ignored = ignoreMap.get(player);
return ignored == null ? 0 : ignored.size();
return ignoreService.getIgnoredCount(player);
}
@Override
public void clearIgnores(UUID player) {
ignoreMap.remove(player);
saveAsync();
ignoreService.clearIgnores(player);
}
// ========== Persistence ==========
@Override
public void load() {
if (!ignoreFile.exists()) return;
YamlConfiguration config = YamlConfiguration.loadConfiguration(ignoreFile);
for (String key : config.getKeys(false)) {
try {
UUID uuid = UUID.fromString(key);
List<String> ignoredList = config.getStringList(key);
Set<UUID> ignored = ConcurrentHashMap.newKeySet();
for (String ignoredStr : ignoredList) {
try {
ignored.add(UUID.fromString(ignoredStr));
} catch (Exception e) {
// Ignore invalid UUID
}
}
if (!ignored.isEmpty()) {
ignoreMap.put(uuid, ignored);
}
} catch (Exception e) {
// Ignore invalid entry
}
}
ignoreService.load();
}
@Override
public void save() {
YamlConfiguration config = new YamlConfiguration();
for (Map.Entry<UUID, Set<UUID>> entry : ignoreMap.entrySet()) {
List<String> ignoredList = new ArrayList<>();
for (UUID ignored : entry.getValue()) {
ignoredList.add(ignored.toString());
}
config.set(entry.getKey().toString(), ignoredList);
}
try {
config.save(ignoreFile);
} catch (IOException e) {
plugin.getLogger().severe("Не удалось сохранить игноры: " + e.getMessage());
}
}
private void saveAsync() {
FoliaUtil.runAsync(plugin, this::save);
ignoreService.save();
}
}

View file

@ -1,48 +1,36 @@
package com.loki.lochat.core.service;
import com.loki.lochat.api.service.MuteService;
import com.loki.lochat.core.service.mute.MuteDataStorage;
import com.loki.lochat.core.service.mute.MuteHistoryManager;
import com.loki.lochat.core.service.mute.MutePermissionChecker;
import com.loki.lochat.core.service.mute.strategies.MuteStrategy;
import com.loki.lochat.data.model.MuteData;
import com.loki.lochat.utils.FoliaUtil;
import com.loki.lochat.utils.TimeFormatter;
import org.bukkit.Bukkit;
import com.loki.lochat.utils.format.TimeFormatter;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.*;
/**
* Сервис мутов с интеграцией Simple Voice Chat
* Сервис мутов с использованием Strategy pattern
* Разделен на: стратегии мута, хранилище данных, история, проверка прав
*/
public class MuteServiceImpl implements MuteService {
private final JavaPlugin plugin;
private final Map<UUID, MuteData> mutes = new HashMap<>();
private final Map<UUID, List<MuteData.MuteHistoryEntry>> history = new HashMap<>();
private Object voicechatService; // Используем Object для опциональной зависимости
private final List<MuteStrategy> strategies;
private final MuteDataStorage storage;
private final MuteHistoryManager historyManager;
private final MutePermissionChecker permissionChecker;
public MuteServiceImpl(JavaPlugin plugin) {
public MuteServiceImpl(JavaPlugin plugin, List<MuteStrategy> strategies,
MuteDataStorage storage, MuteHistoryManager historyManager) {
this.plugin = plugin;
initVoiceChat();
load();
}
private void initVoiceChat() {
if (Bukkit.getPluginManager().isPluginEnabled("voicechat")) {
try {
// Проверяем наличие класса через рефлексию
Class.forName("de.maxhenkel.voicechat.api.BukkitVoicechatService");
voicechatService = Bukkit.getServicesManager().load(
Class.forName("de.maxhenkel.voicechat.api.BukkitVoicechatService")
);
if (voicechatService != null) {
plugin.getLogger().info("Simple Voice Chat integration enabled!");
}
} catch (ClassNotFoundException e) {
plugin.getLogger().info("VoiceChat API not found, voice mute disabled");
} catch (Exception e) {
plugin.getLogger().warning("Failed to hook into Simple Voice Chat: " + e.getMessage());
}
}
this.strategies = strategies;
this.storage = storage;
this.historyManager = historyManager;
this.permissionChecker = new MutePermissionChecker();
}
@Override
@ -51,20 +39,21 @@ public class MuteServiceImpl implements MuteService {
plugin.getLogger().warning("Attempted to mute player with invalid data");
return;
}
long endTime = duration > 0 ? System.currentTimeMillis() + duration : 0;
MuteData data = new MuteData(uuid, playerName, endTime, reason, mutedBy);
mutes.put(uuid, data);
addToHistory(uuid, playerName, duration, reason, mutedBy);
// Мутим в голосовом чате
muteVoiceChat(uuid, true);
saveAsync();
plugin.getLogger().info("Player " + playerName + " muted by " + mutedBy +
" for " + (duration > 0 ? formatTime(duration) : "permanent") +
storage.save(data);
historyManager.addEntry(uuid, playerName, duration, reason, mutedBy);
// Применяем все стратегии мута
strategies.forEach(strategy -> {
strategy.apply(uuid);
plugin.getLogger().fine(strategy.getName() + " mute applied to " + playerName);
});
plugin.getLogger().info("Player " + playerName + " muted by " + mutedBy +
" for " + (duration > 0 ? formatTime(duration) : "permanent") +
(reason != null ? " (reason: " + reason + ")" : ""));
}
@ -74,15 +63,17 @@ public class MuteServiceImpl implements MuteService {
plugin.getLogger().warning("Attempted to unmute player with null UUID");
return false;
}
MuteData removed = mutes.remove(uuid);
MuteData removed = storage.remove(uuid);
if (removed != null) {
updateUnmuteInHistory(uuid, unmutedBy);
// Размутим в голосовом чате
muteVoiceChat(uuid, false);
saveAsync();
historyManager.updateUnmute(uuid, unmutedBy);
// Снимаем все стратегии мута
strategies.forEach(strategy -> {
strategy.remove(uuid);
plugin.getLogger().fine(strategy.getName() + " mute removed from " + removed.getPlayerName());
});
plugin.getLogger().info("Player " + removed.getPlayerName() + " unmuted by " + unmutedBy);
return true;
}
@ -93,26 +84,26 @@ public class MuteServiceImpl implements MuteService {
public boolean isMuted(UUID uuid) {
if (uuid == null) return false;
MuteData data = mutes.get(uuid);
MuteData data = storage.get(uuid);
if (data == null) return false;
if (!isExpired(data)) return true;
mutes.remove(uuid);
muteVoiceChat(uuid, false);
saveAsync();
// Мут истек - удаляем
storage.remove(uuid);
strategies.forEach(strategy -> strategy.remove(uuid));
plugin.getLogger().info("Mute expired for player " + data.getPlayerName());
return false;
}
@Override
public MuteData getMuteData(UUID uuid) {
return isMuted(uuid) ? mutes.get(uuid) : null;
return isMuted(uuid) ? storage.get(uuid) : null;
}
@Override
public long getRemainingTime(UUID uuid) {
MuteData data = mutes.get(uuid);
MuteData data = storage.get(uuid);
if (data == null) return 0;
if (data.getEndTime() == 0) return -1;
return Math.max(0, data.getEndTime() - System.currentTimeMillis());
@ -130,62 +121,32 @@ public class MuteServiceImpl implements MuteService {
@Override
public long getMaxDuration(Player player) {
if (player.hasPermission("lochat.mute.dur.perm")) return 0;
String[] durations = {"30d", "14d", "7d", "3d", "1d", "12h", "6h", "1h", "30m", "10m"};
for (String dur : durations) {
if (player.hasPermission("lochat.mute.dur." + dur)) {
return parseTime(dur);
}
}
return -1;
return permissionChecker.getMaxDuration(player);
}
@Override
public boolean canMuteForDuration(Player player, long duration) {
if (player.hasPermission("lochat.mute.dur.perm")) return true;
if (duration == 0) return false;
long maxDuration = getMaxDuration(player);
if (maxDuration == -1) return false;
if (maxDuration == 0) return true;
return duration <= maxDuration;
return permissionChecker.canMuteForDuration(player, duration);
}
@Override
public List<MuteData.MuteHistoryEntry> getPlayerHistory(UUID uuid) {
return history.getOrDefault(uuid, new ArrayList<>());
return historyManager.getHistory(uuid);
}
@Override
public List<MuteData.MuteHistoryEntry> getMutesByOperator(String operatorName) {
List<MuteData.MuteHistoryEntry> result = new ArrayList<>();
history.values().forEach(entries ->
entries.stream()
.filter(e -> e.mutedBy != null && e.mutedBy.equalsIgnoreCase(operatorName))
.forEach(result::add)
);
result.sort((a, b) -> Long.compare(b.mutedAt, a.mutedAt));
return result;
return historyManager.getMutesByOperator(operatorName);
}
@Override
public UUID getUUIDByName(String name) {
for (Map.Entry<UUID, List<MuteData.MuteHistoryEntry>> entry : history.entrySet()) {
for (MuteData.MuteHistoryEntry e : entry.getValue()) {
if (e.playerName != null && e.playerName.equalsIgnoreCase(name)) {
return entry.getKey();
}
}
}
return null;
return historyManager.getUUIDByName(name);
}
@Override
public Map<UUID, MuteData> getActiveMutes() {
mutes.entrySet().removeIf(e -> isExpired(e.getValue()));
return new HashMap<>(mutes);
return storage.getActiveMutes();
}
@Override
@ -199,63 +160,11 @@ public class MuteServiceImpl implements MuteService {
@Override
public void save() {
// TODO: Implement save to file
storage.saveToFile();
historyManager.save();
}
// ========== Voice Chat Integration ==========
private void muteVoiceChat(UUID uuid, boolean mute) {
if (voicechatService == null) return;
try {
Player player = Bukkit.getPlayer(uuid);
if (player != null && player.isOnline()) {
// Используем рефлексию для вызова метода
voicechatService.getClass()
.getMethod("getVoicechat")
.invoke(voicechatService)
.getClass()
.getMethod("setMuted", UUID.class, boolean.class)
.invoke(voicechatService.getClass().getMethod("getVoicechat").invoke(voicechatService),
player.getUniqueId(), mute);
}
} catch (Exception e) {
plugin.getLogger().warning("Failed to " + (mute ? "mute" : "unmute") +
" player in voice chat: " + e.getMessage());
}
}
// ========== Private Methods ==========
private boolean isExpired(MuteData data) {
return data.getEndTime() > 0 && System.currentTimeMillis() > data.getEndTime();
}
private void addToHistory(UUID uuid, String playerName, long duration, String reason, String mutedBy) {
List<MuteData.MuteHistoryEntry> entries = history.computeIfAbsent(uuid, k -> new ArrayList<>());
entries.add(new MuteData.MuteHistoryEntry(
playerName, duration, reason, mutedBy, System.currentTimeMillis(), false, null, 0
));
}
private void updateUnmuteInHistory(UUID uuid, String unmutedBy) {
List<MuteData.MuteHistoryEntry> entries = history.get(uuid);
if (entries != null && !entries.isEmpty()) {
MuteData.MuteHistoryEntry last = entries.get(entries.size() - 1);
if (!last.unmuted) {
entries.set(entries.size() - 1, new MuteData.MuteHistoryEntry(
last.playerName, last.duration, last.reason, last.mutedBy, last.mutedAt,
true, unmutedBy, System.currentTimeMillis()
));
}
}
}
private void load() {
// TODO: Implement load from file
}
private void saveAsync() {
FoliaUtil.runAsync(plugin, this::save);
}
}

View file

@ -1,7 +1,8 @@
package com.loki.lochat.core.service;
import com.loki.lochat.api.service.NickService;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.config.RatConfig;
import com.loki.lochat.utils.format.ChatFormatter;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import org.bukkit.Bukkit;
@ -21,9 +22,6 @@ import java.util.concurrent.ConcurrentHashMap;
* Реализация сервиса кастомных ников
*/
public class NickServiceImpl implements NickService {
// Настройки
private static final int MIN_LENGTH = 3;
private static final int MAX_LENGTH = 16;
private final JavaPlugin plugin;
private final Map<UUID, String> nicknames = new ConcurrentHashMap<>();
private final File dataFile;
@ -150,7 +148,7 @@ public class NickServiceImpl implements NickService {
String cleanNick = stripColors(nickname);
// Проверка длины
if (cleanNick.length() < MIN_LENGTH || cleanNick.length() > MAX_LENGTH) {
if (cleanNick.length() < RatConfig.NICK_MIN_LENGTH || cleanNick.length() > RatConfig.NICK_MAX_LENGTH) {
return false;
}

View file

@ -1,7 +1,7 @@
package com.loki.lochat.core.service;
import com.loki.lochat.api.service.PlayerService;
import com.loki.lochat.utils.FoliaUtil;
import com.loki.lochat.utils.platform.FoliaUtil;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.java.JavaPlugin;

View file

@ -7,9 +7,9 @@ import com.loki.lochat.api.service.PunishmentService;
import com.loki.lochat.config.MessagesConfig;
import com.loki.lochat.data.model.BanRecord;
import com.loki.lochat.data.model.WarnEntry;
import com.loki.lochat.utils.FoliaUtil;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.TimeFormatter;
import com.loki.lochat.utils.platform.FoliaUtil;
import com.loki.lochat.utils.format.ChatFormatter;
import com.loki.lochat.utils.format.TimeFormatter;
import net.kyori.adventure.text.Component;
import org.bukkit.plugin.java.JavaPlugin;

View file

@ -0,0 +1,110 @@
package com.loki.lochat.core.service.messaging;
import com.loki.lochat.utils.platform.FoliaUtil;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
* Сервис игнорирования игроков
* Управляет списками игнорируемых игроков
*/
public class IgnoreService {
private final JavaPlugin plugin;
private final Map<UUID, Set<UUID>> ignoreMap = new ConcurrentHashMap<>();
private final File ignoreFile;
public IgnoreService(JavaPlugin plugin) {
this.plugin = plugin;
this.ignoreFile = new File(plugin.getDataFolder(), "ignores.yml");
load();
}
public boolean isIgnoring(UUID player, UUID target) {
Set<UUID> ignored = ignoreMap.get(player);
return ignored != null && ignored.contains(target);
}
public boolean addIgnore(UUID player, UUID target) {
Set<UUID> ignored = ignoreMap.computeIfAbsent(player, k -> ConcurrentHashMap.newKeySet());
boolean added = ignored.add(target);
if (added) saveAsync();
return added;
}
public boolean removeIgnore(UUID player, UUID target) {
Set<UUID> ignored = ignoreMap.get(player);
if (ignored == null) return false;
boolean removed = ignored.remove(target);
if (removed) saveAsync();
return removed;
}
public Set<UUID> getIgnoredPlayers(UUID player) {
return ignoreMap.getOrDefault(player, Collections.emptySet());
}
public int getIgnoredCount(UUID player) {
Set<UUID> ignored = ignoreMap.get(player);
return ignored == null ? 0 : ignored.size();
}
public void clearIgnores(UUID player) {
ignoreMap.remove(player);
saveAsync();
}
public void load() {
if (!ignoreFile.exists()) return;
YamlConfiguration config = YamlConfiguration.loadConfiguration(ignoreFile);
for (String key : config.getKeys(false)) {
try {
UUID uuid = UUID.fromString(key);
List<String> ignoredList = config.getStringList(key);
Set<UUID> ignored = ConcurrentHashMap.newKeySet();
for (String ignoredStr : ignoredList) {
try {
ignored.add(UUID.fromString(ignoredStr));
} catch (Exception e) {
// Ignore invalid UUID
}
}
if (!ignored.isEmpty()) {
ignoreMap.put(uuid, ignored);
}
} catch (Exception e) {
// Ignore invalid entry
}
}
}
public void save() {
YamlConfiguration config = new YamlConfiguration();
for (Map.Entry<UUID, Set<UUID>> entry : ignoreMap.entrySet()) {
List<String> ignoredList = new ArrayList<>();
for (UUID ignored : entry.getValue()) {
ignoredList.add(ignored.toString());
}
config.set(entry.getKey().toString(), ignoredList);
}
try {
config.save(ignoreFile);
} catch (IOException e) {
plugin.getLogger().severe("Не удалось сохранить игноры: " + e.getMessage());
}
}
private void saveAsync() {
FoliaUtil.runAsync(plugin, this::save);
}
}

View file

@ -0,0 +1,31 @@
package com.loki.lochat.core.service.messaging;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
/**
* Сервис личных сообщений (PM)
* Отслеживает последние диалоги между игроками
*/
public class PrivateMessageService {
private final Map<UUID, UUID> lastConversation = new ConcurrentHashMap<>();
public void setLastConversation(UUID player, UUID target) {
lastConversation.put(player, target);
}
public Optional<UUID> getLastConversation(UUID player) {
return Optional.ofNullable(lastConversation.get(player));
}
public void removeConversation(UUID player) {
lastConversation.remove(player);
}
public boolean hasConversation(UUID player) {
return lastConversation.containsKey(player);
}
}

View file

@ -0,0 +1,77 @@
package com.loki.lochat.core.service.messaging;
import com.loki.lochat.config.MessageConfig;
import com.loki.lochat.utils.format.ChatFormatter;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
/**
* Сервис шпионажа за личными сообщениями
* Позволяет админам видеть PM других игроков
*/
public class SpyService {
private final Set<UUID> spyEnabled = ConcurrentHashMap.newKeySet();
private final MessageConfig messageConfig;
public SpyService(MessageConfig messageConfig) {
this.messageConfig = messageConfig;
}
public boolean toggleSpy(UUID player) {
if (spyEnabled.contains(player)) {
spyEnabled.remove(player);
return false;
} else {
spyEnabled.add(player);
return true;
}
}
public boolean isSpying(UUID player) {
return spyEnabled.contains(player);
}
public void broadcastPM(Player sender, Player receiver, String message) {
String format = messageConfig.get("spy.format");
for (UUID spyUuid : spyEnabled) {
Player spy = Bukkit.getPlayer(spyUuid);
if (spy != null && spy.isOnline() && !spy.equals(sender) && !spy.equals(receiver)) {
spy.sendMessage(ChatFormatter.parse(format
.replace("{sender}", sender.getName())
.replace("{receiver}", receiver.getName())
.replace("{message}", message)));
}
}
}
public void sendToSpies(Player sender, Component message, boolean isGlobal) {
if (spyEnabled.isEmpty()) return;
String chatType = isGlobal ? "Global" : "Local";
String plainMessage = PlainTextComponentSerializer.plainText().serialize(message);
String format = messageConfig.get("spy.chat-format",
"§7[SPY] §e{type} §7{sender}: §f{message}");
for (UUID spyUuid : spyEnabled) {
Player spy = Bukkit.getPlayer(spyUuid);
if (spy != null && spy.isOnline() && !spy.equals(sender)) {
spy.sendMessage(ChatFormatter.parse(format
.replace("{type}", chatType)
.replace("{sender}", sender.getName())
.replace("{message}", plainMessage)));
}
}
}
public void removeSpy(UUID player) {
spyEnabled.remove(player);
}
}

View file

@ -4,7 +4,7 @@ import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import com.loki.lochat.data.model.MuteData;
import com.loki.lochat.utils.FoliaUtil;
import com.loki.lochat.utils.platform.FoliaUtil;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.*;
@ -27,40 +27,24 @@ public class MuteDataStorage {
this.dataFile = new File(plugin.getDataFolder(), "mutes.json");
}
public void addMute(UUID uuid, MuteData data) {
mutes.put(uuid, data);
public void save(MuteData data) {
mutes.put(data.getUuid(), data);
saveAsync();
}
public MuteData removeMute(UUID uuid) {
public MuteData remove(UUID uuid) {
MuteData removed = mutes.remove(uuid);
if (removed != null) {
saveAsync();
}
return removed;
}
public boolean isMuted(UUID uuid) {
if (uuid == null) return false;
MuteData data = mutes.get(uuid);
if (data == null) return false;
if (!isExpired(data)) return true;
boolean removed = mutes.remove(uuid, data);
if (removed) {
saveAsync();
plugin.getLogger().info("Mute expired for player " + data.getPlayerName());
}
return false;
}
public MuteData getMute(UUID uuid) {
public MuteData get(UUID uuid) {
return mutes.get(uuid);
}
public Map<UUID, MuteData> getAllMutes() {
public Map<UUID, MuteData> getActiveMutes() {
mutes.entrySet().removeIf(entry -> isExpired(entry.getValue()));
return new HashMap<>(mutes);
}
@ -90,7 +74,11 @@ public class MuteDataStorage {
}
}
public void save() {
public void saveToFile() {
save();
}
private void save() {
try {
ensureDataFolderExists();

View file

@ -1,8 +1,9 @@
package com.loki.lochat.core.service;
package com.loki.lochat.core.service.mute;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import com.loki.lochat.config.RatConfig;
import com.loki.lochat.data.model.MuteData;
import java.io.File;
@ -15,9 +16,6 @@ import java.util.concurrent.ConcurrentHashMap;
public class MuteHistoryManager {
// ✅ FIX: Ограничиваем размер истории для предотвращения утечки памяти
private static final int MAX_HISTORY_PER_PLAYER = 50;
private final Map<UUID, List<MuteData.MuteHistoryEntry>> history = new ConcurrentHashMap<>();
private final File historyFile;
private final Gson gson = new GsonBuilder().setPrettyPrinting().create();
@ -41,7 +39,7 @@ public class MuteHistoryManager {
));
// ✅ FIX: Удаляем старые записи если превышен лимит
if (entries.size() > MAX_HISTORY_PER_PLAYER) {
if (entries.size() > RatConfig.MAX_HISTORY_PER_PLAYER) {
entries.remove(0); // Удаляем самую старую запись
}
}
@ -62,6 +60,28 @@ public class MuteHistoryManager {
return history.getOrDefault(uuid, Collections.emptyList());
}
public List<MuteData.MuteHistoryEntry> getMutesByOperator(String operatorName) {
List<MuteData.MuteHistoryEntry> result = new ArrayList<>();
history.values().forEach(entries ->
entries.stream()
.filter(e -> e.mutedBy != null && e.mutedBy.equalsIgnoreCase(operatorName))
.forEach(result::add)
);
result.sort((a, b) -> Long.compare(b.mutedAt, a.mutedAt));
return result;
}
public UUID getUUIDByName(String name) {
for (Map.Entry<UUID, List<MuteData.MuteHistoryEntry>> entry : history.entrySet()) {
for (MuteData.MuteHistoryEntry e : entry.getValue()) {
if (e.playerName != null && e.playerName.equalsIgnoreCase(name)) {
return entry.getKey();
}
}
}
return null;
}
public void save() {
try (FileWriter writer = new FileWriter(historyFile)) {
gson.toJson(history, writer);

View file

@ -1,6 +1,6 @@
package com.loki.lochat.core.service.mute;
import com.loki.lochat.utils.TimeFormatter;
import com.loki.lochat.utils.format.TimeFormatter;
import org.bukkit.entity.Player;
/**

View file

@ -0,0 +1,27 @@
package com.loki.lochat.core.service.mute.strategies;
import java.util.UUID;
/**
* Стратегия мута в чате
* Базовая реализация - мут проверяется через MuteService.isMuted()
*/
public class ChatMuteStrategy implements MuteStrategy {
@Override
public void apply(UUID playerUuid) {
// Чат мут работает через проверку в фильтрах
// Не требует дополнительных действий при применении
}
@Override
public void remove(UUID playerUuid) {
// Чат мут работает через проверку в фильтрах
// Не требует дополнительных действий при снятии
}
@Override
public String getName() {
return "Chat";
}
}

View file

@ -0,0 +1,25 @@
package com.loki.lochat.core.service.mute.strategies;
import java.util.UUID;
/**
* Стратегия применения мута
* Strategy pattern для разных типов мутов (чат, голос)
*/
public interface MuteStrategy {
/**
* Применить мут к игроку
*/
void apply(UUID playerUuid);
/**
* Снять мут с игрока
*/
void remove(UUID playerUuid);
/**
* Название стратегии для логирования
*/
String getName();
}

View file

@ -0,0 +1,78 @@
package com.loki.lochat.core.service.mute.strategies;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.UUID;
/**
* Стратегия мута в голосовом чате (Simple Voice Chat)
*/
public class VoiceMuteStrategy implements MuteStrategy {
private final JavaPlugin plugin;
private final Object voicechatService;
public VoiceMuteStrategy(JavaPlugin plugin) {
this.plugin = plugin;
this.voicechatService = initVoiceChat();
}
private Object initVoiceChat() {
if (!Bukkit.getPluginManager().isPluginEnabled("voicechat")) {
return null;
}
try {
Class.forName("de.maxhenkel.voicechat.api.BukkitVoicechatService");
Object service = Bukkit.getServicesManager().load(
Class.forName("de.maxhenkel.voicechat.api.BukkitVoicechatService")
);
if (service != null) {
plugin.getLogger().info("Simple Voice Chat integration enabled!");
}
return service;
} catch (ClassNotFoundException e) {
plugin.getLogger().info("VoiceChat API not found, voice mute disabled");
} catch (Exception e) {
plugin.getLogger().warning("Failed to hook into Simple Voice Chat: " + e.getMessage());
}
return null;
}
@Override
public void apply(UUID playerUuid) {
muteVoiceChat(playerUuid, true);
}
@Override
public void remove(UUID playerUuid) {
muteVoiceChat(playerUuid, false);
}
@Override
public String getName() {
return "Voice";
}
private void muteVoiceChat(UUID uuid, boolean mute) {
if (voicechatService == null) return;
try {
Player player = Bukkit.getPlayer(uuid);
if (player != null && player.isOnline()) {
voicechatService.getClass()
.getMethod("getVoicechat")
.invoke(voicechatService)
.getClass()
.getMethod("setMuted", UUID.class, boolean.class)
.invoke(voicechatService.getClass().getMethod("getVoicechat").invoke(voicechatService),
player.getUniqueId(), mute);
}
} catch (Exception e) {
plugin.getLogger().warning("Failed to " + (mute ? "mute" : "unmute") +
" player in voice chat: " + e.getMessage());
}
}
}

View file

@ -1,12 +1,13 @@
package com.loki.lochat.gradient.commands;
import com.loki.lochat.config.RatConfig;
import com.loki.lochat.gradient.GradientModule;
import com.loki.lochat.gradient.commands.handlers.ColorCommandHandler;
import com.loki.lochat.gradient.commands.handlers.PrefixCommandHandler;
import com.loki.lochat.gradient.config.GradientMessages;
import com.loki.lochat.gradient.data.GradientPlayerData;
import com.loki.lochat.gradient.util.DisplayNameUtil;
import com.loki.lochat.utils.FoliaUtil;
import com.loki.lochat.utils.platform.FoliaUtil;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command;
@ -26,10 +27,6 @@ import java.util.List;
*/
public class GradientAdminCommand implements CommandExecutor, TabCompleter {
private static final List<String> PRESET_COLORS = Arrays.asList(
"#FF0000", "#FF7F00", "#FFFF00", "#00FF00", "#0000FF", "#4B0082", "#9400D3"
);
private final GradientModule module;
private final ColorCommandHandler colorHandler;
private final PrefixCommandHandler prefixHandler;
@ -149,7 +146,7 @@ public class GradientAdminCommand implements CommandExecutor, TabCompleter {
}
if (args.length >= 3 && args[0].equalsIgnoreCase("setcolor")) {
return PRESET_COLORS.stream()
return RatConfig.PRESET_COLORS.stream()
.filter(s -> s.toLowerCase().startsWith(args[args.length - 1].toLowerCase()))
.toList();
}

View file

@ -1,13 +1,13 @@
package com.loki.lochat.gradient.commands;
import com.loki.lochat.config.RatConfig;
import com.loki.lochat.gradient.GradientModule;
import com.loki.lochat.gradient.config.GradientConfig;
import com.loki.lochat.gradient.config.GradientMessages;
import com.loki.lochat.gradient.data.GradientPlayerData;
import com.loki.lochat.gradient.gui.GradientConfirmGUI;
import com.loki.lochat.gradient.util.DisplayNameUtil;
import com.loki.lochat.utils.FoliaUtil;
import com.loki.lochat.gradient.util.GradientConstants;
import com.loki.lochat.utils.platform.FoliaUtil;
import com.loki.lochat.gradient.util.GradientUtil;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
@ -26,10 +26,6 @@ import java.util.function.BiFunction;
*/
public class GradientColorCommand implements CommandExecutor, TabCompleter {
private static final List<String> PRESET_COLORS = List.of(
"#FF0000", "#FF7F00", "#FFFF00", "#00FF00", "#0000FF", "#4B0082", "#9400D3",
"#FF69B4", "#00FFFF", "#FFD700", "#FFFFFF", "#000000"
);
private static final Set<String> SUB_COMMANDS = Set.of("on", "off", "reset", "copy");
private final GradientModule module;
private final Map<String, BiFunction<Player, String[], Boolean>> subCommands = new HashMap<>();
@ -197,10 +193,10 @@ public class GradientColorCommand implements CommandExecutor, TabCompleter {
}
private boolean checkCooldown(Player player, int cooldownSec, long lastChange) {
long cooldownMs = cooldownSec * GradientConstants.MILLIS_PER_SECOND;
long cooldownMs = cooldownSec * RatConfig.MILLIS_PER_SECOND;
long timePassed = System.currentTimeMillis() - lastChange;
if (timePassed < cooldownMs) {
long remaining = (cooldownMs - timePassed) / GradientConstants.MILLIS_PER_SECOND;
long remaining = (cooldownMs - timePassed) / RatConfig.MILLIS_PER_SECOND;
module.getMessages().send(player, "cooldown", "time", String.valueOf(remaining));
return false;
}
@ -233,7 +229,7 @@ public class GradientColorCommand implements CommandExecutor, TabCompleter {
if (args.length == 1) {
String input = args[0].toLowerCase();
List<String> completions = new ArrayList<>(SUB_COMMANDS);
completions.addAll(PRESET_COLORS);
completions.addAll(RatConfig.PRESET_COLORS);
return completions.stream().filter(s -> s.toLowerCase().startsWith(input)).toList();
}
@ -245,7 +241,7 @@ public class GradientColorCommand implements CommandExecutor, TabCompleter {
}
if (!SUB_COMMANDS.contains(firstArg) && args.length <= module.getConfig().getMaxColors()) {
return PRESET_COLORS.stream()
return RatConfig.PRESET_COLORS.stream()
.filter(s -> s.toLowerCase().startsWith(args[args.length - 1].toLowerCase()))
.toList();
}

View file

@ -1,13 +1,13 @@
package com.loki.lochat.gradient.commands;
import com.loki.lochat.config.RatConfig;
import com.loki.lochat.gradient.GradientModule;
import com.loki.lochat.gradient.config.GradientConfig;
import com.loki.lochat.gradient.config.GradientMessages;
import com.loki.lochat.gradient.data.GradientPlayerData;
import com.loki.lochat.gradient.gui.GradientConfirmGUI;
import com.loki.lochat.gradient.util.DisplayNameUtil;
import com.loki.lochat.utils.FoliaUtil;
import com.loki.lochat.gradient.util.GradientConstants;
import com.loki.lochat.utils.platform.FoliaUtil;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
@ -169,10 +169,10 @@ public class GradientPrefixCommand implements CommandExecutor, TabCompleter {
}
private boolean checkCooldown(Player player, int cooldownSec, long lastChange) {
long cooldownMs = cooldownSec * GradientConstants.MILLIS_PER_SECOND;
long cooldownMs = cooldownSec * RatConfig.MILLIS_PER_SECOND;
long timePassed = System.currentTimeMillis() - lastChange;
if (timePassed < cooldownMs) {
long remaining = (cooldownMs - timePassed) / GradientConstants.MILLIS_PER_SECOND;
long remaining = (cooldownMs - timePassed) / RatConfig.MILLIS_PER_SECOND;
module.getMessages().send(player, "cooldown", "time", String.valueOf(remaining));
return false;
}

View file

@ -5,7 +5,7 @@ import com.loki.lochat.gradient.config.GradientMessages;
import com.loki.lochat.gradient.data.GradientPlayerData;
import com.loki.lochat.gradient.util.DisplayNameUtil;
import com.loki.lochat.gradient.util.GradientUtil;
import com.loki.lochat.utils.FoliaUtil;
import com.loki.lochat.utils.platform.FoliaUtil;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender;

View file

@ -4,7 +4,7 @@ import com.loki.lochat.gradient.GradientModule;
import com.loki.lochat.gradient.config.GradientMessages;
import com.loki.lochat.gradient.data.GradientPlayerData;
import com.loki.lochat.gradient.util.DisplayNameUtil;
import com.loki.lochat.utils.FoliaUtil;
import com.loki.lochat.utils.platform.FoliaUtil;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender;

View file

@ -1,6 +1,6 @@
package com.loki.lochat.gradient.config;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.format.ChatFormatter;
import net.kyori.adventure.text.Component;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.FileConfiguration;

View file

@ -1,7 +1,7 @@
package com.loki.lochat.gradient.gui;
import com.loki.lochat.config.RatConfig;
import com.loki.lochat.gradient.GradientModule;
import com.loki.lochat.gradient.util.GradientConstants;
import com.loki.lochat.gradient.util.GradientUtil;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
@ -81,7 +81,7 @@ public final class GradientConfirmGUI implements InventoryHolder {
}
skullMeta.lore(lore);
head.setItemMeta(skullMeta);
inventory.setItem(GradientConstants.GUI_PREVIEW_SLOT, head);
inventory.setItem(RatConfig.GUI_PREVIEW_SLOT, head);
ItemStack confirm = createItem(Material.LIME_WOOL, "§a§lПодтвердить");
ItemMeta confirmMeta = confirm.getItemMeta();
@ -91,7 +91,7 @@ public final class GradientConfirmGUI implements InventoryHolder {
.decoration(TextDecoration.ITALIC, false));
confirmMeta.lore(confirmLore);
confirm.setItemMeta(confirmMeta);
inventory.setItem(GradientConstants.GUI_CONFIRM_SLOT, confirm);
inventory.setItem(RatConfig.GUI_CONFIRM_SLOT, confirm);
ItemStack cancel = createItem(Material.RED_WOOL, "§c§lОтменить");
ItemMeta cancelMeta = cancel.getItemMeta();
@ -101,7 +101,7 @@ public final class GradientConfirmGUI implements InventoryHolder {
.decoration(TextDecoration.ITALIC, false));
cancelMeta.lore(cancelLore);
cancel.setItemMeta(cancelMeta);
inventory.setItem(GradientConstants.GUI_CANCEL_SLOT, cancel);
inventory.setItem(RatConfig.GUI_CANCEL_SLOT, cancel);
}
private String buildPreview() {

View file

@ -1,12 +1,12 @@
package com.loki.lochat.gradient.listeners;
import com.loki.lochat.config.RatConfig;
import com.loki.lochat.gradient.GradientModule;
import com.loki.lochat.gradient.config.GradientMessages;
import com.loki.lochat.gradient.data.GradientPlayerData;
import com.loki.lochat.gradient.gui.GradientConfirmGUI;
import com.loki.lochat.gradient.util.DisplayNameUtil;
import com.loki.lochat.utils.FoliaUtil;
import com.loki.lochat.gradient.util.GradientConstants;
import com.loki.lochat.utils.platform.FoliaUtil;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
@ -38,8 +38,8 @@ public class GradientGUIListener implements Listener {
if (!(event.getWhoClicked() instanceof Player player) || !player.equals(gui.getPlayer())) return;
switch (event.getRawSlot()) {
case GradientConstants.GUI_CONFIRM_SLOT -> handleConfirm(player, gui);
case GradientConstants.GUI_CANCEL_SLOT -> handleCancel(player);
case RatConfig.GUI_CONFIRM_SLOT -> handleConfirm(player, gui);
case RatConfig.GUI_CANCEL_SLOT -> handleCancel(player);
}
}

View file

@ -1,7 +1,7 @@
package com.loki.lochat.gradient.listeners;
import com.loki.lochat.gradient.GradientModule;
import com.loki.lochat.utils.FoliaUtil;
import com.loki.lochat.utils.platform.FoliaUtil;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;

View file

@ -1,18 +0,0 @@
package com.loki.lochat.gradient.util;
/**
* Константы для градиентного модуля
*/
public final class GradientConstants {
public static final long MILLIS_PER_SECOND = 1000L;
// GUI слоты
public static final int GUI_CONFIRM_SLOT = 11;
public static final int GUI_CANCEL_SLOT = 15;
public static final int GUI_PREVIEW_SLOT = 13;
// LuckPerms
public static final int LUCKPERMS_PREFIX_PRIORITY = 100;
private GradientConstants() {
}
}

View file

@ -1,7 +1,7 @@
package com.loki.lochat.integrations.discord;
import com.loki.lochat.integrations.DiscordWebhook;
import com.loki.lochat.utils.FoliaUtil;
import com.loki.lochat.utils.platform.FoliaUtil;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;

View file

@ -6,7 +6,7 @@ import com.loki.lochat.core.filter.AdvancedMessageFilter;
import com.loki.lochat.core.filter.FilterResult;
import com.loki.lochat.core.registry.ServiceRegistry;
import com.loki.lochat.renderer.EnhancedChatRenderer;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.format.ChatFormatter;
import io.papermc.paper.event.player.AsyncChatEvent;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
@ -124,7 +124,7 @@ public class ChatEventListener implements Listener {
event.viewers().removeIf(v -> {
if (!(v instanceof Player p)) return false;
try {
return !com.loki.lochat.utils.DistanceUtil.isInRange(sender, p, radius);
return !com.loki.lochat.utils.player.DistanceUtil.isInRange(sender, p, radius);
} catch (Exception e) {
return false;
}

View file

@ -7,7 +7,7 @@ import com.loki.lochat.api.service.PlayerService;
import com.loki.lochat.config.ConfigManager;
import com.loki.lochat.core.filter.AdvancedMessageFilter;
import com.loki.lochat.core.registry.ServiceRegistry;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.format.ChatFormatter;
import net.kyori.adventure.text.Component;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;

View file

@ -1,8 +1,8 @@
package com.loki.lochat.managers;
import com.loki.lochat.LoChat;
import com.loki.lochat.utils.FoliaUtil;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.platform.FoliaUtil;
import com.loki.lochat.utils.format.ChatFormatter;
import io.papermc.paper.threadedregions.scheduler.ScheduledTask;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;

View file

@ -4,7 +4,7 @@ import com.loki.lochat.LoChat;
import com.loki.lochat.commands.CustomCommand;
import com.loki.lochat.managers.commands.MessageSender;
import com.loki.lochat.managers.commands.PlaceholderProcessor;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.format.ChatFormatter;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandMap;
import org.bukkit.configuration.ConfigurationSection;

View file

@ -1,6 +1,6 @@
package com.loki.lochat.managers.commands;
import com.loki.lochat.utils.ChatFormatter;
import com.loki.lochat.utils.format.ChatFormatter;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.title.Title;
import org.bukkit.Bukkit;

View file

@ -1,8 +1,8 @@
package com.loki.lochat.renderer;
import com.loki.lochat.renderer.components.*;
import com.loki.lochat.utils.MentionHandler;
import com.loki.lochat.utils.TextFormatter;
import com.loki.lochat.utils.player.MentionHandler;
import com.loki.lochat.utils.format.TextFormatter;
import io.papermc.paper.chat.ChatRenderer;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.text.Component;
@ -112,7 +112,7 @@ public class EnhancedChatRenderer implements ChatRenderer {
if (gradientModule != null && gradientModule.isEnabled()) {
String prefix = gradientModule.getPrefix(player);
if (!prefix.isEmpty()) {
return com.loki.lochat.utils.ChatFormatter.parse(prefix);
return com.loki.lochat.utils.format.ChatFormatter.parse(prefix);
}
}
@ -126,7 +126,7 @@ public class EnhancedChatRenderer implements ChatRenderer {
if (gradientModule != null && gradientModule.isEnabled()) {
String suffix = gradientModule.getSuffix(player);
if (!suffix.isEmpty()) {
return com.loki.lochat.utils.ChatFormatter.parse(suffix);
return com.loki.lochat.utils.format.ChatFormatter.parse(suffix);
}
}
@ -184,7 +184,7 @@ public class EnhancedChatRenderer implements ChatRenderer {
.replace("{health}", String.valueOf(Math.round(player.getHealth())))
.replace("{food}", String.valueOf(player.getFoodLevel()));
hoverBuilder.append(com.loki.lochat.utils.ChatFormatter.parse(line));
hoverBuilder.append(com.loki.lochat.utils.format.ChatFormatter.parse(line));
if (i < hoverLines.size() - 1) hoverBuilder.append(Component.newline());
}

View file

@ -1,26 +0,0 @@
package com.loki.lochat.utils;
/**
* Константы плагина (только неизменяемые системные значения)
*/
public final class Constants {
// Время (системные константы)
public static final long MILLIS_IN_SECOND = 1000L;
public static final int SECONDS_IN_MINUTE = 60;
public static final int MINUTES_IN_HOUR = 60;
public static final int HOURS_IN_DAY = 24;
// Folia/Paper совместимость (системные константы)
public static final int TICKS_PER_SECOND = 20;
public static final int MILLIS_PER_TICK = 50;
// Математические константы
public static final int PERCENTAGE_MULTIPLIER = 100;
// LuckPerms приоритет (системная константа)
public static final int LUCKPERMS_PREFIX_PRIORITY = 100;
private Constants() {
}
}

View file

@ -1,4 +1,4 @@
package com.loki.lochat.utils;
package com.loki.lochat.utils.format;
import com.loki.lochat.utils.color.ColorConverter;
import net.kyori.adventure.text.Component;

View file

@ -1,4 +1,4 @@
package com.loki.lochat.utils;
package com.loki.lochat.utils.format;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;

View file

@ -1,4 +1,4 @@
package com.loki.lochat.utils;
package com.loki.lochat.utils.format;
public final class TimeFormatter {

View file

@ -1,4 +1,4 @@
package com.loki.lochat.utils;
package com.loki.lochat.utils.platform;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;

View file

@ -1,4 +1,4 @@
package com.loki.lochat.utils;
package com.loki.lochat.utils.platform;
import org.bukkit.Bukkit;
import org.bukkit.entity.Entity;

View file

@ -1,4 +1,4 @@
package com.loki.lochat.utils;
package com.loki.lochat.utils.player;
import org.bukkit.entity.Player;

View file

@ -1,6 +1,6 @@
package com.loki.lochat.utils;
package com.loki.lochat.utils.player;
import com.loki.lochat.utils.FoliaUtil;
import com.loki.lochat.utils.platform.FoliaUtil;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextDecoration;

View file

@ -1,4 +1,4 @@
package com.loki.lochat.utils;
package com.loki.lochat.utils.player;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;