Add /lmutelist and /lmutehistory commands
- /lmutelist - shows all active mutes with remaining time - /lmutehistory <player> - shows mute history for a player - Added mute history tracking (mute-history.json) - History includes: who muted, when, duration, reason, unmute info - Permissions: lochat.mutelist, lochat.mutehistory
This commit is contained in:
parent
c6175d9d61
commit
d92799613e
7 changed files with 428 additions and 10 deletions
|
|
@ -120,6 +120,12 @@ public final class LoChat extends JavaPlugin {
|
||||||
UnmuteCommand unmuteCommand = new UnmuteCommand(this);
|
UnmuteCommand unmuteCommand = new UnmuteCommand(this);
|
||||||
getCommand("lunmute").setExecutor(unmuteCommand);
|
getCommand("lunmute").setExecutor(unmuteCommand);
|
||||||
getCommand("lunmute").setTabCompleter(unmuteCommand);
|
getCommand("lunmute").setTabCompleter(unmuteCommand);
|
||||||
|
|
||||||
|
getCommand("lmutelist").setExecutor(new MuteListCommand(this));
|
||||||
|
|
||||||
|
MuteHistoryCommand muteHistoryCommand = new MuteHistoryCommand(this);
|
||||||
|
getCommand("lmutehistory").setExecutor(muteHistoryCommand);
|
||||||
|
getCommand("lmutehistory").setTabCompleter(muteHistoryCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reload() {
|
public void reload() {
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,8 @@ public class MuteCommand implements CommandExecutor, TabCompleter {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Мутим оффлайн игрока
|
// Мутим оффлайн игрока
|
||||||
plugin.getMuteManager().mute(offlinePlayer.getUniqueId(), duration, reason, sender.getName());
|
String offlineName = offlinePlayer.getName() != null ? offlinePlayer.getName() : targetName;
|
||||||
|
plugin.getMuteManager().mute(offlinePlayer.getUniqueId(), offlineName, duration, reason, sender.getName());
|
||||||
|
|
||||||
String timeDisplay = duration == 0 ? "навсегда" : plugin.getMuteManager().formatTime(duration);
|
String timeDisplay = duration == 0 ? "навсегда" : plugin.getMuteManager().formatTime(duration);
|
||||||
sender.sendMessage("§aИгрок §e" + targetName + " §aзамучен на §e" + timeDisplay);
|
sender.sendMessage("§aИгрок §e" + targetName + " §aзамучен на §e" + timeDisplay);
|
||||||
|
|
@ -102,7 +103,7 @@ public class MuteCommand implements CommandExecutor, TabCompleter {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Мутим игрока
|
// Мутим игрока
|
||||||
plugin.getMuteManager().mute(target.getUniqueId(), duration, reason, sender.getName());
|
plugin.getMuteManager().mute(target.getUniqueId(), target.getName(), duration, reason, sender.getName());
|
||||||
|
|
||||||
String timeDisplay = duration == 0 ? "навсегда" : plugin.getMuteManager().formatTime(duration);
|
String timeDisplay = duration == 0 ? "навсегда" : plugin.getMuteManager().formatTime(duration);
|
||||||
|
|
||||||
|
|
|
||||||
142
src/main/java/com/loki/lochat/commands/MuteHistoryCommand.java
Normal file
142
src/main/java/com/loki/lochat/commands/MuteHistoryCommand.java
Normal file
|
|
@ -0,0 +1,142 @@
|
||||||
|
package com.loki.lochat.commands;
|
||||||
|
|
||||||
|
import com.loki.lochat.LoChat;
|
||||||
|
import com.loki.lochat.managers.MuteManager;
|
||||||
|
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.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Команда /lmutehistory [ник] - история мутов игрока
|
||||||
|
*/
|
||||||
|
public class MuteHistoryCommand implements CommandExecutor, TabCompleter {
|
||||||
|
|
||||||
|
private final LoChat plugin;
|
||||||
|
private final SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy HH:mm");
|
||||||
|
|
||||||
|
public MuteHistoryCommand(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.mutehistory")) {
|
||||||
|
sender.sendMessage(plugin.getMessageConfig().getComponent("errors.no-permission"));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.length < 1) {
|
||||||
|
sender.sendMessage("§cИспользование: /lmutehistory <ник>");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
String targetName = args[0];
|
||||||
|
UUID targetUUID = null;
|
||||||
|
|
||||||
|
// Ищем игрока
|
||||||
|
Player target = Bukkit.getPlayer(targetName);
|
||||||
|
if (target != null) {
|
||||||
|
targetUUID = target.getUniqueId();
|
||||||
|
} else {
|
||||||
|
// Пробуем найти оффлайн игрока
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
var offlinePlayer = Bukkit.getOfflinePlayer(targetName);
|
||||||
|
if (offlinePlayer.hasPlayedBefore() || offlinePlayer.isOnline()) {
|
||||||
|
targetUUID = offlinePlayer.getUniqueId();
|
||||||
|
} else {
|
||||||
|
// Пробуем найти по имени в истории
|
||||||
|
targetUUID = plugin.getMuteManager().getUUIDByName(targetName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetUUID == null) {
|
||||||
|
sender.sendMessage(plugin.getMessageConfig().getComponent("errors.player-not-found"));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<MuteManager.MuteHistoryEntry> history = plugin.getMuteManager().getPlayerHistory(targetUUID);
|
||||||
|
|
||||||
|
if (history.isEmpty()) {
|
||||||
|
sender.sendMessage("§aУ игрока §e" + targetName + " §aнет истории мутов");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
sender.sendMessage("§6§l=== История мутов " + targetName + " (" + history.size() + ") ===");
|
||||||
|
|
||||||
|
int index = 1;
|
||||||
|
// Выводим от новых к старым
|
||||||
|
for (int i = history.size() - 1; i >= 0; i--) {
|
||||||
|
MuteManager.MuteHistoryEntry entry = history.get(i);
|
||||||
|
|
||||||
|
// Статус
|
||||||
|
String status;
|
||||||
|
if (entry.unmuted) {
|
||||||
|
status = "§aРазмучен";
|
||||||
|
} else {
|
||||||
|
// Проверяем, активен ли ещё мут
|
||||||
|
if (entry.isPermanent()) {
|
||||||
|
status = "§cАктивен (навсегда)";
|
||||||
|
} else {
|
||||||
|
long endTime = entry.mutedAt + entry.duration;
|
||||||
|
if (System.currentTimeMillis() > endTime) {
|
||||||
|
status = "§7Истёк";
|
||||||
|
} else {
|
||||||
|
long remaining = endTime - System.currentTimeMillis();
|
||||||
|
status = "§cАктивен (" + plugin.getMuteManager().formatTime(remaining) + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Длительность
|
||||||
|
String durationStr = entry.isPermanent() ? "Навсегда" : plugin.getMuteManager().formatTime(entry.duration);
|
||||||
|
|
||||||
|
sender.sendMessage("§7" + index + ". §f" + dateFormat.format(new Date(entry.mutedAt)) + " §7- " + status);
|
||||||
|
sender.sendMessage(" §7Длительность: §f" + durationStr);
|
||||||
|
sender.sendMessage(" §7Причина: §f" + (entry.reason != null ? entry.reason : "Не указана"));
|
||||||
|
sender.sendMessage(" §7Выдал: §f" + entry.mutedBy);
|
||||||
|
|
||||||
|
if (entry.unmuted && entry.unmutedBy != null) {
|
||||||
|
sender.sendMessage(" §7Размутил: §f" + entry.unmutedBy + " §7(" + dateFormat.format(new Date(entry.unmutedAt)) + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
index++;
|
||||||
|
|
||||||
|
// Ограничиваем вывод
|
||||||
|
if (index > 10) {
|
||||||
|
sender.sendMessage("§7... и ещё " + (history.size() - 10) + " записей");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return completions;
|
||||||
|
}
|
||||||
|
}
|
||||||
76
src/main/java/com/loki/lochat/commands/MuteListCommand.java
Normal file
76
src/main/java/com/loki/lochat/commands/MuteListCommand.java
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
package com.loki.lochat.commands;
|
||||||
|
|
||||||
|
import com.loki.lochat.LoChat;
|
||||||
|
import com.loki.lochat.managers.MuteManager;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandExecutor;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Команда /lmutelist - список активных мутов
|
||||||
|
*/
|
||||||
|
public class MuteListCommand implements CommandExecutor {
|
||||||
|
|
||||||
|
private final LoChat plugin;
|
||||||
|
private final SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy HH:mm");
|
||||||
|
|
||||||
|
public MuteListCommand(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.mutelist")) {
|
||||||
|
sender.sendMessage(plugin.getMessageConfig().getComponent("errors.no-permission"));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<UUID, MuteManager.MuteData> activeMutes = plugin.getMuteManager().getActiveMutes();
|
||||||
|
|
||||||
|
if (activeMutes.isEmpty()) {
|
||||||
|
sender.sendMessage("§aНет активных мутов");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
sender.sendMessage("§6§l=== Активные муты (" + activeMutes.size() + ") ===");
|
||||||
|
|
||||||
|
int index = 1;
|
||||||
|
for (Map.Entry<UUID, MuteManager.MuteData> entry : activeMutes.entrySet()) {
|
||||||
|
UUID uuid = entry.getKey();
|
||||||
|
MuteManager.MuteData data = entry.getValue();
|
||||||
|
|
||||||
|
// Получаем имя игрока
|
||||||
|
String playerName = data.playerName;
|
||||||
|
if (playerName == null) {
|
||||||
|
OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(uuid);
|
||||||
|
playerName = offlinePlayer.getName() != null ? offlinePlayer.getName() : uuid.toString().substring(0, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Форматируем время
|
||||||
|
String timeStr;
|
||||||
|
if (data.isPermanent()) {
|
||||||
|
timeStr = "§4Навсегда";
|
||||||
|
} else {
|
||||||
|
long remaining = data.endTime - System.currentTimeMillis();
|
||||||
|
timeStr = "§e" + plugin.getMuteManager().formatTime(remaining);
|
||||||
|
}
|
||||||
|
|
||||||
|
sender.sendMessage("§7" + index + ". §f" + playerName + " §7- " + timeStr);
|
||||||
|
sender.sendMessage(" §7Причина: §f" + (data.reason != null ? data.reason : "Не указана"));
|
||||||
|
sender.sendMessage(" §7Выдал: §f" + data.mutedBy + " §7(" + dateFormat.format(new Date(data.mutedAt)) + ")");
|
||||||
|
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -52,7 +52,7 @@ public class UnmuteCommand implements CommandExecutor, TabCompleter {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Размучиваем оффлайн игрока
|
// Размучиваем оффлайн игрока
|
||||||
if (plugin.getMuteManager().unmute(offlinePlayer.getUniqueId())) {
|
if (plugin.getMuteManager().unmute(offlinePlayer.getUniqueId(), sender.getName())) {
|
||||||
sender.sendMessage("§aИгрок §e" + targetName + " §aразмучен");
|
sender.sendMessage("§aИгрок §e" + targetName + " §aразмучен");
|
||||||
|
|
||||||
if (!silent) {
|
if (!silent) {
|
||||||
|
|
@ -66,7 +66,7 @@ public class UnmuteCommand implements CommandExecutor, TabCompleter {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Размучиваем онлайн игрока
|
// Размучиваем онлайн игрока
|
||||||
if (plugin.getMuteManager().unmute(target.getUniqueId())) {
|
if (plugin.getMuteManager().unmute(target.getUniqueId(), sender.getName())) {
|
||||||
sender.sendMessage("§aИгрок §e" + target.getName() + " §aразмучен");
|
sender.sendMessage("§aИгрок §e" + target.getName() + " §aразмучен");
|
||||||
target.sendMessage("§aВы были размучены!");
|
target.sendMessage("§aВы были размучены!");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,7 @@ import com.loki.lochat.LoChat;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.Map;
|
import java.util.*;
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -18,42 +17,69 @@ public class MuteManager {
|
||||||
|
|
||||||
private final LoChat plugin;
|
private final LoChat plugin;
|
||||||
private final Map<UUID, MuteData> mutes = new ConcurrentHashMap<>();
|
private final Map<UUID, MuteData> mutes = new ConcurrentHashMap<>();
|
||||||
|
private final Map<UUID, List<MuteHistoryEntry>> history = new ConcurrentHashMap<>();
|
||||||
private final File dataFile;
|
private final File dataFile;
|
||||||
|
private final File historyFile;
|
||||||
private final Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
private final Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||||
|
|
||||||
public MuteManager(LoChat plugin) {
|
public MuteManager(LoChat plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.dataFile = new File(plugin.getDataFolder(), "mutes.json");
|
this.dataFile = new File(plugin.getDataFolder(), "mutes.json");
|
||||||
|
this.historyFile = new File(plugin.getDataFolder(), "mute-history.json");
|
||||||
load();
|
load();
|
||||||
|
loadHistory();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Замутить игрока
|
* Замутить игрока
|
||||||
* @param uuid UUID игрока
|
* @param uuid UUID игрока
|
||||||
|
* @param playerName имя игрока
|
||||||
* @param duration длительность в миллисекундах (0 = перманентный)
|
* @param duration длительность в миллисекундах (0 = перманентный)
|
||||||
* @param reason причина
|
* @param reason причина
|
||||||
* @param mutedBy кто замутил
|
* @param mutedBy кто замутил
|
||||||
*/
|
*/
|
||||||
public void mute(UUID uuid, long duration, String reason, String mutedBy) {
|
public void mute(UUID uuid, String playerName, long duration, String reason, String mutedBy) {
|
||||||
long endTime = duration > 0 ? System.currentTimeMillis() + duration : 0;
|
long endTime = duration > 0 ? System.currentTimeMillis() + duration : 0;
|
||||||
mutes.put(uuid, new MuteData(endTime, reason, mutedBy, System.currentTimeMillis()));
|
MuteData data = new MuteData(endTime, reason, mutedBy, System.currentTimeMillis(), playerName);
|
||||||
|
mutes.put(uuid, data);
|
||||||
|
|
||||||
|
// Добавляем в историю
|
||||||
|
addToHistory(uuid, playerName, duration, reason, mutedBy);
|
||||||
|
|
||||||
saveAsync();
|
saveAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Замутить игрока (без имени - для совместимости)
|
||||||
|
*/
|
||||||
|
public void mute(UUID uuid, long duration, String reason, String mutedBy) {
|
||||||
|
mute(uuid, null, duration, reason, mutedBy);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Размутить игрока
|
* Размутить игрока
|
||||||
* @param uuid UUID игрока
|
* @param uuid UUID игрока
|
||||||
|
* @param unmutedBy кто размутил (null если автоматически)
|
||||||
* @return true если игрок был замучен
|
* @return true если игрок был замучен
|
||||||
*/
|
*/
|
||||||
public boolean unmute(UUID uuid) {
|
public boolean unmute(UUID uuid, String unmutedBy) {
|
||||||
MuteData removed = mutes.remove(uuid);
|
MuteData removed = mutes.remove(uuid);
|
||||||
if (removed != null) {
|
if (removed != null) {
|
||||||
|
// Обновляем историю - помечаем как размученный
|
||||||
|
updateHistoryUnmute(uuid, unmutedBy);
|
||||||
saveAsync();
|
saveAsync();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Размутить игрока (для совместимости)
|
||||||
|
*/
|
||||||
|
public boolean unmute(UUID uuid) {
|
||||||
|
return unmute(uuid, null);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Проверить, замучен ли игрок
|
* Проверить, замучен ли игрок
|
||||||
*/
|
*/
|
||||||
|
|
@ -172,8 +198,121 @@ public class MuteManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void loadHistory() {
|
||||||
|
if (!historyFile.exists()) return;
|
||||||
|
|
||||||
|
try (Reader reader = new FileReader(historyFile)) {
|
||||||
|
Type type = new TypeToken<Map<String, List<MuteHistoryEntry>>>(){}.getType();
|
||||||
|
Map<String, List<MuteHistoryEntry>> loaded = gson.fromJson(reader, type);
|
||||||
|
if (loaded != null) {
|
||||||
|
loaded.forEach((key, value) -> {
|
||||||
|
try {
|
||||||
|
history.put(UUID.fromString(key), new ArrayList<>(value));
|
||||||
|
} catch (IllegalArgumentException ignored) {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
plugin.getLogger().warning("Ошибка загрузки истории мутов: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void saveHistory() {
|
||||||
|
try {
|
||||||
|
if (!historyFile.getParentFile().exists()) {
|
||||||
|
historyFile.getParentFile().mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, List<MuteHistoryEntry>> toSave = new ConcurrentHashMap<>();
|
||||||
|
history.forEach((uuid, data) -> toSave.put(uuid.toString(), data));
|
||||||
|
|
||||||
|
try (Writer writer = new FileWriter(historyFile)) {
|
||||||
|
gson.toJson(toSave, writer);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
plugin.getLogger().warning("Ошибка сохранения истории мутов: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveHistoryAsync() {
|
||||||
|
plugin.getServer().getScheduler().runTaskAsynchronously(plugin, this::saveHistory);
|
||||||
|
}
|
||||||
|
|
||||||
private void saveAsync() {
|
private void saveAsync() {
|
||||||
plugin.getServer().getScheduler().runTaskAsynchronously(plugin, this::save);
|
plugin.getServer().getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||||
|
save();
|
||||||
|
saveHistory();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Добавить запись в историю
|
||||||
|
*/
|
||||||
|
private void addToHistory(UUID uuid, String playerName, long duration, String reason, String mutedBy) {
|
||||||
|
List<MuteHistoryEntry> playerHistory = history.computeIfAbsent(uuid, k -> new ArrayList<>());
|
||||||
|
playerHistory.add(new MuteHistoryEntry(
|
||||||
|
playerName,
|
||||||
|
duration,
|
||||||
|
reason,
|
||||||
|
mutedBy,
|
||||||
|
System.currentTimeMillis(),
|
||||||
|
false,
|
||||||
|
null,
|
||||||
|
0
|
||||||
|
));
|
||||||
|
saveHistoryAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Обновить историю при размуте
|
||||||
|
*/
|
||||||
|
private void updateHistoryUnmute(UUID uuid, String unmutedBy) {
|
||||||
|
List<MuteHistoryEntry> playerHistory = history.get(uuid);
|
||||||
|
if (playerHistory != null && !playerHistory.isEmpty()) {
|
||||||
|
// Находим последний активный мут
|
||||||
|
for (int i = playerHistory.size() - 1; i >= 0; i--) {
|
||||||
|
MuteHistoryEntry entry = playerHistory.get(i);
|
||||||
|
if (!entry.unmuted) {
|
||||||
|
entry.unmuted = true;
|
||||||
|
entry.unmutedBy = unmutedBy;
|
||||||
|
entry.unmutedAt = System.currentTimeMillis();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
saveHistoryAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Получить список всех активных мутов
|
||||||
|
*/
|
||||||
|
public Map<UUID, MuteData> getActiveMutes() {
|
||||||
|
// Очищаем истёкшие муты
|
||||||
|
mutes.entrySet().removeIf(entry -> {
|
||||||
|
MuteData data = entry.getValue();
|
||||||
|
return data.endTime > 0 && System.currentTimeMillis() > data.endTime;
|
||||||
|
});
|
||||||
|
return new HashMap<>(mutes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Получить историю мутов игрока
|
||||||
|
*/
|
||||||
|
public List<MuteHistoryEntry> getPlayerHistory(UUID uuid) {
|
||||||
|
return history.getOrDefault(uuid, new ArrayList<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Получить UUID по имени из истории
|
||||||
|
*/
|
||||||
|
public UUID getUUIDByName(String name) {
|
||||||
|
for (Map.Entry<UUID, List<MuteHistoryEntry>> entry : history.entrySet()) {
|
||||||
|
for (MuteHistoryEntry historyEntry : entry.getValue()) {
|
||||||
|
if (historyEntry.playerName != null && historyEntry.playerName.equalsIgnoreCase(name)) {
|
||||||
|
return entry.getKey();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -184,18 +323,56 @@ public class MuteManager {
|
||||||
public String reason;
|
public String reason;
|
||||||
public String mutedBy;
|
public String mutedBy;
|
||||||
public long mutedAt;
|
public long mutedAt;
|
||||||
|
public String playerName;
|
||||||
|
|
||||||
public MuteData() {}
|
public MuteData() {}
|
||||||
|
|
||||||
public MuteData(long endTime, String reason, String mutedBy, long mutedAt) {
|
public MuteData(long endTime, String reason, String mutedBy, long mutedAt) {
|
||||||
|
this(endTime, reason, mutedBy, mutedAt, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MuteData(long endTime, String reason, String mutedBy, long mutedAt, String playerName) {
|
||||||
this.endTime = endTime;
|
this.endTime = endTime;
|
||||||
this.reason = reason;
|
this.reason = reason;
|
||||||
this.mutedBy = mutedBy;
|
this.mutedBy = mutedBy;
|
||||||
this.mutedAt = mutedAt;
|
this.mutedAt = mutedAt;
|
||||||
|
this.playerName = playerName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPermanent() {
|
public boolean isPermanent() {
|
||||||
return endTime == 0;
|
return endTime == 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Запись истории мута
|
||||||
|
*/
|
||||||
|
public static class MuteHistoryEntry {
|
||||||
|
public String playerName;
|
||||||
|
public long duration; // 0 = перманентный
|
||||||
|
public String reason;
|
||||||
|
public String mutedBy;
|
||||||
|
public long mutedAt;
|
||||||
|
public boolean unmuted;
|
||||||
|
public String unmutedBy;
|
||||||
|
public long unmutedAt;
|
||||||
|
|
||||||
|
public MuteHistoryEntry() {}
|
||||||
|
|
||||||
|
public MuteHistoryEntry(String playerName, long duration, String reason, String mutedBy,
|
||||||
|
long mutedAt, boolean unmuted, String unmutedBy, long unmutedAt) {
|
||||||
|
this.playerName = playerName;
|
||||||
|
this.duration = duration;
|
||||||
|
this.reason = reason;
|
||||||
|
this.mutedBy = mutedBy;
|
||||||
|
this.mutedAt = mutedAt;
|
||||||
|
this.unmuted = unmuted;
|
||||||
|
this.unmutedBy = unmutedBy;
|
||||||
|
this.unmutedAt = unmutedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPermanent() {
|
||||||
|
return duration == 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,18 @@ commands:
|
||||||
permission: lochat.unmute
|
permission: lochat.unmute
|
||||||
aliases: [дгтьгеу]
|
aliases: [дгтьгеу]
|
||||||
|
|
||||||
|
lmutelist:
|
||||||
|
description: List all active mutes
|
||||||
|
usage: /lmutelist
|
||||||
|
permission: lochat.mutelist
|
||||||
|
aliases: [дьгеудшые]
|
||||||
|
|
||||||
|
lmutehistory:
|
||||||
|
description: View mute history of a player
|
||||||
|
usage: /lmutehistory <player>
|
||||||
|
permission: lochat.mutehistory
|
||||||
|
aliases: [дьгеершыещку]
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
chat.global.use:
|
chat.global.use:
|
||||||
default: true
|
default: true
|
||||||
|
|
@ -156,3 +168,7 @@ permissions:
|
||||||
default: op
|
default: op
|
||||||
lochat.unmute:
|
lochat.unmute:
|
||||||
default: op
|
default: op
|
||||||
|
lochat.mutelist:
|
||||||
|
default: op
|
||||||
|
lochat.mutehistory:
|
||||||
|
default: op
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue