package com.yourname.rocketplugin;

import java.util.Collection;
import java.util.Iterator;
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;

public class Rocket {
    private final Player launcher;
    private final RocketType type;
    private final Location target;
    private final RocketPlugin plugin;
    private Location currentLocation;
    private double speed = 1.0;

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

    private void explode() {
        final World world = this.target.getWorld();
        if (world == null) {
            this.launcher.sendMessage("§cОшибка: Целевая локация не найдена.");
        } else {
            world.createExplosion(this.target, this.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 (this.type == RocketType.SUPER_NUCLEAR || this.type == RocketType.MEGA_NUCLEAR
                    || this.type == RocketType.EXTREME_NUCLEAR || this.type == RocketType.ULTRA_NUCLEAR
                    || this.type == RocketType.USSR) { // Добавлен новый тип
                double effectRadius = 20.0;
                Collection<Entity> entities = world.getNearbyEntities(this.target, effectRadius, effectRadius, effectRadius);
                Iterator<Entity> var5 = entities.iterator();

                while(var5.hasNext()) {
                    Entity entity = var5.next();
                    if (entity instanceof Player) {
                        Player player = (Player)entity;
                        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;

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

        }
    }
}
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;

public class RocketCommand implements CommandExecutor {
    private final RocketManager rocketManager;
    private final StatsManager statsManager;
    private final RocketPlugin plugin;

    public RocketCommand(RocketManager rocketManager, StatsManager statsManager, RocketPlugin plugin) {
        this.rocketManager = rocketManager;
        this.statsManager = statsManager;
        this.plugin = plugin;
    }

    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
        if (!sender.hasPermission("rocketplugin.use")) {
            sender.sendMessage(ChatColor.RED + "§cУ вас нет разрешения использовать эту команду.");
            return true;
        } else if (args.length == 0) {
            sender.sendMessage(ChatColor.RED + "§cИспользование: /rocket <launch|give|stats> [параметры]");
            return true;
        } else {
            switch (args[0].toLowerCase()) {
                case "launch" -> this.handleLaunch(sender, args);
                case "give" -> this.handleGive(sender, args);
                case "stats" -> this.handleStats(sender, args);
                default -> sender.sendMessage(ChatColor.RED + "§cНеизвестная подкоманда. Использование: /rocket <launch|give|stats> [параметры]");
            }

            return true;
        }
    }

    private void handleLaunch(CommandSender sender, String[] args) {
        if (!(sender instanceof Player player)) {
            sender.sendMessage(ChatColor.RED + "§cТолько игроки могут запускать ракеты.");
        } else if (args.length < 5) {
            player.sendMessage(ChatColor.RED + "§cИспользование: /rocket launch <type> <x> <y> <z> [delay]");
            player.sendMessage(ChatColor.YELLOW + "§eПримечание: delay - опциональный параметр (1-30 секунд)");
        } else {
            RocketType type;
            try {
                type = RocketType.valueOf(args[1].toUpperCase());
            } catch (IllegalArgumentException var14) {
                player.sendMessage(ChatColor.RED + "§cНеверный тип ракеты. Доступные типы: SMALL, MEDIUM, LARGE, EXTRA_LARGE, NUCLEAR, SUPER_NUCLEAR, MEGA_NUCLEAR, EXTREME_NUCLEAR, ULTRA_NUCLEAR, USSR.");
                return;
            }

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

            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 var15) {
                    player.sendMessage(ChatColor.RED + "§cЗадержка должна быть целым числом.");
                    return;
                }
            }

            Location target = new Location(player.getWorld(), x, y, z);
            this.rocketManager.launchRocket(player, type, target, delay);
        }
    }

    private void handleGive(CommandSender sender, String[] args) {
        if (!sender.hasPermission("rocketplugin.give")) {
            sender.sendMessage(ChatColor.RED + "§cУ вас нет разрешения выдавать ракеты.");
        } else if (args.length < 4) {
            sender.sendMessage(ChatColor.RED + "§cИспользование: /rocket give <player> <type> <amount>");
        } else {
            String targetName = args[1];
            Player targetPlayer = Bukkit.getPlayerExact(targetName);
            if (targetPlayer == null) {
                sender.sendMessage(ChatColor.RED + "§cИгрок не найден или не онлайн.");
            } else {
                RocketType type;
                try {
                    type = RocketType.valueOf(args[2].toUpperCase());
                } catch (IllegalArgumentException var8) {
                    sender.sendMessage(ChatColor.RED + "§cНеверный тип ракеты. Доступные типы: SMALL, MEDIUM, LARGE, EXTRA_LARGE, NUCLEAR, SUPER_NUCLEAR, MEGA_NUCLEAR, EXTREME_NUCLEAR, ULTRA_NUCLEAR, USSR.");
                    return;
                }

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

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

    private void handleStats(CommandSender sender, String[] args) {
        if (args.length < 2) {
            if (sender instanceof Player) {
                Player player = (Player)sender;
                sender.sendMessage(this.statsManager.getStats(player));
            } else {
                sender.sendMessage(ChatColor.RED + "§cКонсоль не имеет статистики.");
            }

        } else {
            String targetName = args[1];
            Player targetPlayer = Bukkit.getPlayerExact(targetName);
            if (targetPlayer == null) {
                sender.sendMessage(ChatColor.RED + "§cИгрок не найден или не онлайн.");
            } else {
                sender.sendMessage(this.statsManager.getStats(targetPlayer));
            }
        }
    }
}
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.EntityExplodeEvent;
import org.bukkit.event.entity.ExplosionPrimeEvent;

public class RocketListener implements Listener {
    private final RocketManager rocketManager;

    public RocketListener(RocketManager rocketManager) {
        this.rocketManager = rocketManager;
    }

    @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 = (Player)event.getEntity();
                player.sendMessage(ChatColor.RED + "§cВзрывы вне мира запрещены!");
            }
        }

    }

    @EventHandler
    public void onEntityExplode(EntityExplodeEvent event) {
        World world = event.getEntity().getWorld();
        if (!world.getName().equalsIgnoreCase("P_Drilla")) {
            event.setCancelled(true);
        }

    }
}
package com.yourname.rocketplugin;

import java.util.Random;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;

public class RocketManager {
    private final RocketPlugin plugin;
    private final StatsManager statsManager;
    private final Random random;

    public RocketManager(RocketPlugin plugin, StatsManager statsManager) {
        this.plugin = plugin;
        this.statsManager = statsManager;
        this.random = new Random();
    }

    public void launchRocket(final Player player, final RocketType type, final Location target, final int delay) {
        if (!target.getWorld().getName().equalsIgnoreCase("P_Drilla")) {
            player.sendMessage(ChatColor.RED + "§cРакеты могут взрываться только в мире P_Drilla.");
        } else if (!this.statsManager.hasRockets(player, type)) {
            ChatColor var10001 = ChatColor.RED;
            player.sendMessage("" + var10001 + "§cУ вас нет ракет типа " + type.name() + "!");
        } else {
            this.statsManager.useRocket(player, type);
            if (delay > 0) {
                player.sendMessage(ChatColor.YELLOW + "§eЗапуск ракеты через " + delay + " секунд(ы).");
                (new BukkitRunnable() {
                    private int secondsLeft = delay;

                    public void run() {
                        if (this.secondsLeft <= 0) {
                            this.cancel();
                            boolean success = RocketManager.this.checkLaunchSuccess(type);
                            if (success) {
                                Rocket rocket = new Rocket(player, type, target, RocketManager.this.plugin);
                                rocket.launch();
                                player.sendMessage(ChatColor.GREEN + "§aРакета успешно запущена!");
                            } else {
                                player.sendMessage(ChatColor.RED + "§cРакета не смогла достичь цели и не взорвалась.");
                            }

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

        }
    }

    private boolean checkLaunchSuccess(RocketType type) {
        byte chance;
        switch (type) {
            case NUCLEAR -> chance = 40;
            case SUPER_NUCLEAR -> chance = 30;
            case MEGA_NUCLEAR -> chance = 20;
            case EXTREME_NUCLEAR -> chance = 15;
            case ULTRA_NUCLEAR -> chance = 10;
            case USSR -> chance = 5; // Новый тип с шансом 5%
            default -> chance = 50;
        }

        int roll = this.random.nextInt(100) + 1;
        return roll <= chance;
    }
}
package com.yourname.rocketplugin;

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

public class RocketPlugin extends JavaPlugin {
    private static RocketPlugin instance;
    private RocketManager rocketManager;
    private StatsManager statsManager;

    public RocketPlugin() {
    }

    public static RocketPlugin getInstance() {
        return instance;
    }

    public RocketManager getRocketManager() {
        return this.rocketManager;
    }

    public StatsManager getStatsManager() {
        return this.statsManager;
    }

    public void onEnable() {
        instance = this;
        this.saveDefaultConfig();
        this.statsManager = new StatsManager(this);
        this.rocketManager = new RocketManager(this, this.statsManager);
        this.statsManager.load();
        PluginCommand rocketCommand = this.getCommand("rocket");
        if (rocketCommand != null) {
            rocketCommand.setExecutor(new RocketCommand(this.rocketManager, this.statsManager, this));
            rocketCommand.setTabCompleter(new RocketTabCompleter(this));
            PluginManager var2 = this.getServer().getPluginManager();
            var2.registerEvents(new RocketListener(this.rocketManager), this);
            this.getLogger().info("RocketPlugin был включен!");
        } else {
            this.getLogger().severe("Не удалось зарегистрировать команду 'rocket'. Проверьте plugin.yml.");
            this.setEnabled(false);
        }
    }

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

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

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.bukkit.entity.Player;

public class RocketTabCompleter implements TabCompleter {
    private final RocketPlugin 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 = Arrays.asList("launch", "give", "stats");
            for (String sub : subcommands) {
                if (sub.startsWith(args[0].toLowerCase())) {
                    completions.add(sub);
                }
            }
            return completions;
        }

        // Подкоманда вторая
        if (args.length == 2) {
            String subcommand = args[0].toLowerCase();
            if (subcommand.equals("launch")) {
                for (RocketType type : RocketType.values()) {
                    if (type.name().toLowerCase().startsWith(args[1].toLowerCase())) {
                        completions.add(type.name());
                    }
                }
            } else if (subcommand.equals("give") || subcommand.equals("stats")) {
                for (Player player : Bukkit.getOnlinePlayers()) {
                    if (player.getName().toLowerCase().startsWith(args[1].toLowerCase())) {
                        completions.add(player.getName());
                    }
                }
            }
            return completions;
        }

        // Подкоманда третья
        if (args.length == 3) {
            String subcommand = args[0].toLowerCase();
            if (subcommand.equals("give")) {
                for (RocketType type : RocketType.values()) {
                    if (type.name().toLowerCase().startsWith(args[2].toLowerCase())) {
                        completions.add(type.name());
                    }
                }
            }
            // Для подкоманды 'launch' позиции 3 и 4 это координаты, автодополнение обычно не требуется
            return completions;
        }

        // Подкоманда четвертая
        if (args.length == 4) {
            String subcommand = args[0].toLowerCase();
            if (subcommand.equals("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 == 5) {
            String subcommand = args[0].toLowerCase();
            if (subcommand.equals("launch")) {
                for (int i = 1; i <= 30; i++) { // Максимальная задержка 30 секунд
                    String delay = String.valueOf(i);
                    if (delay.startsWith(args[4])) {
                        completions.add(delay);
                    }
                }
            }
            return completions;
        }

        return completions;
    }
}
package com.yourname.rocketplugin;

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

public enum RocketType {
    SMALL(10.0F, 100, Particle.FLAME, Sound.ENTITY_FIREWORK_ROCKET_LAUNCH, Particle.SMOKE_NORMAL),
    MEDIUM(15.0F, 150, Particle.FLAME, Sound.ENTITY_FIREWORK_ROCKET_LAUNCH, Particle.SMOKE_NORMAL),
    LARGE(20.0F, 200, Particle.EXPLOSION_NORMAL, Sound.ENTITY_FIREWORK_ROCKET_LAUNCH, Particle.SMOKE_LARGE),
    EXTRA_LARGE(25.0F, 300, Particle.EXPLOSION_LARGE, Sound.ENTITY_FIREWORK_ROCKET_LAUNCH, Particle.EXPLOSION_HUGE),
    NUCLEAR(70.0F, 500, Particle.EXPLOSION_HUGE, Sound.ENTITY_GENERIC_EXPLODE, Particle.EXPLOSION_HUGE),
    SUPER_NUCLEAR(100.0F, 700, Particle.EXPLOSION_HUGE, Sound.ENTITY_GENERIC_EXPLODE, Particle.EXPLOSION_HUGE),
    MEGA_NUCLEAR(150.0F, 1000, Particle.EXPLOSION_HUGE, Sound.ENTITY_GENERIC_EXPLODE, Particle.EXPLOSION_HUGE),
    EXTREME_NUCLEAR(750.0F, 1500, Particle.SUSPENDED, Sound.ENTITY_GENERIC_EXPLODE, Particle.EXPLOSION_HUGE),
    ULTRA_NUCLEAR(2500.0F, 2000, Particle.SPELL_INSTANT, Sound.ENTITY_GENERIC_EXPLODE, Particle.EXPLOSION_HUGE),
    USSR(25000.0F, 2500, Particle.PORTAL, Sound.ENTITY_GENERIC_EXPLODE, Particle.EXPLOSION_HUGE); // Новый тип ракеты

    private final float power;
    private final int range;
    private final Particle launchParticle;
    private final Sound explosionSound;
    private final Particle explosionParticle;

    private RocketType(float power, int range, Particle launchParticle, Sound explosionSound, Particle explosionParticle) {
        this.power = power;
        this.range = range;
        this.launchParticle = launchParticle;
        this.explosionSound = explosionSound;
        this.explosionParticle = explosionParticle;
    }

    public float getPower() {
        return this.power;
    }

    public int getRange() {
        return this.range;
    }

    public Particle getLaunchParticle() {
        return this.launchParticle;
    }

    public Sound getExplosionSound() {
        return this.explosionSound;
    }

    public Particle getExplosionParticle() {
        return this.explosionParticle;
    }
}
package com.yourname.rocketplugin;

import java.io.File;
import java.io.IOException;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;

public class StatsManager {
    private final RocketPlugin plugin;
    private final File statsFile;
    private FileConfiguration statsConfig;

    public StatsManager(RocketPlugin plugin) {
        this.plugin = plugin;
        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 var3) {
                IOException e = var3;
                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 var2) {
            Exception e = var2;
            this.plugin.getLogger().severe("§cНе удалось загрузить stats.yml:");
            e.printStackTrace();
        }

    }

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

    }

    public int getRockets(Player player, RocketType type) {
        String var10000 = player.getUniqueId().toString();
        String path = var10000 + ".rockets." + type.name();
        return this.statsConfig.getInt(path, 0);
    }

    public void addRockets(Player player, RocketType type, int amount) {
        String var10000 = player.getUniqueId().toString();
        String path = var10000 + ".rockets." + type.name();
        int current = this.getRockets(player, type);
        this.statsConfig.set(path, current + amount);
        this.save();
    }

    public boolean hasRockets(Player player, RocketType type) {
        return this.getRockets(player, type) > 0;
    }

    public void useRocket(Player player, RocketType type) {
        String var10000 = player.getUniqueId().toString();
        String path = var10000 + ".rockets." + type.name();
        int current = this.getRockets(player, type);
        if (current > 0) {
            this.statsConfig.set(path, current - 1);
            this.save();
        }

    }

    public String getStats(Player player) {
        StringBuilder sb = new StringBuilder("§a§lСтатистика Ракет для " + player.getName() + ":\n");
        RocketType[] var3 = RocketType.values();
        int var4 = var3.length;

        for(int var5 = 0; var5 < var4; ++var5) {
            RocketType type = var3[var5];
            sb.append("§e").append(type.name()).append(": §b").append(this.getRockets(player, type)).append("\n");
        }

        return sb.toString();
    }
}

1) Давай сделаем, чтобы в конфиге можно было изменять/добавлять ракеты. Также, чтобы они добавлялись в статистику и подсказку для команды (Её исправь и сделай рабочей)
2) (Вопрос) Есть ли ещё способ, альтернативный, более оптимизированный и мощный способ разрушения (чтобы сервер не ложился), если да, то сделай отдельно ракету для этого и я проверю.
3) Напиши полный код, на русском, всё локализировано на русском. Исправь баги, ошибки и тд.