package com.yourname.rocketplugin; import org.bukkit.Location; import org.bukkit.Sound; import org.bukkit.Particle; 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 { private final Player launcher; private final RocketType type; private final Location target; private final RocketPlugin plugin; private Location currentLocation; private double speed = 1.0; // Единиц в тике /** * Конструктор для создания новой ракеты. * * @param launcher Игрок, запускающий ракету. * @param type Тип ракеты. * @param target Целевая локация. * @param plugin Основной экземпляр RocketPlugin. */ 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() { World world = launcher.getWorld(); // Визуальные и звуковые эффекты запуска world.spawnParticle(type.getLaunchParticle(), currentLocation, 20, 0.5, 0.5, 0.5, 0.05); world.playSound(currentLocation, Sound.ENTITY_FIREWORK_ROCKET_LAUNCH, 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(); return; } // Нормализация вектора направления и перемещение ракеты direction = direction.normalize().multiply(speed); currentLocation.add(direction); // Визуальные эффекты во время полета world.spawnParticle(type.getLaunchParticle(), currentLocation, 5, 0.1, 0.1, 0.1, 0.02); } }.runTaskTimer(plugin, 0L, 1L); // Выполнять каждый тик (20 тиков в секунду) } /** * Обрабатывает взрыв ракеты в целевой локации. */ private void explode() { World world = target.getWorld(); if (world == null) { launcher.sendMessage("§cОшибка: Целевая локация не найдена."); return; } // Создание взрыва world.createExplosion(target, type.getPower(), false, true); // Второй параметр - сила взрыва, четвертый - ломать блоки // Визуальные и звуковые эффекты взрыва world.spawnParticle(type.getExplosionParticle(), target, 100, 1, 1, 1, 0.1); world.playSound(target, type.getExplosionSound(), 1.0f, 1.0f); // Дополнительные эффекты для новых типов ракет if (type == RocketType.SUPER_NUCLEAR || type == RocketType.MEGA_NUCLEAR) { double effectRadius = 20.0; // Радиус действия эффектов, можно настроить // Получение всех сущностей в радиусе Collection<Entity> entities = world.getNearbyEntities(target, effectRadius, effectRadius, effectRadius); for (Entity entity : entities) { if (entity instanceof Player) { Player player = (Player) entity; // Применение эффектов player.addPotionEffect(new PotionEffect(PotionEffectType.CONFUSION, 200, 1)); // Тошнота на 10 секунд player.addPotionEffect(new PotionEffect(PotionEffectType.POISON, 200, 1)); // Отравление на 10 секунд } } // Усиленные и длительные визуальные эффекты new BukkitRunnable() { private int ticks = 0; private final int maxTicks = 100; // 5 секунд (100 тиков) @Override public void run() { if (ticks >= maxTicks) { this.cancel(); return; } // Создание дополнительных частиц для длительных эффектов world.spawnParticle(Particle.EXPLOSION_HUGE, target, 50, 2, 2, 2, 0.05); world.spawnParticle(Particle.LAVA, target, 100, 3, 3, 3, 0.02); world.spawnParticle(Particle.FIREWORKS_SPARK, target, 100, 4, 4, 4, 0.1); world.spawnParticle(Particle.END_ROD, target, 50, 2, 2, 2, 0.05); world.playSound(target, Sound.ENTITY_GENERIC_EXPLODE, 1.0f, 1.0f); ticks++; } }.runTaskTimer(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; /** * Обрабатывает команду /rocket и ее подкоманды. */ public class RocketCommand implements CommandExecutor { private final RocketManager rocketManager; private final StatsManager statsManager; private final RocketPlugin plugin; /** * Конструктор для RocketCommand. * * @param rocketManager Экземпляр RocketManager. * @param statsManager Экземпляр StatsManager. * @param plugin Основной экземпляр RocketPlugin. */ public RocketCommand(RocketManager rocketManager, StatsManager statsManager, RocketPlugin plugin) { this.rocketManager = rocketManager; this.statsManager = statsManager; this.plugin = plugin; } /** * Выполняет команду /rocket. * * @param sender Отправитель команды. * @param command Команда, которая выполняется. * @param label Псевдоним команды. * @param args Аргументы команды. * @return true, если команда была обработана, иначе false. */ @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> [параметры]"); 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; default: sender.sendMessage(ChatColor.RED + "§cНеизвестная подкоманда. Использование: /rocket <launch|give|stats> [параметры]"); } 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; } // Парсинг типа ракеты RocketType type; try { type = RocketType.valueOf(args[1].toUpperCase()); } catch (IllegalArgumentException e) { player.sendMessage(ChatColor.RED + "§cНеверный тип ракеты. Доступные типы: SMALL, MEDIUM, LARGE, EXTRA_LARGE, NUCLEAR, SUPER_NUCLEAR, MEGA_NUCLEAR."); 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; } // Парсинг опционального параметра delay 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; } } // Создание целевой локации Location target = new Location(player.getWorld(), x, y, z); // Запуск ракеты с учётом задержки и шанса успеха 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; } // Парсинг типа ракеты RocketType type; try { type = RocketType.valueOf(args[2].toUpperCase()); } catch (IllegalArgumentException e) { sender.sendMessage(ChatColor.RED + "§cНеверный тип ракеты. Доступные типы: SMALL, MEDIUM, LARGE, EXTRA_LARGE, NUCLEAR, SUPER_NUCLEAR, MEGA_NUCLEAR."); 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.name() + " игроку " + targetPlayer.getName() + "."); targetPlayer.sendMessage(ChatColor.GREEN + "§aВам выдали " + amount + " ракет типа " + type.name() + " от " + sender.getName() + "."); } /** * Обрабатывает подкоманду 'stats'. * * @param sender Отправитель команды. * @param args Аргументы команды. */ private void handleStats(CommandSender sender, String[] args) { if (args.length < 2) { // Показать статистику отправителю, если это игрок if (sender instanceof Player) { Player player = (Player) sender; 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)); } } package com.yourname.rocketplugin; import org.bukkit.ChatColor; import org.bukkit.entity.Player; import org.bukkit.World; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityExplodeEvent; import org.bukkit.event.entity.ExplosionPrimeEvent; /** * Слушает события, связанные с ракетами. * Обрабатывает взрывы, чтобы убедиться, что они происходят только в мире P_Drilla. */ public class RocketListener implements Listener { private final RocketManager rocketManager; /** * Конструктор для RocketListener. * * @param rocketManager Экземпляр RocketManager. */ public RocketListener(RocketManager rocketManager) { this.rocketManager = rocketManager; } /** * Обрабатывает событие Prime Explosion. * Убеждается, что взрывы происходят только в мире P_Drilla. * * @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 = (Player) event.getEntity(); 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); } } } package com.yourname.rocketplugin; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; import java.util.Random; /** * Управляет операциями, связанными с ракетами, такими как запуск ракет. */ public class RocketManager { private final RocketPlugin plugin; private final StatsManager statsManager; private final Random random; /** * Конструктор для RocketManager. * * @param plugin Основной экземпляр RocketPlugin. * @param statsManager Экземпляр StatsManager. */ public RocketManager(RocketPlugin plugin, StatsManager statsManager) { this.plugin = plugin; this.statsManager = statsManager; this.random = new Random(); } /** * Запускает ракету для игрока с учётом задержки и вероятности успеха. * * @param player Игрок, запускающий ракету. * @param type Тип ракеты. * @param target Целевая локация для ракеты. * @param delay Задержка перед запуском в секундах (0 - немедленно). */ public void launchRocket(Player player, RocketType type, Location target, int delay) { // Проверка, находится ли целевая локация в мире P_Drilla if (!target.getWorld().getName().equalsIgnoreCase("P_Drilla")) { player.sendMessage(ChatColor.RED + "§cРакеты могут взрываться только в мире P_Drilla."); return; } // Проверка, есть ли у игрока ракеты указанного типа if (!statsManager.hasRockets(player, type)) { player.sendMessage(ChatColor.RED + "§cУ вас нет ракет типа " + type.name() + "!"); return; } // Потребление одной ракеты statsManager.useRocket(player, type); if (delay > 0) { // Отправка сообщений об отсчёте player.sendMessage(ChatColor.YELLOW + "§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(ChatColor.GREEN + "§aРакета успешно запущена!"); } else { player.sendMessage(ChatColor.RED + "§cРакета не смогла достичь цели и не взорвалась."); } return; } // Отправка сообщения каждую секунду player.sendMessage(ChatColor.YELLOW + "§eЗапуск ракеты через " + secondsLeft + " секунд(ы)."); secondsLeft--; } }.runTaskTimer(plugin, 0L, 20L); // Запуск задачи каждую секунду (20 тиков) } else { // Проверка шанса успешного запуска без задержки boolean success = checkLaunchSuccess(type); if (success) { // Создание и запуск ракеты без задержки Rocket rocket = new Rocket(player, type, target, plugin); rocket.launch(); player.sendMessage(ChatColor.GREEN + "§aРакета успешно запущена!"); } else { player.sendMessage(ChatColor.RED + "§cРакета не смогла достичь цели и не взорвалась."); } } } /** * Проверяет, успешен ли запуск ракеты на основе её типа. * * @param type Тип ракеты. * @return true, если ракета успешно долетела, иначе false. */ private boolean checkLaunchSuccess(RocketType type) { int chance; switch (type) { case NUCLEAR: chance = 40; break; case SUPER_NUCLEAR: chance = 30; break; case MEGA_NUCLEAR: chance = 20; break; default: chance = 50; break; } int roll = random.nextInt(100) + 1; // 1-100 return roll <= chance; } } package com.yourname.rocketplugin; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.PluginManager; import org.bukkit.command.PluginCommand; /** * Основной класс плагина RocketPlugin. * Инициализирует и управляет всеми компонентами плагина. */ public class RocketPlugin extends JavaPlugin { private static RocketPlugin instance; private RocketManager rocketManager; private StatsManager statsManager; /** * Получает экземпляр плагина. * * @return экземпляр RocketPlugin. */ public static RocketPlugin getInstance() { return instance; } /** * Получает экземпляр RocketManager. * * @return экземпляр RocketManager. */ public RocketManager getRocketManager() { return rocketManager; } /** * Получает экземпляр StatsManager. * * @return экземпляр StatsManager. */ public StatsManager getStatsManager() { return statsManager; } @Override public void onEnable() { instance = this; saveDefaultConfig(); // Сохранение config.yml, если он присутствует // Инициализация менеджеров statsManager = new StatsManager(this); rocketManager = new RocketManager(this, statsManager); // Загрузка статистики statsManager.load(); // Регистрация команд PluginCommand rocketCommand = this.getCommand("rocket"); if (rocketCommand != null) { rocketCommand.setExecutor(new RocketCommand(rocketManager, statsManager, this)); rocketCommand.setTabCompleter(new RocketTabCompleter(this)); } else { getLogger().severe("Не удалось зарегистрировать команду 'rocket'. Проверьте plugin.yml."); this.setEnabled(false); return; } // Регистрация слушателей событий PluginManager pm = getServer().getPluginManager(); pm.registerEvents(new RocketListener(rocketManager), this); getLogger().info("RocketPlugin был включен!"); } @Override public void onDisable() { if (statsManager != null) { // Сохранение статистики statsManager.save(); } getLogger().info("RocketPlugin был отключен!"); } } 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.Arrays; import java.util.List; /** * Предоставляет автодополнение для команды /rocket. */ public class RocketTabCompleter implements TabCompleter { private final RocketPlugin plugin; /** * Конструктор для RocketTabCompleter. * * @param plugin Основной экземпляр RocketPlugin. */ public RocketTabCompleter(RocketPlugin plugin) { this.plugin = plugin; } /** * Обрабатывает автодополнение для команды /rocket. * * @param sender Отправитель команды. * @param command Команда, которая выполняется. * @param alias Псевдоним команды. * @param args Текущие аргументы команды. * @return Список возможных дополнений. */ @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("give") || subcommand.equals("stats")) { // Предложить имена игроков for (Player player : Bukkit.getOnlinePlayers()) { if (player.getName().toLowerCase().startsWith(args[1].toLowerCase())) { completions.add(player.getName()); } } } else if (subcommand.equals("launch")) { // Предложить типы ракет for (RocketType type : RocketType.values()) { if (type.name().toLowerCase().startsWith(args[1].toLowerCase())) { completions.add(type.name()); } } } return completions; } if (args.length == 3 || args.length == 4) { String subcommand = args[0].toLowerCase(); if (subcommand.equals("launch")) { // Предложить координаты или оставить пустым return completions; } else if (subcommand.equals("give")) { // Предложить типы ракет for (RocketType type : RocketType.values()) { if (type.name().toLowerCase().startsWith(args[2].toLowerCase())) { completions.add(type.name()); } } } return completions; } if (args.length == 5 && args[0].toLowerCase().equals("launch")) { // Предложить задержку для команды launch for (int i = 1; i <= 30; i++) { String delay = String.valueOf(i); if (delay.startsWith(args[4])) { completions.add(delay); } } return completions; } if (args.length == 4 && args[0].toLowerCase().equals("give")) { // Предложить количество (1-64) for (int i = 1; i <= 64; i++) { String amount = String.valueOf(i); if (amount.startsWith(args[3])) { completions.add(amount); } } 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); private final float power; private final int range; private final Particle launchParticle; private final Sound explosionSound; private final Particle explosionParticle; /** * Конструктор для RocketType. * * @param power Сила взрыва. * @param range Максимальное расстояние, на которое может перемещаться ракета. * @param launchParticle Частица, используемая при запуске. * @param explosionSound Звуковой эффект при взрыве. * @param explosionParticle Частица, используемая при взрыве. */ 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; } /** * Получает силу взрыва ракеты. * * @return сила взрыва. */ public float getPower() { return power; } /** * Получает максимальный радиус ракеты. * * @return радиус в блоках. */ public int getRange() { return range; } /** * Получает частицу, используемую при запуске ракеты. * * @return частица запуска. */ public Particle getLaunchParticle() { return launchParticle; } /** * Получает звуковой эффект, используемый при взрыве ракеты. * * @return звуковой эффект взрыва. */ public Sound getExplosionSound() { return explosionSound; } /** * Получает частицу, используемую при взрыве ракеты. * * @return частица взрыва. */ public Particle getExplosionParticle() { return explosionParticle; } } 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; /** * Управляет статистикой игроков, связанной с ракетами. * Обрабатывает загрузку и сохранение данных в YAML файл. */ public class StatsManager { private final RocketPlugin plugin; private final File statsFile; private FileConfiguration statsConfig; /** * Конструктор для StatsManager. * * @param plugin Основной экземпляр RocketPlugin. */ public StatsManager(RocketPlugin plugin) { this.plugin = plugin; this.statsFile = new File(plugin.getDataFolder(), "stats.yml"); if (!statsFile.exists()) { try { if (plugin.getResource("stats.yml") != null) { plugin.saveResource("stats.yml", false); } else { statsConfig = new YamlConfiguration(); statsConfig.save(statsFile); } } catch (IOException e) { plugin.getLogger().severe("§cНе удалось создать stats.yml:"); e.printStackTrace(); } } this.statsConfig = YamlConfiguration.loadConfiguration(statsFile); } /** * Загружает статистику из YAML файла. */ public void load() { try { statsConfig.load(statsFile); } catch (Exception e) { plugin.getLogger().severe("§cНе удалось загрузить stats.yml:"); e.printStackTrace(); } } /** * Сохраняет статистику в YAML файл. */ public void save() { try { statsConfig.save(statsFile); } catch (IOException e) { 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.name(); 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.name(); int current = getRockets(player, type); statsConfig.set(path, current + amount); save(); } /** * Проверяет, есть ли у игрока ракеты определенного типа. * * @param player Игрок. * @param type Тип ракеты. * @return true, если ракеты есть, иначе false. */ 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.name(); int current = getRockets(player, type); if (current > 0) { statsConfig.set(path, current - 1); save(); } } /** * Получает отформатированную строку статистики игрока по ракетам. * * @param player Игрок, для которого нужно получить статистику. * @return Отформатированная строка со статистикой игрока. */ public String getStats(Player player) { StringBuilder sb = new StringBuilder("§a§lСтатистика Ракет для " + player.getName() + ":\n"); for (RocketType type : RocketType.values()) { sb.append("§e").append(type.name()).append(": §b").append(getRockets(player, type)).append("\n"); } return sb.toString(); } } Нужно, чтобы только в мире спавнилось (название есть), проверь это, чтобы было, а также улучши плагин и напиши полный код