1) Я скину сначала тебе реализацию суперновы, затем мой плагин, тебе надо, чтобы взрыв + анимация были в моём плагине, а также настройки под неё, чтобы я мог настраивать
2) Я скину ошибки, тебе надо исправить
3) Ты сразу напиши полный код, на русском
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.github.jewishbanana.deadlydisasters.events.disasters;

import com.github.jewishbanana.deadlydisasters.events.DestructionDisaster;
import com.github.jewishbanana.deadlydisasters.events.DestructionDisasterEvent;
import com.github.jewishbanana.deadlydisasters.events.Disaster;
import com.github.jewishbanana.deadlydisasters.listeners.DeathMessages;
import com.github.jewishbanana.deadlydisasters.utils.Metrics;
import com.github.jewishbanana.deadlydisasters.utils.RepeatingTask;
import com.github.jewishbanana.deadlydisasters.utils.Utils;
import com.github.jewishbanana.deadlydisasters.utils.VersionUtils;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Random;
import java.util.Set;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Particle;
import org.bukkit.Sound;
import org.bukkit.World;
import org.bukkit.World.Environment;
import org.bukkit.block.Block;
import org.bukkit.entity.EnderCrystal;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.util.BlockVector;
import org.bukkit.util.Vector;

public class Supernova extends DestructionDisaster {
    private double size;
    private double sizeMultiplier;
    private double particleMultiplier;
    private double fallSpeedMultiplier;
    private int tick = 1;
    private EnderCrystal crystal;
    private Particle particle;
    private Material[] materials;
    private boolean flash;
    private boolean farParticles;
    private int blocksDestroyed;

    public Supernova(int level, World world) {
        super(level, world);
        switch (level) {
            case 1:
            default:
                this.size = 35.0;
                break;
            case 2:
                this.size = 45.0;
                break;
            case 3:
                this.size = 57.0;
                break;
            case 4:
                this.size = 70.0;
                break;
            case 5:
                this.size = 85.0;
                break;
            case 6:
                this.size = 100.0;
        }

        this.volume = this.configFile.getDouble("supernova.volume");
        this.particleMultiplier = this.configFile.getDouble("supernova.particle_multiplier");
        this.flash = this.configFile.getBoolean("supernova.flash");
        this.sizeMultiplier = this.configFile.getDouble("supernova.size");
        this.particle = VersionUtils.getLargeExplosion();
        this.materials = new Material[]{Material.OBSIDIAN, Material.BLACK_CONCRETE, Material.FIRE};
        if (!this.configFile.getBoolean("supernova.place_fire")) {
            this.materials = new Material[]{Material.OBSIDIAN, Material.BLACK_CONCRETE};
        }

        this.farParticles = this.configFile.getBoolean("supernova.far_particles");
        this.fallSpeedMultiplier = this.configFile.getDouble("supernova.fall_speed_multiplier");
        this.type = Disaster.SUPERNOVA;
    }

    public void start(final Location loc, Player p) {
        DestructionDisasterEvent event = new DestructionDisasterEvent(this, loc, this.level, p);
        Bukkit.getPluginManager().callEvent(event);
        if (!event.isCancelled()) {
            this.loc = loc;
            ongoingDisasters.add(this);
            DeathMessages.supernovas.add(this);
            this.size *= this.sizeMultiplier;
            final World world = loc.getWorld();
            final Location top = loc.clone();
            top.setY(320.0);
            final Location crystalLoc = top.clone();
            this.crystal = (EnderCrystal)world.spawn(crystalLoc, EnderCrystal.class);
            this.crystal.setShowingBottom(false);
            this.crystal.setBeamTarget(top);
            final Vector vec = new Vector(0.0, -2.0 * this.fallSpeedMultiplier, 0.0);
            RepeatingTask var10000 = new RepeatingTask(this.plugin, 0, 1) {
                public void run() {
                    crystalLoc.add(vec);
                    if (vec.getY() < -0.5) {
                        vec.setY(vec.getY() + 0.01);
                    }

                    Supernova.this.crystal.remove();
                    Supernova.this.crystal = (EnderCrystal)world.spawn(crystalLoc, EnderCrystal.class);
                    Supernova.this.crystal.setShowingBottom(false);
                    Supernova.this.crystal.setBeamTarget(top);
                    world.spawnParticle(Particle.CLOUD, crystalLoc, 10, 0.5, 0.5, 0.5, 0.01, (Object)null, true);
                    world.spawnParticle(Particle.FLAME, crystalLoc, 10, 0.5, 0.5, 0.5, 0.01, (Object)null, true);
                    Block b = crystalLoc.clone().subtract(0.0, 1.0, 0.0).getBlock();
                    if (b.getType() != Material.AIR && !Utils.isBlockImmune(b.getType()) && !Utils.isZoneProtected(b.getLocation())) {
                        if (Supernova.this.plugin.CProtect) {
                            Utils.getCoreProtect().logRemoval("Deadly-Disasters", b.getLocation(), b.getType(), b.getBlockData());
                        }

                        b.setType(Material.AIR);
                        ++Supernova.this.blocksDestroyed;
                    }

                    if (crystalLoc.distance(loc) < 3.0) {
                        Supernova.this.crystal.remove();
                        this.cancel();
                        Supernova.this.explode(world);
                    }

                    if (Supernova.this.flash) {
                        Iterator var3 = world.getNearbyEntities(loc, 140.0, 100.0, 140.0).iterator();

                        while(var3.hasNext()) {
                            Entity e = (Entity)var3.next();
                            if (e instanceof Player) {
                                Location temp = e.getLocation();
                                ((Player)e).spawnParticle(Particle.FLASH, temp.clone().add((new Vector(temp.getX() - crystalLoc.getX(), temp.getY() - crystalLoc.getY(), temp.getZ() - crystalLoc.getZ())).normalize().multiply(-3)), 1, 1.0, 1.0, 1.0, 0.001);
                            }
                        }
                    }

                }
            };
            var10000 = new RepeatingTask(this.plugin, 0, 10) {
                public void run() {
                    if (Supernova.this.tick > 1) {
                        this.cancel();
                    }

                    if (Supernova.this.plugin.mcVersion >= 1.16) {
                        Iterator var2 = world.getNearbyEntities(loc, 140.0, 140.0, 140.0).iterator();

                        while(var2.hasNext()) {
                            Entity e = (Entity)var2.next();
                            if (e instanceof Player) {
                                Location temp = e.getLocation();
                                ((Player)e).playSound(temp.clone().add((new Vector(temp.getX() - crystalLoc.getX(), temp.getY() - crystalLoc.getY(), temp.getZ() - crystalLoc.getZ())).normalize().multiply(-4)), Sound.AMBIENT_NETHER_WASTES_MOOD, (float)((2.0 - 0.002 * crystalLoc.distance(e.getLocation())) * Supernova.this.volume), 0.5F);
                            }
                        }
                    }

                }
            };
        }
    }

    private void explode(final World world) {
        final BlockVector block = new BlockVector(this.loc.getX(), this.loc.getY(), this.loc.getZ());
        final Random rand = new Random();
        final boolean CP = this.plugin.CProtect;
        final Supernova instance = this;
        RepeatingTask var10000 = new RepeatingTask(this.plugin, 0, 1) {
            public void run() {
                if ((double)Supernova.this.tick > Supernova.this.size) {
                    this.cancel();
                    Supernova.ongoingDisasters.remove(instance);
                    DeathMessages.supernovas.remove(instance);
                    Metrics.incrementValue(Metrics.disasterDestroyedMap, Supernova.this.type.getMetricsLabel(), Supernova.this.blocksDestroyed);
                } else {
                    final Set<Block> blocks = new LinkedHashSet(Supernova.this.tick * Supernova.this.tick * Supernova.this.tick);

                    for(int x = -Supernova.this.tick; x < Supernova.this.tick; ++x) {
                        for(int y = -Supernova.this.tick; y < Supernova.this.tick; ++y) {
                            for(int z = -Supernova.this.tick; z < Supernova.this.tick; ++z) {
                                Vector position = block.clone().add(new Vector(x, y, z));
                                if (block.distance(position) >= (double)(Supernova.this.tick - 1) && block.distance(position) <= (double)Supernova.this.tick) {
                                    Block b = world.getBlockAt(position.toLocation(world));
                                    blocks.add(b);
                                    if (b.getType() != Material.AIR && !Utils.isBlockImmune(b.getType()) && !Utils.isZoneProtected(b.getLocation())) {
                                        if (CP) {
                                            Utils.getCoreProtect().logRemoval("Deadly-Disasters", b.getLocation(), b.getType(), b.getBlockData());
                                        }

                                        if ((double)Supernova.this.tick > Supernova.this.size - 2.0 && rand.nextInt(8) == 0) {
                                            Material mat = Supernova.this.materials[rand.nextInt(Supernova.this.materials.length)];
                                            if (CP) {
                                                Utils.getCoreProtect().logPlacement("Deadly-Disasters", b.getLocation(), mat, mat.createBlockData());
                                            }

                                            b.setType(mat);
                                            ++Supernova.this.blocksDestroyed;
                                        } else {
                                            b.setType(Material.AIR);
                                            ++Supernova.this.blocksDestroyed;
                                        }
                                    }
                                }
                            }
                        }
                    }

                    ++Supernova.this.tick;
                    Supernova.this.plugin.getServer().getScheduler().runTaskAsynchronously(Supernova.this.plugin, new Runnable() {
                        public void run() {
                            int chance = (int)Math.ceil((double)(1 + blocks.size() / 1000) * Supernova.this.particleMultiplier);
                            Iterator var3 = blocks.iterator();

                            while(var3.hasNext()) {
                                Block b = (Block)var3.next();
                                if (rand.nextInt(chance) == 0) {
                                    world.spawnParticle(Supernova.this.particle, b.getLocation(), 1, 0.0, 0.0, 0.0, 1.0, (Object)null, Supernova.this.farParticles);
                                }
                            }

                        }
                    });
                }
            }
        };
        var10000 = new RepeatingTask(this.plugin, 0, 10) {
            public void run() {
                if ((double)Supernova.this.tick > Supernova.this.size) {
                    this.cancel();
                } else {
                    Iterator var2 = world.getNearbyEntities(Supernova.this.loc, (double)(Supernova.this.tick + 100), (double)(Supernova.this.tick + 100), (double)(Supernova.this.tick + 100)).iterator();

                    while(true) {
                        Entity e;
                        do {
                            do {
                                do {
                                    while(true) {
                                        do {
                                            do {
                                                if (!var2.hasNext()) {
                                                    return;
                                                }

                                                e = (Entity)var2.next();
                                            } while(!(e instanceof LivingEntity));
                                        } while(e.isDead());

                                        if (Supernova.this.loc.distance(e.getLocation()) < (double)Supernova.this.tick) {
                                            break;
                                        }

                                        if (e instanceof Player) {
                                            Location temp = e.getLocation().clone().add((new Vector(e.getLocation().getX() - Supernova.this.loc.getX(), e.getLocation().getY() - Supernova.this.loc.getY(), e.getLocation().getZ() - Supernova.this.loc.getZ())).normalize().multiply(-4));
                                            float vol = (float)((2.0 - (5.0E-4 * Supernova.this.loc.distance(e.getLocation()) - (double)Supernova.this.tick)) * Supernova.this.volume);
                                            if (Supernova.this.plugin.mcVersion >= 1.16) {
                                                ((Player)e).playSound(temp, Sound.AMBIENT_WARPED_FOREST_MOOD, vol, 0.5F);
                                            }

                                            ((Player)e).playSound(temp, Sound.ENTITY_LIGHTNING_BOLT_THUNDER, vol, 0.5F);
                                            ((Player)e).playSound(temp, Sound.ENTITY_DRAGON_FIREBALL_EXPLODE, vol / 30.0F, 0.5F);
                                        }
                                    }
                                } while(Supernova.this.isEntityTypeProtected(e));
                            } while(Utils.isZoneProtected(e.getLocation()));
                        } while(e instanceof Player && Utils.isPlayerImmune((Player)e));

                        Utils.pureDamageEntity((LivingEntity)e, 20.0, "dd-supernova", true, DamageCause.BLOCK_EXPLOSION);
                    }
                }
            }
        };
    }

    public void removeCrystal() {
        if (this.crystal != null) {
            this.crystal.remove();
        }

    }

    public Location findApplicableLocation(Location temp, Player p) {
        temp = Utils.getBlockBelow(temp).getLocation();
        return temp.getBlockY() >= this.type.getMinHeight() && temp.getWorld().getEnvironment() != Environment.NETHER ? temp : null;
    }

    public void startAdjustment(Location loc, Player p) {
        this.start(Utils.getBlockBelow(loc).getLocation(), p);
    }

    public double getSizeMultiplier() {
        return this.sizeMultiplier;
    }

    public void setSizeMultiplier(double sizeMultiplier) {
        this.sizeMultiplier = sizeMultiplier;
    }

    public Particle getParticle() {
        return this.particle;
    }

    public void setParticle(Particle particle) {
        this.particle = particle;
    }

    public Material[] getMaterials() {
        return this.materials;
    }

    public void setMaterials(Material[] materials) {
        this.materials = materials;
    }

    public boolean isFlash() {
        return this.flash;
    }

    public void setFlash(boolean flash) {
        this.flash = flash;
    }

    public double getParticles() {
        return this.particleMultiplier;
    }

    public void setParticles(double particles) {
        this.particleMultiplier = particles;
    }
}


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

import com.github.jewishbanana.deadlydisasters.utils.Utils;
import org.bukkit.*;
import org.bukkit.Location;
import org.bukkit.Particle;
import org.bukkit.Sound;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.EnderCrystal;
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.getEyeLocation().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;
        }

        // Создание анимации взрыва, подобной супернове
        Location explosionLocation = this.target.clone();
        double explosionSize = this.type.getPower(); // Используем power как размер взрыва

        // Создаём EnderCrystal для анимации падения (имитация суперновы)
        EnderCrystal crystal = (EnderCrystal) world.spawn(explosionLocation, EnderCrystal.class);
        crystal.setShowBottom(false);
        crystal.setBeamTarget(explosionLocation.clone().add(0, 50, 0)); // Направляем луч вверх

        Vector fallVector = new Vector(0.0, -2.0, 0.0); // Скорость падения
        final double fallSpeedDecrease = 0.05; // Замедление падения

        new BukkitRunnable() {
            Location crystalLoc = explosionLocation.clone();

            @Override
            public void run() {
                // Обновление позиции кристалла
                crystalLoc.add(fallVector);
                if (fallVector.getY() < -0.5) {
                    fallVector.setY(fallVector.getY() + fallSpeedDecrease);
                }

                // Переспавн кристалла
                crystal.remove();
                crystal.setBeamTarget(explosionLocation.clone().add(0, 50, 0));
                crystal = (EnderCrystal) world.spawn(crystalLoc, EnderCrystal.class);
                crystal.setShowBottom(false);

                // Спавн частиц для анимации
                world.spawnParticle(Particle.CLOUD, crystalLoc, 10, 0.5, 0.5, 0.5, 0.01);
                world.spawnParticle(Particle.FLAME, crystalLoc, 10, 0.5, 0.5, 0.5, 0.01);

                // Разрушение блока под кристаллом
                Block blockBelow = crystalLoc.clone().subtract(0, 1, 0).getBlock();
                if (blockBelow.getType() != Material.AIR && !Utils.isBlockImmune(blockBelow.getType()) && !Utils.isZoneProtected(blockBelow.getLocation())) {
                    blockBelow.setType(Material.AIR);
                }

                // Проверка близости к исходной локации для взрыва
                if (crystalLoc.distance(explosionLocation) < 3.0) {
                    crystal.remove();
                    this.cancel();
                    performExplosion(world, explosionLocation, explosionSize);
                }
            }
        }.runTaskTimer(this.plugin, 0L, 1L);
    }

    /**
     * Выполняет сам взрыв ракеты с анимацией.
     *
     * @param world            Мир, в котором происходит взрыв.
     * @param explosionLocation Локация взрыва.
     * @param size             Размер взрыва.
     */
    private void performExplosion(World world, Location explosionLocation, double size) {
        // Визуальные эффекты взрыва
        world.spawnParticle(this.type.getExplosionParticle(), explosionLocation, 200, size, size, size, 0.1);
        world.playSound(explosionLocation, this.type.getExplosionSound(), 2.0F, 1.0F);

        // Создание анимации расширяющегося взрыва
        new BukkitRunnable() {
            private double currentRadius = 0.0;
            private final double maxRadius = size;
            private final double step = 2.0;

            @Override
            public void run() {
                if (currentRadius > maxRadius) {
                    this.cancel();
                    return;
                }

                // Спавн частиц по кругу взрыва
                for (double angle = 0; angle < 360; angle += 10) {
                    double rad = Math.toRadians(angle);
                    double x = explosionLocation.getX() + currentRadius * Math.cos(rad);
                    double z = explosionLocation.getZ() + currentRadius * Math.sin(rad);
                    Location particleLoc = new Location(world, x, explosionLocation.getY(), z);
                    world.spawnParticle(Particle.EXPLOSION_NORMAL, particleLoc, 1);
                }

                currentRadius += step;
            }
        }.runTaskTimer(this.plugin, 0L, 2L); // Выполняется каждые 2 тика
    }
}
(Cannot resolve method 'setShowBottom' in 'EnderCrystal'
Variable 'crystal' is accessed from within inner class, needs to be final or effectively final
Variable 'crystal' is accessed from within inner class, needs to be final or effectively final
Variable 'crystal' is accessed from within inner class, needs to be final or effectively final
Variable 'crystal' is accessed from within inner class, needs to be final or effectively final
Variable 'crystal' is accessed from within inner class, needs to be final or effectively final)
// RocketCommand.java
package com.yourname.rocketplugin;

import org.bukkit.Bukkit;
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.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.inventory.ItemStack;

/**
 * Класс обработки команды /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|craft> [параметры]");
            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;
            case "craft":
                handleCraft(sender, args);
                break;
            default:
                sender.sendMessage(ChatColor.RED + "§cНеизвестная подкоманда. Использование: /rocket <launch|give|stats|reload|craft> [параметры]");
        }

        return true;
    }

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

        Player player = (Player) sender;

        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Конфигурация плагина успешно перезагружена.");
    }

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

        Player player = (Player) sender;

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

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

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

        // Получаем рецепт из конфигурации
        FileConfiguration config = plugin.getConfig();
        ConfigurationSection recipeSection = config.getConfigurationSection("craftingRecipes." + type.getName() + ".ingredients");
        if (recipeSection == null) {
            player.sendMessage(ChatColor.RED + "§cРецепт для этой ракеты не найден.");
            return;
        }

        // Проверяем наличие ингредиентов
        boolean hasAll = true;
        for (String materialStr : recipeSection.getKeys(false)) {
            Material material;
            try {
                material = Material.valueOf(materialStr);
            } catch (IllegalArgumentException e) {
                player.sendMessage(ChatColor.RED + "§cНеверный материал в рецепте: " + materialStr);
                hasAll = false;
                break;
            }
            int required = recipeSection.getInt(materialStr);
            int available = player.getInventory().all(material).values().stream().mapToInt(ItemStack::getAmount).sum();
            if (available < required) {
                player.sendMessage(ChatColor.RED + "§cУ вас недостаточно " + material.name() + " для производства ракеты.");
                hasAll = false;
                break;
            }
        }

        if (!hasAll) return;

        // Списываем ингредиенты
        for (String materialStr : recipeSection.getKeys(false)) {
            Material material = Material.valueOf(materialStr);
            int required = recipeSection.getInt(materialStr);
            int removed = 0;
            for (ItemStack item : player.getInventory().all(material).values()) {
                if (removed >= required) break;
                int toRemove = Math.min(item.getAmount(), required - removed);
                ItemStack toBeRemoved = new ItemStack(material, toRemove);
                player.getInventory().removeItem(toBeRemoved);
                removed += toRemove;
            }
        }

        // Добавляем ракету в инвентарь (увеличиваем статистику)
        statsManager.addRockets(player, type, 1);
        player.sendMessage(ChatColor.GREEN + "§aВы успешно произвели ракету типа " + type.getName() + ".");
    }
}
// RocketCraftListener.java
package com.yourname.rocketplugin;

import org.bukkit.event.Listener;
import org.bukkit.event.EventHandler;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.inventory.Inventory;

/**
 * Класс слушателя для RocketCraft (может быть расширен в будущем).
 */
public class RocketCraftListener implements Listener {
    private final RocketPlugin plugin;

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

    /**
     * Обработчик закрытия инвентаря.
     *
     * @param event Событие закрытия инвентаря.
     */
    @EventHandler
    public void onInventoryClose(InventoryCloseEvent event) {
        Inventory closed = event.getInventory();
        // Метод getTitle() больше не поддерживается. Нужно использовать getView().getTitle()
        if (event.getView().getTitle().equals("§6§lРынок Ракет")) {
            // Можно добавить дополнительные действия при закрытии рынка, если необходимо
        }
    }
}
// RocketListener.java
package com.yourname.rocketplugin;

import org.bukkit.Bukkit;
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.EntityExplodeEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.Location;

import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * Класс слушателя событий взрыва и ПВО.
 */
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 onEntityExplode(EntityExplodeEvent event) {
        World world = event.getEntity().getWorld();
        if (!world.getName().equalsIgnoreCase("P_Drilla")) {
            event.setCancelled(true);
            return;
        }

        // Здесь вы можете добавить дополнительные проверки или модификации взрыва
    }

    /**
     * Событие повреждения сущности ракетой (опционально).
     *
     * @param event Событие.
     */
    @EventHandler
    public void onEntityDamageByEntity(EntityDamageByEntityEvent event) {
        // Реализуйте, если необходимо обрабатывать повреждения от ракет
    }
}
// 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;

/**
 * Класс управления ракетами и ПВО.
 */
public class RocketManager {
    private final RocketPlugin plugin;
    private StatsManager statsManager;
    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();
    }

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

    /**
     * Загружает типы ракет из 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 = 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 = 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;

    public RocketPlugin() { }

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

    public RocketManager getRocketManager() {
        return rocketManager;
    }

    public StatsManager getStatsManager() {
        return statsManager;
    }

    @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);
        // Загрузка статистики
        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;
        }

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

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

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

        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", "craft");
            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") || subcommand.equals("craft")) {
                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;
        }

        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 {
                plugin.saveResource("stats.yml", false);
            } catch (IllegalArgumentException e) {
                // Файл stats.yml не найден в ресурсах, создаём пустой
                this.statsConfig = new YamlConfiguration();
                try {
                    this.statsConfig.save(this.statsFile);
                } catch (IOException ex) {
                    plugin.getLogger().severe("§cНе удалось создать stats.yml:");
                    ex.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
  # Удалены разделы для USSRRocket и OptimizedRocket

craftingRecipes:
  SMALL:
    ingredients:
      DIAMOND: 2
      FIREWORK_ROCKET: 1
  MEDIUM:
    ingredients:
      DIAMOND: 3
      FIREWORK_ROCKET: 2
  LARGE:
    ingredients:
      DIAMOND: 4
      FIREWORK_ROCKET: 3
  EXTRA_LARGE:
    ingredients:
      DIAMOND: 5
      FIREWORK_ROCKET: 4
  NUCLEAR:
    ingredients:
      DIAMOND: 6
      FIREWORK_ROCKET: 5
  SUPER_NUCLEAR:
    ingredients:
      DIAMOND: 7
      FIREWORK_ROCKET: 6
  MEGA_NUCLEAR:
    ingredients:
      DIAMOND: 8
      FIREWORK_ROCKET: 7
  EXTREME_NUCLEAR:
    ingredients:
      DIAMOND: 10
      FIREWORK_ROCKET: 8
  ULTRA_NUCLEAR:
    ingredients:
      DIAMOND: 12
      FIREWORK_ROCKET: 10
  # USSR уже удалён