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
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue