// src/main/java/com/yourname/pvoplugin/listeners/BlockPlaceListener.java
package com.example.pVOPlugin;

import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPlaceEvent;

import java.util.HashSet;

public class BlockPlaceListener implements Listener {

    private final PVOPlugin plugin;

    public BlockPlaceListener(PVOPlugin plugin) {
        this.plugin = plugin;
    }

    @EventHandler
    public void onBlockPlace(BlockPlaceEvent event) {
        Player player = event.getPlayer();
        Block block = event.getBlockPlaced();

        // Проверяем, является ли размещённый блок PVO
        if (isPVOBlock(block.getType())) {
            PVO pvo = new PVO(block.getLocation(), true, plugin.getConfigManager().getConfig().getInt("pvo.initial_energy", 1000), new HashSet<>());
            plugin.getPvoManager().addPVO(block.getLocation(), pvo);
            plugin.getPvoManager().savePVOs();
            player.sendMessage(ChatColor.GREEN + "PVO размещено и сохранено.");
        }
    }

    private boolean isPVOBlock(Material type) {
        return type == Material.REDSTONE_BLOCK ||
                type == Material.EMERALD_BLOCK ||
                type == Material.DIAMOND_BLOCK ||
                type == Material.GOLD_BLOCK ||
                type == Material.IRON_BLOCK;
    }
}
// src/main/java/com/yourname/pvoplugin/utils/ConfigManager.java
package com.example.pVOPlugin;

import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;

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

public class ConfigManager {
    private final PVOPlugin plugin;
    private File configFile;
    private FileConfiguration config;

    public ConfigManager(PVOPlugin plugin) {
        this.plugin = plugin;
    }

    public void setup() {
        if (!plugin.getDataFolder().exists()) {
            plugin.getDataFolder().mkdirs();
        }

        configFile = new File(plugin.getDataFolder(), "config.yml");
        if (!configFile.exists()) {
            plugin.saveResource("config.yml", false);
        }

        config = YamlConfiguration.loadConfiguration(configFile);
    }

    public FileConfiguration getConfig() {
        return config;
    }

    public void saveConfig() {
        try {
            config.save(configFile);
        } catch (IOException e) {
            plugin.getLogger().severe("Не удалось сохранить config.yml!");
            e.printStackTrace();
        }
    }

    public void reloadConfigFile() {
        config = YamlConfiguration.loadConfiguration(configFile);
    }
}
// src/main/java/com/yourname/pvoplugin/gui/EnergyInputListener.java
package com.example.pVOPlugin;

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

public class EnergyInputListener implements Listener {

    private final PVOPlugin plugin;
    private final Player player;
    private final PVO pvo;
    private final PVOGUI gui;

    public EnergyInputListener(PVOPlugin plugin, Player player, PVO pvo, PVOGUI gui) {
        this.plugin = plugin;
        this.player = player;
        this.pvo = pvo;
        this.gui = gui;
    }

    @EventHandler
    public void onPlayerChat(AsyncPlayerChatEvent event) {
        if (!event.getPlayer().equals(player)) return;

        String message = event.getMessage();
        if (message.matches("\\d+")) {
            int amount = Integer.parseInt(message);
            pvo.addEnergy(amount);
            plugin.getPvoManager().addPVO(pvo.getLocation(), pvo);
            plugin.getPvoManager().savePVOs();

            player.sendMessage(ChatColor.GREEN + "Добавлено энергии: " + amount);
            gui.update();
        } else {
            player.sendMessage(ChatColor.RED + "Введите корректное число.");
        }

        // Отменяем событие и снимаем слушатель
        event.setCancelled(true);
        plugin.getServer().getPluginManager().disablePlugin(plugin); // Необходимо улучшить снятие слушателя
    }
}
// src/main/java/com/yourname/pvoplugin/gui/ExclusionInputListener.java
package com.example.pVOPlugin;

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

public class ExclusionInputListener implements Listener {

    private final PVOPlugin plugin;
    private final Player player;
    private final PVO pvo;
    private final PVOGUI gui;

    public ExclusionInputListener(PVOPlugin plugin, Player player, PVO pvo, PVOGUI gui) {
        this.plugin = plugin;
        this.player = player;
        this.pvo = pvo;
        this.gui = gui;
    }

    @EventHandler
    public void onPlayerChat(AsyncPlayerChatEvent event) {
        if (!event.getPlayer().equals(player)) return;

        String targetPlayer = event.getMessage().toLowerCase();
        pvo.addExclusion(targetPlayer);
        plugin.getPvoManager().addPVO(pvo.getLocation(), pvo);
        plugin.getPvoManager().savePVOs();

        player.sendMessage(ChatColor.GREEN + "Игрок " + targetPlayer + " добавлен в исключения.");
        gui.update();

        // Отменяем событие и снимаем слушатель
        event.setCancelled(true);
        plugin.getServer().getPluginManager().disablePlugin(plugin); // Необходимо улучшить снятие слушателя
    }
}
// src/main/java/com/yourname/pvoplugin/listeners/GUIListener.java
package com.example.pVOPlugin;

import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;

public class GUIListener implements Listener {

    private final PVOPlugin plugin;

    public GUIListener(PVOPlugin plugin) {
        this.plugin = plugin;
    }

    @EventHandler
    public void onInventoryClick(InventoryClickEvent event) {
        String title = event.getView().getTitle();
        if (title.equals("§cНастройки PVO")) {
            if (event.getWhoClicked() instanceof org.bukkit.entity.Player) {
                org.bukkit.entity.Player player = (org.bukkit.entity.Player) event.getWhoClicked();
                // Получаем PVO блок, связанный с этим GUI
                // Для упрощения предполагаем, что один GUI на игрока
                // В реальной реализации необходимо хранить связь Player <-> PVO
                // Например, через метаданные или карту
                // В данном примере обработка кликов делегирована в PVOGUI

                // Ищем PVO, связанный с открытым GUI
                for (PVOGUI gui : plugin.getPvoManager().getAllPVOs().stream().map(pvo -> new PVOGUI(plugin, player, pvo)).toList()) {
                    if (event.getInventory().equals(gui.getInventory())) {
                        gui.handleClick(event);
                        break;
                    }
                }
            }
        }
    }
}
// src/main/java/com/yourname/pvoplugin/listeners/PlayerInteractListener.java
package com.example.pVOPlugin;

import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.EquipmentSlot;

public class PlayerInteractListener implements Listener {

    private final PVOPlugin plugin;

    public PlayerInteractListener(PVOPlugin plugin) {
        this.plugin = plugin;
    }

    @EventHandler
    public void onPlayerInteract(PlayerInteractEvent event) {
        // Проверяем, что игрок нажал правой кнопкой мыши на блок
        if (!event.hasBlock() || !event.getAction().isRightClick()) return;

        // Проверяем, что используется главная рука
        if (event.getHand() != EquipmentSlot.HAND) return;

        Player player = event.getPlayer();
        Block block = event.getClickedBlock();

        if (block == null) return;

        // Проверяем, является ли блок PVO
        if (isPVOBlock(block.getType())) {
            // Проверяем, что игрок приседает
            if (player.isSneaking()) {
                PVO pvo = plugin.getPvoManager().getPVO(block.getLocation());
                if (pvo != null) {
                    PVOGUI gui = new PVOGUI(plugin, player, pvo);
                    gui.open();
                    event.setCancelled(true);
                }
            }
        }
    }

    private boolean isPVOBlock(Material type) {
        return type == Material.REDSTONE_BLOCK ||
                type == Material.EMERALD_BLOCK ||
                type == Material.DIAMOND_BLOCK ||
                type == Material.GOLD_BLOCK ||
                type == Material.IRON_BLOCK;
    }
}
// src/main/java/com/yourname/pvoplugin/listeners/PlayerMoveListener.java
package com.example.pVOPlugin;

import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Particle;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitRunnable;

import java.util.Collection;

public class PlayerMoveListener implements Listener {

    private final PVOPlugin plugin;

    public PlayerMoveListener(PVOPlugin plugin) {
        this.plugin = plugin;
        startEffectTask();
    }

    private void startEffectTask() {
        new BukkitRunnable() {
            @Override
            public void run() {
                Collection<PVO> pvos = plugin.getPvoManager().getAllPVOs();
                for (PVO pvo : pvos) {
                    if (!pvo.isEnabled()) continue;

                    Location loc = pvo.getLocation();
                    double radius = plugin.getConfigManager().getConfig().getDouble("pvo.radius", 10.0);

                    for (Player player : Bukkit.getOnlinePlayers()) {
                        if (!player.getWorld().equals(loc.getWorld())) continue;

                        double distance = player.getLocation().distance(loc);
                        if (distance <= radius) {
                            if (!pvo.getExclusions().contains(player.getName().toLowerCase())) {
                                if (pvo.getEnergy() >= plugin.getConfigManager().getConfig().getInt("pvo.energy_cost", 10)) {
                                    player.addPotionEffect(new PotionEffect(PotionEffectType.WITHER, 60, 1), true);
                                    pvo.removeEnergy(plugin.getConfigManager().getConfig().getInt("pvo.energy_cost", 10));
                                    showEffect(loc);
                                    plugin.getPvoManager().addPVO(loc, pvo);
                                }
                            }
                        }
                    }
                }
                plugin.getPvoManager().savePVOs();
            }
        }.runTaskTimer(plugin, 0L, 20L); // Запуск каждую секунду
    }

    private void showEffect(Location loc) {
        loc.getWorld().spawnParticle(Particle.SMOKE_NORMAL, loc, 10, 1, 1, 1, 0.1);
    }
}
// src/main/java/com/yourname/pvoplugin/managers/PVO.java
package com.example.pVOPlugin;

import org.bukkit.Location;

import java.util.Set;

public class PVO {
    private final Location location;
    private boolean enabled;
    private int energy;
    private final Set<String> exclusions;

    public PVO(Location location, boolean enabled, int energy, Set<String> exclusions) {
        this.location = location;
        this.enabled = enabled;
        this.energy = energy;
        this.exclusions = exclusions;
    }

    public Location getLocation() {
        return location;
    }

    public boolean isEnabled() {
        return enabled;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    public int getEnergy() {
        return energy;
    }

    public void addEnergy(int amount) {
        this.energy += amount;
    }

    public void removeEnergy(int amount) {
        this.energy = Math.max(this.energy - amount, 0);
    }

    public Set<String> getExclusions() {
        return exclusions;
    }

    public void addExclusion(String playerName) {
        this.exclusions.add(playerName.toLowerCase());
    }

    public void removeExclusion(String playerName) {
        this.exclusions.remove(playerName.toLowerCase());
    }
}
// src/main/java/com/yourname/pvoplugin/commands/PVOCommand.java
package com.example.pVOPlugin;

import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.command.*;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;

import java.util.*;

public class PVOCommand implements CommandExecutor, TabCompleter {

    private final PVOPlugin plugin;

    // Карта для ассоциации игроков с действиями (например, ввод энергии или исключений)
    private final Map<UUID, String> pendingActions = new HashMap<>();

    public PVOCommand(PVOPlugin plugin) {
        this.plugin = plugin;
    }

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

        if (command.getName().equalsIgnoreCase("givepvo")) {
            return handleGivePVO(sender, args);
        }

        if (command.getName().equalsIgnoreCase("pvo")) {
            return handlePVO(sender, args);
        }

        return false;
    }

    private boolean handleGivePVO(CommandSender sender, String[] args) {
        if (!(sender instanceof Player)) {
            sender.sendMessage("Эта команда может быть использована только игроками.");
            return true;
        }

        Player player = (Player) sender;

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

        String type = args[0].toLowerCase();

        Material pvoMaterial;
        String displayName;

        switch (type) {
            case "km-1":
                pvoMaterial = Material.REDSTONE_BLOCK;
                displayName = ChatColor.AQUA + "PVO KM-1";
                break;
            case "km-2":
                pvoMaterial = Material.EMERALD_BLOCK;
                displayName = ChatColor.AQUA + "PVO KM-2";
                break;
            case "rtio-100":
                pvoMaterial = Material.DIAMOND_BLOCK;
                displayName = ChatColor.AQUA + "PVO RTIO-100";
                break;
            case "rtio-200":
                pvoMaterial = Material.GOLD_BLOCK;
                displayName = ChatColor.AQUA + "PVO RTIO-200";
                break;
            case "rtio-300":
                pvoMaterial = Material.IRON_BLOCK;
                displayName = ChatColor.AQUA + "PVO RTIO-300";
                break;
            default:
                player.sendMessage(ChatColor.RED + "Неизвестный тип PVO.");
                return true;
        }

        ItemStack pvoItem = new ItemStack(pvoMaterial);
        ItemMeta meta = pvoItem.getItemMeta();
        if (meta != null) {
            meta.setDisplayName(displayName);
            pvoItem.setItemMeta(meta);
        }

        player.getInventory().addItem(pvoItem);
        player.sendMessage(ChatColor.GREEN + "Вы получили " + displayName + ".");
        return true;
    }

    private boolean handlePVO(CommandSender sender, String[] args) {
        if (!(sender instanceof Player)) {
            sender.sendMessage("Эта команда может быть использована только игроками.");
            return true;
        }

        Player player = (Player) sender;

        if (!player.hasPermission("pvoplugin.admin")) {
            player.sendMessage(ChatColor.RED + "У вас нет прав для использования этой команды.");
            return true;
        }

        if (args.length < 1) {
            player.sendMessage(ChatColor.RED + "Использование: /pvo <on|off|addenergy|exclude>");
            return true;
        }

        String subCommand = args[0].toLowerCase();

        switch (subCommand) {
            case "on":
                activatePVO(player, true);
                break;
            case "off":
                activatePVO(player, false);
                break;
            case "addenergy":
                if (args.length != 2) {
                    player.sendMessage(ChatColor.RED + "Использование: /pvo addenergy <количество>");
                    return true;
                }
                try {
                    int amount = Integer.parseInt(args[1]);
                    promptEnergyInput(player, amount);
                } catch (NumberFormatException e) {
                    player.sendMessage(ChatColor.RED + "Введите корректное число.");
                }
                break;
            case "exclude":
                if (args.length != 2) {
                    player.sendMessage(ChatColor.RED + "Использование: /pvo exclude <ник>");
                    return true;
                }
                String targetPlayer = args[1].toLowerCase();
                addExclusion(player, targetPlayer);
                break;
            default:
                player.sendMessage(ChatColor.RED + "Неизвестная подкоманда.");
                break;
        }

        return true;
    }

    private void activatePVO(Player player, boolean activate) {
        // Активируем или деактивируем все PVO блоки
        for (PVO pvo : plugin.getPvoManager().getAllPVOs()) {
            pvo.setEnabled(activate);
        }
        plugin.getPvoManager().savePVOs();
        player.sendMessage(ChatColor.GREEN + "Все PVO " + (activate ? "включены." : "выключены."));
    }

    private void promptEnergyInput(Player player, int amount) {
        player.sendMessage(ChatColor.YELLOW + "Введите количество энергии через чат.");
        pendingActions.put(player.getUniqueId(), "addenergy:" + amount);
    }

    private void addExclusion(Player player, String targetPlayer) {
        // Добавляем игрока в исключения всех PVO блоков
        for (PVO pvo : plugin.getPvoManager().getAllPVOs()) {
            pvo.addExclusion(targetPlayer);
        }
        plugin.getPvoManager().savePVOs();
        player.sendMessage(ChatColor.GREEN + "Игрок " + targetPlayer + " добавлен в исключения всех PVO.");
    }

    @Override
    public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
        if (command.getName().equalsIgnoreCase("givepvo")) {
            if (args.length == 1) {
                return Arrays.asList("km-1", "km-2", "rtio-100", "rtio-200", "rtio-300");
            }
        }

        if (command.getName().equalsIgnoreCase("pvo")) {
            if (args.length == 1) {
                return Arrays.asList("on", "off", "addenergy", "exclude");
            }
            if (args.length == 2) {
                if (args[0].equalsIgnoreCase("addenergy")) {
                    return null; // Нет автодополнения для чисел
                }
                if (args[0].equalsIgnoreCase("exclude")) {
                    // Возвращаем список онлайн игроков
                    List<String> players = new ArrayList<>();
                    for (Player p : Bukkit.getOnlinePlayers()) {
                        players.add(p.getName());
                    }
                    return players;
                }
            }
        }

        return Collections.emptyList();
    }

    // Метод для обработки ввода через чат
    public void handleChatInput(Player player, String message) {
        UUID uuid = player.getUniqueId();
        if (pendingActions.containsKey(uuid)) {
            String action = pendingActions.get(uuid);
            if (action.startsWith("addenergy")) {
                String[] parts = action.split(":");
                if (parts.length == 2) {
                    try {
                        int amount = Integer.parseInt(parts[1]);
                        // Добавляем энергию всем PVO блокам
                        for (PVO pvo : plugin.getPvoManager().getAllPVOs()) {
                            pvo.addEnergy(amount);
                        }
                        plugin.getPvoManager().savePVOs();
                        player.sendMessage(ChatColor.GREEN + "Добавлено энергии: " + amount);
                    } catch (NumberFormatException e) {
                        player.sendMessage(ChatColor.RED + "Неверный формат числа.");
                    }
                }
            }
            pendingActions.remove(uuid);
        }
    }
}
// src/main/java/com/yourname/pvoplugin/gui/PVOGUI.java
package com.example.pVOPlugin;

import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.*;
import org.bukkit.inventory.meta.ItemMeta;

public class PVOGUI {

    private final PVOPlugin plugin;
    private final Player player;
    private final PVO pvo;
    private Inventory inventory;

    public PVOGUI(PVOPlugin plugin, Player player, PVO pvo) {
        this.plugin = plugin;
        this.player = player;
        this.pvo = pvo;
        createInventory();
    }

    private void createInventory() {
        inventory = Bukkit.createInventory(null, 27, ChatColor.RED + "Настройки PVO");

        // Кнопка включения/выключения PVO
        ItemStack toggleItem = new ItemStack(pvo.isEnabled() ? Material.LIME_WOOL : Material.RED_WOOL);
        ItemMeta toggleMeta = toggleItem.getItemMeta();
        toggleMeta.setDisplayName(ChatColor.GREEN + (pvo.isEnabled() ? "Выключить PVO" : "Включить PVO"));
        toggleItem.setItemMeta(toggleMeta);
        inventory.setItem(11, toggleItem);

        // Кнопка добавления энергии
        ItemStack energyItem = new ItemStack(Material.GLOWSTONE_DUST);
        ItemMeta energyMeta = energyItem.getItemMeta();
        energyMeta.setDisplayName(ChatColor.YELLOW + "Добавить энергию");
        energyMeta.setLore(java.util.Arrays.asList(ChatColor.GRAY + "Текущая энергия: " + pvo.getEnergy()));
        energyItem.setItemMeta(energyMeta);
        inventory.setItem(13, energyItem);

        // Кнопка управления исключениями
        ItemStack excludeItem = new ItemStack(Material.PLAYER_HEAD);
        ItemMeta excludeMeta = excludeItem.getItemMeta();
        excludeMeta.setDisplayName(ChatColor.BLUE + "Управление исключениями");
        excludeMeta.setLore(java.util.Arrays.asList(ChatColor.GRAY + "Исключено игроков: " + pvo.getExclusions().size()));
        excludeItem.setItemMeta(excludeMeta);
        inventory.setItem(15, excludeItem);
    }

    public void open() {
        player.openInventory(inventory);
    }

    public Inventory getInventory() {
        return inventory;
    }

    public void handleClick(InventoryClickEvent event) {
        if (!event.getInventory().equals(inventory)) return;

        event.setCancelled(true);
        ItemStack clicked = event.getCurrentItem();

        if (clicked == null || clicked.getType() == Material.AIR) return;

        switch (clicked.getType()) {
            case LIME_WOOL:
            case RED_WOOL:
                togglePVO();
                break;
            case GLOWSTONE_DUST:
                promptEnergyInput();
                break;
            case PLAYER_HEAD:
                promptExclusionInput();
                break;
            default:
                break;
        }
    }

    private void togglePVO() {
        pvo.setEnabled(!pvo.isEnabled());
        plugin.getPvoManager().addPVO(pvo.getLocation(), pvo);
        plugin.getPvoManager().savePVOs();

        player.sendMessage(ChatColor.GREEN + "PVO " + (pvo.isEnabled() ? "включено." : "выключено."));
        // Обновляем GUI
        createInventory();
        player.openInventory(inventory);
    }

    private void promptEnergyInput() {
        player.sendMessage(ChatColor.YELLOW + "Введите количество энергии через команду /pvo addenergy <количество>");
    }

    private void promptExclusionInput() {
        player.sendMessage(ChatColor.BLUE + "Введите ник игрока через команду /pvo exclude <ник>");
    }

    public void update() {
        createInventory();
        player.openInventory(inventory);
    }
}// src/main/java/com/yourname/pvoplugin/managers/PVOManager.java
package com.example.pVOPlugin;

import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;

import java.util.*;

public class PVOManager {

    private final PVOPlugin plugin;
    private final Map<Location, PVO> pvoMap;

    public PVOManager(PVOPlugin plugin) {
        this.plugin = plugin;
        this.pvoMap = new HashMap<>();
    }

    public void loadPVOs() {
        FileConfiguration config = plugin.getConfigManager().getConfig();
        ConfigurationSection section = config.getConfigurationSection("pvos");
        if (section != null) {
            for (String key : section.getKeys(false)) {
                ConfigurationSection pvoSection = section.getConfigurationSection(key);
                if (pvoSection != null) {
                    double x = pvoSection.getDouble("location.x");
                    double y = pvoSection.getDouble("location.y");
                    double z = pvoSection.getDouble("location.z");
                    String worldName = pvoSection.getString("location.world");
                    boolean enabled = pvoSection.getBoolean("enabled");
                    int energy = pvoSection.getInt("energy");
                    List<String> exclusions = pvoSection.getStringList("exclusions");

                    Location loc = new Location(Bukkit.getWorld(worldName), x, y, z);
                    PVO pvo = new PVO(loc, enabled, energy, new HashSet<>(exclusions));
                    pvoMap.put(loc, pvo);
                }
            }
        }
        plugin.getLogger().info("Загружено " + pvoMap.size() + " PVO блоков.");
    }

    public void savePVOs() {
        FileConfiguration config = plugin.getConfigManager().getConfig();
        config.set("pvos", null); // Очистка секции перед сохранением

        int count = 0;
        for (Map.Entry<Location, PVO> entry : pvoMap.entrySet()) {
            Location loc = entry.getKey();
            PVO pvo = entry.getValue();
            String key = "pvo_" + count++;
            config.set("pvos." + key + ".location.x", loc.getX());
            config.set("pvos." + key + ".location.y", loc.getY());
            config.set("pvos." + key + ".location.z", loc.getZ());
            config.set("pvos." + key + ".location.world", loc.getWorld().getName());
            config.set("pvos." + key + ".enabled", pvo.isEnabled());
            config.set("pvos." + key + ".energy", pvo.getEnergy());
            config.set("pvos." + key + ".exclusions", new ArrayList<>(pvo.getExclusions()));
        }

        plugin.getConfigManager().saveConfig();
    }

    public void addPVO(Location loc, PVO pvo) {
        pvoMap.put(loc, pvo);
    }

    public void removePVO(Location loc) {
        pvoMap.remove(loc);
    }

    public PVO getPVO(Location loc) {
        return pvoMap.get(loc);
    }

    public Collection<PVO> getAllPVOs() {
        return pvoMap.values();
    }
}
// Изменение в PVOPlugin.java
package com.example.pVOPlugin;

import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.plugin.java.JavaPlugin;

public class PVOPlugin extends JavaPlugin implements Listener {

    private static PVOPlugin instance;
    private ConfigManager configManager;
    private PVOManager pvoManager;

    @Override
    public void onEnable() {
        instance = this;

        // Инициализация менеджера конфигурации
        configManager = new ConfigManager(this);
        configManager.setup();

        // Инициализация менеджера PVO
        pvoManager = new PVOManager(this);
        pvoManager.loadPVOs();

        // Регистрация команд
        PVOCommand pvoCommand = new PVOCommand(this);
        this.getCommand("givepvo").setExecutor(pvoCommand);
        this.getCommand("pvo").setExecutor(pvoCommand);
        this.getCommand("pvo").setTabCompleter(pvoCommand);

        // Регистрация слушателей событий
        getServer().getPluginManager().registerEvents(new BlockPlaceListener(this), this);
        getServer().getPluginManager().registerEvents(new PlayerInteractListener(this), this);
        getServer().getPluginManager().registerEvents(new PlayerMoveListener(this), this);
        getServer().getPluginManager().registerEvents(new GUIListener(this), this);

        // Регистрация рецептов крафта
        new RecipeManager(this).registerRecipes();

        // Регистрация слушателя чата
        getServer().getPluginManager().registerEvents(this, this);

        getLogger().info("PVOPlugin включён!");
    }

    @Override
    public void onDisable() {
        pvoManager.savePVOs();
        getLogger().info("PVOPlugin выключен.");
    }

    public static PVOPlugin getInstance() {
        return instance;
    }

    public ConfigManager getConfigManager() {
        return configManager;
    }

    public PVOManager getPvoManager() {
        return pvoManager;
    }

    // Слушатель для обработки ввода через чат
    @EventHandler
    public void onPlayerChat(AsyncPlayerChatEvent event) {
        Player player = event.getPlayer();
        PVOCommand commandExecutor = (PVOCommand) getCommand("pvo").getExecutor();
        commandExecutor.handleChatInput(player, event.getMessage());
    }
}
// src/main/java/com/yourname/pvoplugin/managers/RecipeManager.java
package com.example.pVOPlugin;

import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.ShapedRecipe;
import org.bukkit.inventory.meta.ItemMeta;

public class RecipeManager {

    private final PVOPlugin plugin;

    public RecipeManager(PVOPlugin plugin) {
        this.plugin = plugin;
    }

    public void registerRecipes() {
        // Рецепты для каждого типа PVO
        registerPVORecipe("km1", Material.REDSTONE_BLOCK, "PVO KM-1", new String[]{" R ", " E ", " R "}, 'R', Material.REDSTONE, 'E', Material.EMERALD);
        registerPVORecipe("km2", Material.EMERALD_BLOCK, "PVO KM-2", new String[]{" E ", " D ", " E "}, 'E', Material.EMERALD, 'D', Material.DIAMOND);
        registerPVORecipe("rtio100", Material.DIAMOND_BLOCK, "PVO RTIO-100", new String[]{" G ", " C ", " G "}, 'G', Material.GOLD_INGOT, 'C', Material.CAULDRON);
        registerPVORecipe("rtio200", Material.GOLD_BLOCK, "PVO RTIO-200", new String[]{" S ", " L ", " S "}, 'S', Material.STICK, 'L', Material.LAVA_BUCKET);
        registerPVORecipe("rtio300", Material.IRON_BLOCK, "PVO RTIO-300", new String[]{" I ", " N ", " I "}, 'I', Material.IRON_INGOT, 'N', Material.NETHER_STAR);
    }

    private void registerPVORecipe(String key, Material resultMaterial, String displayName, String[] shape, char ingredient1, Material material1, char ingredient2, Material material2) {
        ItemStack item = new ItemStack(resultMaterial);
        ItemMeta meta = item.getItemMeta();
        if (meta != null) {
            meta.setDisplayName("§b" + displayName);
            item.setItemMeta(meta);
        }

        ShapedRecipe recipe = new ShapedRecipe(NamespacedKey.minecraft("pvo_" + key), item);
        recipe.shape(shape);
        recipe.setIngredient(ingredient1, material1);
        recipe.setIngredient(ingredient2, material2);
        plugin.getServer().addRecipe(recipe);
    }
}
# src/main/resources/plugin.yml
name: PVOPlugin
main: com.yourname.pvoplugin.PVOPlugin
version: 1.1
api-version: 1.20.1
description: Плагин ПВО с эффектом исушения и настраиваемым GUI.
commands:
  givepvo:
    description: Выдача PVO.
    usage: /givepvo <тип>
    permission: pvoplugin.givepvo
  pvo:
    description: Управление PVO.
    usage: /pvo <подкоманда>
    permission: pvoplugin.admin
permissions:
  pvoplugin.givepvo:
    description: Разрешение на выдачу PVO.
    default: op
  pvoplugin.admin:
    description: Административные права PVO.
    default: op
depend: [TechnologicalPlugin] # Зависимость от технологического плагина (замените на реальное название)


1) Улучшить плагин, реализовать все механики (если там комментарий - заменить на механику), улучшить существующие (например энергию, синтез, характеристики индивидуальные у каждого пво и тд)
2) TecnologicalPlugin - реализовать в этом плагине, это плагин на технологический прогресс, там есть разные улучшения, можно открывать всякие запчасти (для пво) и тд. прокачивать с помощью синтеза, а также он тратиться за иследования (в gui), за улучшения разные (в gui) и за производство пво и тд
3) Исправь ошибки:
Cannot resolve method 'isRightClick' in 'Action'
Cannot resolve symbol 'Player'
'handleChatInput(org.bukkit.entity.Player, java.lang.String)' in 'com.example.pVOPlugin.PVOCommand' cannot be applied to '(Player, java.lang.String)'

4) Написать полный код сразу, на русском