Remove TextDisplay, display name updates, mute system, and filter/censorship
This commit is contained in:
parent
a87a942b28
commit
712a8a3353
15 changed files with 2 additions and 1064 deletions
|
|
@ -20,14 +20,12 @@ public final class LoChat extends JavaPlugin {
|
|||
private PMManager pmManager;
|
||||
private IgnoreManager ignoreManager;
|
||||
private AutoMessageManager autoMessageManager;
|
||||
private FilterManager filterManager;
|
||||
private AntiSpamManager antiSpamManager;
|
||||
private CooldownManager cooldownManager;
|
||||
private MentionManager mentionManager;
|
||||
private SpyManager spyManager;
|
||||
private EmojiManager emojiManager;
|
||||
private CustomCommandManager customCommandManager;
|
||||
private MuteManager muteManager;
|
||||
private GradientModule gradientModule;
|
||||
|
||||
@Override
|
||||
|
|
@ -42,13 +40,11 @@ public final class LoChat extends JavaPlugin {
|
|||
emojiManager = new EmojiManager(this);
|
||||
ignoreManager = new IgnoreManager(this);
|
||||
pmManager = new PMManager();
|
||||
filterManager = new FilterManager(this);
|
||||
antiSpamManager = new AntiSpamManager(this);
|
||||
cooldownManager = new CooldownManager();
|
||||
mentionManager = new MentionManager(this);
|
||||
spyManager = new SpyManager(this);
|
||||
customCommandManager = new CustomCommandManager(this);
|
||||
muteManager = new MuteManager(this);
|
||||
chatManager = new ChatManager(this);
|
||||
autoMessageManager = new AutoMessageManager(this);
|
||||
|
||||
|
|
@ -84,9 +80,6 @@ public final class LoChat extends JavaPlugin {
|
|||
if (ignoreManager != null) {
|
||||
ignoreManager.save();
|
||||
}
|
||||
if (muteManager != null) {
|
||||
muteManager.saveData();
|
||||
}
|
||||
if (gradientModule != null) {
|
||||
gradientModule.shutdown();
|
||||
}
|
||||
|
|
@ -104,8 +97,6 @@ public final class LoChat extends JavaPlugin {
|
|||
getCommand("announce").setExecutor(new AnnounceCommand(this));
|
||||
getCommand("chatspy").setExecutor(new ChatSpyCommand(this));
|
||||
getCommand("clearchat").setExecutor(new ClearChatCommand(this));
|
||||
getCommand("mute").setExecutor(new MuteCommand(this));
|
||||
getCommand("unmute").setExecutor(new UnmuteCommand(this));
|
||||
|
||||
LoChatCommand loChatCommand = new LoChatCommand(this);
|
||||
getCommand("lochat").setExecutor(loChatCommand);
|
||||
|
|
@ -124,9 +115,6 @@ public final class LoChat extends JavaPlugin {
|
|||
if (customCommandManager != null) {
|
||||
customCommandManager.reload();
|
||||
}
|
||||
if (filterManager != null) {
|
||||
filterManager.reload();
|
||||
}
|
||||
}
|
||||
|
||||
public static LoChat getInstance() {
|
||||
|
|
@ -157,9 +145,6 @@ public final class LoChat extends JavaPlugin {
|
|||
return autoMessageManager;
|
||||
}
|
||||
|
||||
public FilterManager getFilterManager() {
|
||||
return filterManager;
|
||||
}
|
||||
|
||||
public AntiSpamManager getAntiSpamManager() {
|
||||
return antiSpamManager;
|
||||
|
|
@ -189,7 +174,4 @@ public final class LoChat extends JavaPlugin {
|
|||
return customCommandManager;
|
||||
}
|
||||
|
||||
public MuteManager getMuteManager() {
|
||||
return muteManager;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,122 +0,0 @@
|
|||
package com.loki.lochat.commands;
|
||||
|
||||
import com.loki.lochat.LoChat;
|
||||
import com.loki.lochat.utils.ChatFormatter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
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("chat.mute")) {
|
||||
sender.sendMessage(ChatFormatter.parse(plugin.getMessageConfig().getNoPermission()));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length < 2) {
|
||||
sender.sendMessage(ChatFormatter.parse(plugin.getMessageConfig().getInvalidUsage("/mute <игрок> <время> [причина]")));
|
||||
sender.sendMessage(ChatFormatter.parse("󅒐Время: 1m, 1h, 1d, permanent"));
|
||||
return true;
|
||||
}
|
||||
|
||||
String playerName = args[0];
|
||||
String timeStr = args[1];
|
||||
String reason = args.length > 2 ? String.join(" ", Arrays.copyOfRange(args, 2, args.length)) : "Нарушение правил чата";
|
||||
|
||||
Player target = Bukkit.getPlayer(playerName);
|
||||
if (target == null) {
|
||||
sender.sendMessage(ChatFormatter.parse(plugin.getMessageConfig().getPlayerNotFound()));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Парсим время
|
||||
long duration = parseTime(timeStr);
|
||||
if (duration == -1) {
|
||||
sender.sendMessage(ChatFormatter.parse("&#FF0000Неверный формат времени! Используйте: 1m, 1h, 1d, permanent"));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Мутим игрока
|
||||
plugin.getMuteManager().mutePlayer(target.getUniqueId(), duration, reason, sender.getName());
|
||||
|
||||
// Уведомления
|
||||
String timeDisplay = duration == 0 ? "навсегда" : formatTime(duration);
|
||||
sender.sendMessage(ChatFormatter.parse(
|
||||
plugin.getMessageConfig().get("mute.muted", "{player}", target.getName(), "{time}", timeDisplay)
|
||||
));
|
||||
|
||||
if (target.isOnline()) {
|
||||
target.sendMessage(ChatFormatter.parse(
|
||||
plugin.getMessageConfig().get("mute.you-muted", "{time}", timeDisplay)
|
||||
));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private long parseTime(String timeStr) {
|
||||
if (timeStr.equalsIgnoreCase("permanent") || timeStr.equalsIgnoreCase("perm")) {
|
||||
return 0; // 0 = permanent
|
||||
}
|
||||
|
||||
try {
|
||||
char unit = timeStr.charAt(timeStr.length() - 1);
|
||||
int amount = Integer.parseInt(timeStr.substring(0, timeStr.length() - 1));
|
||||
|
||||
return switch (unit) {
|
||||
case 'm' -> amount * 60L * 1000L; // минуты
|
||||
case 'h' -> amount * 60L * 60L * 1000L; // часы
|
||||
case 'd' -> amount * 24L * 60L * 60L * 1000L; // дни
|
||||
default -> -1;
|
||||
};
|
||||
} catch (NumberFormatException | StringIndexOutOfBoundsException e) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private String formatTime(long millis) {
|
||||
long seconds = millis / 1000;
|
||||
long minutes = seconds / 60;
|
||||
long hours = minutes / 60;
|
||||
long days = hours / 24;
|
||||
|
||||
if (days > 0) return days + "д";
|
||||
if (hours > 0) return hours + "ч";
|
||||
if (minutes > 0) return minutes + "м";
|
||||
return seconds + "с";
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) {
|
||||
if (args.length == 1) {
|
||||
return Bukkit.getOnlinePlayers().stream()
|
||||
.map(Player::getName)
|
||||
.filter(name -> name.toLowerCase().startsWith(args[0].toLowerCase()))
|
||||
.collect(Collectors.toList());
|
||||
} else if (args.length == 2) {
|
||||
List<String> times = Arrays.asList("1m", "5m", "10m", "30m", "1h", "2h", "6h", "12h", "1d", "3d", "7d", "permanent");
|
||||
return times.stream()
|
||||
.filter(time -> time.toLowerCase().startsWith(args[1].toLowerCase()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
package com.loki.lochat.commands;
|
||||
|
||||
import com.loki.lochat.LoChat;
|
||||
import com.loki.lochat.utils.ChatFormatter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
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("chat.mute")) {
|
||||
sender.sendMessage(ChatFormatter.parse(plugin.getMessageConfig().getNoPermission()));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length != 1) {
|
||||
sender.sendMessage(ChatFormatter.parse(plugin.getMessageConfig().getInvalidUsage("/unmute <игрок>")));
|
||||
return true;
|
||||
}
|
||||
|
||||
String playerName = args[0];
|
||||
Player target = Bukkit.getPlayer(playerName);
|
||||
if (target == null) {
|
||||
sender.sendMessage(ChatFormatter.parse(plugin.getMessageConfig().getPlayerNotFound()));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!plugin.getMuteManager().isMuted(target.getUniqueId())) {
|
||||
sender.sendMessage(ChatFormatter.parse(
|
||||
plugin.getMessageConfig().get("mute.not-muted", "{player}", target.getName())
|
||||
));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Размучиваем
|
||||
plugin.getMuteManager().unmutePlayer(target.getUniqueId());
|
||||
|
||||
// Уведомления
|
||||
sender.sendMessage(ChatFormatter.parse(
|
||||
plugin.getMessageConfig().get("mute.unmuted", "{player}", target.getName())
|
||||
));
|
||||
|
||||
if (target.isOnline()) {
|
||||
target.sendMessage(ChatFormatter.parse("�FF00Вы были размучены!"));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) {
|
||||
if (args.length == 1) {
|
||||
return Bukkit.getOnlinePlayers().stream()
|
||||
.map(Player::getName)
|
||||
.filter(name -> name.toLowerCase().startsWith(args[0].toLowerCase()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -12,7 +12,6 @@ import com.loki.lochat.gradient.listeners.GradientGUIListener;
|
|||
import com.loki.lochat.gradient.listeners.GradientPlayerListener;
|
||||
import com.loki.lochat.gradient.util.DisplayNameUtil;
|
||||
import com.loki.lochat.gradient.util.GradientUtil;
|
||||
import com.loki.lochat.gradient.util.TextDisplayManager;
|
||||
import org.black_ixx.playerpoints.PlayerPoints;
|
||||
import org.black_ixx.playerpoints.PlayerPointsAPI;
|
||||
import org.bukkit.Bukkit;
|
||||
|
|
@ -30,7 +29,6 @@ public class GradientModule {
|
|||
private GradientDataManager dataManager;
|
||||
private GradientLuckPermsHook luckPermsHook;
|
||||
private PlayerPointsAPI playerPointsAPI;
|
||||
private TextDisplayManager textDisplayManager;
|
||||
private boolean enabled;
|
||||
|
||||
public GradientModule(JavaPlugin plugin) {
|
||||
|
|
@ -66,8 +64,6 @@ public class GradientModule {
|
|||
// Подключение LuckPerms
|
||||
luckPermsHook = new GradientLuckPermsHook(plugin);
|
||||
|
||||
// Инициализация TextDisplayManager
|
||||
textDisplayManager = new TextDisplayManager(this);
|
||||
|
||||
// Регистрация команд
|
||||
registerCommands();
|
||||
|
|
@ -105,9 +101,6 @@ public class GradientModule {
|
|||
* Выключение модуля
|
||||
*/
|
||||
public void shutdown() {
|
||||
if (textDisplayManager != null) {
|
||||
textDisplayManager.removeAllDisplays();
|
||||
}
|
||||
if (dataManager != null) {
|
||||
dataManager.saveAll();
|
||||
}
|
||||
|
|
@ -268,7 +261,6 @@ public class GradientModule {
|
|||
public GradientDataManager getDataManager() { return dataManager; }
|
||||
public GradientLuckPermsHook getLuckPermsHook() { return luckPermsHook; }
|
||||
public PlayerPointsAPI getPlayerPointsAPI() { return playerPointsAPI; }
|
||||
public TextDisplayManager getTextDisplayManager() { return textDisplayManager; }
|
||||
public boolean hasPlayerPoints() { return playerPointsAPI != null; }
|
||||
public boolean isEnabled() { return enabled; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,9 +87,6 @@ public class GradientAdminCommand implements CommandExecutor, TabCompleter {
|
|||
case "updateall" -> {
|
||||
handleUpdateAll(sender, msg);
|
||||
}
|
||||
case "toggledisplay" -> {
|
||||
handleToggleDisplay(sender, msg);
|
||||
}
|
||||
default -> sendHelp(sender);
|
||||
}
|
||||
|
||||
|
|
@ -334,36 +331,6 @@ public class GradientAdminCommand implements CommandExecutor, TabCompleter {
|
|||
sender.sendMessage("§aОбновлены display names для §f" + count + " §aигроков");
|
||||
}
|
||||
|
||||
private void handleToggleDisplay(CommandSender sender, GradientMessages msg) {
|
||||
// Переключаем режим TextDisplay в конфиге
|
||||
boolean currentMode = module.getConfig().isUseTextDisplay();
|
||||
boolean newMode = !currentMode;
|
||||
|
||||
// Обновляем конфиг (временно в памяти)
|
||||
module.getConfig().setUseTextDisplay(newMode);
|
||||
|
||||
if (newMode) {
|
||||
// Переключаемся на TextDisplay
|
||||
sender.sendMessage("§aВключен режим TextDisplay");
|
||||
// Удаляем все обычные display names и создаем TextDisplay
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
player.displayName(null); // Сбрасываем обычный display name
|
||||
GradientPlayerData data = module.getDataManager().getPlayerData(player.getUniqueId());
|
||||
FoliaUtil.runEntityTask(module.getPlugin(), player,
|
||||
() -> module.getTextDisplayManager().updatePlayerDisplay(player));
|
||||
}
|
||||
} else {
|
||||
// Переключаемся на обычный display name
|
||||
sender.sendMessage("§cВыключен режим TextDisplay");
|
||||
// Удаляем все TextDisplay и обновляем обычные display names
|
||||
module.getTextDisplayManager().removeAllDisplays();
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
GradientPlayerData data = module.getDataManager().getPlayerData(player.getUniqueId());
|
||||
FoliaUtil.runEntityTask(module.getPlugin(), player,
|
||||
() -> DisplayNameUtil.updateDisplayName(module, player, data));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command,
|
||||
|
|
@ -372,7 +339,7 @@ public class GradientAdminCommand implements CommandExecutor, TabCompleter {
|
|||
|
||||
if (args.length == 1) {
|
||||
return Arrays.asList("reload", "info", "setcolor", "setprefix", "coloron", "coloroff",
|
||||
"prefixon", "prefixoff", "resetcolor", "resetprefix", "updateall", "toggledisplay").stream()
|
||||
"prefixon", "prefixoff", "resetcolor", "resetprefix", "updateall").stream()
|
||||
.filter(s -> s.startsWith(args[0].toLowerCase()))
|
||||
.toList();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,7 +83,6 @@ public class GradientConfig {
|
|||
.anyMatch(blacklisted -> lowerPrefix.contains(blacklisted.toLowerCase()));
|
||||
}
|
||||
|
||||
// Display settings - читаем из main config.yml, если есть, иначе из gradient-config.yml
|
||||
public boolean isUpdateDisplayName() {
|
||||
if (mainConfig.contains("display.update-display-name")) {
|
||||
return mainConfig.getBoolean("display.update-display-name", true);
|
||||
|
|
@ -97,44 +96,4 @@ public class GradientConfig {
|
|||
}
|
||||
return config.getBoolean("display.update-tab-list", true);
|
||||
}
|
||||
|
||||
public boolean isUseTextDisplay() {
|
||||
if (mainConfig.contains("display.use-text-display")) {
|
||||
return mainConfig.getBoolean("display.use-text-display", true);
|
||||
}
|
||||
return config.getBoolean("display.use-text-display", true);
|
||||
}
|
||||
|
||||
public double getTextDisplayHeight() {
|
||||
if (mainConfig.contains("display.text-display-height")) {
|
||||
return mainConfig.getDouble("display.text-display-height", 2.8);
|
||||
}
|
||||
return config.getDouble("display.text-display-height", 2.8);
|
||||
}
|
||||
|
||||
public float getTextDisplayScale() {
|
||||
if (mainConfig.contains("display.text-display-scale")) {
|
||||
return (float) mainConfig.getDouble("display.text-display-scale", 0.8);
|
||||
}
|
||||
return (float) config.getDouble("display.text-display-scale", 0.8);
|
||||
}
|
||||
|
||||
public boolean isTextDisplaySeeThrough() {
|
||||
if (mainConfig.contains("display.text-display-see-through")) {
|
||||
return mainConfig.getBoolean("display.text-display-see-through", false);
|
||||
}
|
||||
return config.getBoolean("display.text-display-see-through", false);
|
||||
}
|
||||
|
||||
public String getTextDisplayFormat() {
|
||||
if (mainConfig.contains("display.text-display-format")) {
|
||||
return mainConfig.getString("display.text-display-format", "{prefix}{player}");
|
||||
}
|
||||
return config.getString("display.text-display-format", "{prefix}{player}");
|
||||
}
|
||||
|
||||
// Метод для временного изменения настройки TextDisplay
|
||||
public void setUseTextDisplay(boolean useTextDisplay) {
|
||||
config.set("display.use-text-display", useTextDisplay);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
package com.loki.lochat.gradient.listeners;
|
||||
|
||||
import com.loki.lochat.gradient.GradientModule;
|
||||
import com.loki.lochat.gradient.data.GradientPlayerData;
|
||||
import com.loki.lochat.gradient.util.DisplayNameUtil;
|
||||
import com.loki.lochat.gradient.util.FoliaUtil;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
|
|
@ -10,7 +8,6 @@ import org.bukkit.event.EventPriority;
|
|||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
|
||||
/**
|
||||
* Слушатель событий игроков для градиентного модуля
|
||||
|
|
@ -26,69 +23,15 @@ public class GradientPlayerListener implements Listener {
|
|||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
|
||||
FoliaUtil.runAsync(module.getPlugin(), () -> {
|
||||
GradientPlayerData data = module.getDataManager().getPlayerData(player.getUniqueId());
|
||||
|
||||
FoliaUtil.runEntityTask(module.getPlugin(), player, () -> {
|
||||
if (!player.isOnline()) return;
|
||||
|
||||
// Обновляем display name если включено
|
||||
if (module.getConfig().isUpdateDisplayName()) {
|
||||
DisplayNameUtil.updateDisplayName(module, player, data);
|
||||
}
|
||||
|
||||
if (data.hasPrefix() && data.isPrefixEnabled()) {
|
||||
module.getLuckPermsHook().setPrefix(player,
|
||||
DisplayNameUtil.buildColoredPrefix(module, data));
|
||||
}
|
||||
});
|
||||
module.getDataManager().getPlayerData(player.getUniqueId());
|
||||
});
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
|
||||
// Удаляем TextDisplay если есть
|
||||
if (module.getTextDisplayManager() != null) {
|
||||
module.getTextDisplayManager().removePlayerDisplay(player.getUniqueId());
|
||||
}
|
||||
|
||||
FoliaUtil.runAsync(module.getPlugin(),
|
||||
() -> module.getDataManager().savePlayerData(player.getUniqueId()));
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerToggleSneak(org.bukkit.event.player.PlayerToggleSneakEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
|
||||
// Скрываем/показываем TextDisplay при приседании
|
||||
if (module.getTextDisplayManager() != null && module.getTextDisplayManager().hasDisplay(player.getUniqueId())) {
|
||||
FoliaUtil.runEntityTask(module.getPlugin(), player, () -> {
|
||||
if (event.isSneaking()) {
|
||||
// Игрок начал приседать - скрываем TextDisplay
|
||||
module.getTextDisplayManager().hidePlayerDisplay(player.getUniqueId());
|
||||
} else {
|
||||
// Игрок перестал приседать - показываем TextDisplay
|
||||
module.getTextDisplayManager().showPlayerDisplay(player.getUniqueId());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPlayerTeleport(PlayerTeleportEvent event) {
|
||||
if (event.isCancelled()) return;
|
||||
|
||||
Player player = event.getPlayer();
|
||||
|
||||
// Обновляем TextDisplay после телепортации
|
||||
if (module.getTextDisplayManager() != null && module.getTextDisplayManager().hasDisplay(player.getUniqueId())) {
|
||||
FoliaUtil.runEntityTask(module.getPlugin(), player, () -> {
|
||||
if (!player.isOnline()) return;
|
||||
module.getTextDisplayManager().updateDisplayPosition(player);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,13 +25,6 @@ public final class DisplayNameUtil {
|
|||
|
||||
public static void updateDisplayName(GradientModule module, Player player, GradientPlayerData data) {
|
||||
GradientConfig cfg = module.getConfig();
|
||||
|
||||
// Если включен TextDisplay, используем его вместо обычного display name
|
||||
if (cfg.isUseTextDisplay()) {
|
||||
module.getTextDisplayManager().updatePlayerDisplay(player);
|
||||
return;
|
||||
}
|
||||
|
||||
String prefix = null;
|
||||
String prefixFormat = cfg.getPrefixFormat();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,165 +0,0 @@
|
|||
package com.loki.lochat.gradient.util;
|
||||
|
||||
import com.loki.lochat.gradient.GradientModule;
|
||||
import com.loki.lochat.gradient.data.GradientPlayerData;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.TextDisplay;
|
||||
import org.bukkit.util.Transformation;
|
||||
import org.joml.AxisAngle4f;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class TextDisplayManager {
|
||||
|
||||
private final GradientModule module;
|
||||
private final Map<UUID, TextDisplay> playerDisplays = new ConcurrentHashMap<>();
|
||||
private static final MiniMessage MINI_MESSAGE = MiniMessage.miniMessage();
|
||||
|
||||
public TextDisplayManager(GradientModule module) {
|
||||
this.module = module;
|
||||
}
|
||||
public void updatePlayerDisplay(Player player) {
|
||||
if (!module.getConfig().isUpdateDisplayName() || !module.getConfig().isUseTextDisplay()) {
|
||||
return;
|
||||
}
|
||||
|
||||
GradientPlayerData data = module.getDataManager().getPlayerData(player.getUniqueId());
|
||||
String displayText = getDisplayText(player, data);
|
||||
Component textComponent = MINI_MESSAGE.deserialize(displayText);
|
||||
|
||||
TextDisplay display = playerDisplays.get(player.getUniqueId());
|
||||
|
||||
if (display == null || !display.isValid()) {
|
||||
createTextDisplay(player, textComponent);
|
||||
} else {
|
||||
updateTextDisplay(display, player, textComponent);
|
||||
}
|
||||
}
|
||||
private void createTextDisplay(Player player, Component textComponent) {
|
||||
removePlayerDisplay(player.getUniqueId());
|
||||
|
||||
double height = module.getConfig().getTextDisplayHeight();
|
||||
float scale = module.getConfig().getTextDisplayScale();
|
||||
boolean seeThrough = module.getConfig().isTextDisplaySeeThrough();
|
||||
|
||||
TextDisplay display = player.getWorld().spawn(
|
||||
player.getLocation().add(0, height, 0),
|
||||
TextDisplay.class,
|
||||
entity -> {
|
||||
entity.text(textComponent);
|
||||
entity.setBillboard(org.bukkit.entity.Display.Billboard.CENTER);
|
||||
entity.setViewRange(64.0f);
|
||||
entity.setSeeThrough(seeThrough);
|
||||
entity.setShadowRadius(0.0f);
|
||||
entity.setShadowStrength(0.0f);
|
||||
entity.setTransformation(new Transformation(
|
||||
new Vector3f(0, 0, 0),
|
||||
new AxisAngle4f(0, 0, 0, 1),
|
||||
new Vector3f(scale, scale, scale),
|
||||
new AxisAngle4f(0, 0, 0, 1)
|
||||
));
|
||||
entity.setVisibleByDefault(true);
|
||||
}
|
||||
);
|
||||
|
||||
player.addPassenger(display);
|
||||
playerDisplays.put(player.getUniqueId(), display);
|
||||
}
|
||||
private void updateTextDisplay(TextDisplay display, Player player, Component textComponent) {
|
||||
display.text(textComponent);
|
||||
if (!player.getPassengers().contains(display)) {
|
||||
player.addPassenger(display);
|
||||
}
|
||||
}
|
||||
private String getDisplayText(Player player, GradientPlayerData data) {
|
||||
String format = module.getConfig().getTextDisplayFormat();
|
||||
String prefix = getPlayerPrefix(player, data);
|
||||
String playerName = getPlayerName(player, data);
|
||||
String result = format
|
||||
.replace("{prefix}", prefix != null ? prefix : "")
|
||||
.replace("{player}", playerName)
|
||||
.replace("{name}", playerName);
|
||||
return convertLegacyFormats(result);
|
||||
}
|
||||
private String convertLegacyFormats(String message) {
|
||||
if (message == null) return "";
|
||||
message = message.replaceAll("&#([0-9a-fA-F]{6})", "<#$1>");
|
||||
message = message.replaceAll("(?<!<)#([0-9a-fA-F]{6})(?![^<]*>)", "<#$1>");
|
||||
return message;
|
||||
}
|
||||
private String getPlayerPrefix(Player player, GradientPlayerData data) {
|
||||
String prefixFormat = module.getConfig().getPrefixFormat();
|
||||
if (data.isPrefixEnabled() && data.hasPrefix()) {
|
||||
String prefix = prefixFormat.replace("{prefix}", data.getPrefix());
|
||||
if (data.isColorEnabled() && data.hasColors() && module.getConfig().isGradientOnPrefix()) {
|
||||
return GradientUtil.applyGradient(prefix, data.getColors(), false);
|
||||
}
|
||||
return prefix;
|
||||
} else if (module.getLuckPermsHook().isEnabled()) {
|
||||
String lpPrefix = module.getLuckPermsHook().getActivePrefix(player);
|
||||
if (lpPrefix != null && !lpPrefix.isEmpty()) {
|
||||
if (data.isColorEnabled() && data.hasColors() && module.getConfig().isGradientOnLuckPermsPrefix()) {
|
||||
String cleanPrefix = stripColors(lpPrefix);
|
||||
return GradientUtil.applyGradient(cleanPrefix, data.getColors(), false);
|
||||
}
|
||||
return lpPrefix;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
private String getPlayerName(Player player, GradientPlayerData data) {
|
||||
if (data.isColorEnabled() && data.hasColors()) {
|
||||
return GradientUtil.applyGradient(player.getName(), data.getColors(), false);
|
||||
}
|
||||
return player.getName();
|
||||
}
|
||||
private String stripColors(String text) {
|
||||
if (text == null) return "";
|
||||
return text.replaceAll("(?i)(┬зx(┬з[0-9a-f]){6}|┬з[0-9a-fk-or]|&[0-9a-fk-or]|&#[0-9a-f]{6}|<[^>]+>)", "");
|
||||
}
|
||||
public void removePlayerDisplay(UUID playerId) {
|
||||
TextDisplay display = playerDisplays.remove(playerId);
|
||||
if (display != null && display.isValid()) {
|
||||
display.remove();
|
||||
}
|
||||
}
|
||||
public void removeAllDisplays() {
|
||||
for (TextDisplay display : playerDisplays.values()) {
|
||||
if (display != null && display.isValid()) {
|
||||
display.remove();
|
||||
}
|
||||
}
|
||||
playerDisplays.clear();
|
||||
}
|
||||
public void updateDisplayPosition(Player player) {
|
||||
TextDisplay display = playerDisplays.get(player.getUniqueId());
|
||||
if (display != null && display.isValid()) {
|
||||
if (!player.getPassengers().contains(display)) {
|
||||
player.addPassenger(display);
|
||||
}
|
||||
}
|
||||
}
|
||||
public boolean hasDisplay(UUID playerId) {
|
||||
TextDisplay display = playerDisplays.get(playerId);
|
||||
return display != null && display.isValid();
|
||||
}
|
||||
|
||||
public void hidePlayerDisplay(UUID playerId) {
|
||||
TextDisplay display = playerDisplays.get(playerId);
|
||||
if (display != null && display.isValid()) {
|
||||
display.setViewRange(0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
public void showPlayerDisplay(UUID playerId) {
|
||||
TextDisplay display = playerDisplays.get(playerId);
|
||||
if (display != null && display.isValid()) {
|
||||
display.setViewRange(64.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -57,17 +57,6 @@ public class PlaceholderAPIHook extends PlaceholderExpansion {
|
|||
}
|
||||
case "spy_enabled" -> String.valueOf(plugin.getSpyManager().isSpying(uuid));
|
||||
|
||||
// Mute placeholders
|
||||
case "muted" -> String.valueOf(plugin.getMuteManager().isMuted(uuid));
|
||||
case "mute_time" -> {
|
||||
if (!plugin.getMuteManager().isMuted(uuid)) yield "";
|
||||
yield plugin.getMuteManager().formatRemainingTime(uuid);
|
||||
}
|
||||
case "mute_reason" -> {
|
||||
var muteData = plugin.getMuteManager().getMuteData(uuid);
|
||||
yield muteData != null ? muteData.reason : "";
|
||||
}
|
||||
|
||||
// Gradient placeholders (совместимость с LoPreff)
|
||||
// Используем TAB формат §x§R§R§G§G§B§B для совместимости с TAB плагином
|
||||
case "gradient_full", "full" -> {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package com.loki.lochat.listeners;
|
|||
|
||||
import com.loki.lochat.LoChat;
|
||||
import com.loki.lochat.managers.AntiSpamManager;
|
||||
import com.loki.lochat.managers.FilterManager;
|
||||
import io.papermc.paper.event.player.AsyncChatEvent;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextReplacementConfig;
|
||||
|
|
@ -13,8 +12,6 @@ import org.bukkit.event.EventPriority;
|
|||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class ChatListener implements Listener {
|
||||
|
||||
private final LoChat plugin;
|
||||
|
|
@ -40,25 +37,6 @@ public class ChatListener implements Listener {
|
|||
}
|
||||
|
||||
private void processChat(Player player, Component message, String plainMessage) {
|
||||
|
||||
// ===== MUTE =====
|
||||
if (plugin.getMuteManager().isMuted(player.getUniqueId())) {
|
||||
String timeLeft = plugin.getMuteManager()
|
||||
.formatRemainingTime(player.getUniqueId());
|
||||
|
||||
if (timeLeft.equals("навсегда")) {
|
||||
player.sendMessage(
|
||||
plugin.getMessageConfig().getComponent("mute.permanent")
|
||||
);
|
||||
} else {
|
||||
player.sendMessage(
|
||||
plugin.getMessageConfig()
|
||||
.getComponent("mute.you-muted", "{time}", timeLeft)
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// ===== GLOBAL / LOCAL =====
|
||||
String globalSymbol = plugin.getConfigManager().getGlobalSymbol();
|
||||
boolean isGlobal = plainMessage.startsWith(globalSymbol)
|
||||
|
|
@ -125,27 +103,6 @@ public class ChatListener implements Listener {
|
|||
}
|
||||
}
|
||||
|
||||
// ===== FILTER =====
|
||||
if (!player.hasPermission("chat.bypass.filter")) {
|
||||
FilterManager.FilterResult filter =
|
||||
plugin.getFilterManager().checkMessage(processedPlain);
|
||||
|
||||
switch (filter) {
|
||||
case BLOCKED -> {
|
||||
player.sendMessage(
|
||||
plugin.getMessageConfig().getComponent("filter.blocked")
|
||||
);
|
||||
return;
|
||||
}
|
||||
case WARNED -> {
|
||||
player.sendMessage(
|
||||
plugin.getMessageConfig().getComponent("filter.warned")
|
||||
);
|
||||
processedMessage = censor(processedMessage);
|
||||
}
|
||||
case CENSORED -> processedMessage = censor(processedMessage);
|
||||
}
|
||||
}
|
||||
|
||||
plugin.getCooldownManager().setCooldown(player.getUniqueId(), chatType);
|
||||
|
||||
|
|
@ -157,13 +114,6 @@ public class ChatListener implements Listener {
|
|||
}
|
||||
}
|
||||
|
||||
private Component censor(Component component) {
|
||||
return component.replaceText(TextReplacementConfig.builder()
|
||||
.match(Pattern.compile("(?i)badword"))
|
||||
.replacement("***")
|
||||
.build());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onQuit(PlayerQuitEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
|
|
|
|||
|
|
@ -1,302 +0,0 @@
|
|||
package com.loki.lochat.managers;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.loki.lochat.LoChat;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class FilterManager {
|
||||
|
||||
private final LoChat plugin;
|
||||
private List<String> badWords = new ArrayList<>();
|
||||
private List<String> fragments = new ArrayList<>();
|
||||
|
||||
public FilterManager(LoChat plugin) {
|
||||
this.plugin = plugin;
|
||||
loadFilterWords();
|
||||
}
|
||||
|
||||
/**
|
||||
* Загружает плохие слова из JSON файла
|
||||
*/
|
||||
private void loadFilterWords() {
|
||||
badWords.clear();
|
||||
fragments.clear();
|
||||
|
||||
try {
|
||||
// Сначала пытаемся загрузить из data folder (если есть кастомный)
|
||||
File customFile = new File(plugin.getDataFolder(), "filter-words.json");
|
||||
if (customFile.exists()) {
|
||||
try (FileReader reader = new FileReader(customFile, StandardCharsets.UTF_8)) {
|
||||
JsonObject json = JsonParser.parseReader(reader).getAsJsonObject();
|
||||
loadFromJsonObject(json);
|
||||
plugin.getLogger().info("Загружены плохие слова из filter-words.json (data folder): " + badWords.size() + " слов, " + fragments.size() + " фрагментов");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Если кастомного нет, копируем из ресурсов
|
||||
plugin.saveResource("filter-words.json", false);
|
||||
|
||||
// Теперь загружаем из data folder
|
||||
if (customFile.exists()) {
|
||||
try (FileReader reader = new FileReader(customFile, StandardCharsets.UTF_8)) {
|
||||
JsonObject json = JsonParser.parseReader(reader).getAsJsonObject();
|
||||
loadFromJsonObject(json);
|
||||
plugin.getLogger().info("Загружено " + badWords.size() + " плохих слов и " + fragments.size() + " фрагментов из filter-words.json");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback на старый способ из config.yml
|
||||
List<String> configWords = plugin.getConfigManager().getFilterWords();
|
||||
if (configWords != null && !configWords.isEmpty()) {
|
||||
badWords.addAll(configWords);
|
||||
plugin.getLogger().warning("Используются слова из config.yml (filter-words.json не найден)");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
plugin.getLogger().severe("Ошибка загрузки filter-words.json: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
// Fallback на старый способ
|
||||
List<String> configWords = plugin.getConfigManager().getFilterWords();
|
||||
if (configWords != null && !configWords.isEmpty()) {
|
||||
badWords.addAll(configWords);
|
||||
plugin.getLogger().info("Используются слова из config.yml (fallback)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Загружает данные из JSON объекта
|
||||
*/
|
||||
private void loadFromJsonObject(JsonObject json) {
|
||||
if (json.has("words")) {
|
||||
JsonArray wordsArray = json.getAsJsonArray("words");
|
||||
for (JsonElement element : wordsArray) {
|
||||
String word = element.getAsString();
|
||||
if (word != null && !word.trim().isEmpty()) {
|
||||
badWords.add(word.trim().toLowerCase());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (json.has("fragments")) {
|
||||
JsonArray fragmentsArray = json.getAsJsonArray("fragments");
|
||||
for (JsonElement element : fragmentsArray) {
|
||||
String fragment = element.getAsString();
|
||||
if (fragment != null && !fragment.trim().isEmpty()) {
|
||||
fragments.add(fragment.trim().toLowerCase());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Перезагружает список плохих слов
|
||||
*/
|
||||
public void reload() {
|
||||
loadFilterWords();
|
||||
}
|
||||
|
||||
public enum FilterResult {
|
||||
ALLOWED,
|
||||
CENSORED,
|
||||
BLOCKED,
|
||||
WARNED
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет сообщение на наличие запрещенных слов
|
||||
*/
|
||||
public FilterResult checkMessage(String message) {
|
||||
if (!plugin.getConfigManager().isFilterEnabled()) {
|
||||
return FilterResult.ALLOWED;
|
||||
}
|
||||
|
||||
if (message == null || message.trim().isEmpty()) {
|
||||
return FilterResult.ALLOWED;
|
||||
}
|
||||
|
||||
if (badWords.isEmpty() && fragments.isEmpty()) {
|
||||
return FilterResult.ALLOWED;
|
||||
}
|
||||
|
||||
// Нормализуем сообщение (убираем обход фильтра)
|
||||
String normalizedMessage = normalizeMessage(message);
|
||||
String lowerMessage = normalizedMessage.toLowerCase();
|
||||
String originalLower = message.toLowerCase();
|
||||
|
||||
// Проверяем полные слова
|
||||
for (String word : badWords) {
|
||||
if (word == null || word.trim().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String lowerWord = word.toLowerCase().trim();
|
||||
|
||||
// Проверяем точное совпадение слова (с границами слов)
|
||||
Pattern wordPattern = Pattern.compile("\\b" + Pattern.quote(lowerWord) + "\\b", Pattern.CASE_INSENSITIVE);
|
||||
if (wordPattern.matcher(normalizedMessage).find() || wordPattern.matcher(originalLower).find()) {
|
||||
return getFilterResult();
|
||||
}
|
||||
|
||||
// Также проверяем как подстроку
|
||||
if (lowerMessage.contains(lowerWord) || originalLower.contains(lowerWord)) {
|
||||
return getFilterResult();
|
||||
}
|
||||
}
|
||||
|
||||
// Проверяем фрагменты (поиск по фрагментам типа "пизд" найдет "пизда", "пиздец" и т.д.)
|
||||
for (String fragment : fragments) {
|
||||
if (fragment == null || fragment.trim().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String lowerFragment = fragment.toLowerCase().trim();
|
||||
|
||||
// Ищем фрагмент в нормализованном сообщении
|
||||
if (lowerMessage.contains(lowerFragment) || originalLower.contains(lowerFragment)) {
|
||||
return getFilterResult();
|
||||
}
|
||||
}
|
||||
|
||||
return FilterResult.ALLOWED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает результат фильтрации на основе настроек
|
||||
*/
|
||||
private FilterResult getFilterResult() {
|
||||
String action = plugin.getConfigManager().getFilterAction();
|
||||
return switch (action.toLowerCase()) {
|
||||
case "block" -> FilterResult.BLOCKED;
|
||||
case "warn" -> FilterResult.WARNED;
|
||||
default -> FilterResult.CENSORED;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Цензурирует сообщение, заменяя запрещенные слова
|
||||
*/
|
||||
public String censorMessage(String message) {
|
||||
if (!plugin.getConfigManager().isFilterEnabled()) {
|
||||
return message;
|
||||
}
|
||||
|
||||
if (message == null || message.trim().isEmpty()) {
|
||||
return message;
|
||||
}
|
||||
|
||||
if (badWords.isEmpty() && fragments.isEmpty()) {
|
||||
return message;
|
||||
}
|
||||
|
||||
String replacement = plugin.getConfigManager().getFilterReplacement();
|
||||
if (replacement == null) {
|
||||
replacement = "***";
|
||||
}
|
||||
|
||||
String result = message;
|
||||
String normalizedMessage = normalizeMessage(message);
|
||||
|
||||
// Заменяем полные слова
|
||||
for (String word : badWords) {
|
||||
if (word == null || word.trim().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Заменяем точные совпадения слов
|
||||
Pattern wordPattern = Pattern.compile("\\b" + Pattern.quote(word) + "\\b", Pattern.CASE_INSENSITIVE);
|
||||
result = wordPattern.matcher(result).replaceAll(replacement);
|
||||
|
||||
// Также заменяем как подстроку
|
||||
Pattern substringPattern = Pattern.compile("(?i)" + Pattern.quote(word));
|
||||
result = substringPattern.matcher(result).replaceAll(replacement);
|
||||
}
|
||||
|
||||
// Заменяем фрагменты (находим слова содержащие фрагмент и заменяем их)
|
||||
for (String fragment : fragments) {
|
||||
if (fragment == null || fragment.trim().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ищем слова содержащие фрагмент и заменяем весь фрагмент
|
||||
Pattern fragmentPattern = Pattern.compile("(?i)" + Pattern.quote(fragment));
|
||||
result = fragmentPattern.matcher(result).replaceAll(replacement);
|
||||
|
||||
// Также заменяем слова начинающиеся с фрагмента
|
||||
Pattern wordStartPattern = Pattern.compile("\\b" + Pattern.quote(fragment) + "\\w*", Pattern.CASE_INSENSITIVE);
|
||||
result = wordStartPattern.matcher(result).replaceAll(replacement);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Нормализует сообщение, убирая попытки обхода фильтра
|
||||
* Заменяет специальные символы на обычные буквы
|
||||
* Например: "пизд@" -> "пизда", "х*й" -> "хай" (но "хуй" найдет)
|
||||
*/
|
||||
private String normalizeMessage(String message) {
|
||||
if (message == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
// Заменяем символы обхода на буквы (для обнаружения х*й, х_уй, пизд@ и т.д.)
|
||||
String normalized = message;
|
||||
|
||||
// Заменяем символы обхода на похожие буквы
|
||||
normalized = normalized.replace('*', 'а');
|
||||
normalized = normalized.replace('_', 'а');
|
||||
normalized = normalized.replace('-', 'а');
|
||||
normalized = normalized.replace('.', 'а');
|
||||
normalized = normalized.replace(',', 'а');
|
||||
normalized = normalized.replace('|', 'и');
|
||||
normalized = normalized.replace('1', 'и');
|
||||
normalized = normalized.replace('!', 'и');
|
||||
normalized = normalized.replace('0', 'о');
|
||||
normalized = normalized.replace('3', 'з');
|
||||
normalized = normalized.replace('4', 'ч');
|
||||
normalized = normalized.replace('5', 'с');
|
||||
normalized = normalized.replace('6', 'б');
|
||||
normalized = normalized.replace('7', 'т');
|
||||
normalized = normalized.replace('8', 'в');
|
||||
normalized = normalized.replace('9', 'д');
|
||||
normalized = normalized.replace('@', 'а'); // пизд@ -> пизда
|
||||
normalized = normalized.replace('#', 'х');
|
||||
normalized = normalized.replace('$', 'с');
|
||||
normalized = normalized.replace('%', 'о');
|
||||
normalized = normalized.replace('^', 'х');
|
||||
normalized = normalized.replace('&', 'а');
|
||||
normalized = normalized.replace('~', 'а');
|
||||
normalized = normalized.replace('`', 'а');
|
||||
normalized = normalized.replace('=', 'а');
|
||||
normalized = normalized.replace('+', 'а');
|
||||
normalized = normalized.replace('[', 'а');
|
||||
normalized = normalized.replace(']', 'а');
|
||||
normalized = normalized.replace('{', 'а');
|
||||
normalized = normalized.replace('}', 'а');
|
||||
normalized = normalized.replace('(', 'а');
|
||||
normalized = normalized.replace(')', 'а');
|
||||
normalized = normalized.replace('/', 'а');
|
||||
normalized = normalized.replace('\\', 'а');
|
||||
normalized = normalized.replace('?', 'а');
|
||||
normalized = normalized.replace('<', 'а');
|
||||
normalized = normalized.replace('>', 'а');
|
||||
|
||||
// Убираем множественные пробелы
|
||||
normalized = normalized.replaceAll("\\s+", " ");
|
||||
|
||||
return normalized;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,147 +0,0 @@
|
|||
package com.loki.lochat.managers;
|
||||
|
||||
import com.loki.lochat.LoChat;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class MuteManager {
|
||||
|
||||
private final LoChat plugin;
|
||||
private final Map<UUID, MuteData> mutedPlayers;
|
||||
private File dataFile;
|
||||
private FileConfiguration dataConfig;
|
||||
|
||||
public MuteManager(LoChat plugin) {
|
||||
this.plugin = plugin;
|
||||
this.mutedPlayers = new HashMap<>();
|
||||
loadData();
|
||||
}
|
||||
|
||||
private void loadData() {
|
||||
dataFile = new File(plugin.getDataFolder(), "mutes.yml");
|
||||
if (!dataFile.exists()) {
|
||||
try {
|
||||
dataFile.createNewFile();
|
||||
} catch (IOException e) {
|
||||
plugin.getLogger().severe("Не удалось создать файл mutes.yml: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
dataConfig = YamlConfiguration.loadConfiguration(dataFile);
|
||||
|
||||
// Загружаем муты из файла
|
||||
for (String key : dataConfig.getKeys(false)) {
|
||||
try {
|
||||
UUID uuid = UUID.fromString(key);
|
||||
long expiry = dataConfig.getLong(key + ".expiry");
|
||||
String reason = dataConfig.getString(key + ".reason", "Нарушение правил");
|
||||
String mutedBy = dataConfig.getString(key + ".muted_by", "Система");
|
||||
|
||||
// Проверяем не истёк ли мут
|
||||
if (expiry > 0 && System.currentTimeMillis() > expiry) {
|
||||
dataConfig.set(key, null);
|
||||
continue;
|
||||
}
|
||||
|
||||
mutedPlayers.put(uuid, new MuteData(expiry, reason, mutedBy));
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
// Неверный UUID, пропускаем
|
||||
}
|
||||
}
|
||||
|
||||
saveData();
|
||||
}
|
||||
|
||||
public void saveData() {
|
||||
for (Map.Entry<UUID, MuteData> entry : mutedPlayers.entrySet()) {
|
||||
String key = entry.getKey().toString();
|
||||
MuteData data = entry.getValue();
|
||||
|
||||
dataConfig.set(key + ".expiry", data.expiry);
|
||||
dataConfig.set(key + ".reason", data.reason);
|
||||
dataConfig.set(key + ".muted_by", data.mutedBy);
|
||||
}
|
||||
|
||||
try {
|
||||
dataConfig.save(dataFile);
|
||||
} catch (IOException e) {
|
||||
plugin.getLogger().severe("Не удалось сохранить mutes.yml: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void mutePlayer(UUID playerId, long duration, String reason, String mutedBy) {
|
||||
long expiry = duration == 0 ? 0 : System.currentTimeMillis() + duration;
|
||||
mutedPlayers.put(playerId, new MuteData(expiry, reason, mutedBy));
|
||||
saveData();
|
||||
}
|
||||
|
||||
public void unmutePlayer(UUID playerId) {
|
||||
mutedPlayers.remove(playerId);
|
||||
dataConfig.set(playerId.toString(), null);
|
||||
saveData();
|
||||
}
|
||||
|
||||
public boolean isMuted(UUID playerId) {
|
||||
MuteData data = mutedPlayers.get(playerId);
|
||||
if (data == null) return false;
|
||||
|
||||
// Проверяем не истёк ли мут
|
||||
if (data.expiry > 0 && System.currentTimeMillis() > data.expiry) {
|
||||
unmutePlayer(playerId);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public MuteData getMuteData(UUID playerId) {
|
||||
return mutedPlayers.get(playerId);
|
||||
}
|
||||
|
||||
public long getRemainingTime(UUID playerId) {
|
||||
MuteData data = mutedPlayers.get(playerId);
|
||||
if (data == null || data.expiry == 0) return 0;
|
||||
|
||||
long remaining = data.expiry - System.currentTimeMillis();
|
||||
return Math.max(0, remaining);
|
||||
}
|
||||
|
||||
public String formatRemainingTime(UUID playerId) {
|
||||
long remaining = getRemainingTime(playerId);
|
||||
if (remaining == 0) {
|
||||
MuteData data = getMuteData(playerId);
|
||||
if (data != null && data.expiry == 0) {
|
||||
return "навсегда";
|
||||
}
|
||||
return "0с";
|
||||
}
|
||||
|
||||
long seconds = remaining / 1000;
|
||||
long minutes = seconds / 60;
|
||||
long hours = minutes / 60;
|
||||
long days = hours / 24;
|
||||
|
||||
if (days > 0) return days + "д " + (hours % 24) + "ч";
|
||||
if (hours > 0) return hours + "ч " + (minutes % 60) + "м";
|
||||
if (minutes > 0) return minutes + "м " + (seconds % 60) + "с";
|
||||
return seconds + "с";
|
||||
}
|
||||
|
||||
public static class MuteData {
|
||||
public final long expiry; // 0 = permanent
|
||||
public final String reason;
|
||||
public final String mutedBy;
|
||||
|
||||
public MuteData(long expiry, String reason, String mutedBy) {
|
||||
this.expiry = expiry;
|
||||
this.reason = reason;
|
||||
this.mutedBy = mutedBy;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue