package com.example.adminpasswordplugin;

import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;

import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

public class AdminManager {

    private final Main plugin;
    private final Map<String, AdminCredentials> adminCredentialsMap;
    private final Map<String, Boolean> adminLoggedIn;

    private static final String CONFIG_SECTION = "admin-credentials";
    private static final int SALT_LENGTH = 16; // bytes
    private static final int HASH_ITERATIONS = 65536;
    private static final int KEY_LENGTH = 256; // bits

    public AdminManager(Main plugin) {
        this.plugin = plugin;
        this.adminCredentialsMap = new HashMap<>();
        this.adminLoggedIn = new HashMap<>();
        loadData();
    }

    /**
     * Registers a new admin password.
     *
     * @param player  The player registering the password.
     * @param password The password to register.
     * @return True if registration is successful, false if already registered or error occurs.
     */
    public boolean registerPassword(Player player, String password) {
        String playerName = player.getName().toLowerCase();
        if (adminCredentialsMap.containsKey(playerName)) {
            return false; // Already registered
        }

        byte[] salt = generateSalt();
        String saltEncoded = Base64.getEncoder().encodeToString(salt);
        String hashedPassword = hashPassword(password, salt);

        if (hashedPassword == null) {
            return false; // Hashing failed
        }

        AdminCredentials credentials = new AdminCredentials(saltEncoded, hashedPassword);
        adminCredentialsMap.put(playerName, credentials);
        adminLoggedIn.put(playerName, false);
        saveData();
        return true;
    }

    /**
     * Authenticates an admin using the provided password.
     *
     * @param player  The player attempting to log in.
     * @param password The password provided.
     * @return True if authentication is successful, false otherwise.
     */
    public boolean login(Player player, String password) {
        String playerName = player.getName().toLowerCase();
        if (!adminCredentialsMap.containsKey(playerName)) {
            return false; // Not registered
        }

        AdminCredentials credentials = adminCredentialsMap.get(playerName);
        byte[] salt = Base64.getDecoder().decode(credentials.getSalt());
        String hashedInput = hashPassword(password, salt);

        if (hashedInput == null) {
            return false; // Hashing failed
        }

        if (hashedInput.equals(credentials.getHash())) {
            adminLoggedIn.put(playerName, true);
            return true;
        }

        return false;
    }

    /**
     * Checks if an admin is currently logged in.
     *
     * @param player The player to check.
     * @return True if logged in, false otherwise.
     */
    public boolean isLoggedIn(Player player) {
        String playerName = player.getName().toLowerCase();
        return adminLoggedIn.getOrDefault(playerName, false);
    }

    /**
     * Logs out an admin, resetting their authentication state.
     *
     * @param player The player to log out.
     */
    public void logout(Player player) {
        String playerName = player.getName().toLowerCase();
        adminLoggedIn.put(playerName, false);
    }

    /**
     * Changes an admin's password.
     *
     * @param player      The player changing the password.
     * @param oldPassword The current password.
     * @param newPassword The new password to set.
     * @return True if the password was successfully changed, false otherwise.
     */
    public boolean changePassword(Player player, String oldPassword, String newPassword) {
        String playerName = player.getName().toLowerCase();
        if (!adminCredentialsMap.containsKey(playerName)) {
            return false; // Not registered
        }

        AdminCredentials credentials = adminCredentialsMap.get(playerName);
        byte[] salt = Base64.getDecoder().decode(credentials.getSalt());
        String hashedOldPassword = hashPassword(oldPassword, salt);

        if (hashedOldPassword == null || !hashedOldPassword.equals(credentials.getHash())) {
            return false; // Old password incorrect or hashing failed
        }

        // Generate new salt and hash for the new password
        byte[] newSalt = generateSalt();
        String newSaltEncoded = Base64.getEncoder().encodeToString(newSalt);
        String newHashedPassword = hashPassword(newPassword, newSalt);

        if (newHashedPassword == null) {
            return false; // Hashing failed
        }

        // Update credentials
        AdminCredentials newCredentials = new AdminCredentials(newSaltEncoded, newHashedPassword);
        adminCredentialsMap.put(playerName, newCredentials);
        saveData();
        return true;
    }

    /**
     * Generates a random salt.
     *
     * @return A byte array representing the salt.
     */
    private byte[] generateSalt() {
        SecureRandom sr = new SecureRandom();
        byte[] salt = new byte[SALT_LENGTH];
        sr.nextBytes(salt);
        return salt;
    }

    /**
     * Hashes a password using PBKDF2 with the provided salt.
     *
     * @param password The password to hash.
     * @param salt     The salt to use.
     * @return The hashed password encoded in Base64, or null if hashing fails.
     */
    private String hashPassword(String password, byte[] salt) {
        try {
            PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, HASH_ITERATIONS, KEY_LENGTH);
            SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
            byte[] hash = skf.generateSecret(spec).getEncoded();
            return Base64.getEncoder().encodeToString(hash);
        } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
            plugin.getLogger().severe("Ошибка при хэшировании пароля: " + e.getMessage());
            return null;
        }
    }

    /**
     * Loads admin credentials from config.yml.
     */
    private void loadData() {
        FileConfiguration config = plugin.getConfig();
        if (config.contains(CONFIG_SECTION)) {
            ConfigurationSection section = config.getConfigurationSection(CONFIG_SECTION);
            for (String playerName : section.getKeys(false)) {
                String salt = section.getString(playerName + ".salt");
                String hash = section.getString(playerName + ".hash");
                if (salt != null && hash != null) {
                    AdminCredentials credentials = new AdminCredentials(salt, hash);
                    adminCredentialsMap.put(playerName, credentials);
                }
            }
        }
    }

    /**
     * Saves admin credentials to config.yml.
     */
    public void saveData() {
        FileConfiguration config = plugin.getConfig();
        ConfigurationSection section = config.createSection(CONFIG_SECTION);
        for (Map.Entry<String, AdminCredentials> entry : adminCredentialsMap.entrySet()) {
            String playerName = entry.getKey();
            AdminCredentials credentials = entry.getValue();
            section.set(playerName + ".salt", credentials.getSalt());
            section.set(playerName + ".hash", credentials.getHash());
        }
        plugin.saveConfig();
    }

    /**
     * Inner class to store admin credentials.
     */
    private static class AdminCredentials {
        private final String salt;
        private final String hash;

        public AdminCredentials(String salt, String hash) {
            this.salt = salt;
            this.hash = hash;
        }

        public String getSalt() {
            return salt;
        }

        public String getHash() {
            return hash;
        }
    }
}
package com.example.adminpasswordplugin;

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

public class CommandBlockListener implements Listener {

    private final Main plugin;
    private final AdminManager adminManager;

    public CommandBlockListener(Main plugin, AdminManager adminManager) {
        this.plugin = plugin;
        this.adminManager = adminManager;
    }

    @EventHandler
    public void onCommandPreprocess(PlayerCommandPreprocessEvent event) {
        Player player = event.getPlayer();
        String message = event.getMessage().toLowerCase();
        String command = message.split(" ")[0];

        // Allow access to registration, login, and password change commands without restriction
        if (command.equals("/adminreg") || command.equals("/adminlogin") || command.equals("/adminchangepassword")) {
            return;
        }

        // Check if the player has admin permissions
        if (player.hasPermission("adminpasswordplugin.admin")) {
            // Check if the admin is logged in
            if (!adminManager.isLoggedIn(player)) {
                // Block the command
                event.setCancelled(true);
                player.sendMessage(ChatColor.RED + plugin.getMessage("command_blocked"));
            }
        }
    }
}
package com.example.adminpasswordplugin;

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

public class CommandHandler implements CommandExecutor {

    private final Main plugin;
    private final AdminManager adminManager;

    public CommandHandler(Main plugin, AdminManager adminManager) {
        this.plugin = plugin;
        this.adminManager = adminManager;

        // Register commands
        PluginCommand adminRegCommand = plugin.getCommand("adminreg");
        if (adminRegCommand != null) {
            adminRegCommand.setExecutor(this);
        } else {
            plugin.getLogger().severe("Не удалось зарегистрировать команду /adminreg");
        }

        PluginCommand adminLoginCommand = plugin.getCommand("adminlogin");
        if (adminLoginCommand != null) {
            adminLoginCommand.setExecutor(this);
        } else {
            plugin.getLogger().severe("Не удалось зарегистрировать команду /adminlogin");
        }

        PluginCommand adminChangePasswordCommand = plugin.getCommand("adminchangepassword");
        if (adminChangePasswordCommand != null) {
            adminChangePasswordCommand.setExecutor(this);
        } else {
            plugin.getLogger().severe("Не удалось зарегистрировать команду /adminchangepassword");
        }
    }

    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
        if (!(sender instanceof Player)) {
            sender.sendMessage(plugin.getMessage("not_player"));
            return true;
        }

        Player player = (Player) sender;
        String cmdName = command.getName().toLowerCase();

        switch (cmdName) {
            case "adminreg":
                handleAdminReg(player, args);
                break;
            case "adminlogin":
                handleAdminLogin(player, args);
                break;
            case "adminchangepassword":
                handleAdminChangePassword(player, args);
                break;
            default:
                return false;
        }

        return true;
    }

    /**
     * Handles the /adminreg command for registering admin passwords.
     *
     * @param player The player executing the command.
     * @param args   Command arguments.
     */
    private void handleAdminReg(Player player, String[] args) {
        if (!player.hasPermission("adminpasswordplugin.register")) {
            player.sendMessage(plugin.getMessage("no_permission"));
            return;
        }

        if (args.length != 1) {
            player.sendMessage(plugin.getMessage("usage_adminreg"));
            return;
        }

        String password = args[0];
        boolean registered = adminManager.registerPassword(player, password);

        if (registered) {
            player.sendMessage(plugin.getMessage("register_success"));
        } else {
            player.sendMessage(plugin.getMessage("register_already"));
        }
    }

    /**
     * Handles the /adminlogin command for admin authentication.
     *
     * @param player The player executing the command.
     * @param args   Command arguments.
     */
    private void handleAdminLogin(Player player, String[] args) {
        if (!player.hasPermission("adminpasswordplugin.login")) {
            player.sendMessage(plugin.getMessage("no_permission"));
            return;
        }

        if (args.length != 1) {
            player.sendMessage(plugin.getMessage("usage_adminlogin"));
            return;
        }

        String password = args[0];
        boolean loggedIn = adminManager.login(player, password);

        if (loggedIn) {
            player.sendMessage(plugin.getMessage("login_success"));
        } else {
            player.sendMessage(plugin.getMessage("login_failure"));
        }
    }

    /**
     * Handles the /adminchangepassword command for changing admin passwords.
     *
     * @param player The player executing the command.
     * @param args   Command arguments.
     */
    private void handleAdminChangePassword(Player player, String[] args) {
        if (!player.hasPermission("adminpasswordplugin.change_password")) {
            player.sendMessage(plugin.getMessage("no_permission"));
            return;
        }

        if (args.length != 2) {
            player.sendMessage(plugin.getMessage("password_change_usage"));
            return;
        }

        String oldPassword = args[0];
        String newPassword = args[1];
        boolean changed = adminManager.changePassword(player, oldPassword, newPassword);

        if (changed) {
            player.sendMessage(plugin.getMessage("password_change_success"));
        } else {
            player.sendMessage(plugin.getMessage("password_change_failure"));
        }
    }
}
package com.example.adminpasswordplugin;

import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.java.JavaPlugin;

import java.io.File;
import java.io.IOException;

public class Main extends JavaPlugin {

    private AdminManager adminManager;
    private File messagesFile;
    private FileConfiguration messagesConfig;

    @Override
    public void onEnable() {
        // Save default config.yml and messages.yml
        saveDefaultConfig();
        createMessagesConfig();

        // Initialize AdminManager
        adminManager = new AdminManager(this);

        // Register command handlers
        new CommandHandler(this, adminManager);

        // Register event listeners
        getServer().getPluginManager().registerEvents(new CommandBlockListener(this, adminManager), this);
        getServer().getPluginManager().registerEvents(new PlayerListener(this, adminManager), this);

        getLogger().info("AdminPasswordPlugin успешно включён!");
    }

    @Override
    public void onDisable() {
        // Save admin credentials when plugin is disabled
        if (adminManager != null) {
            adminManager.saveData();
        }
        getLogger().info("AdminPasswordPlugin отключён!");
    }

    /**
     * Creates and loads the messages.yml configuration file.
     */
    private void createMessagesConfig() {
        messagesFile = new File(getDataFolder(), "messages.yml");
        if (!messagesFile.exists()) {
            saveResource("messages.yml", false);
        }
        messagesConfig = YamlConfiguration.loadConfiguration(messagesFile);
    }

    /**
     * Retrieves a message from messages.yml.
     *
     * @param path The path to the message.
     * @return The formatted message.
     */
    public String getMessage(String path) {
        return messagesConfig.getString("messages." + path, "Message not found!");
    }

    /**
     * Retrieves the AdminManager instance.
     *
     * @return The AdminManager.
     */
    public AdminManager getAdminManager() {
        return adminManager;
    }
}
package com.example.adminpasswordplugin;

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

public class PlayerListener implements Listener {

    private final Main plugin;
    private final AdminManager adminManager;

    public PlayerListener(Main plugin, AdminManager adminManager) {
        this.plugin = plugin;
        this.adminManager = adminManager;
    }

    @EventHandler
    public void onPlayerQuit(PlayerQuitEvent event) {
        Player player = event.getPlayer();
        adminManager.logout(player);
    }
}
messages:
  not_player: "Только игроки могут выполнять эту команду."
  no_permission: "У вас нет разрешения на выполнение этого действия."
  usage_adminreg: "/adminreg <password>"
  register_success: "Вы успешно зарегистрировались как администратор."
  register_already: "Вы уже зарегистрированы как администратор."
  usage_adminlogin: "/adminlogin <password>"
  login_success: "Вы успешно вошли в систему как администратор."
  login_failure: "Неверный пароль. Пожалуйста, попробуйте ещё раз."
  usage_adminchangepassword: "/adminchangepassword <старый_пароль> <новый_пароль>"
  password_change_success: "Ваш пароль успешно изменён."
  password_change_failure: "Не удалось изменить пароль. Пожалуйста, убедитесь, что ваш старый пароль верен."
  command_blocked: "Вы должны войти в систему как администратор, чтобы использовать эту команду."

name: AdminPasswordPlugin
version: 1.2
main: com.example.adminpasswordplugin.Main
api-version: 1.20
commands:
  adminreg:
    description: Register an admin password.
    usage: /adminreg <password>
    permission: adminpasswordplugin.register
  adminlogin:
    description: Login as an admin.
    usage: /adminlogin <password>
    permission: adminpasswordplugin.login
  adminchangepassword:
    description: Change your admin password.
    usage: /adminchangepassword <oldpassword> <newpassword>
    permission: adminpasswordplugin.change_password
permissions:
  adminpasswordplugin.admin:
    description: Grants access to admin commands.
    category: Admin
    default: op
  adminpasswordplugin.register:
    description: Allows a player to register as an admin.
    category: Admin
    default: op
  adminpasswordplugin.login:
    description: Allows a player to login as an admin.
    category: Admin
    default: op
  adminpasswordplugin.change_password:
    description: Allows a player to change their admin password.
    category: Admin
    default: op

Проверь, чтобы оно работало. Я хочу, чтобы работало так:
Админ, заходит на сервер, может писать обычные команды, которые доступны для всех, но команды, требующие опки, он не может, и для начало, ему надо ввести пароль (или зарегаться), после этого он может. Чтобы это работало даже с другими плагинами. Но, сделай так, чтобы команды из этого плагина, он мог вводить, а остальные, требующие опки, даже в других плагинах, были заблокированы, пока не ввели пароль. Напиши полный код сразу