Add built-in mute system with /lmute and /lunmute commands
- Added MuteManager for handling mutes with persistence (mutes.json) - Added /lmute <nick> <time> [-s] [reason] command - Added /lunmute <nick> [-s] command - Time formats: 1d, 2h, 30m, 60s, 0 for permanent - -s flag for silent mute/unmute (no broadcast) - Mute check integrated into ChatListener - Removed LibertyBans API dependency (using built-in system)
This commit is contained in:
parent
d44c5f811f
commit
c6175d9d61
7 changed files with 524 additions and 85 deletions
|
|
@ -29,6 +29,7 @@ public final class LoChat extends JavaPlugin {
|
||||||
private CustomCommandManager customCommandManager;
|
private CustomCommandManager customCommandManager;
|
||||||
private GradientModule gradientModule;
|
private GradientModule gradientModule;
|
||||||
private LibertyBansHook libertyBansHook;
|
private LibertyBansHook libertyBansHook;
|
||||||
|
private MuteManager muteManager;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
|
|
@ -47,6 +48,7 @@ public final class LoChat extends JavaPlugin {
|
||||||
mentionManager = new MentionManager(this);
|
mentionManager = new MentionManager(this);
|
||||||
spyManager = new SpyManager(this);
|
spyManager = new SpyManager(this);
|
||||||
customCommandManager = new CustomCommandManager(this);
|
customCommandManager = new CustomCommandManager(this);
|
||||||
|
muteManager = new MuteManager(this);
|
||||||
chatManager = new ChatManager(this);
|
chatManager = new ChatManager(this);
|
||||||
autoMessageManager = new AutoMessageManager(this);
|
autoMessageManager = new AutoMessageManager(this);
|
||||||
|
|
||||||
|
|
@ -88,6 +90,9 @@ public final class LoChat extends JavaPlugin {
|
||||||
if (gradientModule != null) {
|
if (gradientModule != null) {
|
||||||
gradientModule.shutdown();
|
gradientModule.shutdown();
|
||||||
}
|
}
|
||||||
|
if (muteManager != null) {
|
||||||
|
muteManager.save();
|
||||||
|
}
|
||||||
getLogger().info("LoChat отключен!");
|
getLogger().info("LoChat отключен!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -106,6 +111,15 @@ public final class LoChat extends JavaPlugin {
|
||||||
LoChatCommand loChatCommand = new LoChatCommand(this);
|
LoChatCommand loChatCommand = new LoChatCommand(this);
|
||||||
getCommand("lochat").setExecutor(loChatCommand);
|
getCommand("lochat").setExecutor(loChatCommand);
|
||||||
getCommand("lochat").setTabCompleter(loChatCommand);
|
getCommand("lochat").setTabCompleter(loChatCommand);
|
||||||
|
|
||||||
|
// Команды мутов
|
||||||
|
MuteCommand muteCommand = new MuteCommand(this);
|
||||||
|
getCommand("lmute").setExecutor(muteCommand);
|
||||||
|
getCommand("lmute").setTabCompleter(muteCommand);
|
||||||
|
|
||||||
|
UnmuteCommand unmuteCommand = new UnmuteCommand(this);
|
||||||
|
getCommand("lunmute").setExecutor(unmuteCommand);
|
||||||
|
getCommand("lunmute").setTabCompleter(unmuteCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reload() {
|
public void reload() {
|
||||||
|
|
@ -183,4 +197,8 @@ public final class LoChat extends JavaPlugin {
|
||||||
return libertyBansHook;
|
return libertyBansHook;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MuteManager getMuteManager() {
|
||||||
|
return muteManager;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
160
src/main/java/com/loki/lochat/commands/MuteCommand.java
Normal file
160
src/main/java/com/loki/lochat/commands/MuteCommand.java
Normal file
|
|
@ -0,0 +1,160 @@
|
||||||
|
package com.loki.lochat.commands;
|
||||||
|
|
||||||
|
import com.loki.lochat.LoChat;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandExecutor;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.command.TabCompleter;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Команда /lmute nick time [-s] причина
|
||||||
|
*/
|
||||||
|
public class MuteCommand implements CommandExecutor, TabCompleter {
|
||||||
|
|
||||||
|
private final LoChat plugin;
|
||||||
|
|
||||||
|
public MuteCommand(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.mute")) {
|
||||||
|
sender.sendMessage(plugin.getMessageConfig().getComponent("errors.no-permission"));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// /lmute nick time [-s] причина
|
||||||
|
if (args.length < 2) {
|
||||||
|
sender.sendMessage("§cИспользование: /lmute <ник> <время> [-s] [причина]");
|
||||||
|
sender.sendMessage("§7Время: 1d, 2h, 30m, 60s или 0 для перманентного");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
String targetName = args[0];
|
||||||
|
String timeStr = args[1];
|
||||||
|
|
||||||
|
// Парсим время
|
||||||
|
long duration = plugin.getMuteManager().parseTime(timeStr);
|
||||||
|
if (duration < 0) {
|
||||||
|
sender.sendMessage("§cНеверный формат времени! Используйте: 1d, 2h, 30m, 60s");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверяем флаг -s (silent) и собираем причину
|
||||||
|
boolean silent = false;
|
||||||
|
StringBuilder reasonBuilder = new StringBuilder();
|
||||||
|
|
||||||
|
for (int i = 2; i < args.length; i++) {
|
||||||
|
if (args[i].equalsIgnoreCase("-s")) {
|
||||||
|
silent = true;
|
||||||
|
} else {
|
||||||
|
if (reasonBuilder.length() > 0) reasonBuilder.append(" ");
|
||||||
|
reasonBuilder.append(args[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String reason = reasonBuilder.length() > 0 ? reasonBuilder.toString() : "Не указана";
|
||||||
|
|
||||||
|
// Ищем игрока (онлайн или оффлайн)
|
||||||
|
Player target = Bukkit.getPlayer(targetName);
|
||||||
|
if (target == null) {
|
||||||
|
// Пробуем найти оффлайн игрока
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
var offlinePlayer = Bukkit.getOfflinePlayer(targetName);
|
||||||
|
if (!offlinePlayer.hasPlayedBefore() && !offlinePlayer.isOnline()) {
|
||||||
|
sender.sendMessage(plugin.getMessageConfig().getComponent("errors.player-not-found"));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Мутим оффлайн игрока
|
||||||
|
plugin.getMuteManager().mute(offlinePlayer.getUniqueId(), duration, reason, sender.getName());
|
||||||
|
|
||||||
|
String timeDisplay = duration == 0 ? "навсегда" : plugin.getMuteManager().formatTime(duration);
|
||||||
|
sender.sendMessage("§aИгрок §e" + targetName + " §aзамучен на §e" + timeDisplay);
|
||||||
|
sender.sendMessage("§7Причина: §f" + reason);
|
||||||
|
|
||||||
|
if (!silent) {
|
||||||
|
Bukkit.broadcast(plugin.getMessageConfig().getComponent("mute.muted",
|
||||||
|
"{player}", targetName, "{time}", timeDisplay));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверяем, не пытается ли замутить себя
|
||||||
|
if (sender instanceof Player && ((Player) sender).getUniqueId().equals(target.getUniqueId())) {
|
||||||
|
sender.sendMessage("§cВы не можете замутить себя!");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверяем, не замучен ли уже
|
||||||
|
if (plugin.getMuteManager().isMuted(target.getUniqueId())) {
|
||||||
|
sender.sendMessage("§cИгрок уже замучен!");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Мутим игрока
|
||||||
|
plugin.getMuteManager().mute(target.getUniqueId(), duration, reason, sender.getName());
|
||||||
|
|
||||||
|
String timeDisplay = duration == 0 ? "навсегда" : plugin.getMuteManager().formatTime(duration);
|
||||||
|
|
||||||
|
// Уведомляем отправителя
|
||||||
|
sender.sendMessage("§aИгрок §e" + target.getName() + " §aзамучен на §e" + timeDisplay);
|
||||||
|
sender.sendMessage("§7Причина: §f" + reason);
|
||||||
|
|
||||||
|
// Уведомляем замученного
|
||||||
|
if (duration == 0) {
|
||||||
|
target.sendMessage(plugin.getMessageConfig().getComponent("mute.permanent"));
|
||||||
|
} else {
|
||||||
|
target.sendMessage(plugin.getMessageConfig().getComponent("mute.you-muted",
|
||||||
|
"{time}", timeDisplay));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Broadcast если не silent
|
||||||
|
if (!silent) {
|
||||||
|
Bukkit.broadcast(plugin.getMessageConfig().getComponent("mute.muted",
|
||||||
|
"{player}", target.getName(), "{time}", timeDisplay));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command,
|
||||||
|
@NotNull String alias, @NotNull String[] args) {
|
||||||
|
List<String> completions = new ArrayList<>();
|
||||||
|
|
||||||
|
if (args.length == 1) {
|
||||||
|
// Ники игроков
|
||||||
|
String prefix = args[0].toLowerCase();
|
||||||
|
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||||
|
if (player.getName().toLowerCase().startsWith(prefix)) {
|
||||||
|
completions.add(player.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (args.length == 2) {
|
||||||
|
// Время
|
||||||
|
completions.add("10m");
|
||||||
|
completions.add("30m");
|
||||||
|
completions.add("1h");
|
||||||
|
completions.add("6h");
|
||||||
|
completions.add("12h");
|
||||||
|
completions.add("1d");
|
||||||
|
completions.add("7d");
|
||||||
|
completions.add("30d");
|
||||||
|
completions.add("0");
|
||||||
|
} else if (args.length == 3) {
|
||||||
|
completions.add("-s");
|
||||||
|
}
|
||||||
|
|
||||||
|
return completions;
|
||||||
|
}
|
||||||
|
}
|
||||||
102
src/main/java/com/loki/lochat/commands/UnmuteCommand.java
Normal file
102
src/main/java/com/loki/lochat/commands/UnmuteCommand.java
Normal file
|
|
@ -0,0 +1,102 @@
|
||||||
|
package com.loki.lochat.commands;
|
||||||
|
|
||||||
|
import com.loki.lochat.LoChat;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandExecutor;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.command.TabCompleter;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Команда /lunmute nick [-s]
|
||||||
|
*/
|
||||||
|
public class UnmuteCommand implements CommandExecutor, TabCompleter {
|
||||||
|
|
||||||
|
private final LoChat plugin;
|
||||||
|
|
||||||
|
public UnmuteCommand(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.unmute")) {
|
||||||
|
sender.sendMessage(plugin.getMessageConfig().getComponent("errors.no-permission"));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.length < 1) {
|
||||||
|
sender.sendMessage("§cИспользование: /lunmute <ник> [-s]");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
String targetName = args[0];
|
||||||
|
boolean silent = args.length > 1 && args[1].equalsIgnoreCase("-s");
|
||||||
|
|
||||||
|
// Ищем игрока
|
||||||
|
Player target = Bukkit.getPlayer(targetName);
|
||||||
|
if (target == null) {
|
||||||
|
// Пробуем найти оффлайн игрока
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
var offlinePlayer = Bukkit.getOfflinePlayer(targetName);
|
||||||
|
if (!offlinePlayer.hasPlayedBefore() && !offlinePlayer.isOnline()) {
|
||||||
|
sender.sendMessage(plugin.getMessageConfig().getComponent("errors.player-not-found"));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Размучиваем оффлайн игрока
|
||||||
|
if (plugin.getMuteManager().unmute(offlinePlayer.getUniqueId())) {
|
||||||
|
sender.sendMessage("§aИгрок §e" + targetName + " §aразмучен");
|
||||||
|
|
||||||
|
if (!silent) {
|
||||||
|
Bukkit.broadcast(plugin.getMessageConfig().getComponent("mute.unmuted",
|
||||||
|
"{player}", targetName));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sender.sendMessage("§cИгрок не замучен!");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Размучиваем онлайн игрока
|
||||||
|
if (plugin.getMuteManager().unmute(target.getUniqueId())) {
|
||||||
|
sender.sendMessage("§aИгрок §e" + target.getName() + " §aразмучен");
|
||||||
|
target.sendMessage("§aВы были размучены!");
|
||||||
|
|
||||||
|
if (!silent) {
|
||||||
|
Bukkit.broadcast(plugin.getMessageConfig().getComponent("mute.unmuted",
|
||||||
|
"{player}", target.getName()));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sender.sendMessage("§cИгрок не замучен!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command,
|
||||||
|
@NotNull String alias, @NotNull String[] args) {
|
||||||
|
List<String> completions = new ArrayList<>();
|
||||||
|
|
||||||
|
if (args.length == 1) {
|
||||||
|
String prefix = args[0].toLowerCase();
|
||||||
|
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||||
|
if (player.getName().toLowerCase().startsWith(prefix)) {
|
||||||
|
completions.add(player.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (args.length == 2) {
|
||||||
|
completions.add("-s");
|
||||||
|
}
|
||||||
|
|
||||||
|
return completions;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,102 +2,36 @@ package com.loki.lochat.integrations;
|
||||||
|
|
||||||
import com.loki.lochat.LoChat;
|
import com.loki.lochat.LoChat;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
|
||||||
import org.bukkit.event.EventPriority;
|
|
||||||
import org.bukkit.event.Listener;
|
|
||||||
import org.bukkit.event.player.AsyncPlayerChatEvent;
|
|
||||||
import org.bukkit.plugin.Plugin;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Интеграция с LibertyBans для проверки мутов
|
* Заглушка для совместимости с LibertyBans
|
||||||
* Использует событийный подход для отслеживания мутов
|
* Теперь используется встроенная система мутов LoChat
|
||||||
*/
|
*/
|
||||||
public class LibertyBansHook implements Listener {
|
public class LibertyBansHook {
|
||||||
|
|
||||||
private final LoChat plugin;
|
private final LoChat plugin;
|
||||||
private boolean enabled = false;
|
|
||||||
private Plugin libertyBansPlugin;
|
|
||||||
private final Set<UUID> mutedPlayers = ConcurrentHashMap.newKeySet();
|
|
||||||
|
|
||||||
public LibertyBansHook(LoChat plugin) {
|
public LibertyBansHook(LoChat plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
initialize();
|
|
||||||
}
|
// Проверяем наличие LibertyBans
|
||||||
|
if (plugin.getServer().getPluginManager().getPlugin("LibertyBans") != null) {
|
||||||
private void initialize() {
|
plugin.getLogger().info("LibertyBans обнаружен. Используйте встроенную систему мутов LoChat (/lmute, /lunmute)");
|
||||||
libertyBansPlugin = plugin.getServer().getPluginManager().getPlugin("LibertyBans");
|
|
||||||
if (libertyBansPlugin == null || !libertyBansPlugin.isEnabled()) {
|
|
||||||
plugin.getLogger().info("LibertyBans не найден, интеграция отключена");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.enabled = true;
|
|
||||||
// Регистрируем слушатель для отслеживания попыток чата замученных игроков
|
|
||||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
|
||||||
plugin.getLogger().info("LibertyBans интеграция включена (событийный режим)");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Слушаем события чата с высоким приоритетом, чтобы отследить,
|
* Проверяет, замучен ли игрок через встроенную систему LoChat
|
||||||
* какие игроки не могут писать (значит они замучены)
|
|
||||||
*/
|
*/
|
||||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
public boolean isMuted(Player player) {
|
||||||
public void onAsyncPlayerChat(AsyncPlayerChatEvent event) {
|
return plugin.getMuteManager().isMuted(player.getUniqueId());
|
||||||
// Если событие не отменено, значит игрок не замучен
|
|
||||||
UUID playerId = event.getPlayer().getUniqueId();
|
|
||||||
mutedPlayers.remove(playerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Проверяет, замучен ли игрок
|
|
||||||
* В событийном режиме мы полагаемся на LibertyBans для блокировки чата
|
|
||||||
* @param player игрок для проверки
|
|
||||||
* @return CompletableFuture<Boolean> - результат проверки
|
|
||||||
*/
|
|
||||||
public CompletableFuture<Boolean> isMuted(Player player) {
|
|
||||||
if (!enabled) {
|
|
||||||
return CompletableFuture.completedFuture(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// В событийном режиме мы не можем точно определить мут без API
|
|
||||||
// Поэтому возвращаем false и полагаемся на то, что LibertyBans сам заблокирует чат
|
|
||||||
return CompletableFuture.completedFuture(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* В событийном режиме недоступно без API
|
|
||||||
*/
|
|
||||||
public CompletableFuture<Object> getActiveMute(Player player) {
|
|
||||||
return CompletableFuture.completedFuture(null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEnabled() {
|
public boolean isEnabled() {
|
||||||
return enabled;
|
return true; // Всегда используем встроенную систему
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPluginPresent() {
|
public boolean isPluginPresent() {
|
||||||
return libertyBansPlugin != null && libertyBansPlugin.isEnabled();
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Добавляет игрока в список потенциально замученных
|
|
||||||
* (используется когда LibertyBans блокирует чат)
|
|
||||||
*/
|
|
||||||
public void markAsPotentiallyMuted(UUID playerId) {
|
|
||||||
if (enabled) {
|
|
||||||
mutedPlayers.add(playerId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Проверяет, был ли игрок отмечен как потенциально замученный
|
|
||||||
*/
|
|
||||||
public boolean isPotentiallyMuted(UUID playerId) {
|
|
||||||
return enabled && mutedPlayers.contains(playerId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -37,12 +37,20 @@ public class ChatListener implements Listener {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processChat(Player player, Component message, String plainMessage) {
|
private void processChat(Player player, Component message, String plainMessage) {
|
||||||
// ===== LIBERTYBANS COMPATIBILITY =====
|
// ===== MUTE CHECK =====
|
||||||
// LibertyBans будет сам блокировать чат для замученных игроков
|
if (plugin.getMuteManager().isMuted(player.getUniqueId())) {
|
||||||
// Наша интеграция просто обеспечивает совместимость
|
var muteData = plugin.getMuteManager().getMuteData(player.getUniqueId());
|
||||||
if (plugin.getLibertyBansHook().isPluginPresent()) {
|
if (muteData != null) {
|
||||||
// LibertyBans присутствует, он сам обработает муты
|
if (muteData.isPermanent()) {
|
||||||
// Мы просто продолжаем нормальную обработку
|
player.sendMessage(plugin.getMessageConfig().getComponent("mute.permanent"));
|
||||||
|
} else {
|
||||||
|
long remaining = plugin.getMuteManager().getRemainingTime(player.getUniqueId());
|
||||||
|
String timeStr = plugin.getMuteManager().formatTime(remaining);
|
||||||
|
player.sendMessage(plugin.getMessageConfig().getComponent("mute.you-muted",
|
||||||
|
"{time}", timeStr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Продолжаем обработку чата
|
// Продолжаем обработку чата
|
||||||
|
|
|
||||||
201
src/main/java/com/loki/lochat/managers/MuteManager.java
Normal file
201
src/main/java/com/loki/lochat/managers/MuteManager.java
Normal file
|
|
@ -0,0 +1,201 @@
|
||||||
|
package com.loki.lochat.managers;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
import com.loki.lochat.LoChat;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Менеджер мутов для LoChat
|
||||||
|
*/
|
||||||
|
public class MuteManager {
|
||||||
|
|
||||||
|
private final LoChat plugin;
|
||||||
|
private final Map<UUID, MuteData> mutes = new ConcurrentHashMap<>();
|
||||||
|
private final File dataFile;
|
||||||
|
private final Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||||
|
|
||||||
|
public MuteManager(LoChat plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.dataFile = new File(plugin.getDataFolder(), "mutes.json");
|
||||||
|
load();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Замутить игрока
|
||||||
|
* @param uuid UUID игрока
|
||||||
|
* @param duration длительность в миллисекундах (0 = перманентный)
|
||||||
|
* @param reason причина
|
||||||
|
* @param mutedBy кто замутил
|
||||||
|
*/
|
||||||
|
public void mute(UUID uuid, long duration, String reason, String mutedBy) {
|
||||||
|
long endTime = duration > 0 ? System.currentTimeMillis() + duration : 0;
|
||||||
|
mutes.put(uuid, new MuteData(endTime, reason, mutedBy, System.currentTimeMillis()));
|
||||||
|
saveAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Размутить игрока
|
||||||
|
* @param uuid UUID игрока
|
||||||
|
* @return true если игрок был замучен
|
||||||
|
*/
|
||||||
|
public boolean unmute(UUID uuid) {
|
||||||
|
MuteData removed = mutes.remove(uuid);
|
||||||
|
if (removed != null) {
|
||||||
|
saveAsync();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Проверить, замучен ли игрок
|
||||||
|
*/
|
||||||
|
public boolean isMuted(UUID uuid) {
|
||||||
|
MuteData data = mutes.get(uuid);
|
||||||
|
if (data == null) return false;
|
||||||
|
|
||||||
|
// Проверяем истёк ли мут
|
||||||
|
if (data.endTime > 0 && System.currentTimeMillis() > data.endTime) {
|
||||||
|
mutes.remove(uuid);
|
||||||
|
saveAsync();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Получить данные мута
|
||||||
|
*/
|
||||||
|
public MuteData getMuteData(UUID uuid) {
|
||||||
|
if (!isMuted(uuid)) return null;
|
||||||
|
return mutes.get(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Получить оставшееся время мута
|
||||||
|
*/
|
||||||
|
public long getRemainingTime(UUID uuid) {
|
||||||
|
MuteData data = mutes.get(uuid);
|
||||||
|
if (data == null) return 0;
|
||||||
|
if (data.endTime == 0) return -1; // Перманентный
|
||||||
|
return Math.max(0, data.endTime - System.currentTimeMillis());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Форматировать время
|
||||||
|
*/
|
||||||
|
public String formatTime(long millis) {
|
||||||
|
if (millis <= 0) return "0с";
|
||||||
|
|
||||||
|
long seconds = millis / 1000;
|
||||||
|
long minutes = seconds / 60;
|
||||||
|
long hours = minutes / 60;
|
||||||
|
long days = hours / 24;
|
||||||
|
|
||||||
|
if (days > 0) {
|
||||||
|
return days + "д " + (hours % 24) + "ч";
|
||||||
|
} else if (hours > 0) {
|
||||||
|
return hours + "ч " + (minutes % 60) + "м";
|
||||||
|
} else if (minutes > 0) {
|
||||||
|
return minutes + "м " + (seconds % 60) + "с";
|
||||||
|
} else {
|
||||||
|
return seconds + "с";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Парсинг времени из строки (1d, 2h, 30m, 60s)
|
||||||
|
*/
|
||||||
|
public long parseTime(String timeStr) {
|
||||||
|
if (timeStr == null || timeStr.isEmpty()) return 0;
|
||||||
|
|
||||||
|
timeStr = timeStr.toLowerCase();
|
||||||
|
long multiplier = 1000; // базово в миллисекундах
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (timeStr.endsWith("d")) {
|
||||||
|
return Long.parseLong(timeStr.replace("d", "")) * 24 * 60 * 60 * multiplier;
|
||||||
|
} else if (timeStr.endsWith("h")) {
|
||||||
|
return Long.parseLong(timeStr.replace("h", "")) * 60 * 60 * multiplier;
|
||||||
|
} else if (timeStr.endsWith("m")) {
|
||||||
|
return Long.parseLong(timeStr.replace("m", "")) * 60 * multiplier;
|
||||||
|
} else if (timeStr.endsWith("s")) {
|
||||||
|
return Long.parseLong(timeStr.replace("s", "")) * multiplier;
|
||||||
|
} else {
|
||||||
|
// Если без суффикса - считаем минутами
|
||||||
|
return Long.parseLong(timeStr) * 60 * multiplier;
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return -1; // Ошибка парсинга
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void load() {
|
||||||
|
if (!dataFile.exists()) return;
|
||||||
|
|
||||||
|
try (Reader reader = new FileReader(dataFile)) {
|
||||||
|
Type type = new TypeToken<Map<String, MuteData>>(){}.getType();
|
||||||
|
Map<String, MuteData> loaded = gson.fromJson(reader, type);
|
||||||
|
if (loaded != null) {
|
||||||
|
loaded.forEach((key, value) -> {
|
||||||
|
try {
|
||||||
|
mutes.put(UUID.fromString(key), value);
|
||||||
|
} catch (IllegalArgumentException ignored) {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
plugin.getLogger().warning("Ошибка загрузки мутов: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save() {
|
||||||
|
try {
|
||||||
|
if (!dataFile.getParentFile().exists()) {
|
||||||
|
dataFile.getParentFile().mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, MuteData> toSave = new ConcurrentHashMap<>();
|
||||||
|
mutes.forEach((uuid, data) -> toSave.put(uuid.toString(), data));
|
||||||
|
|
||||||
|
try (Writer writer = new FileWriter(dataFile)) {
|
||||||
|
gson.toJson(toSave, writer);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
plugin.getLogger().warning("Ошибка сохранения мутов: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveAsync() {
|
||||||
|
plugin.getServer().getScheduler().runTaskAsynchronously(plugin, this::save);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Данные о муте
|
||||||
|
*/
|
||||||
|
public static class MuteData {
|
||||||
|
public long endTime; // 0 = перманентный
|
||||||
|
public String reason;
|
||||||
|
public String mutedBy;
|
||||||
|
public long mutedAt;
|
||||||
|
|
||||||
|
public MuteData() {}
|
||||||
|
|
||||||
|
public MuteData(long endTime, String reason, String mutedBy, long mutedAt) {
|
||||||
|
this.endTime = endTime;
|
||||||
|
this.reason = reason;
|
||||||
|
this.mutedBy = mutedBy;
|
||||||
|
this.mutedAt = mutedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPermanent() {
|
||||||
|
return endTime == 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -97,6 +97,18 @@ commands:
|
||||||
permission: gradient.admin
|
permission: gradient.admin
|
||||||
aliases: [gradientadmin, азкуашч, пкфвшуетефвьшт]
|
aliases: [gradientadmin, азкуашч, пкфвшуетефвьшт]
|
||||||
|
|
||||||
|
lmute:
|
||||||
|
description: Mute a player
|
||||||
|
usage: /lmute <player> <time> [-s] [reason]
|
||||||
|
permission: lochat.mute
|
||||||
|
aliases: [дьгеу]
|
||||||
|
|
||||||
|
lunmute:
|
||||||
|
description: Unmute a player
|
||||||
|
usage: /lunmute <player> [-s]
|
||||||
|
permission: lochat.unmute
|
||||||
|
aliases: [дгтьгеу]
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
chat.global.use:
|
chat.global.use:
|
||||||
default: true
|
default: true
|
||||||
|
|
@ -140,3 +152,7 @@ permissions:
|
||||||
default: op
|
default: op
|
||||||
lochat.admin:
|
lochat.admin:
|
||||||
default: op
|
default: op
|
||||||
|
lochat.mute:
|
||||||
|
default: op
|
||||||
|
lochat.unmute:
|
||||||
|
default: op
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue