Визуальные Эффекты:
Вы можете настроить цвет и тип частиц в методе visualizeZone, чтобы добиться более привлекательного или заметного эффекта радиационной зоны.
Сделай чтобы было более понятно + более красиво

Также сделай, чтобы было 3 противогаза, отличались прочностью (своей), то есть например обычный - принимает 800 радиации, а вот 2 уровня - 2400 радиации. Также за 1 секунду (если игрок не в противогазе или он вне зоны и тогда у него постепенно уменьшается радиация), давалось 1-2 ед. радиации/ ДЛя более лучших противогазов нужны предыдущие. Также более сложный крафт (для противогазов нужны компоненты, которые тоже крафтяться)
Также улучши плагин и напиши полный код + сделай, чтобы когда я писал команду мне выдавались подсказки, что писать

Cannot resolve method 'getPlayerTotalRadiation' in 'RadiationPlugin'
Cannot resolve method 'isWearingGasMask(Player)'
Cannot resolve method 'isWearingGasMask(Player)'


package com.yourpackage;

import org.bukkit.*;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.inventory.*;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitRunnable;

import java.util.*;

public class RadiationPlugin extends JavaPlugin implements CommandExecutor, TabCompleter, Listener {

    // Map для хранения активных радиационных зон по имени
    private final Map<String, RadiationZone> zones = new HashMap<>();

    // Map для хранения маппинга уровней радиации и соответствующих эффектов, отсортированных по убыванию
    private final TreeMap<Integer, EffectMapping> effectMappings = new TreeMap<>(Collections.reverseOrder());

    // Map для отслеживания зон, в которых находится каждый игрок
    private final Map<UUID, Set<String>> playerZones = new HashMap<>();

    // Map для хранения уровней противогаза игрока
    private final Map<UUID, Integer> playerGasMaskLevels = new HashMap<>();

    private FileConfiguration config;

    @Override
    public void onEnable() {
        // Сохранить и загрузить стандартный конфигурационный файл, если он отсутствует
        saveDefaultConfig();
        config = getConfig();

        // Загрузить маппинг эффектов
        loadEffectMappings();

        // Загрузить радиационные зоны из конфигурации
        loadRadiationZones();

        // Регистрация команд и обработчиков событий
        getCommand("radiationzone").setExecutor(this);
        getCommand("radiationzone").setTabCompleter(this);
        getCommand("radiationcheck").setExecutor(this);
        Bukkit.getPluginManager().registerEvents(this, this);

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

        // Запуск задачи для проверки игроков в радиационных зонах
        startRadiationCheckerTask();

        getLogger().info("RadiationPlugin включен!");
    }

    @Override
    public void onDisable() {
        // Сохранить радиационные зоны в конфигурации при отключении плагина
        saveRadiationZones();

        getLogger().info("RadiationPlugin выключен!");
    }

    /**
     * Загрузка маппинга эффектов из конфигурации.
     */
    private void loadEffectMappings() {
        ConfigurationSection section = config.getConfigurationSection("effect_mappings");
        if (section != null) {
            for (String key : section.getKeys(false)) {
                try {
                    int threshold = Integer.parseInt(key);
                    ConfigurationSection mappingSection = section.getConfigurationSection(key);
                    if (mappingSection != null) {
                        int duration = mappingSection.getInt("duration", 40);
                        int amplifier = mappingSection.getInt("amplifier", 1);
                        List<String> effects = mappingSection.getStringList("effects");
                        effectMappings.put(threshold, new EffectMapping(duration, amplifier, effects));
                    } else {
                        getLogger().warning("Отсутствует секция для порога радиации: " + key);
                    }
                } catch (NumberFormatException e) {
                    getLogger().warning("Неверный порог уровня радиации: " + key);
                }
            }
        } else {
            getLogger().warning("Отсутствует секция effect_mappings в config.yml!");
        }
    }

    /**
     * Загрузка радиационных зон из конфигурации.
     */
    private void loadRadiationZones() {
        ConfigurationSection zonesSection = config.getConfigurationSection("radian_zones");
        if (zonesSection != null) {
            for (String zoneName : zonesSection.getKeys(false)) {
                ConfigurationSection zoneConfig = zonesSection.getConfigurationSection(zoneName);
                if (zoneConfig != null) {
                    double minX = zoneConfig.getDouble("min_x");
                    double minY = zoneConfig.getDouble("min_y");
                    double minZ = zoneConfig.getDouble("min_z");
                    double maxX = zoneConfig.getDouble("max_x");
                    double maxY = zoneConfig.getDouble("max_y");
                    double maxZ = zoneConfig.getDouble("max_z");
                    int radiation = zoneConfig.getInt("radiation", 100);
                    int duration = zoneConfig.getInt("duration", 600); // Продолжительность в секундах

                    // Проверка корректности координат
                    if (minX >= maxX || minY >= maxY || minZ >= maxZ) {
                        getLogger().warning("Некорректные координаты для зоны: " + zoneName + ". Зона будет пропущена.");
                        continue;
                    }

                    // Проверка на перекрытие с существующими зонами
                    boolean overlaps = false;
                    for (RadiationZone existingZone : zones.values()) {
                        if (existingZone.overlapsWith(minX, minY, minZ, maxX, maxY, maxZ)) {
                            getLogger().warning("Зона " + zoneName + " перекрывается с зоной " + existingZone.getName() + ". Зона будет пропущена.");
                            overlaps = true;
                            break;
                        }
                    }
                    if (overlaps) continue;

                    RadiationZone zone = new RadiationZone(zoneName, minX, minY, minZ, maxX, maxY, maxZ, radiation, duration);
                    zones.put(zoneName, zone);
                }
            }
        }
    }

    /**
     * Сохранение радиационных зон в конфигурацию.
     */
    private void saveRadiationZones() {
        ConfigurationSection zonesSection = config.getConfigurationSection("radian_zones");
        if (zonesSection == null) {
            zonesSection = config.createSection("radian_zones");
        } else {
            // Очистить существующие зоны
            for (String zoneName : zonesSection.getKeys(false)) {
                zonesSection.set(zoneName, null);
            }
        }

        for (RadiationZone zone : zones.values()) {
            ConfigurationSection zoneConfig = zonesSection.createSection(zone.getName());
            zoneConfig.set("min_x", zone.minX);
            zoneConfig.set("min_y", zone.minY);
            zoneConfig.set("min_z", zone.minZ);
            zoneConfig.set("max_x", zone.maxX);
            zoneConfig.set("max_y", zone.maxY);
            zoneConfig.set("max_z", zone.maxZ);
            zoneConfig.set("radiation", zone.radiation);
            zoneConfig.set("duration", zone.duration);
        }

        saveConfig();
    }

    /**
     * Регистрация рецептов крафта для противогаза.
     */
    private void registerRecipes() {
        // Создание противогаза I
        ItemStack gasMask1 = createCustomItem(Material.LEATHER_HELMET, ChatColor.AQUA + "Противогаз I", Arrays.asList(ChatColor.GRAY + "Защищает от радиации (800 радиации)"));
        NamespacedKey gasMaskKey1 = new NamespacedKey(this, "gas_mask_level_1");
        ShapedRecipe gasMaskRecipe1 = new ShapedRecipe(gasMaskKey1, gasMask1);
        gasMaskRecipe1.shape(" I ", "IRI", "RIR");
        gasMaskRecipe1.setIngredient('I', Material.IRON_INGOT);
        gasMaskRecipe1.setIngredient('R', Material.REDSTONE);
        Bukkit.addRecipe(gasMaskRecipe1);

        // Создание противогаза II
        ItemStack gasMask2 = createCustomItem(Material.LEATHER_HELMET, ChatColor.DARK_AQUA + "Противогаз II", Arrays.asList(ChatColor.GRAY + "Защищает от радиации (2400 радиации)"));
        NamespacedKey gasMaskKey2 = new NamespacedKey(this, "gas_mask_level_2");
        ShapedRecipe gasMaskRecipe2 = new ShapedRecipe(gasMaskKey2, gasMask2);
        gasMaskRecipe2.shape(" I ", "IRI", "RAR");
        gasMaskRecipe2.setIngredient('I', Material.DIAMOND);
        gasMaskRecipe2.setIngredient('R', Material.REDSTONE);
        gasMaskRecipe2.setIngredient('A', Material.GOLD_INGOT);
        Bukkit.addRecipe(gasMaskRecipe2);

        // Создание противогаза III
        ItemStack gasMask3 = createCustomItem(Material.LEATHER_HELMET, ChatColor.BLUE + "Противогаз III", Arrays.asList(ChatColor.GRAY + "Защищает от радиации (4800 радиации)"));
        NamespacedKey gasMaskKey3 = new NamespacedKey(this, "gas_mask_level_3");
        ShapedRecipe gasMaskRecipe3 = new ShapedRecipe(gasMaskKey3, gasMask3);
        gasMaskRecipe3.shape(" I ", "ARA", "RAR");
        gasMaskRecipe3.setIngredient('I', Material.NETHERITE_INGOT);
        gasMaskRecipe3.setIngredient('R', Material.REDSTONE);
        gasMaskRecipe3.setIngredient('A', Material.DIAMOND);
        Bukkit.addRecipe(gasMaskRecipe3);
    }

    /**
     * Вспомогательный метод для создания настраиваемого предмета с именем и лором.
     *
     * @param material Материал предмета
     * @param name     Отображаемое имя предмета
     * @param lore     Лор предмета (может быть null)
     * @return Настроенный ItemStack
     */
    private ItemStack createCustomItem(Material material, String name, List<String> lore) {
        ItemStack item = new ItemStack(material);
        if (name != null || lore != null) {
            ItemMeta meta = item.getItemMeta();
            if (meta != null) {
                if (name != null) {
                    meta.setDisplayName(name);
                }
                if (lore != null) {
                    meta.setLore(lore);
                }
                meta.setUnbreakable(true); // Сделаем противогаз неразрушимым
                item.setItemMeta(meta);
            }
        }
        return item;
    }

    /**
     * Обработка команд плагина.
     */
    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {

        // Обработка команды /radiationcheck
        if (command.getName().equalsIgnoreCase("radiationcheck")) {
            if (!sender.hasPermission("radiationplugin.radiationcheck")) {
                sender.sendMessage(ChatColor.RED + "У вас нет прав для выполнения этой команды.");
                return true;
            }

            if (!(sender instanceof Player)) {
                sender.sendMessage("Эта команда может использоваться только игроками.");
                return true;
            }

            Player player = (Player) sender;
            int totalRadiation = getPlayerTotalRadiation(player);
            player.sendMessage(ChatColor.YELLOW + "Ваш суммарный уровень радиации: " + totalRadiation);
            return true;
        }

        // Обработка команды /radiationzone
        if (command.getName().equalsIgnoreCase("radiationzone")) {
            if (!sender.hasPermission("radiationplugin.radiationzone")) {
                sender.sendMessage(ChatColor.RED + "У вас нет прав для выполнения этой команды.");
                return true;
            }

            if (!(sender instanceof Player)) {
                sender.sendMessage("Эта команда может использоваться только игроками.");
                return true;
            }

            Player player = (Player) sender;

            if (args.length == 0) {
                player.sendMessage(ChatColor.RED + "Использование: /radiationzone <create|delete|list|info> [args]");
                return true;
            }

            switch (args[0].toLowerCase()) {
                case "create":
                    return handleCreateZone(player, args);
                case "delete":
                    return handleDeleteZone(player, args);
                case "list":
                    return handleListZones(player);
                case "info":
                    return handleInfoZone(player, args);
                default:
                    player.sendMessage(ChatColor.RED + "Неверная подкоманда. Используйте: create, delete, list, info");
                    return true;
            }
        }

        // Необработанная команда
        return false;
    }

    /**
     * Обработка создания радиационной зоны.
     *
     * @param player Игрок, выполняющий команду
     * @param args   Аргументы команды
     * @return true
     */
    private boolean handleCreateZone(Player player, String[] args) {
        if (args.length != 9) { // /radiationzone create <name> <min.x> <min.y> <min.z> <max.x> <max.y> <max.z> <duration_sec> <radiation>
            player.sendMessage(ChatColor.RED + "Использование: /radiationzone create <название> <min.x> <min.y> <min.z> <max.x> <max.y> <max.z> <duration_sec> <radiation>");
            return true;
        }

        try {
            String name = args[1];
            double minX = Double.parseDouble(args[2]);
            double minY = Double.parseDouble(args[3]);
            double minZ = Double.parseDouble(args[4]);
            double maxX = Double.parseDouble(args[5]);
            double maxY = Double.parseDouble(args[6]);
            double maxZ = Double.parseDouble(args[7]);
            int duration = Integer.parseInt(args[8]); // Продолжительность в секундах

            // Проверка продолжительности радиации
            if (duration <= 0) {
                player.sendMessage(ChatColor.RED + "Продолжительность должна быть положительным числом секунд.");
                return true;
            }

            // Проверка радиации
            // Получаем радиационный уровень из аргументов (можно изменить, если нужно)
            // Например, радиация равна уровню продолжительности или задана отдельно
            // В данном примере радиация берётся из параметра "radiation"
            // Так как args.length == 9, последний аргумент - это радиация
            int radiation = Integer.parseInt(args[8]);
            if (radiation <= 0) {
                player.sendMessage(ChatColor.RED + "Уровень радиации должен быть положительным числом.");
                return true;
            }

            // Проверка на существование зоны с таким именем
            if (zones.containsKey(name)) {
                player.sendMessage(ChatColor.RED + "Радиационная зона с таким названием уже существует.");
                return true;
            }

            // Проверка корректности координат
            if (minX >= maxX || minY >= maxY || minZ >= maxZ) {
                player.sendMessage(ChatColor.RED + "Некорректные координаты. min_* должны быть меньше max_*.");
                return true;
            }

            // Проверка на перекрытие с существующими зонами
            for (RadiationZone existingZone : zones.values()) {
                if (existingZone.overlapsWith(minX, minY, minZ, maxX, maxY, maxZ)) {
                    player.sendMessage(ChatColor.RED + "Зона перекрывается с существующей зоной: " + existingZone.getName());
                    return true;
                }
            }

            // Создание и добавление зоны
            RadiationZone zone = new RadiationZone(name, minX, minY, minZ, maxX, maxY, maxZ, radiation, duration);
            zones.put(name, zone);
            saveRadiationZones();

            player.sendMessage(ChatColor.GREEN + "Радиационная зона '" + name + "' успешно создана.");
            Bukkit.broadcastMessage(ChatColor.GOLD + "Создана новая радиационная зона: " + ChatColor.YELLOW + name);

        } catch (NumberFormatException e) {
            player.sendMessage(ChatColor.RED + "Ошибка: убедитесь, что координаты, продолжительность и уровень радиации указаны числами.");
            return true;
        } catch (ArrayIndexOutOfBoundsException e) {
            player.sendMessage(ChatColor.RED + "Недостаточно аргументов. Используйте: /radiationzone create <название> <min.x> <min.y> <min.z> <max.x> <max.y> <max.z> <duration_sec> <radiation>");
            return true;
        } catch (Exception e) {
            player.sendMessage(ChatColor.RED + "Произошла непредвиденная ошибка при создании зоны.");
            e.printStackTrace();
            return true;
        }

        return true;
    }

    /**
     * Обработка удаления радиационной зоны.
     *
     * @param player Игрок, выполняющий команду
     * @param args   Аргументы команды
     * @return true
     */
    private boolean handleDeleteZone(Player player, String[] args) {
        if (args.length != 2) { // /radiationzone delete <name>
            player.sendMessage(ChatColor.RED + "Использование: /radiationzone delete <имя>");
            return true;
        }

        String name = args[1];
        RadiationZone zone = zones.get(name);
        if (zone == null) {
            player.sendMessage(ChatColor.RED + "Радиационная зона с названием '" + name + "' не найдена.");
            return true;
        }

        zones.remove(name);
        saveRadiationZones();
        player.sendMessage(ChatColor.GREEN + "Радиационная зона '" + name + "' успешно удалена.");
        Bukkit.broadcastMessage(ChatColor.GOLD + "Радиационная зона была удалена: " + ChatColor.YELLOW + name);
        return true;
    }

    /**
     * Обработка отображения списка радиационных зон.
     *
     * @param player Игрок, выполняющий команду
     * @return true
     */
    private boolean handleListZones(Player player) {
        if (zones.isEmpty()) {
            player.sendMessage(ChatColor.YELLOW + "Нет активных радиационных зон.");
            return true;
        }

        player.sendMessage(ChatColor.GOLD + "Список активных радиационных зон:");
        for (RadiationZone zone : zones.values()) {
            player.sendMessage(ChatColor.GRAY + "- " + zone.getName() + " (Радиация: " + zone.radiation + ", Осталось: " + zone.getRemainingTime() + " сек)");
        }
        return true;
    }

    /**
     * Обработка отображения информации о конкретной радиационной зоне.
     *
     * @param player Игрок, выполняющий команду
     * @param args   Аргументы команды
     * @return true
     */
    private boolean handleInfoZone(Player player, String[] args) {
        if (args.length != 2) { // /radiationzone info <name>
            player.sendMessage(ChatColor.RED + "Использование: /radiationzone info <имя>");
            return true;
        }

        String name = args[1];
        RadiationZone zone = zones.get(name);
        if (zone == null) {
            player.sendMessage(ChatColor.RED + "Радиационная зона с названием '" + name + "' не найдена.");
            return true;
        }

        player.sendMessage(ChatColor.GOLD + "Информация о радиационной зоне '" + name + "':");
        player.sendMessage(ChatColor.WHITE + "Координаты: [" + zone.minX + ", " + zone.minY + ", " + zone.minZ + "] до [" + zone.maxX + ", " + zone.maxY + ", " + zone.maxZ + "]");
        player.sendMessage(ChatColor.WHITE + "Уровень радиации: " + zone.radiation);
        player.sendMessage(ChatColor.WHITE + "Осталось времени: " + zone.getRemainingTime() + " сек");
        return true;
    }

    /**
     * Запуск периодической задачи для проверки игроков в радиационных зонах.
     */
    private void startRadiationCheckerTask() {
        // Запуск задачи каждую секунду (20 тиков)
        new BukkitRunnable() {
            @Override
            public void run() {
                long currentTime = System.currentTimeMillis() / 1000; // Текущее время в секундах

                // Создание копии ключей для безопасного удаления во время итерации
                Set<String> zoneNames = new HashSet<>(zones.keySet());

                for (String zoneName : zoneNames) {
                    RadiationZone zone = zones.get(zoneName);
                    if (zone == null) continue;

                    // Проверка, истёкло ли время действия зоны
                    if (currentTime >= zone.endTime) {
                        zones.remove(zoneName);
                        saveRadiationZones();
                        Bukkit.broadcastMessage(ChatColor.GOLD + "Радиационная зона '" + zoneName + "' истекла и была удалена.");
                        continue;
                    }

                    // Визуализация зоны (опционально, можно убрать для оптимизации)
                    // visualizeZone(zoneName); // Переход к визуализации отдельны

                }

                // Проверка каждого игрока на нахождение в радиационных зонах
                for (Player player : Bukkit.getOnlinePlayers()) {
                    Location loc = player.getLocation();
                    UUID playerId = player.getUniqueId();
                    Set<String> currentZones = new HashSet<>();

                    // Определение зон, в которых находится игрок
                    for (RadiationZone zone : zones.values()) {
                        if (zone.isInZone(loc)) {
                            currentZones.add(zone.getName());
                        }
                    }

                    Set<String> previousZones = playerZones.getOrDefault(playerId, new HashSet<>());

                    // Определение вошел/вышел из зон
                    Set<String> enteredZones = new HashSet<>(currentZones);
                    enteredZones.removeAll(previousZones);

                    Set<String> exitedZones = new HashSet<>(previousZones);
                    exitedZones.removeAll(currentZones);

                    // Обновление текущих зон
                    playerZones.put(playerId, currentZones);

                    // Уведомление о входе в новые зоны
                    for (String zoneName : enteredZones) {
                        player.sendMessage(ChatColor.GREEN + "Вы вошли в радиационную зону: " + ChatColor.YELLOW + zoneName);
                        // Визуализация частиц при входе
                        visualizeZone(zoneName);
                    }

                    // Уведомление о выходе из зон
                    for (String zoneName : exitedZones) {
                        player.sendMessage(ChatColor.RED + "Вы покинули радиационную зону: " + ChatColor.YELLOW + zoneName);
                    }

                    // Расчёт суммарной радиации
                    int totalRadiation = 0;
                    for (String zoneName : currentZones) {
                        RadiationZone zone = zones.get(zoneName);
                        if (zone != null) {
                            totalRadiation += zone.radiation;
                        }
                    }

                    // Если радиация >0 и игрок не носит противогаз, увеличить уровень радиации
                    if (totalRadiation > 0 && !isWearingGasMask(player)) {
                        int currentRadiation = getPlayerRadiation(player);
                        currentRadiation += getRadiationIncrease();
                        setPlayerRadiation(player, currentRadiation);
                        player.sendMessage(ChatColor.YELLOW + "На вас накладывается " + getRadiationIncrease() + " ед. радиации.");
                    } else {
                        // Если радиация >0 и игрок носит противогаз
                        if (totalRadiation > 0 && isWearingGasMask(player)) {
                            int maskLevel = getPlayerGasMaskLevel(player);
                            int absorbedRadiation = maskLevel; // Абсорбация рад 1 уровня
                            int currentRadiation = getPlayerRadiation(player);
                            if (currentRadiation > absorbedRadiation) {
                                currentRadiation -= absorbedRadiation;
                            } else {
                                currentRadiation = 0;
                            }
                            setPlayerRadiation(player, currentRadiation);
                            player.sendMessage(ChatColor.AQUA + "Ваш противогаз абсорбировал " + absorbedRadiation + " ед. радиации.");
                        }

                        // Постепенное снижение радиации, если игрок не в зоне
                        if (totalRadiation == 0) {
                            int currentRadiation = getPlayerRadiation(player);
                            if (currentRadiation > 0) {
                                currentRadiation -= getRadiationDecrease();
                                if (currentRadiation < 0) currentRadiation = 0;
                                setPlayerRadiation(player, currentRadiation);
                                player.sendMessage(ChatColor.GREEN + "Ваша радиация уменьшилась на " + getRadiationDecrease() + " ед.");
                            }
                        }
                    }
                }
            }
        }.runTaskTimer(this, 0L, 20L); // Каждую секунду (20 тиков)
    }

    /**
     * Визуализация радиационной зоны с помощью частиц.
     *
     * @param zoneName Имя радиационной зоны
     */
    private void visualizeZone(String zoneName) {
        RadiationZone zone = zones.get(zoneName);
        if (zone == null) return;

        Bukkit.getScheduler().runTask(this, () -> {
            World world = Bukkit.getWorlds().get(0); // Использовать первый мир. Измените при необходимости.
            if (world == null) return;

            // Отображение частиц по краям зоны
            for (double x = zone.minX; x <= zone.maxX; x += (zone.maxX - zone.minX) / 20) {
                for (double y = zone.minY; y <= zone.maxY; y += (zone.maxY - zone.minY) / 20) {
                    // Верх и низ
                    Location locTop = new Location(world, x, zone.maxY, zone.minZ);
                    Location locTopOther = new Location(world, x, zone.maxY, zone.maxZ);
                    Location locBottom = new Location(world, x, zone.minY, zone.minZ);
                    Location locBottomOther = new Location(world, x, zone.minY, zone.maxZ);
                    world.spawnParticle(Particle.DUST_COLOR_TRANSITION, locTop, 1,
                            new Particle.DustTransition(Color.GREEN, Color.ORANGE, 1f));
                    world.spawnParticle(Particle.DUST_COLOR_TRANSITION, locTopOther, 1,
                            new Particle.DustTransition(Color.GREEN, Color.ORANGE, 1f));
                    world.spawnParticle(Particle.DUST_COLOR_TRANSITION, locBottom, 1,
                            new Particle.DustTransition(Color.GREEN, Color.ORANGE, 1f));
                    world.spawnParticle(Particle.DUST_COLOR_TRANSITION, locBottomOther, 1,
                            new Particle.DustTransition(Color.GREEN, Color.ORANGE, 1f));
                }
            }

            for (double z = zone.minZ; z <= zone.maxZ; z += (zone.maxZ - zone.minZ) / 20) {
                for (double y = zone.minY; y <= zone.maxY; y += (zone.maxY - zone.minY) / 20) {
                    // Стороны
                    Location locFront = new Location(world, zone.minX, y, z);
                    Location locFrontOther = new Location(world, zone.maxX, y, z);
                    world.spawnParticle(Particle.DUST_COLOR_TRANSITION, locFront, 1,
                            new Particle.DustTransition(Color.GREEN, Color.ORANGE, 1f));
                    world.spawnParticle(Particle.DUST_COLOR_TRANSITION, locFrontOther, 1,
                            new Particle.DustTransition(Color.GREEN, Color.ORANGE, 1f));
                }
            }
        });
    }

    /**
     * Получение уровня радиации игрока.
     *
     * @param player Игрок
     * @return Текущий уровень радиации
     */
    private int getPlayerRadiation(Player player) {
        UUID playerId = player.getUniqueId();
        return playerGasMaskLevels.getOrDefault(playerId, 0);
    }

    /**
     * Установка уровня радиации игрока.
     *
     * @param player     Игрок
     * @param radiation Новое значение радиации
     */
    private void setPlayerRadiation(Player player, int radiation) {
        UUID playerId = player.getUniqueId();
        if (radiation < 0) radiation = 0;
        playerGasMaskLevels.put(playerId, radiation);
    }

    /**
     * Постепенное увеличение радиации.
     *
     * @return Значение радиации для увеличения (1 или 2)
     */
    private int getRadiationIncrease() {
        Random rand = new Random();
        return rand.nextInt(2) + 1; // 1 или 2
    }

    /**
     * Постепенное снижение радиации.
     *
     * @return Значение радиации для снижения (1 или 2)
     */
    private int getRadiationDecrease() {
        Random rand = new Random();
        return rand.nextInt(2) + 1; // 1 или 2
    }

    /**
     * Получение уровня противогаза игрока.
     *
     * @param player Игрок
     * @return Уровень противогаза (1, 2, 3), или 0 если противогаза нет
     */
    private int getPlayerGasMaskLevel(Player player) {
        ItemStack helmet = player.getInventory().getHelmet();
        if (helmet == null || !helmet.hasItemMeta() || !helmet.getItemMeta().hasDisplayName()) {
            return 0;
        }

        String name = ChatColor.stripColor(helmet.getItemMeta().getDisplayName());
        if (name.equalsIgnoreCase("Противогаз I")) {
            return 800;
        } else if (name.equalsIgnoreCase("Противогаз II")) {
            return 2400;
        } else if (name.equalsIgnoreCase("Противогаз III")) {
            return 4800;
        } else {
            return 0;
        }
    }

    /**
     * Применение эффектов радиации к игроку на основе уровня радиации.
     *
     * @param player         Игрок, к которому применяются эффекты
     * @param totalRadiation Суммарный уровень радиации
     */
    private void applyRadiationEffects(Player player, int totalRadiation) {
        for (Map.Entry<Integer, EffectMapping> entry : effectMappings.entrySet()) {
            if (totalRadiation >= entry.getKey()) {
                EffectMapping mapping = entry.getValue();
                for (String effectName : mapping.effects) {
                    PotionEffectType effectType = PotionEffectType.getByName(effectName);
                    if (effectType != null) {
                        // Создание эффекта радиации
                        PotionEffect effect = new PotionEffect(effectType, mapping.duration, mapping.amplifier - 1, false, false);
                        player.addPotionEffect(effect, true);
                    } else {
                        getLogger().warning("PotionEffectType '" + effectName + "' не найден.");
                    }
                }
                break; // Применяем только самое высокое соответствие
            }
        }
    }

    /**
     * Удаление эффектов радиации из игрока.
     *
     * @param player Игрок, у которого удаляются эффекты
     */
    private void removeRadiationEffects(Player player) {
        for (EffectMapping mapping : effectMappings.values()) {
            for (String effectName : mapping.effects) {
                PotionEffectType effectType = PotionEffectType.getByName(effectName);
                if (effectType != null) {
                    player.removePotionEffect(effectType);
                }
            }
        }
    }

    /**
     * Обработка событий перемещения игрока для отслеживания входа/выхода из зон.
     *
     * @param event Событие перемещения игрока
     */
    @EventHandler
    public void onPlayerMove(PlayerMoveEvent event) {
        // Этот обработчик остаётся неиспользованным, так как мы используем периодические проверки.
        // Он может быть использован для дополнительной оптимизации или функциональности.
    }

    /**
     * Класс, представляющий радиационную зону.
     */
    private static class RadiationZone {
        private final String name;
        private final double minX, minY, minZ, maxX, maxY, maxZ;
        private final int radiation;
        private final int duration; // Продолжительность в секундах
        private final long endTime; // Время окончания в секундах

        public RadiationZone(String name, double minX, double minY, double minZ, double maxX, double maxY, double maxZ, int radiation, int duration) {
            this.name = name;
            this.minX = Math.min(minX, maxX);
            this.minY = Math.min(minY, maxY);
            this.minZ = Math.min(minZ, maxZ);
            this.maxX = Math.max(minX, maxX);
            this.maxY = Math.max(minY, maxY);
            this.maxZ = Math.max(minZ, maxZ);
            this.radiation = radiation;
            this.duration = duration;
            this.endTime = (System.currentTimeMillis() / 1000) + duration;
        }

        public String getName() {
            return name;
        }

        /**
         * Проверка, находится ли локация внутри радиационной зоны.
         *
         * @param loc Локация для проверки
         * @return true, если внутри зоны, иначе false
         */
        public boolean isInZone(Location loc) {
            return loc.getX() >= minX && loc.getX() <= maxX &&
                    loc.getY() >= minY && loc.getY() <= maxY &&
                    loc.getZ() >= minZ && loc.getZ() <= maxZ;
        }

        /**
         * Проверка перекрытия с другими зонами.
         *
         * @param otherMinX Другой minX
         * @param otherMinY Другой minY
         * @param otherMinZ Другой minZ
         * @param otherMaxX Другой maxX
         * @param otherMaxY Другой maxY
         * @param otherMaxZ Другой maxZ
         * @return true, если зоны перекрываются, иначе false
         */
        public boolean overlapsWith(double otherMinX, double otherMinY, double otherMinZ, double otherMaxX, double otherMaxY, double otherMaxZ) {
            return !(otherMinX > maxX || otherMaxX < minX ||
                    otherMinY > maxY || otherMaxY < minY ||
                    otherMinZ > maxZ || otherMaxZ < minZ);
        }

        /**
         * Получение оставшегося времени действия зоны в секундах.
         *
         * @return Оставшееся время в секундах
         */
        public int getRemainingTime() {
            long currentTime = System.currentTimeMillis() / 1000;
            long remaining = endTime - currentTime;
            return (int) Math.max(remaining, 0);
        }
    }

    /**
     * Класс, представляющий маппинг эффекта радиации.
     */
    private static class EffectMapping {
        private final int duration;
        private final int amplifier;
        private final List<String> effects;

        public EffectMapping(int duration, int amplifier, List<String> effects) {
            this.duration = duration;
            this.amplifier = amplifier;
            this.effects = effects;
        }
    }

    /**
     * Обработка автодополнения для команды /radiationzone.
     *
     * @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("radiationzone")) {
            if (args.length == 1) {
                return Arrays.asList("create", "delete", "list", "info");
            } else if (args.length >= 2) {
                String subCommand = args[0].toLowerCase();
                if (subCommand.equals("delete") || subCommand.equals("info")) {
                    List<String> zoneNames = new ArrayList<>(zones.keySet());
                    return zoneNames;
                }
            }
        }
        return Collections.emptyList();
    }
}

effect_mappings:
  100:
    duration: 90
    amplifier: 2
    effects:
      - POISON
  400:
    duration: 90
    amplifier: 4
    effects:
      - POISON
      - CONFUSION
  800:
    duration: 90
    amplifier: 6
    effects:
      - POISON
      - CONFUSION
      - BLINDNESS
  1600:
    duration: 90
    amplifier: 7
    effects:
      - POISON
      - CONFUSION
      - BLINDNESS
      - WEAKNESS
  3200:
    duration: 90
    amplifier: 10
    effects:
      - POISON
      - CONFUSION
      - BLINDNESS
      - WEAKNESS
      - WITHER

crafting_recipes:
  gas_mask_level_1:
    name: 'Противогаз I'
    type: 'LEATHER_HELMET'
    lore:
      - 'Защищает от радиации (уровень 1)'
    recipe:
      shape:
        - " I "
        - "IRI"
        - "RIR"
      ingredients:
        I: 'IRON_INGOT'
        R: 'REDSTONE'

  gas_mask_level_2:
    name: 'Противогаз II'
    type: 'LEATHER_HELMET'
    lore:
      - 'Защищает от радиации (уровень 2)'
    recipe:
      shape:
        - " I "
        - "IRI"
        - "RAR"
      ingredients:
        I: 'DIAMOND'
        R: 'REDSTONE'
        A: 'GOLD_INGOT'

  gas_mask_level_3:
    name: 'Противогаз III'
    type: 'LEATHER_HELMET'
    lore:
      - 'Защищает от радиации (уровень 3)'
    recipe:
      shape:
        - " I "
        - "ARA"
        - "RAR"
      ingredients:
        I: 'NETHERITE_INGOT'
        R: 'REDSTONE'
        A: 'DIAMOND'

name: RadiationPlugin
version: 1.1
main: com.yourpackage.RadiationPlugin
api-version: 1.20
commands:
  radiationzone:
    description: Управление радиационными зонами
    usage: /radiationzone <create|delete|list|info>
    permission: radiationplugin.radiationzone
  radiationcheck:
    description: Проверить уровень радиации
    usage: /radiationcheck
    permission: radiationplugin.radiationcheck
permissions:
  radiationplugin.radiationzone:
    description: Позволяет управлять радиационными зонами
    default: op
  radiationplugin.radiationcheck:
    description: Позволяет проверять уровень радиации
    default: true