package com.yourname.authadminplugin;

import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;

/**
 * Обработчик команды принятия/отклонения заявки на регистрацию администратора.
 * Команда: /adminmanage <ник> <принять|отклонить|блэклист>
 */
public class AcceptAdminRegCommand implements CommandExecutor {

    private final AuthAdminPlugin plugin;

    public AcceptAdminRegCommand(AuthAdminPlugin plugin) {
        this.plugin = plugin;
    }

    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {

        // Проверка, что команда выполняется из консоли
        if (sender instanceof Player) {
            sender.sendMessage(ChatColor.RED + "Только консоль может использовать эту команду.");
            return true;
        }

        // Проверка количества аргументов
        if (args.length != 2) {
            sender.sendMessage(ChatColor.RED + "Использование: /adminmanage <ник> <принять|отклонить|блэклист>");
            return true;
        }

        String targetPlayerName = args[0];
        String action = args[1].toLowerCase();

        switch (action) {
            case "принять":
                if (plugin.acceptAdminRegistration(targetPlayerName)) {
                    sender.sendMessage(ChatColor.GREEN + "Игрок " + targetPlayerName + " был принят как администратор.");
                    plugin.logEvent("Консоль приняла игрока " + targetPlayerName + " как администратора.");
                } else {
                    sender.sendMessage(ChatColor.RED + "Не удалось принять игрока " + targetPlayerName + ".");
                }
                break;

            case "отклонить":
                if (plugin.declineAdminRegistration(targetPlayerName)) {
                    sender.sendMessage(ChatColor.GREEN + "Заявка игрока " + targetPlayerName + " была отклонена.");
                    plugin.logEvent("Консоль отклонила заявку игрока " + targetPlayerName + " на регистрацию администратора.");
                } else {
                    sender.sendMessage(ChatColor.RED + "Не удалось отклонить заявку игрока " + targetPlayerName + ".");
                }
                break;

            case "блэклист":
                if (plugin.blacklistAdminRegistration(targetPlayerName)) {
                    sender.sendMessage(ChatColor.GREEN + "Игрок " + targetPlayerName + " был добавлен в blacklist.");
                    plugin.logEvent("Консоль добавила игрока " + targetPlayerName + " в blacklist.");
                } else {
                    sender.sendMessage(ChatColor.RED + "Не удалось добавить игрока " + targetPlayerName + " в blacklist.");
                }
                break;

            default:
                sender.sendMessage(ChatColor.RED + "Неизвестное действие. Используйте: принять, отклонить, блэклист.");
                break;
        }

        return true;
    }
}
package com.yourname.authadminplugin;

import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;

/**
 * Обработчик команды аутентификации администратора.
 */
public class AdminLoginCommand implements CommandExecutor {

    private final AuthAdminPlugin plugin;

    public AdminLoginCommand(AuthAdminPlugin plugin) {
        this.plugin = plugin;
    }

    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {

        // Команду могут выполнять только игроки
        if (!(sender instanceof Player)) {
            sender.sendMessage(ChatColor.RED + "Только игроки могут использовать эту команду.");
            return true;
        }

        Player player = (Player) sender;
        String playerName = player.getName();

        // Проверка, является ли игрок одобренным администратором
        if (!plugin.isApprovedAdmin(playerName)) {
            player.sendMessage(ChatColor.RED + "Вы не одобренный администратор и не можете использовать эту команду.");
            plugin.logEvent(playerName + " попытался использовать команду adminlogin, но не одобрен как администратор.");
            return true;
        }

        // Проверка, зарегистрирован ли игрок как администратор
        if (!plugin.isRegisteredAdmin(playerName)) {
            plugin.deauthenticatePlayer(player);
            player.sendMessage(ChatColor.RED + "Вы не зарегистрированы как администратор.");
            plugin.logEvent(playerName + " попытался аутентифицироваться, но не зарегистрирован как администратор.");
            return true;
        }

        // Проверка на наличие в blacklist
        if (plugin.isBlacklisted(playerName)) {
            player.sendMessage(ChatColor.RED + "Вы заблокированы и не можете аутентифицироваться.");
            plugin.logEvent(playerName + " попытался аутентифицироваться, но он в blacklist.");
            return true;
        }

        // Проверка количества аргументов
        if (args.length != 1) {
            player.sendMessage(ChatColor.RED + "Использование: /adminlogin <пароль>");
            return true;
        }

        String password = args[0];

        // Аутентификация администратора
        if (plugin.authenticateAdmin(player, password)) {
            // Дополнительные действия, если необходимо
        }

        return true;
    }
}
package com.yourname.authadminplugin;

import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;

/**
 * Обработчик команды деаутентификации администратора.
 */
public class AdminLogoutCommand implements CommandExecutor {

    private final AuthAdminPlugin plugin;

    public AdminLogoutCommand(AuthAdminPlugin plugin) {
        this.plugin = plugin;
    }

    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {

        // Команду могут выполнять только игроки
        if (!(sender instanceof Player)) {
            sender.sendMessage(ChatColor.RED + "Только игроки могут использовать эту команду.");
            return true;
        }

        Player player = (Player) sender;
        String playerName = player.getName();

        // Проверка, является ли игрок одобренным администратором
        if (!plugin.isApprovedAdmin(playerName)) {
            plugin.deauthenticatePlayer(player);
            player.sendMessage(ChatColor.RED + "Вы не одобренный администратор и не можете использовать эту команду.");
            plugin.logEvent(playerName + " попытался использовать команду adminlogout, но не одобрен как администратор.");
            return true;
        }

        // Проверка, зарегистрирован ли игрок как администратор
        if (!plugin.isRegisteredAdmin(playerName)) {
            plugin.deauthenticatePlayer(player);
            player.sendMessage(ChatColor.RED + "Вы не зарегистрированы как администратор.");
            plugin.logEvent(playerName + " попытался деаутентифицироваться, но не зарегистрирован как администратор.");
            return true;
        }

        // Деаутентификация администратора
        if (plugin.getAuthenticatedAdmins().contains(playerName)) {
            plugin.deauthenticateAdmin(player);
        } else {
            player.sendMessage(ChatColor.YELLOW + "Вы не аутентифицированы как администратор.");
        }

        return true;
    }
}
package com.yourname.authadminplugin;

import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerQuitEvent;

/**
 * Слушатель события выхода игрока из игры.
 */
public class AdminLogoutListener implements Listener {

    private final AuthAdminPlugin plugin;

    public AdminLogoutListener(AuthAdminPlugin plugin) {
        this.plugin = plugin;
    }

    @EventHandler
    public void onPlayerQuit(PlayerQuitEvent event) {
        String playerName = event.getPlayer().getName();
        if (plugin.getAuthenticatedAdmins().contains(playerName)) {
            plugin.deauthenticateAdmin(event.getPlayer());
            plugin.logEvent(playerName + " вышел из игры и `op` доступ был снят.");
        }

        // Логирование выхода игрока
        plugin.logEvent(playerName + " вышел из игры.");
    }
}
package com.yourname.authadminplugin;

import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;

/**
 * Обработчик команды управления регистрацией администратора.
 * Команда: /adminmanage <ник> <принять|отклонить|блэклист>
 */
public class AdminManageCommand implements CommandExecutor {

    private final AuthAdminPlugin plugin;

    public AdminManageCommand(AuthAdminPlugin plugin) {
        this.plugin = plugin;
    }

    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {

        // Убедитесь, что команду выполняет только консоль
        if (sender instanceof Player) {
            sender.sendMessage(ChatColor.RED + "Эта команда может быть выполнена только из консоли.");
            return true;
        }

        // Проверка количества аргументов
        if (args.length != 2) {
            sender.sendMessage("Использование: /adminmanage <ник> <принять|отклонить|блэклист>");
            return true;
        }

        String targetPlayerName = args[0];
        String action = args[1].toLowerCase();

        switch (action) {
            case "принять":
                if (plugin.acceptAdminRegistration(targetPlayerName)) {
                    sender.sendMessage("Игрок " + targetPlayerName + " был принят как администратор.");
                    plugin.logEvent("Консоль приняла игрока " + targetPlayerName + " как администратора.");
                } else {
                    sender.sendMessage("Не удалось принять игрока " + targetPlayerName + ".");
                }
                break;

            case "отклонить":
                if (plugin.declineAdminRegistration(targetPlayerName)) {
                    sender.sendMessage("Заявка игрока " + targetPlayerName + " была отклонена.");
                    plugin.logEvent("Консоль отклонила заявку игрока " + targetPlayerName + " на регистрацию администратора.");
                } else {
                    sender.sendMessage("Не удалось отклонить заявку игрока " + targetPlayerName + ".");
                }
                break;

            case "блэклист":
                if (plugin.blacklistAdminRegistration(targetPlayerName)) {
                    sender.sendMessage("Игрок " + targetPlayerName + " был добавлен в blacklist.");
                    plugin.logEvent("Консоль добавила игрока " + targetPlayerName + " в blacklist.");
                } else {
                    sender.sendMessage("Не удалось добавить игрока " + targetPlayerName + " в blacklist.");
                }
                break;

            default:
                sender.sendMessage("Неизвестное действие. Используйте: принять, отклонить, блэклист.");
                break;
        }

        return true;
    }
}
package com.yourname.authadminplugin;

import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;

/**
 * Обработчик команды регистрации администратора.
 */
public class AdminRegisterCommand implements CommandExecutor {

    private final AuthAdminPlugin plugin;

    public AdminRegisterCommand(AuthAdminPlugin plugin) {
        this.plugin = plugin;
    }

    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {

        // Команду могут выполнять только игроки
        if (!(sender instanceof Player)) {
            sender.sendMessage(ChatColor.RED + "Только игроки могут использовать эту команду.");
            return true;
        }

        Player player = (Player) sender;
        String playerName = player.getName();

        // Проверка, является ли игрок уже одобренным администратором
        if (plugin.isApprovedAdmin(playerName)) {
            player.sendMessage(ChatColor.YELLOW + "Вы уже одобренный администратор.");
            return true;
        }

        // Проверка, находится ли игрок уже в списке ожидающих регистрации
        if (plugin.isPendingAdmin(playerName)) {
            player.sendMessage(ChatColor.YELLOW + "Ваша заявка уже отправлена и ожидает одобрения.");
            return true;
        }

        // Проверка количества аргументов
        if (args.length != 1) {
            player.sendMessage(ChatColor.RED + "Использование: /adminregister <пароль>");
            return true;
        }

        String password = args[0];

        // Регистрация администратора (отправка заявки на одобрение)
        if (plugin.registerAdmin(player, password)) {
            // Дополнительные действия при успешной регистрации заявки, если необходимо
        }

        return true;
    }
}
package com.yourname.authadminplugin;

import org.bukkit.BanList;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.plugin.PluginManager;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.MessageDigest;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Основной класс плагина AuthAdminPlugin.
 */
public class AuthAdminPlugin extends JavaPlugin {

    private File adminFile;
    private File regAdminFile;
    private File pendingAdminFile;
    private File blacklistFile;
    private FileConfiguration adminConfig;
    private FileConfiguration regAdminConfig;
    private FileConfiguration pendingAdminConfig;
    private FileConfiguration blacklistConfig;

    private File logFile;
    private List<String> logEntries = Collections.synchronizedList(new ArrayList<>());

    private Set<String> authenticatedAdmins = Collections.newSetFromMap(new ConcurrentHashMap<>());
    private Map<String, Integer> failedAttempts = new ConcurrentHashMap<>();
    private Set<String> blacklist = Collections.newSetFromMap(new ConcurrentHashMap<>());

    @Override
    public void onEnable() {
        // Создание папки плагина, если не существует
        if (!getDataFolder().exists()) {
            getDataFolder().mkdirs();
        }

        // Загрузка admins.yml
        adminFile = new File(getDataFolder(), "admins.yml");
        if (!adminFile.exists()) {
            saveResource("admins.yml", false);
        }
        adminConfig = YamlConfiguration.loadConfiguration(adminFile);

        // Загрузка regadmin.yml
        regAdminFile = new File(getDataFolder(), "regadmin.yml");
        if (!regAdminFile.exists()) {
            saveResource("regadmin.yml", false);
        }
        regAdminConfig = YamlConfiguration.loadConfiguration(regAdminFile);

        // Загрузка pendingadmins.yml
        pendingAdminFile = new File(getDataFolder(), "pendingadmins.yml");
        if (!pendingAdminFile.exists()) {
            saveResource("pendingadmins.yml", false);
        }
        pendingAdminConfig = YamlConfiguration.loadConfiguration(pendingAdminFile);

        // Загрузка blacklist.yml
        blacklistFile = new File(getDataFolder(), "blacklist.yml");
        if (!blacklistFile.exists()) {
            saveResource("blacklist.yml", false);
        }
        blacklistConfig = YamlConfiguration.loadConfiguration(blacklistFile);
        loadBlacklist();

        // Настройка логирования
        setupLogging();

        // Регистрация команд
        this.getCommand("adminregister").setExecutor(new AdminRegisterCommand(this));
        this.getCommand("adminmanage").setExecutor(new AdminManageCommand(this));
        this.getCommand("adminlogin").setExecutor(new AdminLoginCommand(this));
        this.getCommand("adminlogout").setExecutor(new AdminLogoutCommand(this));
        this.getCommand("blacklist").setExecutor(new BlacklistCommand(this));
        this.getCommand("authadminreload").setExecutor(new ReloadCommand(this));
        this.getCommand("acceptadminreg").setExecutor(new AcceptAdminRegCommand(this));

        // Регистрация событий
        PluginManager pm = getServer().getPluginManager();
        pm.registerEvents(new AdminLogoutListener(this), this);
        pm.registerEvents(new PlayerJoinListener(this), this);

        getLogger().info("AuthAdminPlugin включен!");
    }

    @Override
    public void onDisable() {
        // Снимаем `op` со всех аутентифицированных администраторов
        for (String playerName : authenticatedAdmins) {
            Player player = Bukkit.getPlayerExact(playerName);
            if (player != null && player.isOp()) {
                player.setOp(false);
                logEvent(playerName + " был деопирован при отключении плагина.");
            }
        }

        // Сохраняем логи
        saveLogs();

        getLogger().info("AuthAdminPlugin отключен!");
    }

    /**
     * Перезагрузка конфигурационных файлов плагина.
     *
     * @return true, если перезагрузка прошла успешно, иначе false.
     */
    public boolean reloadConfigurations() {
        try {
            // Перезагрузка admins.yml
            adminConfig = YamlConfiguration.loadConfiguration(adminFile);

            // Перезагрузка regadmin.yml
            regAdminConfig = YamlConfiguration.loadConfiguration(regAdminFile);

            // Перезагрузка pendingadmins.yml
            pendingAdminConfig = YamlConfiguration.loadConfiguration(pendingAdminFile);

            // Перезагрузка blacklist.yml
            blacklistConfig = YamlConfiguration.loadConfiguration(blacklistFile);
            loadBlacklist();

            // Очистка и обновление аутентифицированных администраторов
            for (String playerName : authenticatedAdmins) {
                Player player = Bukkit.getPlayerExact(playerName);
                if (player != null) {
                    player.setOp(false);
                    player.sendMessage(ChatColor.YELLOW + "Ваши права администратора были сняты. Пожалуйста, выполните повторную аутентификацию.");
                }
            }
            authenticatedAdmins.clear();

            logEvent("Конфигурационные файлы были перезагружены.");
            getLogger().info("Конфигурационные файлы перезагружены.");

            return true;
        } catch (Exception e) {
            logEvent("Ошибка при перезагрузке конфигураций: " + e.getMessage());
            getLogger().severe("Ошибка при перезагрузке конфигураций: " + e.getMessage());
            return false;
        }
    }

    /**
     * Проверка, зарегистрирован ли игрок как администратор.
     *
     * @param playerName Имя игрока.
     * @return true, если игрок зарегистрирован как администратор, иначе false.
     */
    public boolean isRegisteredAdmin(String playerName) {
        return adminConfig.contains("admins." + playerName);
    }

    /**
     * Проверка, является ли игрок одобренным администратором.
     *
     * @param playerName Имя игрока.
     * @return true, если игрок одобрен, иначе false.
     */
    public boolean isApprovedAdmin(String playerName) {
        return regAdminConfig.contains("regadmins." + playerName);
    }

    /**
     * Проверка, находится ли игрок в списке ожидающих регистрации.
     *
     * @param playerName Имя игрока.
     * @return true, если игрок ожидает регистрации, иначе false.
     */
    public boolean isPendingAdmin(String playerName) {
        return pendingAdminConfig.contains("pendingadmins." + playerName);
    }

    /**
     * Регистрация администратора (добавление заявки).
     *
     * @param player   Игрок, который регистрируется.
     * @param password Пароль для администратора.
     * @return true, если регистрация успешна, иначе false.
     */
    public boolean registerAdmin(Player player, String password) {
        String playerName = player.getName();

        if (isRegisteredAdmin(playerName)) {
            player.sendMessage(ChatColor.RED + "Вы уже зарегистрированы как администратор.");
            return false;
        }

        if (isPendingAdmin(playerName)) {
            player.sendMessage(ChatColor.YELLOW + "Ваша заявка уже отправлена и ожидает одобрения.");
            return false;
        }

        // Добавление игрока в pendingadmins.yml
        pendingAdminConfig.set("pendingadmins." + playerName + ".password", hashPassword(password));
        try {
            pendingAdminConfig.save(pendingAdminFile);
        } catch (IOException e) {
            getLogger().severe("Не удалось сохранить pendingadmins.yml: " + e.getMessage());
            player.sendMessage(ChatColor.RED + "Произошла ошибка при регистрации. Попробуйте позже.");
            return false;
        }

        player.sendMessage(ChatColor.GREEN + "Ваша заявка на регистрацию администратора отправлена и ожидает одобрения.");
        logEvent(playerName + " отправил заявку на регистрацию администратора.");
        return true;
    }

    /**
     * Принятие или отклонение заявки на регистрацию администратора.
     *
     * @param playerName Имя игрока.
     * @param action     Действие: accept, decline, blacklist.
     * @return true, если действие выполнено успешно, иначе false.
     */
    public boolean manageAdminRegistration(String playerName, String action) {
        if (!isPendingAdmin(playerName)) {
            return false;
        }

        switch (action.toLowerCase()) {
            case "accept":
                // Получение пароля из pendingadmins.yml
                String hashedPassword = pendingAdminConfig.getString("pendingadmins." + playerName + ".password");
                if (hashedPassword == null) {
                    return false;
                }

                // Добавление в admins.yml
                adminConfig.set("admins." + playerName + ".password", hashedPassword);
                try {
                    adminConfig.save(adminFile);
                } catch (IOException e) {
                    getLogger().severe("Не удалось сохранить admins.yml: " + e.getMessage());
                    return false;
                }

                // Добавление в regadmin.yml
                regAdminConfig.set("regadmins." + playerName, true);
                try {
                    regAdminConfig.save(regAdminFile);
                } catch (IOException e) {
                    getLogger().severe("Не удалось сохранить regadmin.yml: " + e.getMessage());
                    return false;
                }

                // Удаление из pendingadmins.yml
                pendingAdminConfig.set("pendingadmins." + playerName, null);
                try {
                    pendingAdminConfig.save(pendingAdminFile);
                } catch (IOException e) {
                    getLogger().severe("Не удалось сохранить pendingadmins.yml: " + e.getMessage());
                }

                Player player = Bukkit.getPlayerExact(playerName);
                if (player != null) {
                    player.sendMessage(ChatColor.GREEN + "Ваша заявка на регистрацию администратора была одобрена.");
                }

                logEvent(playerName + " был одобрен как администратор.");
                return true;

            case "decline":
                // Удаление заявки из pendingadmins.yml
                pendingAdminConfig.set("pendingadmins." + playerName, null);
                try {
                    pendingAdminConfig.save(pendingAdminFile);
                } catch (IOException e) {
                    getLogger().severe("Не удалось сохранить pendingadmins.yml: " + e.getMessage());
                    return false;
                }

                player = Bukkit.getPlayerExact(playerName);
                if (player != null) {
                    player.sendMessage(ChatColor.RED + "Ваша заявка на регистрацию администратора была отклонена.");
                }

                logEvent(playerName + " был отклонен как администратор.");
                return true;

            case "blacklist":
                // Добавление в blacklist
                blacklist.add(playerName);
                blacklistConfig.set("blacklist", new ArrayList<>(blacklist));
                try {
                    blacklistConfig.save(blacklistFile);
                } catch (IOException e) {
                    getLogger().severe("Не удалось сохранить blacklist.yml: " + e.getMessage());
                    return false;
                }

                // Удаление заявки из pendingadmins.yml
                pendingAdminConfig.set("pendingadmins." + playerName, null);
                try {
                    pendingAdminConfig.save(pendingAdminFile);
                } catch (IOException e) {
                    getLogger().severe("Не удалось сохранить pendingadmins.yml: " + e.getMessage());
                }

                player = Bukkit.getPlayerExact(playerName);
                if (player != null) {
                    // Деоп игрока, если был опом
                    if (player.isOp()) {
                        player.setOp(false);
                        logEvent(playerName + " был деопнут при добавлении в blacklist.");
                    }
                    // Бан игрока на сервере
                    Bukkit.getBanList(BanList.Type.NAME).addBan(playerName, "Добавлен в blacklist администратором.", null, "AuthAdminPlugin");
                    player.kickPlayer("Вы были добавлены в blacklist администрацией.");
                }

                logEvent(playerName + " был добавлен в blacklist.");
                notifyAdmins(ChatColor.RED + "Игрок " + playerName + " был добавлен в blacklist.");
                return true;

            default:
                return false;
        }
    }

    /**
     * Принятие заявки на регистрацию администратора.
     *
     * @param playerName Имя игрока.
     * @return true, если заявка принята, иначе false.
     */
    public boolean acceptAdminRegistration(String playerName) {
        return manageAdminRegistration(playerName, "accept");
    }

    /**
     * Отклонение заявки на регистрацию администратора.
     *
     * @param playerName Имя игрока.
     * @return true, если заявка отклонена, иначе false.
     */
    public boolean declineAdminRegistration(String playerName) {
        return manageAdminRegistration(playerName, "decline");
    }

    /**
     * Добавление игрока в черный список через управление регистрацией.
     *
     * @param playerName Имя игрока.
     * @return true, если добавление прошло успешно, иначе false.
     */
    public boolean blacklistAdminRegistration(String playerName) {
        return manageAdminRegistration(playerName, "blacklist");
    }

    /**
     * Проверка, находится ли игрок в черном списке.
     *
     * @param playerName Имя игрока.
     * @return true, если игрок в blacklist, иначе false.
     */
    public boolean isBlacklisted(String playerName) {
        return blacklist.contains(playerName);
    }

    /**
     * Загрузка чёрного списка из конфигурационного файла.
     */
    private void loadBlacklist() {
        blacklist.clear();
        if (blacklistConfig.contains("blacklist")) {
            List<String> blacklistedPlayers = blacklistConfig.getStringList("blacklist");
            blacklist.addAll(blacklistedPlayers);
        }
    }

    /**
     * Логирование событий с временной меткой.
     *
     * @param message Сообщение для логирования.
     */
    public void logEvent(String message) {
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        String logMessage = "[" + timestamp + "] " + message;
        getLogger().info(logMessage);
        logEntries.add(logMessage);
    }

    /**
     * Настройка логирования в отдельный файл.
     */
    private void setupLogging() {
        logFile = new File(getDataFolder(), "plugin.log");
        if (!logFile.exists()) {
            try {
                Files.createFile(Paths.get(logFile.getPath()));
            } catch (IOException e) {
                getLogger().severe("Не удалось создать файл логов: " + e.getMessage());
            }
        }
    }

    /**
     * Сохранение логов в файл.
     */
    private void saveLogs() {
        try {
            StringBuilder sb = new StringBuilder();
            for (String entry : logEntries) {
                sb.append(entry).append(System.lineSeparator());
            }
            Files.write(logFile.toPath(), sb.toString().getBytes());
        } catch (IOException e) {
            getLogger().severe("Не удалось сохранить логи: " + e.getMessage());
        }
    }

    /**
     * Аутентификация администратора.
     *
     * @param player   Игрок, который аутентифицируется.
     * @param password Пароль для аутентификации.
     * @return true, если аутентификация успешна, иначе false.
     */
    public boolean authenticateAdmin(Player player, String password) {
        String playerName = player.getName();

        if (isBlacklisted(playerName)) {
            player.sendMessage(ChatColor.RED + "Вы заблокированы и не можете аутентифицироваться.");
            logEvent(playerName + " попытался аутентифицироваться, но он в blacklist.");
            return false;
        }

        if (isRegisteredAdmin(playerName)) {
            String hashedPassword = adminConfig.getString("admins." + playerName + ".password");
            if (hashedPassword != null && checkPassword(password, hashedPassword)) {
                authenticatedAdmins.add(playerName);
                player.setOp(true);
                logEvent(playerName + " успешно аутентифицирован и получил `op` доступ.");
                player.sendMessage(ChatColor.GREEN + "Вы успешно аутентифицировались как администратор.");

                // Сброс счетчика неудачных попыток
                failedAttempts.remove(playerName);
                return true;
            } else {
                incrementFailedAttempts(playerName);
                player.sendMessage(ChatColor.RED + "Неверный пароль.");
                logEvent(playerName + " попытался аутентифицироваться с неверным паролем.");
                return false;
            }
        } else {
            deauthenticatePlayer(player);
            player.sendMessage(ChatColor.RED + "Вы не зарегистрированы как администратор. Используйте /adminregister <пароль>");
            logEvent(playerName + " попытался аутентифицироваться, но не зарегистрирован как администратор.");
            return false;
        }
    }

    /**
     * Деаутентификация администратора.
     *
     * @param player Игрок, который деаутентифицируется.
     */
    public void deauthenticateAdmin(Player player) {
        String playerName = player.getName();
        if (authenticatedAdmins.contains(playerName)) {
            deauthenticatePlayer(player);
            logEvent(playerName + " деаутентифицирован и `op` доступ снят.");
            player.sendMessage(ChatColor.YELLOW + "Ваш `op` доступ был снят.");
        }
    }

    /**
     * Деаутентификация игрока.
     *
     * @param player Игрок для деаутентификации.
     */
    public void deauthenticatePlayer(Player player) {
        String playerName = player.getName();
        if (authenticatedAdmins.contains(playerName)) {
            player.setOp(false);
            authenticatedAdmins.remove(playerName);
        }
    }

    /**
     * Увеличение счётчика неудачных попыток аутентификации.
     *
     * @param playerName Имя игрока.
     */
    private void incrementFailedAttempts(String playerName) {
        int attempts = failedAttempts.getOrDefault(playerName, 0) + 1;
        failedAttempts.put(playerName, attempts);
        if (attempts >= 3) {
            // Блокировка игрока
            banPlayer(playerName);
        }
    }

    /**
     * Бан игрока за 3 неудачные попытки аутентификации.
     *
     * @param playerName Имя игрока.
     */
    private void banPlayer(String playerName) {
        blacklist.add(playerName);
        blacklistConfig.set("blacklist", new ArrayList<>(blacklist));
        try {
            blacklistConfig.save(blacklistFile);
        } catch (IOException e) {
            getLogger().severe("Не удалось сохранить blacklist.yml: " + e.getMessage());
        }

        // Деоп игрока, если он был опом и онлайн
        Player player = Bukkit.getPlayerExact(playerName);
        if (player != null) {
            if (player.isOp()) {
                player.setOp(false);
                logEvent(playerName + " был деопнут из-за 3 неудачных попыток аутентификации.");
            }
            // Бан игрока на сервере
            Bukkit.getBanList(BanList.Type.NAME).addBan(playerName, "3 неудачные попытки аутентификации администратора.", null, "AuthAdminPlugin");
            player.kickPlayer("Вы были забанены за 3 неудачные попытки аутентификации администратора.");
            logEvent(playerName + " был забанен за 3 неудачные попытки аутентификации.");
        } else {
            // Если игрок офлайн, просто записать в blacklist
            logEvent(playerName + " добавлен в blacklist за 3 неудачные попытки аутентификации.");
        }

        // Уведомление других администраторов
        notifyAdmins(ChatColor.RED + "Игрок " + playerName + " был добавлен в blacklist за 3 неудачные попытки аутентификации.");
    }

    /**
     * Отправка уведомлений всем одобренным администраторам.
     *
     * @param message Сообщение для отправки.
     */
    public void notifyAdmins(String message) {
        for (Player admin : Bukkit.getOnlinePlayers()) {
            if (admin.isOp() && isApprovedAdmin(admin.getName())) {
                admin.sendMessage(message);
            }
        }
    }

    /**
     * Генерация хэша пароля с использованием SHA-256.
     *
     * @param password Пароль в открытом виде.
     * @return Хэшированный пароль в шестнадцатеричном формате.
     */
    public static String hashPassword(String password) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] hashedBytes = digest.digest(password.getBytes("UTF-8"));
            StringBuilder sb = new StringBuilder();
            for (byte b : hashedBytes) {
                sb.append(String.format("%02x", b));
            }
            return sb.toString();
        } catch (Exception e) {
            throw new RuntimeException("Не удалось хэшировать пароль", e);
        }
    }

    /**
     * Проверка соответствия пароля хэшу.
     *
     * @param password       Пароль в открытом виде.
     * @param hashedPassword Хэшированный пароль.
     * @return true, если пароль соответствует хэшу, иначе false.
     */
    public static boolean checkPassword(String password, String hashedPassword) {
        return hashPassword(password).equals(hashedPassword);
    }

    /**
     * Получение списка аутентифицированных администраторов.
     *
     * @return Набор имен администраторов.
     */
    public Set<String> getAuthenticatedAdmins() {
        return authenticatedAdmins;
    }

    /**
     * Получение конфигурации blacklist.yml.
     *
     * @return Конфигурация blacklist.yml.
     */
    public FileConfiguration getBlacklistConfig() {
        return blacklistConfig;
    }

    /**
     * Получение файла blacklist.yml.
     *
     * @return Файл blacklist.yml.
     */
    public File getBlacklistFile() {
        return blacklistFile;
    }

    /**
     * Получение набора черного списка.
     *
     * @return Набор имен игроков в blacklist.
     */
    public Set<String> getBlacklist() {
        return blacklist;
    }

    /**
     * Получение конфигурации regadmin.yml.
     *
     * @return Конфигурация regadmin.yml.
     */
    public FileConfiguration getRegAdminConfig() {
        return regAdminConfig;
    }

    /**
     * Получение файла regadmin.yml.
     *
     * @return Файл regadmin.yml.
     */
    public File getRegAdminFile() {
        return regAdminFile;
    }

    /**
     * Получение конфигурации pendingadmins.yml.
     *
     * @return Конфигурация pendingadmins.yml.
     */
    public FileConfiguration getPendingAdminConfig() {
        return pendingAdminConfig;
    }

    /**
     * Получение файла pendingadmins.yml.
     *
     * @return Файл pendingadmins.yml.
     */
    public File getPendingAdminFile() {
        return pendingAdminFile;
    }
}
package com.yourname.authadminplugin;

import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.ArrayList;

/**
 * Обработчик команды управления черным списком.
 * Команды:
 * /blacklist add <player>
 * /blacklist remove <player>
 */
public class BlacklistCommand implements CommandExecutor {

    private final AuthAdminPlugin plugin;

    public BlacklistCommand(AuthAdminPlugin plugin) {
        this.plugin = plugin;
    }

    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {

        // Команду могут выполнять только одобренные администраторы
        if (!(sender instanceof Player)) {
            sender.sendMessage(ChatColor.RED + "Только игроки могут использовать эту команду.");
            return true;
        }

        Player player = (Player) sender;
        String playerName = player.getName();

        // Проверка, является ли игрок одобренным администратором
        if (!plugin.isApprovedAdmin(playerName)) {
            sender.sendMessage(ChatColor.RED + "У вас нет прав для использования этой команды.");
            plugin.logEvent(playerName + " попытался использовать команду blacklist, но не является одобренным администратором.");
            return true;
        }

        if (args.length != 2) {
            player.sendMessage(ChatColor.RED + "Использование: /blacklist <add|remove> <player>");
            return true;
        }

        String action = args[0].toLowerCase();
        String targetPlayer = args[1];

        switch (action) {
            case "add":
                if (plugin.isBlacklisted(targetPlayer)) {
                    player.sendMessage(ChatColor.YELLOW + "Игрок " + targetPlayer + " уже находится в blacklist.");
                } else {
                    plugin.getBlacklist().add(targetPlayer);
                    plugin.getBlacklistConfig().set("blacklist", new ArrayList<>(plugin.getBlacklist()));
                    try {
                        plugin.getBlacklistConfig().save(plugin.getBlacklistFile());
                        player.sendMessage(ChatColor.GREEN + "Игрок " + targetPlayer + " добавлен в blacklist.");
                        plugin.logEvent(playerName + " добавил " + targetPlayer + " в blacklist.");
                        // Уведомление других администраторов
                        plugin.notifyAdmins(ChatColor.RED + "Игрок " + targetPlayer + " был добавлен в blacklist.");
                    } catch (Exception e) {
                        player.sendMessage(ChatColor.RED + "Не удалось сохранить blacklist.yml.");
                        plugin.getLogger().severe("Ошибка при сохранении blacklist.yml: " + e.getMessage());
                    }
                }
                break;
            case "remove":
                if (!plugin.isBlacklisted(targetPlayer)) {
                    player.sendMessage(ChatColor.YELLOW + "Игрок " + targetPlayer + " не находится в blacklist.");
                } else {
                    plugin.getBlacklist().remove(targetPlayer);
                    plugin.getBlacklistConfig().set("blacklist", new ArrayList<>(plugin.getBlacklist()));
                    try {
                        plugin.getBlacklistConfig().save(plugin.getBlacklistFile());
                        player.sendMessage(ChatColor.GREEN + "Игрок " + targetPlayer + " удален из blacklist.");
                        plugin.logEvent(playerName + " удалил " + targetPlayer + " из blacklist.");
                        // Уведомление других администраторов
                        plugin.notifyAdmins(ChatColor.GREEN + "Игрок " + targetPlayer + " был удален из blacklist.");
                    } catch (Exception e) {
                        player.sendMessage(ChatColor.RED + "Не удалось сохранить blacklist.yml.");
                        plugin.getLogger().severe("Ошибка при сохранении blacklist.yml: " + e.getMessage());
                    }
                }
                break;
            default:
                player.sendMessage(ChatColor.RED + "Неизвестное действие. Используйте add или remove.");
                break;
        }

        return true;
    }
}
package com.yourname.authadminplugin;

import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;

/**
 * Слушатель события входа игрока в игру.
 */
public class PlayerJoinListener implements Listener {

    private final AuthAdminPlugin plugin;

    public PlayerJoinListener(AuthAdminPlugin plugin) {
        this.plugin = plugin;
    }

    @EventHandler
    public void onPlayerJoin(PlayerJoinEvent event) {
        Player player = event.getPlayer();
        String playerName = player.getName();

        // Логирование входа игрока
        plugin.logEvent(playerName + " вошел в игру.");

        // Снимаем `op` при входе, если игрок ранее не аутентифицирован
        if (!plugin.getAuthenticatedAdmins().contains(playerName)) {
            if (player.isOp()) {
                player.setOp(false);
                plugin.logEvent(playerName + " был деопнут при входе на сервер.");
            }
        } else {
            // Если админ уже аутентифицирован, восстанавливаем `op`
            player.setOp(true);
        }

    }
}
package com.yourname.authadminplugin;

import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;

/**
 * Обработчик команды перезагрузки конфигурации плагина.
 */
public class ReloadCommand implements CommandExecutor {

    private final AuthAdminPlugin plugin;

    public ReloadCommand(AuthAdminPlugin plugin) {
        this.plugin = plugin;
    }

    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {

        // Команду могут выполнять только одобренные администраторы
        if (!(sender instanceof Player)) {
            sender.sendMessage(ChatColor.RED + "Только игроки могут использовать эту команду.");
            return true;
        }

        Player player = (Player) sender;
        String playerName = player.getName();

        // Проверка, является ли игрок одобренным администратором
        if (!plugin.isApprovedAdmin(playerName)) {
            sender.sendMessage(ChatColor.RED + "У вас нет прав для использования этой команды.");
            plugin.logEvent(playerName + " попытался использовать команду authadminreload, но не является одобренным администратором.");
            return true;
        }

        // Проверка количества аргументов
        if (args.length != 0) {
            player.sendMessage(ChatColor.RED + "Использование: /authadminreload");
            return true;
        }

        if (plugin.reloadConfigurations()) {
            player.sendMessage(ChatColor.GREEN + "Конфигурации плагина успешно перезагружены.");
        } else {
            player.sendMessage(ChatColor.RED + "Произошла ошибка при перезагрузке конфигураций. Проверьте логи сервера.");
        }

        return true;
    }
}
Сделай, чтобы команды не писались никак в консоли, и если что, сразу шифровались в шифровке, сделай сразу полный код, на русском