// OptimizedRocket.java
package com.yourname.rocketplugin;

import org.bukkit.Location;
import org.bukkit.Particle;
import org.bukkit.Sound;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;

/**
 * Класс, представляющий оптимизированную ракету для разрушения.
 */
public class OptimizedRocket extends Rocket {

    /**
     * Конструктор OptimizedRocket.
     *
     * @param launcher Игрок, запустивший ракету.
     * @param type     Тип ракеты.
     * @param target   Целевая локация.
     * @param plugin   Главный плагин.
     */
    public OptimizedRocket(Player launcher, RocketType type, Location target, RocketPlugin plugin) {
        super(launcher, type, target, plugin);
    }

    @Override
    protected void explode() {
        final World world = this.target.getWorld();
        if (world == null) {
            this.launcher.sendMessage("§cОшибка: Целевая локация не найдена.");
            return;
        }

        // Особая логика взрыва для OptimizedRocket
        world.createExplosion(this.target, (float) type.getPower(), false, true); // Теперь разрушает блоки
        world.spawnParticle(this.type.getExplosionParticle(), this.target, 50, 0.5, 0.5, 0.5, 0.02);
        world.playSound(this.target, this.type.getExplosionSound(), 1.0F, 1.0F);

        // Минимальный набор эффектов для оптимизации
        new BukkitRunnable() {
            private int ticks = 0;
            private final int maxTicks = 30;

            @Override
            public void run() {
                if (ticks >= maxTicks) {
                    this.cancel();
                } else {
                    world.spawnParticle(Particle.SMOKE_NORMAL, target, 20, 0.3, 0.3, 0.3, 0.01);
                    world.spawnParticle(Particle.FLAME, target, 50, 0.5, 0.5, 0.5, 0.02);
                    world.playSound(target, Sound.ENTITY_GENERIC_EXPLODE, 1.0F, 1.0F);
                    ticks++;
                }
            }
        }.runTaskTimer(this.plugin, 0L, 1L);
    }
}
// PVOBlock.java
package com.yourname.rocketplugin;

import org.bukkit.Location;

import java.util.Set;
import java.util.UUID;

/**
 * Класс, представляющий ПВО блок.
 */
public class PVOBlock {
    private final Location location;
    private final Set<UUID> excludedPlayers;

    /**
     * Конструктор PVOBlock.
     *
     * @param location         Локация блока.
     * @param excludedPlayers Множество UUID игроков, исключённых из защиты.
     */
    public PVOBlock(Location location, Set<UUID> excludedPlayers) {
        this.location = location;
        this.excludedPlayers = excludedPlayers;
    }

    public Location getLocation() { return location; }

    public Set<UUID> getExcludedPlayers() { return excludedPlayers; }
}
// PVOCommand.java
package com.yourname.rocketplugin;

import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;

/**
 * Класс обработки команды /pvo.
 */
public class PVOCommand implements CommandExecutor {
    private final RocketManager rocketManager;
    private final RocketPlugin plugin;

    /**
     * Конструктор PVOCommand.
     *
     * @param rocketManager Менеджер ракет и ПВО.
     * @param plugin        Главный плагин.
     */
    public PVOCommand(RocketManager rocketManager, RocketPlugin plugin) {
        this.rocketManager = rocketManager;
        this.plugin = plugin;
    }

    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
        if (!sender.hasPermission("pvo.use")) {
            sender.sendMessage(ChatColor.RED + "§cУ вас нет разрешения использовать эту команду.");
            return true;
        }

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

        if (args.length == 0) {
            sender.sendMessage(ChatColor.RED + "§cИспользование: /pvo <give|exclude|remove>");
            return true;
        }

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

        switch (subcommand) {
            case "give":
                handleGive(sender, args);
                break;
            case "exclude":
                handleExclude(sender, args);
                break;
            case "remove":
                handleRemove(sender, args);
                break;
            default:
                sender.sendMessage(ChatColor.RED + "§cНеизвестная подкоманда. Используйте /pvo <give|exclude|remove>");
        }

        return true;
    }

    /**
     * Обработка подкоманды give.
     *
     * @param sender Отправитель команды.
     * @param args   Аргументы команды.
     */
    private void handleGive(CommandSender sender, String[] args) {
        if (!sender.hasPermission("pvo.give")) {
            sender.sendMessage(ChatColor.RED + "§cУ вас нет разрешения выдавать ПВО блоки.");
            return;
        }

        // Предоставляем игроку специальный блок ПВО (маяк)
        ItemStack pvoItem = new ItemStack(Material.BEACON);
        ItemMeta meta = pvoItem.getItemMeta();
        if (meta != null) {
            meta.setDisplayName(ChatColor.GOLD + "§lПВО Блок");
            pvoItem.setItemMeta(meta);
        }

        Player player = (Player) sender;
        player.getInventory().addItem(pvoItem);
        player.sendMessage(ChatColor.GREEN + "§aВы получили ПВО блок (маяк). Установите его в мире P_Drilla.");
    }

    /**
     * Обработка подкоманды exclude.
     *
     * @param sender Отправитель команды.
     * @param args   Аргументы команды.
     */
    private void handleExclude(CommandSender sender, String[] args) {
        if (args.length < 3) {
            sender.sendMessage(ChatColor.RED + "§cИспользование: /pvo exclude <add|remove> <player>");
            return;
        }

        String action = args[1].toLowerCase();
        String targetName = args[2];
        Player targetPlayer = plugin.getServer().getPlayerExact(targetName);

        if (targetPlayer == null) {
            sender.sendMessage(ChatColor.RED + "§cИгрок не найден или не онлайн.");
            return;
        }

        Player owner = (Player) sender;

        switch (action) {
            case "add":
                rocketManager.getPvoManager().addExcludedPlayer(owner, targetPlayer);
                break;
            case "remove":
                rocketManager.getPvoManager().removeExcludedPlayer(owner, targetPlayer);
                break;
            default:
                sender.sendMessage(ChatColor.RED + "§cНеизвестное действие. Используйте add или remove.");
        }
    }

    /**
     * Обработка подкоманды remove.
     *
     * @param sender Отправитель команды.
     * @param args   Аргументы команды.
     */
    private void handleRemove(CommandSender sender, String[] args) {
        // Это действие уже покрыто в handleExclude, поэтому можно оставить пустым или удалить этот метод
        sender.sendMessage(ChatColor.RED + "§cИспользуйте /pvo exclude <add|remove> <player> для управления исключениями.");
    }
}
// PVOListener.java
package com.yourname.rocketplugin;

import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.ExplosionPrimeEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.block.BlockBreakEvent;

import java.util.List;

/**
 * Класс слушателя событий, связанных с ПВО.
 */
public class PVOListener implements Listener {
    private final RocketManager rocketManager;
    private final RocketPlugin plugin;

    /**
     * Конструктор PVOListener.
     *
     * @param rocketManager Менеджер ракет и ПВО.
     * @param plugin        Главный плагин.
     */
    public PVOListener(RocketManager rocketManager, RocketPlugin plugin) {
        this.rocketManager = rocketManager;
        this.plugin = plugin;
    }

    /**
     * Событие размещения блока.
     *
     * @param event Событие.
     */
    @EventHandler
    public void onBlockPlace(BlockPlaceEvent event) {
        Player player = event.getPlayer();
        Location loc = event.getBlock().getLocation();

        // Проверяем, является ли размещённый блок ПВО блоком (маяк)
        if (event.getBlock().getType().equals(Material.BEACON)) {
            boolean added = rocketManager.getPvoManager().addPVOBlock(player, loc);
            if (!added) {
                event.setCancelled(true);
            } else {
                player.sendMessage(ChatColor.GREEN + "§aПВО блок установлен.");
            }
        }
    }

    /**
     * Событие разрушения блока.
     *
     * @param event Событие.
     */
    @EventHandler
    public void onBlockBreak(BlockBreakEvent event) {
        Player player = event.getPlayer();
        Location loc = event.getBlock().getLocation();

        // Проверяем, является ли разрушённый блок ПВО блоком (маяк)
        if (event.getBlock().getType().equals(Material.BEACON)) {
            boolean removed = rocketManager.getPvoManager().removePVOBlock(player, loc);
            if (removed) {
                player.sendMessage(ChatColor.GREEN + "§aПВО блок удалён.");
            }
        }
    }

    /**
     * Событие взрыва для обработки ПВО.
     *
     * @param event Событие.
     */
    @EventHandler
    public void onExplosionPrime(ExplosionPrimeEvent event) {
        World world = event.getEntity().getWorld();
        if (!world.getName().equalsIgnoreCase("P_Drilla")) {
            event.setCancelled(true);
            if (event.getEntity() instanceof Player player) {
                player.sendMessage(ChatColor.RED + "§cВзрывы вне мира запрещены!");
            }
            return;
        }

        Location explosionLocation = event.getEntity().getLocation();
        double radius = 10.0; // Радиус взрыва

        // Получаем ПВО блоки в радиусе взрыва
        List<PVOBlock> nearbyPVO = rocketManager.getPvoManager().getPVOBlocksInRadius(explosionLocation, radius);

        if (!nearbyPVO.isEmpty()) {
            // Применяем логику защиты
            // Например, не наносим эффекты владельцу ПВО блоков
            for (PVOBlock block : nearbyPVO) {
                Player owner = plugin.getServer().getPlayer(block.getLocation().getWorld().getName()); // Получаем владельца по UUID
                if (owner != null) {
                    // Проверяем, является ли цель владельцем или исключённым игроком
                    // Эта логика должна быть доработана в зависимости от точных требований
                }
            }
        }
    }

    /**
     * Событие нанесения вреда игроку.
     *
     * @param event Событие.
     */
    @EventHandler
    public void onEntityDamageByEntity(EntityDamageByEntityEvent event) {
        if (!(event.getEntity() instanceof Player damaged)) return;

        Location damageLocation = damaged.getLocation();
        double radius = 10.0; // Радиус действия ПВО

        // Получаем ПВО блоки в радиусе действия от повреждения
        List<PVOBlock> nearbyPVO = rocketManager.getPvoManager().getPVOBlocksInRadius(damageLocation, radius);

        if (!nearbyPVO.isEmpty()) {
            // Проверяем, имеет ли ПВО блока право защищать повреждённого
            for (PVOBlock block : nearbyPVO) {
                Player owner = plugin.getServer().getPlayer(block.getLocation().getWorld().getName()); // Получаем владельца по UUID
                if (owner != null) {
                    if (block.getExcludedPlayers().contains(damaged.getUniqueId())) {
                        // Игрок в списке исключений, защита не применяется
                        continue;
                    }

                    if (!damaged.equals(owner)) {
                        // Отменяем урон, если повреждённый не владелец ПВО
                        event.setCancelled(true);
                        damaged.sendMessage(ChatColor.YELLOW + "§eВаш ПВО блок защитил вас от урона!");
                        break;
                    }
                }
            }
        }
    }
}
// PVOManager.java
package com.yourname.rocketplugin;

import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;

import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * Класс управления ПВО (Противовоздушной Обороны).
 */
public class PVOManager {
    private final RocketPlugin plugin;
    private StatsManager statsManager;
    private final File pvoFile;
    private FileConfiguration pvoConfig;
    private final Map<UUID, List<PVOBlock>> playerPVOBlocks; // Список ПВО блоков для каждого игрока

    /**
     * Конструктор PVOManager.
     *
     * @param plugin Главный плагин.
     */
    public PVOManager(RocketPlugin plugin) {
        this.plugin = plugin;
        this.pvoFile = new File(plugin.getDataFolder(), "pvo.yml");
        if (!this.pvoFile.exists()) {
            try {
                plugin.saveResource("pvo.yml", false);
            } catch (IllegalArgumentException e) {
                // Файл pvo.yml не найден в ресурсах, создаём пустой
                this.pvoConfig = new YamlConfiguration();
                try {
                    this.pvoConfig.save(this.pvoFile);
                } catch (IOException ex) {
                    plugin.getLogger().severe("§cНе удалось создать pvo.yml:");
                    ex.printStackTrace();
                }
            }
        }

        this.pvoConfig = YamlConfiguration.loadConfiguration(this.pvoFile);
        this.playerPVOBlocks = new HashMap<>();
        loadPVOBlocks();
    }

    /**
     * Устанавливает ссылку на StatsManager.
     *
     * @param statsManager Экземпляр StatsManager.
     */
    public void setStatsManager(StatsManager statsManager) {
        this.statsManager = statsManager;
    }

    /**
     * Загружает ПВО блоки из pvo.yml.
     */
    private void loadPVOBlocks() {
        ConfigurationSection pvoSection = pvoConfig.getConfigurationSection("pvo");
        if (pvoSection == null) return;

        for (String playerUUID : pvoSection.getKeys(false)) {
            UUID uuid = UUID.fromString(playerUUID);
            List<PVOBlock> blocks = new ArrayList<>();
            ConfigurationSection playerSection = pvoSection.getConfigurationSection(playerUUID);
            if (playerSection == null) continue;

            for (String blockKey : playerSection.getKeys(false)) {
                ConfigurationSection blockSection = playerSection.getConfigurationSection(blockKey);
                if (blockSection == null) continue;

                String worldName = blockSection.getString("world");
                double x = blockSection.getDouble("x");
                double y = blockSection.getDouble("y");
                double z = blockSection.getDouble("z");
                List<String> excludedList = blockSection.getStringList("excluded");
                Set<UUID> excluded = new HashSet<>();
                for (String excludedUUID : excludedList) {
                    excluded.add(UUID.fromString(excludedUUID));
                }

                Location loc = new Location(Bukkit.getWorld(worldName), x, y, z);
                blocks.add(new PVOBlock(loc, excluded));
            }

            playerPVOBlocks.put(uuid, blocks);
        }
    }

    /**
     * Сохраняет ПВО блоки в pvo.yml.
     */
    public void savePVOBlocks() {
        pvoConfig.set("pvo", null); // Очищаем секцию
        for (Map.Entry<UUID, List<PVOBlock>> entry : playerPVOBlocks.entrySet()) {
            UUID owner = entry.getKey();
            List<PVOBlock> blocks = entry.getValue();
            for (int i = 0; i < blocks.size(); i++) {
                PVOBlock block = blocks.get(i);
                String path = "pvo." + owner.toString() + ".block" + i;
                pvoConfig.set(path + ".world", block.getLocation().getWorld().getName());
                pvoConfig.set(path + ".x", block.getLocation().getX());
                pvoConfig.set(path + ".y", block.getLocation().getY());
                pvoConfig.set(path + ".z", block.getLocation().getZ());

                List<String> excludedUUIDs = new ArrayList<>();
                for (UUID excluded : block.getExcludedPlayers()) {
                    excludedUUIDs.add(excluded.toString());
                }
                pvoConfig.set(path + ".excluded", excludedUUIDs);
            }
        }

        try {
            pvoConfig.save(pvoFile);
        } catch (IOException e) {
            plugin.getLogger().severe("§cНе удалось сохранить pvo.yml:");
            e.printStackTrace();
        }
    }

    /**
     * Добавляет ПВО блок для игрока.
     *
     * @param player Игрок.
     * @param block  Блок.
     * @return true, если блок успешно добавлен.
     */
    public boolean addPVOBlock(Player player, Location block) {
        UUID playerUUID = player.getUniqueId();
        List<PVOBlock> blocks = playerPVOBlocks.getOrDefault(playerUUID, new ArrayList<>());

        if (blocks.size() >= 5) {
            player.sendMessage("§cВы достигли максимального количества ПВО блоков (5).");
            return false;
        }

        // Проверяем, что блок имеет нужный тип (маяк)
        if (!block.getBlock().getType().equals(Material.BEACON)) {
            player.sendMessage("§cПВО блоки должны быть маяками (Beacon).");
            return false;
        }

        // Проверяем, что блок ещё не зарегистрирован
        for (PVOBlock existingBlock : blocks) {
            if (existingBlock.getLocation().equals(block)) {
                player.sendMessage("§cЭтот блок уже зарегистрирован как ПВО.");
                return false;
            }
        }

        PVOBlock pvoBlock = new PVOBlock(block, new HashSet<>());
        blocks.add(pvoBlock);
        playerPVOBlocks.put(playerUUID, blocks);
        savePVOBlocks();
        player.sendMessage("§aПВО блок успешно добавлен.");
        return true;
    }

    /**
     * Удаляет ПВО блок для игрока.
     *
     * @param player Игрок.
     * @param block  Блок.
     * @return true, если блок успешно удалён.
     */
    public boolean removePVOBlock(Player player, Location block) {
        UUID playerUUID = player.getUniqueId();
        List<PVOBlock> blocks = playerPVOBlocks.getOrDefault(playerUUID, new ArrayList<>());

        PVOBlock target = null;
        for (PVOBlock pvoBlock : blocks) {
            if (pvoBlock.getLocation().equals(block)) {
                target = pvoBlock;
                break;
            }
        }

        if (target != null) {
            blocks.remove(target);
            playerPVOBlocks.put(playerUUID, blocks);
            savePVOBlocks();
            player.sendMessage("§aПВО блок успешно удалён.");
            return true;
        } else {
            player.sendMessage("§cЭтот блок не зарегистрирован как ПВО.");
            return false;
        }
    }

    /**
     * Добавляет игрока в список исключений для ПВО блоков владельца.
     *
     * @param owner    Владелец ПВО.
     * @param excluded Игрок для исключения.
     */
    public void addExcludedPlayer(Player owner, Player excluded) {
        UUID ownerUUID = owner.getUniqueId();
        UUID excludedUUID = excluded.getUniqueId();
        List<PVOBlock> blocks = playerPVOBlocks.getOrDefault(ownerUUID, new ArrayList<>());

        for (PVOBlock block : blocks) {
            block.getExcludedPlayers().add(excludedUUID);
        }

        savePVOBlocks();
        owner.sendMessage("§aИгрок " + excluded.getName() + " добавлен в список исключений ПВО.");
        excluded.sendMessage("§aВас добавили в список исключений ПВО игрока " + owner.getName() + ".");
    }

    /**
     * Удаляет игрока из списка исключений для ПВО блоков владельца.
     *
     * @param owner    Владелец ПВО.
     * @param excluded Игрок для удаления из исключений.
     */
    public void removeExcludedPlayer(Player owner, Player excluded) {
        UUID ownerUUID = owner.getUniqueId();
        UUID excludedUUID = excluded.getUniqueId();
        List<PVOBlock> blocks = playerPVOBlocks.getOrDefault(ownerUUID, new ArrayList<>());

        for (PVOBlock block : blocks) {
            block.getExcludedPlayers().remove(excludedUUID);
        }

        savePVOBlocks();
        owner.sendMessage("§aИгрок " + excluded.getName() + " удалён из списка исключений ПВО.");
        excluded.sendMessage("§aВас удалили из списка исключений ПВО игрока " + owner.getName() + ".");
    }

    /**
     * Получает список ПВО блоков в радиусе действия от локации.
     *
     * @param location Локация взрыва.
     * @param radius   Радиус действия.
     * @return Список ПВО блоков.
     */
    public List<PVOBlock> getPVOBlocksInRadius(Location location, double radius) {
        List<PVOBlock> nearbyBlocks = new ArrayList<>();
        for (List<PVOBlock> blocks : playerPVOBlocks.values()) {
            for (PVOBlock block : blocks) {
                if (block.getLocation().getWorld().equals(location.getWorld()) &&
                        block.getLocation().distance(location) <= radius) {
                    nearbyBlocks.add(block);
                }
            }
        }
        return nearbyBlocks;
    }
}// Rocket.java
package com.yourname.rocketplugin;

import org.bukkit.Location;
import org.bukkit.Particle;
import org.bukkit.Sound;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;

import java.util.Collection;

/**
 * Класс, представляющий ракету.
 */
public class Rocket {
    protected final Player launcher;
    protected final RocketType type;
    protected final Location target;
    protected final RocketPlugin plugin;
    protected Location currentLocation;
    protected double speed = 1.0;

    /**
     * Конструктор ракеты.
     *
     * @param launcher Игрок, запустивший ракету.
     * @param type     Тип ракеты.
     * @param target   Целевая локация.
     * @param plugin   Главный плагин.
     */
    public Rocket(Player launcher, RocketType type, Location target, RocketPlugin plugin) {
        this.launcher = launcher;
        this.type = type;
        this.target = target;
        this.plugin = plugin;
        this.currentLocation = launcher.getLocation().clone();
    }

    /**
     * Запускает ракету.
     */
    public void launch() {
        final World world = this.launcher.getWorld();
        if (world == null) {
            this.launcher.sendMessage("§cОшибка: Мир не найден.");
            return;
        }

        world.spawnParticle(this.type.getLaunchParticle(), this.currentLocation, 20, 0.5, 0.5, 0.5, 0.05);
        world.playSound(this.currentLocation, this.type.getLaunchSound(), 1.0F, 1.0F);
        new BukkitRunnable() {
            @Override
            public void run() {
                Vector direction = target.clone().subtract(currentLocation).toVector();
                double distance = direction.length();
                if (distance < type.getRange()) {
                    explode();
                    this.cancel();
                } else {
                    direction = direction.normalize().multiply(speed);
                    currentLocation.add(direction);
                    world.spawnParticle(type.getLaunchParticle(), currentLocation, 5, 0.1, 0.1, 0.1, 0.02);
                }
            }
        }.runTaskTimer(this.plugin, 0L, 1L);
    }

    /**
     * Вызывает взрыв ракеты.
     */
    protected void explode() {
        final World world = this.target.getWorld();
        if (world == null) {
            this.launcher.sendMessage("§cОшибка: Целевая локация не найдена.");
            return;
        }

        if (type.isOptimized()) {
            optimizedExplode(world);
        } else {
            standardExplode(world);
        }
    }

    /**
     * Стандартный взрыв ракеты.
     *
     * @param world Мир, в котором происходит взрыв.
     */
    protected void standardExplode(World world) {
        world.createExplosion(this.target, (float) type.getPower(), false, true);
        world.spawnParticle(this.type.getExplosionParticle(), this.target, 100, 1.0, 1.0, 1.0, 0.1);
        world.playSound(this.target, this.type.getExplosionSound(), 1.0F, 1.0F);

        if (type.getName().equalsIgnoreCase("SUPER_NUCLEAR") ||
                type.getName().equalsIgnoreCase("MEGA_NUCLEAR") ||
                type.getName().equalsIgnoreCase("EXTREME_NUCLEAR") ||
                type.getName().equalsIgnoreCase("ULTRA_NUCLEAR") ||
                type.getName().equalsIgnoreCase("USSR")) {

            double effectRadius = 20.0;
            Collection<Entity> entities = world.getNearbyEntities(this.target, effectRadius, effectRadius, effectRadius);

            for (Entity entity : entities) {
                if (entity instanceof Player player) {
                    player.addPotionEffect(new PotionEffect(PotionEffectType.CONFUSION, 200, 1));
                    player.addPotionEffect(new PotionEffect(PotionEffectType.POISON, 200, 1));
                }
            }

            new BukkitRunnable() {
                private int ticks = 0;
                private final int maxTicks = 100;

                @Override
                public void run() {
                    if (ticks >= maxTicks) {
                        this.cancel();
                    } else {
                        world.spawnParticle(Particle.EXPLOSION_HUGE, target, 50, 2.0, 2.0, 2.0, 0.05);
                        world.spawnParticle(Particle.LAVA, target, 100, 3.0, 3.0, 3.0, 0.02);
                        world.spawnParticle(Particle.FIREWORKS_SPARK, target, 100, 4.0, 4.0, 4.0, 0.1);
                        world.spawnParticle(Particle.END_ROD, target, 50, 2.0, 2.0, 2.0, 0.05);
                        world.playSound(target, Sound.ENTITY_GENERIC_EXPLODE, 1.0F, 1.0F);
                        ticks++;
                    }
                }
            }.runTaskTimer(this.plugin, 0L, 1L);
        }
    }

    /**
     * Оптимизированный взрыв ракеты для снижения нагрузки на сервер.
     *
     * @param world Мир, в котором происходит взрыв.
     */
    protected void optimizedExplode(World world) {
        // Минимизация ущерба и нагрузки
        world.createExplosion(this.target, (float) type.getPower(), false, true); // Теперь разрушает блоки
        world.spawnParticle(this.type.getExplosionParticle(), this.target, 50, 0.5, 0.5, 0.5, 0.02);
        world.playSound(this.target, this.type.getExplosionSound(), 1.0F, 1.0F);

        double effectRadius = type.getRange() / 2; // Настройка радиуса воздействия
        Collection<Entity> entities = world.getNearbyEntities(this.target, effectRadius, effectRadius, effectRadius);

        for (Entity entity : entities) {
            if (entity instanceof Player player) {
                player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 100, 1));
            }
        }

        // Дополнительные оптимизированные эффекты
        new BukkitRunnable() {
            private int ticks = 0;
            private final int maxTicks = 50;

            @Override
            public void run() {
                if (ticks >= maxTicks) {
                    this.cancel();
                } else {
                    world.spawnParticle(Particle.SMOKE_NORMAL, target, 30, 1.0, 1.0, 1.0, 0.01);
                    world.spawnParticle(Particle.FLAME, target, 50, 1.0, 1.0, 1.0, 0.02);
                    world.playSound(target, Sound.ENTITY_GENERIC_EXPLODE, 1.0F, 1.0F);
                    ticks++;
                }
            }
        }.runTaskTimer(this.plugin, 0L, 1L);
    }
}
// RocketCommand.java
package com.yourname.rocketplugin;

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

/**
 * Класс обработки команды /rocket.
 */
public class RocketCommand implements CommandExecutor {
    private final RocketManager rocketManager;
    private final StatsManager statsManager;
    private final RocketPlugin plugin;

    /**
     * Конструктор RocketCommand.
     *
     * @param rocketManager Менеджер ракет.
     * @param statsManager  Менеджер статистики.
     * @param plugin        Главный плагин.
     */
    public RocketCommand(RocketManager rocketManager, StatsManager statsManager, RocketPlugin plugin) {
        this.rocketManager = rocketManager;
        this.statsManager = statsManager;
        this.plugin = plugin;
    }

    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
        if (!sender.hasPermission("rocketplugin.use")) {
            sender.sendMessage(ChatColor.RED + "§cУ вас нет разрешения использовать эту команду.");
            return true;
        }

        if (args.length == 0) {
            sender.sendMessage(ChatColor.RED + "§cИспользование: /rocket <launch|give|stats|reload> [параметры]");
            return true;
        }

        String subcommand = args[0].toLowerCase();
        switch (subcommand) {
            case "launch":
                handleLaunch(sender, args);
                break;
            case "give":
                handleGive(sender, args);
                break;
            case "stats":
                handleStats(sender, args);
                break;
            case "reload":
                handleReload(sender, args);
                break;
            default:
                sender.sendMessage(ChatColor.RED + "§cНеизвестная подкоманда. Использование: /rocket <launch|give|stats|reload> [параметры]");
        }

        return true;
    }

    /**
     * Обработка подкоманды launch.
     *
     * @param sender Отправитель команды.
     * @param args   Аргументы команды.
     */
    private void handleLaunch(CommandSender sender, String[] args) {
        if (!(sender instanceof Player player)) {
            sender.sendMessage(ChatColor.RED + "§cТолько игроки могут запускать ракеты.");
            return;
        }

        if (args.length < 5) {
            player.sendMessage(ChatColor.RED + "§cИспользование: /rocket launch <type> <x> <y> <z> [delay]");
            player.sendMessage(ChatColor.YELLOW + "§eПримечание: delay - опциональный параметр (1-30 секунд)");
            return;
        }

        String typeName = args[1].toUpperCase();
        RocketType type = rocketManager.getRocketType(typeName);

        if (type == null) {
            player.sendMessage(ChatColor.RED + "§cНеверный тип ракеты. Используйте /rocket для просмотра доступных типов.");
            return;
        }

        double x, y, z;
        try {
            x = Double.parseDouble(args[2]);
            y = Double.parseDouble(args[3]);
            z = Double.parseDouble(args[4]);
        } catch (NumberFormatException e) {
            player.sendMessage(ChatColor.RED + "§cКоординаты должны быть действительными числами.");
            return;
        }

        Location target = new Location(player.getWorld(), x, y, z);

        int delay = 0;
        if (args.length >= 6) {
            try {
                delay = Integer.parseInt(args[5]);
                if (delay < 1 || delay > 30) {
                    player.sendMessage(ChatColor.RED + "§cЗадержка должна быть между 1 и 30 секундами.");
                    return;
                }
            } catch (NumberFormatException e) {
                player.sendMessage(ChatColor.RED + "§cЗадержка должна быть целым числом.");
                return;
            }
        }

        rocketManager.launchRocket(player, type, target, delay);
    }

    /**
     * Обработка подкоманды give.
     *
     * @param sender Отправитель команды.
     * @param args   Аргументы команды.
     */
    private void handleGive(CommandSender sender, String[] args) {
        if (!sender.hasPermission("rocketplugin.give")) {
            sender.sendMessage(ChatColor.RED + "§cУ вас нет разрешения выдавать ракеты.");
            return;
        }

        if (args.length < 4) {
            sender.sendMessage(ChatColor.RED + "§cИспользование: /rocket give <player> <type> <amount>");
            return;
        }

        String targetName = args[1];
        Player targetPlayer = Bukkit.getPlayerExact(targetName);
        if (targetPlayer == null) {
            sender.sendMessage(ChatColor.RED + "§cИгрок не найден или не онлайн.");
            return;
        }

        String typeName = args[2].toUpperCase();
        RocketType type = rocketManager.getRocketType(typeName);
        if (type == null) {
            sender.sendMessage(ChatColor.RED + "§cНеверный тип ракеты. Используйте /rocket для просмотра доступных типов.");
            return;
        }

        int amount;
        try {
            amount = Integer.parseInt(args[3]);
            if (amount <= 0) {
                throw new NumberFormatException();
            }
        } catch (NumberFormatException e) {
            sender.sendMessage(ChatColor.RED + "§cКоличество должно быть положительным целым числом.");
            return;
        }

        statsManager.addRockets(targetPlayer, type, amount);
        sender.sendMessage(ChatColor.GREEN + "§aВыдали " + amount + " ракет типа " + type.getName() + " игроку " + targetPlayer.getName() + ".");
        targetPlayer.sendMessage(ChatColor.GREEN + "§aВам выдали " + amount + " ракет типа " + type.getName() + " от " + sender.getName() + ".");
    }

    /**
     * Обработка подкоманды stats.
     *
     * @param sender Отправитель команды.
     * @param args   Аргументы команды.
     */
    private void handleStats(CommandSender sender, String[] args) {
        if (args.length < 2) {
            if (sender instanceof Player player) {
                sender.sendMessage(statsManager.getStats(player));
            } else {
                sender.sendMessage(ChatColor.RED + "§cКонсоль не имеет статистики.");
            }
            return;
        }

        String targetName = args[1];
        Player targetPlayer = Bukkit.getPlayerExact(targetName);
        if (targetPlayer == null) {
            sender.sendMessage(ChatColor.RED + "§cИгрок не найден или не онлайн.");
            return;
        }

        sender.sendMessage(statsManager.getStats(targetPlayer));
    }

    /**
     * Обработка подкоманды reload.
     *
     * @param sender Отправитель команды.
     * @param args   Аргументы команды.
     */
    private void handleReload(CommandSender sender, String[] args) {
        if (!sender.hasPermission("rocketplugin.reload")) {
            sender.sendMessage(ChatColor.RED + "§cУ вас нет разрешения перезагружать конфигурацию.");
            return;
        }

        plugin.reloadConfig();
        rocketManager.loadRocketTypes(); // Перезагружаем типы ракет
        sender.sendMessage(ChatColor.GREEN + "§aКонфигурация плагина успешно перезагружена.");
    }
}
// RocketListener.java
package com.yourname.rocketplugin;

import org.bukkit.ChatColor;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.ExplosionPrimeEvent;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.Location;

import java.util.List;

/**
 * Класс слушателя событий взрыва и ПВО.
 */
public class RocketListener implements Listener {
    private final RocketManager rocketManager;
    private final RocketPlugin plugin;

    /**
     * Конструктор RocketListener.
     *
     * @param rocketManager Менеджер ракет и ПВО.
     * @param plugin        Главный плагин.
     */
    public RocketListener(RocketManager rocketManager, RocketPlugin plugin) {
        this.rocketManager = rocketManager;
        this.plugin = plugin;
    }

    /**
     * Событие перед взрывом.
     *
     * @param event Событие.
     */
    @EventHandler
    public void onExplosionPrime(ExplosionPrimeEvent event) {
        World world = event.getEntity().getWorld();
        if (!world.getName().equalsIgnoreCase("P_Drilla")) {
            event.setCancelled(true);
            if (event.getEntity() instanceof Player player) {
                player.sendMessage(ChatColor.RED + "§cВзрывы вне мира запрещены!");
            }
        }
    }

    /**
     * Событие взрыва сущности.
     *
     * @param event Событие.
     */
    @EventHandler
    public void onEntityExplode(EntityExplodeEvent event) {
        World world = event.getEntity().getWorld();
        if (!world.getName().equalsIgnoreCase("P_Drilla")) {
            event.setCancelled(true);
            return;
        }

        Location explosionLocation = event.getLocation();
        double radius = 10.0; // Радиус воздействия ПВО

        // Получаем ПВО блоки в радиусе взрыва
        List<PVOBlock> nearbyPVO = rocketManager.getPvoManager().getPVOBlocksInRadius(explosionLocation, radius);

        if (!nearbyPVO.isEmpty()) {
            for (PVOBlock block : nearbyPVO) {
                Player owner = plugin.getServer().getPlayer(block.getLocation().getWorld().getName());
                if (owner != null) {
                    List<Player> affectedPlayers = (List<Player>) world.getPlayers();
                    for (Player p : affectedPlayers) {
                        if (!p.equals(owner) && !block.getExcludedPlayers().contains(p.getUniqueId())) {
                            // Не допускаем повреждение игрока, вне исключений
                            event.setCancelled(true);
                            p.sendMessage(ChatColor.RED + "§cВаш ПВО блок предотвратил взрыв!");
                        }
                    }
                }
            }
        }
    }

    /**
     * Событие нанесения урона игроку.
     *
     * @param event Событие.
     */
    @EventHandler
    public void onEntityDamageByEntity(EntityDamageByEntityEvent event) {
        if (!(event.getEntity() instanceof Player damaged)) return;

        Location damageLocation = damaged.getLocation();
        double radius = 10.0; // Радиус действия ПВО

        // Получаем ПВО блоки в радиусе действия от повреждения
        List<PVOBlock> nearbyPVO = rocketManager.getPvoManager().getPVOBlocksInRadius(damageLocation, radius);

        if (!nearbyPVO.isEmpty()) {
            for (PVOBlock block : nearbyPVO) {
                Player owner = plugin.getServer().getPlayer(block.getLocation().getWorld().getName());
                if (owner != null) {
                    if (block.getExcludedPlayers().contains(damaged.getUniqueId())) {
                        // Игрок в списке исключений, защита не применяется
                        continue;
                    }

                    if (!damaged.equals(owner)) {
                        // Отменяем урон, если повреждённый не владелец ПВО
                        event.setCancelled(true);
                        damaged.sendMessage(ChatColor.YELLOW + "§eВаш ПВО блок защитил вас от урона!");
                        break;
                    }
                }
            }
        }
    }
}
// RocketManager.java
package com.yourname.rocketplugin;

import org.bukkit.Particle;
import org.bukkit.Sound;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.World;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.Collection;

/**
 * Класс управления ракетами и ПВО.
 */
public class RocketManager {
    private final RocketPlugin plugin;
    private StatsManager statsManager;
    private PVOManager pvoManager; // Добавляем PVOManager
    private final Random random;
    private final Map<String, RocketType> rocketTypes;

    /**
     * Конструктор RocketManager.
     *
     * @param plugin Главный плагин.
     */
    public RocketManager(RocketPlugin plugin) {
        this.plugin = plugin;
        this.random = new Random();
        this.rocketTypes = new HashMap<>();
        loadRocketTypes();

        // Инициализация PVOManager
        this.pvoManager = new PVOManager(plugin);
    }

    /**
     * Устанавливает ссылку на StatsManager.
     *
     * @param statsManager Экземпляр StatsManager.
     */
    public void setStatsManager(StatsManager statsManager) {
        this.statsManager = statsManager;
        this.pvoManager.setStatsManager(statsManager);
    }

    /**
     * Возвращает экземпляр PVOManager.
     *
     * @return PVOManager.
     */
    public PVOManager getPvoManager() {
        return pvoManager;
    }

    /**
     * Загружает типы ракет из config.yml.
     */
    public void loadRocketTypes() {
        FileConfiguration config = plugin.getConfig();
        ConfigurationSection rocketsSection = config.getConfigurationSection("rockets");
        if (rocketsSection == null) {
            plugin.getLogger().severe("§cРаздел 'rockets' не найден в config.yml! Плагин отключен.");
            plugin.getServer().getPluginManager().disablePlugin(plugin);
            return;
        }

        for (String key : rocketsSection.getKeys(false)) {
            ConfigurationSection rocketSection = rocketsSection.getConfigurationSection(key);
            if (rocketSection == null) continue;

            double power = rocketSection.getDouble("power");
            int range = rocketSection.getInt("range");
            String launchParticleStr = rocketSection.getString("launchParticle", "FLAME");
            String launchSoundStr = rocketSection.getString("launchSound", "ENTITY_FIREWORK_ROCKET_LAUNCH");
            String explosionSoundStr = rocketSection.getString("explosionSound", "ENTITY_FIREWORK_ROCKET_LAUNCH");
            String explosionParticleStr = rocketSection.getString("explosionParticle", "SMOKE_NORMAL");
            int successChance = rocketSection.getInt("successChance", 50);
            boolean optimized = rocketSection.getBoolean("optimized", false);

            Particle launchParticle;
            Sound launchSound;
            Sound explosionSound;
            Particle explosionParticle;

            try {
                launchParticle = Particle.valueOf(launchParticleStr);
            } catch (IllegalArgumentException e) {
                plugin.getLogger().warning("§cНеизвестный тип частицы запуска '" + launchParticleStr + "' для ракеты '" + key + "'. Используется FLAME.");
                launchParticle = Particle.FLAME;
            }

            try {
                launchSound = Sound.valueOf(launchSoundStr);
            } catch (IllegalArgumentException e) {
                plugin.getLogger().warning("§cНеизвестный звук запуска '" + launchSoundStr + "' для ракеты '" + key + "'. Используется ENTITY_FIREWORK_ROCKET_LAUNCH.");
                launchSound = Sound.ENTITY_FIREWORK_ROCKET_LAUNCH;
            }

            try {
                explosionSound = Sound.valueOf(explosionSoundStr);
            } catch (IllegalArgumentException e) {
                plugin.getLogger().warning("§cНеизвестный звук взрыва '" + explosionSoundStr + "' для ракеты '" + key + "'. Используется ENTITY_FIREWORK_ROCKET_LAUNCH.");
                explosionSound = Sound.ENTITY_FIREWORK_ROCKET_LAUNCH;
            }

            try {
                explosionParticle = Particle.valueOf(explosionParticleStr);
            } catch (IllegalArgumentException e) {
                plugin.getLogger().warning("§cНеизвестный тип частицы взрыва '" + explosionParticleStr + "' для ракеты '" + key + "'. Используется SMOKE_NORMAL.");
                explosionParticle = Particle.SMOKE_NORMAL;
            }

            RocketType rocketType = new RocketType(key, power, range, launchParticle, launchSound, explosionSound, explosionParticle, successChance, optimized);
            rocketTypes.put(key.toUpperCase(), rocketType);
        }

        plugin.getLogger().info("§aЗагружено " + rocketTypes.size() + " типов ракет.");
    }

    /**
     * Получает тип ракеты по имени.
     *
     * @param name Имя ракеты.
     * @return RocketType или null, если не найден.
     */
    public RocketType getRocketType(String name) {
        return rocketTypes.get(name.toUpperCase());
    }

    /**
     * Возвращает все загруженные типы ракет.
     *
     * @return Карта типов ракет.
     */
    public Map<String, RocketType> getAllRocketTypes() {
        return rocketTypes;
    }

    /**
     * Запускает ракету.
     *
     * @param player Игрок, запустивший ракету.
     * @param type   Тип ракеты.
     * @param target Целевая локация.
     * @param delay  Задержка запуска в секундах.
     */
    public void launchRocket(final Player player, final RocketType type, final Location target, final int delay) {
        if (!target.getWorld().getName().equalsIgnoreCase("P_Drilla")) {
            player.sendMessage("§cРакеты могут взрываться только в мире P_Drilla.");
            return;
        }

        if (!this.statsManager.hasRockets(player, type)) {
            player.sendMessage("§cУ вас нет ракет типа " + type.getName() + "!");
            return;
        }

        this.statsManager.useRocket(player, type);

        if (delay > 0) {
            player.sendMessage("§eЗапуск ракеты через " + delay + " секунд(ы).");
            new BukkitRunnable() {
                private int secondsLeft = delay;

                @Override
                public void run() {
                    if (secondsLeft <= 0) {
                        this.cancel();
                        boolean success = checkLaunchSuccess(type);
                        if (success) {
                            Rocket rocket = type.isOptimized() ? new OptimizedRocket(player, type, target, plugin) : new Rocket(player, type, target, plugin);
                            rocket.launch();
                            player.sendMessage("§aРакета успешно запущена!");
                        } else {
                            player.sendMessage("§cРакета не смогла достичь цели и не взорвалась.");
                        }
                    } else {
                        player.sendMessage("§eЗапуск ракеты через " + secondsLeft + " секунд(ы).");
                        secondsLeft--;
                    }
                }
            }.runTaskTimer(plugin, 0L, 20L);
        } else {
            boolean success = checkLaunchSuccess(type);
            if (success) {
                Rocket rocket = type.isOptimized() ? new OptimizedRocket(player, type, target, plugin) : new Rocket(player, type, target, plugin);
                rocket.launch();
                player.sendMessage("§aРакета успешно запущена!");
            } else {
                player.sendMessage("§cРакета не смогла достичь цели и не взорвалась.");
            }
        }
    }

    /**
     * Проверяет вероятность успешного запуска ракеты.
     *
     * @param type Тип ракеты.
     * @return true, если ракета успешно запущена.
     */
    private boolean checkLaunchSuccess(RocketType type) {
        int chance = type.getSuccessChance();
        int roll = random.nextInt(100) + 1;
        return roll <= chance;
    }
}
// RocketPlugin.java
package com.yourname.rocketplugin;

import org.bukkit.command.PluginCommand;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;

/**
 * Главный класс плагина RocketPlugin.
 */
public class RocketPlugin extends JavaPlugin {
    private static RocketPlugin instance;
    private RocketManager rocketManager;
    private StatsManager statsManager;
    private PVOManager pvoManager;

    public RocketPlugin() { }

    /**
     * Возвращает экземпляр плагина.
     *
     * @return Экземпляр RocketPlugin.
     */
    public static RocketPlugin getInstance() {
        return instance;
    }

    public RocketManager getRocketManager() {
        return rocketManager;
    }

    public StatsManager getStatsManager() {
        return statsManager;
    }

    public PVOManager getPvoManager() {
        return pvoManager;
    }

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

        // Инициализация RocketManager
        this.rocketManager = new RocketManager(this);
        // Инициализация StatsManager с RocketManager
        this.statsManager = new StatsManager(this, this.rocketManager);
        // Установка StatsManager в RocketManager
        this.rocketManager.setStatsManager(this.statsManager);
        // Получение PVOManager из RocketManager
        this.pvoManager = this.rocketManager.getPvoManager();

        this.statsManager.load();

        PluginCommand rocketCommand = this.getCommand("rocket");
        PluginCommand pvoCommand = this.getCommand("pvo");

        if (rocketCommand != null) {
            rocketCommand.setExecutor(new RocketCommand(this.rocketManager, this.statsManager, this));
            rocketCommand.setTabCompleter(new RocketTabCompleter(this));
        } else {
            this.getLogger().severe("§cНе удалось зарегистрировать команду 'rocket'. Проверьте plugin.yml.");
            this.setEnabled(false);
            return;
        }

        if (pvoCommand != null) {
            pvoCommand.setExecutor(new PVOCommand(this.rocketManager, this));
        } else {
            this.getLogger().severe("§cНе удалось зарегистрировать команду 'pvo'. Проверьте plugin.yml.");
            this.setEnabled(false);
            return;
        }

        PluginManager pm = this.getServer().getPluginManager();
        pm.registerEvents(new RocketListener(this.rocketManager, this), this);
        pm.registerEvents(new PVOListener(this.rocketManager, this), this);

        this.getLogger().info("§aRocketPlugin был включен!");
    }

    @Override
    public void onDisable() {
        if (this.statsManager != null) {
            this.statsManager.save();
        }

        if (this.pvoManager != null) {
            this.pvoManager.savePVOBlocks();
        }

        this.getLogger().info("§cRocketPlugin был отключен!");
    }
}
// RocketTabCompleter.java
package com.yourname.rocketplugin;

import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.bukkit.entity.Player;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Класс для автодополнения команды /rocket.
 */
public class RocketTabCompleter implements TabCompleter {
    private final RocketPlugin plugin;

    /**
     * Конструктор RocketTabCompleter.
     *
     * @param plugin Главный плагин.
     */
    public RocketTabCompleter(RocketPlugin plugin) {
        this.plugin = plugin;
    }

    @Override
    public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
        if (!command.getName().equalsIgnoreCase("rocket")) {
            return null;
        }

        List<String> completions = new ArrayList<>();

        if (args.length == 1) {
            List<String> subcommands = List.of("launch", "give", "stats", "reload");
            for (String sub : subcommands) {
                if (sub.startsWith(args[0].toLowerCase())) {
                    completions.add(sub);
                }
            }
            return completions;
        }

        if (args.length == 2) {
            String subcommand = args[0].toLowerCase();
            RocketManager rocketManager = plugin.getRocketManager();
            if (subcommand.equals("launch") || subcommand.equals("give")) {
                Map<String, RocketType> types = rocketManager.getAllRocketTypes();
                for (RocketType type : types.values()) {
                    if (type.getName().toLowerCase().startsWith(args[1].toLowerCase())) {
                        completions.add(type.getName());
                    }
                }
            } else if (subcommand.equals("stats")) {
                for (Player player : Bukkit.getOnlinePlayers()) {
                    if (player.getName().toLowerCase().startsWith(args[1].toLowerCase())) {
                        completions.add(player.getName());
                    }
                }
            } else if (subcommand.equals("reload")) {
                // Нет дополнительных аргументов
            }
            return completions;
        }

        if (args.length == 3 && args[0].equalsIgnoreCase("give")) {
            RocketManager rocketManager = plugin.getRocketManager();
            String typeQuery = args[2].toUpperCase();
            Map<String, RocketType> types = rocketManager.getAllRocketTypes();
            for (RocketType type : types.values()) {
                if (type.getName().toLowerCase().startsWith(typeQuery.toLowerCase())) {
                    completions.add(type.getName());
                }
            }
            return completions;
        }

        if (args.length == 4 && args[0].equalsIgnoreCase("give")) {
            for (int i = 1; i <= 64; i++) { // Максимум 64 ракеты за раз
                String amount = String.valueOf(i);
                if (amount.startsWith(args[3])) {
                    completions.add(amount);
                }
            }
            return completions;
        }

        if (args.length == 2 && args[0].equalsIgnoreCase("reload")) {
            // Нет дополнительных аргументов
        }

        return completions;
    }
}
// RocketType.java
package com.yourname.rocketplugin;

import org.bukkit.Particle;
import org.bukkit.Sound;

/**
 * Класс, представляющий тип ракеты.
 */
public class RocketType {
    private final String name;
    private final double power;
    private final int range;
    private final Particle launchParticle;
    private final Sound launchSound;
    private final Sound explosionSound;
    private final Particle explosionParticle;
    private final int successChance;
    private final boolean optimized;

    /**
     * Конструктор типа ракеты.
     *
     * @param name              Имя ракеты.
     * @param power             Сила взрыва.
     * @param range             Дальность полета.
     * @param launchParticle    Частица при запуске.
     * @param launchSound       Звук при запуске.
     * @param explosionSound    Звук взрыва.
     * @param explosionParticle Частица при взрыве.
     * @param successChance     Шанс успешного запуска.
     * @param optimized         Флаг оптимизированного взрыва.
     */
    public RocketType(String name, double power, int range, Particle launchParticle,
                      Sound launchSound, Sound explosionSound, Particle explosionParticle, int successChance, boolean optimized) {
        this.name = name;
        this.power = power;
        this.range = range;
        this.launchParticle = launchParticle;
        this.launchSound = launchSound;
        this.explosionSound = explosionSound;
        this.explosionParticle = explosionParticle;
        this.successChance = successChance;
        this.optimized = optimized;
    }

    public String getName() { return name; }

    public double getPower() { return power; }

    public int getRange() { return range; }

    public Particle getLaunchParticle() { return launchParticle; }

    public Sound getLaunchSound() { return launchSound; }

    public Sound getExplosionSound() { return explosionSound; }

    public Particle getExplosionParticle() { return explosionParticle; }

    public int getSuccessChance() { return successChance; }

    public boolean isOptimized() { return optimized; }
}
// StatsManager.java
package com.yourname.rocketplugin;

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

import java.io.File;
import java.io.IOException;
import java.util.Map;

/**
 * Класс для управления статистикой игроков по ракетам.
 */
public class StatsManager {
    private final RocketPlugin plugin;
    private final File statsFile;
    private FileConfiguration statsConfig;
    private final RocketManager rocketManager;

    /**
     * Конструктор StatsManager.
     *
     * @param plugin        Главный плагин.
     * @param rocketManager Менеджер ракет.
     */
    public StatsManager(RocketPlugin plugin, RocketManager rocketManager) {
        this.plugin = plugin;
        this.rocketManager = rocketManager;
        this.statsFile = new File(plugin.getDataFolder(), "stats.yml");
        if (!this.statsFile.exists()) {
            try {
                if (plugin.getResource("stats.yml") != null) {
                    plugin.saveResource("stats.yml", false);
                } else {
                    this.statsConfig = new YamlConfiguration();
                    this.statsConfig.save(this.statsFile);
                }
            } catch (IOException e) {
                plugin.getLogger().severe("§cНе удалось создать stats.yml:");
                e.printStackTrace();
            }
        }

        this.statsConfig = YamlConfiguration.loadConfiguration(this.statsFile);
    }

    /**
     * Загружает статистику из файла.
     */
    public void load() {
        try {
            this.statsConfig.load(this.statsFile);
        } catch (Exception e) {
            this.plugin.getLogger().severe("§cНе удалось загрузить stats.yml:");
            e.printStackTrace();
        }
    }

    /**
     * Сохраняет статистику в файл.
     */
    public void save() {
        try {
            this.statsConfig.save(this.statsFile);
        } catch (IOException e) {
            this.plugin.getLogger().severe("§cНе удалось сохранить stats.yml:");
            e.printStackTrace();
        }
    }

    /**
     * Получает количество ракет определенного типа у игрока.
     *
     * @param player Игрок.
     * @param type   Тип ракеты.
     * @return Количество ракет.
     */
    public int getRockets(Player player, RocketType type) {
        String path = player.getUniqueId().toString() + ".rockets." + type.getName();
        return statsConfig.getInt(path, 0);
    }

    /**
     * Добавляет ракеты игроку.
     *
     * @param player Игрок.
     * @param type   Тип ракеты.
     * @param amount Количество.
     */
    public void addRockets(Player player, RocketType type, int amount) {
        String path = player.getUniqueId().toString() + ".rockets." + type.getName();
        int current = getRockets(player, type);
        statsConfig.set(path, current + amount);
        save();
    }

    /**
     * Проверяет, есть ли у игрока ракеты определенного типа.
     *
     * @param player Игрок.
     * @param type   Тип ракеты.
     * @return true, если есть.
     */
    public boolean hasRockets(Player player, RocketType type) {
        return getRockets(player, type) > 0;
    }

    /**
     * Использует одну ракету определенного типа у игрока.
     *
     * @param player Игрок.
     * @param type   Тип ракеты.
     */
    public void useRocket(Player player, RocketType type) {
        String path = player.getUniqueId().toString() + ".rockets." + type.getName();
        int current = getRockets(player, type);
        if (current > 0) {
            this.statsConfig.set(path, current - 1);
            save();
        }
    }

    /**
     * Получает статистику по ракетам игрока.
     *
     * @param player Игрок.
     * @return Строка с статистикой.
     */
    public String getStats(Player player) {
        StringBuilder sb = new StringBuilder("§a§lСтатистика Ракет для " + player.getName() + ":\n");
        Map<String, RocketType> allTypes = rocketManager.getAllRocketTypes();

        for (RocketType type : allTypes.values()) {
            sb.append("§e").append(type.getName()).append(": §b").append(getRockets(player, type)).append("\n");
        }

        return sb.toString();
    }
}
rockets:
  SMALL:
    power: 10.0
    range: 100
    launchParticle: FLAME
    launchSound: ENTITY_FIREWORK_ROCKET_LAUNCH
    explosionSound: ENTITY_FIREWORK_ROCKET_LAUNCH
    explosionParticle: SMOKE_NORMAL
    successChance: 50
    optimized: false
  MEDIUM:
    power: 15.0
    range: 150
    launchParticle: FLAME
    launchSound: ENTITY_FIREWORK_ROCKET_LAUNCH
    explosionSound: ENTITY_FIREWORK_ROCKET_LAUNCH
    explosionParticle: SMOKE_NORMAL
    successChance: 50
    optimized: false
  LARGE:
    power: 20.0
    range: 200
    launchParticle: EXPLOSION_NORMAL
    launchSound: ENTITY_FIREWORK_ROCKET_LAUNCH
    explosionSound: ENTITY_FIREWORK_ROCKET_LAUNCH
    explosionParticle: SMOKE_LARGE
    successChance: 50
    optimized: false
  EXTRA_LARGE:
    power: 25.0
    range: 300
    launchParticle: EXPLOSION_LARGE
    launchSound: ENTITY_FIREWORK_ROCKET_LAUNCH
    explosionSound: ENTITY_FIREWORK_ROCKET_LAUNCH
    explosionParticle: EXPLOSION_HUGE
    successChance: 50
    optimized: false
  NUCLEAR:
    power: 70.0
    range: 500
    launchParticle: EXPLOSION_HUGE
    launchSound: ENTITY_GENERIC_EXPLODE
    explosionSound: ENTITY_GENERIC_EXPLODE
    explosionParticle: EXPLOSION_HUGE
    successChance: 40
    optimized: false
  SUPER_NUCLEAR:
    power: 100.0
    range: 700
    launchParticle: EXPLOSION_HUGE
    launchSound: ENTITY_GENERIC_EXPLODE
    explosionSound: ENTITY_GENERIC_EXPLODE
    explosionParticle: EXPLOSION_HUGE
    successChance: 30
    optimized: false
  MEGA_NUCLEAR:
    power: 150.0
    range: 1000
    launchParticle: EXPLOSION_HUGE
    launchSound: ENTITY_GENERIC_EXPLODE
    explosionSound: ENTITY_GENERIC_EXPLODE
    explosionParticle: EXPLOSION_HUGE
    successChance: 20
    optimized: false
  EXTREME_NUCLEAR:
    power: 250.0
    range: 1500
    launchParticle: SUSPENDED
    launchSound: ENTITY_GENERIC_EXPLODE
    explosionSound: ENTITY_GENERIC_EXPLODE
    explosionParticle: EXPLOSION_HUGE
    successChance: 15
    optimized: true
  ULTRA_NUCLEAR:
    power: 400.0
    range: 2000
    launchParticle: SPELL_INSTANT
    launchSound: ENTITY_GENERIC_EXPLODE
    explosionSound: ENTITY_GENERIC_EXPLODE
    explosionParticle: EXPLOSION_HUGE
    successChance: 10
    optimized: true
  USSR:
    power: 500.0
    range: 2500
    launchParticle: PORTAL
    launchSound: ENTITY_GENERIC_EXPLODE
    explosionSound: ENTITY_GENERIC_EXPLODE
    explosionParticle: EXPLOSION_HUGE
    successChance: 100
    optimized: false
1) Сделай, чтобы ракеты USSR могла взорвать 521x512 блоков, в виде сферы, и там всё в огне. Главное - чтобы сервер выдержал. 2) Доделай механику пво, создай 5 разных пво, а также команду для выдачи пво 3) Исправь я хочу прикрепить к этому плагину playervaribles 3.2.7, чтобы за деньги можно было покупать ракеты 4)Чтобы был рынок ракет 5)Чтобы была механика производства ракет
Напиши полный код, на русском