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;

        // Проверка на наличие в blacklist
        if (plugin.isBlacklisted(player.getName())) {
            player.sendMessage(ChatColor.RED + "Вы заблокированы и не можете аутентифицироваться.");
            plugin.logEvent(player.getName() + " попытался аутентифицироваться, но он в 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;

        if (plugin.getAuthenticatedAdmins().contains(player.getName())) {
            plugin.deauthenticateAdmin(player);
        } else {
            player.sendMessage(ChatColor.YELLOW + "Вы не имеете `op` доступа.");
        }

        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` доступ был снят.");
        }
    }
}
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;

        // Проверка количества аргументов
        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 blacklistFile;
    private FileConfiguration adminConfig;
    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);

        // Загрузка 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("adminlogin").setExecutor(new AdminLoginCommand(this));
        this.getCommand("adminlogout").setExecutor(new AdminLogoutCommand(this));
        this.getCommand("blacklist").setExecutor(new BlacklistCommand(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 отключен!");
    }

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

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

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

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

    /**
     * Аутентификация администратора.
     *
     * @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 (adminConfig.contains("admins." + 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 {
            player.sendMessage(ChatColor.RED + "Вы не зарегистрированы как администратор. Используйте /adminregister <password>");
            return false;
        }
    }

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

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

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

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

    /**
     * Получение конфигурации администраторов.
     *
     * @return Конфигурация admins.yml.
     */
    public FileConfiguration getAdminConfig() {
        return adminConfig;
    }

    /**
     * Логирование событий с временной меткой.
     *
     * @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 message Сообщение для отправки.
     */
    public void notifyAdmins(String message) {
        for (Player admin : Bukkit.getOnlinePlayers()) {
            if (admin.isOp()) {
                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;
    }
}
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) {

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

        Player player = (Player) sender;

        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(player.getName() + " добавил " + 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(player.getName() + " удалил " + 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();

        // Проверка, зарегистрирован ли игрок как администратор
        if (!plugin.getAdminConfig().contains("admins." + playerName)) {
            // Игрок не зарегистрирован как администратор, отправляем напоминание
            player.sendMessage(ChatColor.YELLOW + "Если вы администратор, зарегистрируйтесь с помощью команды /adminregister <пароль>");
        }
    }
}
Исправь, чтобы игроков deop когда 3 раза подряд неправильно пароль, также чтобы появился доступ к командам этим, нужно чтобы они были в списке admins.yml, если нет - deop + сообщение
Также чтобы после выхода из сервера deop админа, и пока не ведёт пароль - не даётся op, а когда ввёл - даём op
Напиши полный код на русском