Так у нас не созданы уровни радиации. Потом, в консоли очень часто пишется, что очищаются эффекты, давай без этого, чтобы как только была радиация 0, то ничего не очищалось, ладно?

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.InvalidConfigurationException;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.CraftItemEvent;
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.io.File;
import java.io.IOException;
import java.util.*;

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

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

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

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

    // Хранение уровней радиации для каждого игрока
    private final Map<UUID, Integer> playerRadiationLevels = new HashMap<>();

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

    // Файлы для хранения данных игроков
    private File playerDataFile;
    private FileConfiguration playerDataConfig;

    private FileConfiguration config;

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

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

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

        // Инициализация файла данных игроков
        initPlayerData();

        // Регистрация команд и обработчиков событий
        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();

        // Сохранение данных игроков
        savePlayerData();

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

    /**
     * Инициализация файла данных игроков.
     */
    private void initPlayerData() {
        playerDataFile = new File(getDataFolder(), "playerData.yml");
        if (!playerDataFile.exists()) {
            playerDataFile.getParentFile().mkdirs();
            saveResource("playerData.yml", false);
        }

        playerDataConfig = new YamlConfiguration();
        try {
            playerDataConfig.load(playerDataFile);
        } catch (IOException | InvalidConfigurationException e) {
            getLogger().severe("Не удалось загрузить playerData.yml");
            e.printStackTrace();
        }

        // Загрузка данных из файла
        for (String uuidString : playerDataConfig.getKeys(false)) {
            UUID uuid = UUID.fromString(uuidString);
            ConfigurationSection section = playerDataConfig.getConfigurationSection(uuidString);
            if (section != null) {
                int radiation = section.getInt("radiation", 0);
                int gasMask = section.getInt("gasMaskLevel", 0);
                playerRadiationLevels.put(uuid, radiation);
                playerGasMaskLevels.put(uuid, gasMask);
            }
        }
    }

    /**
     * Сохранение данных игроков в файл.
     */
    private void savePlayerData() {
        playerDataConfig = new YamlConfiguration();
        for (Map.Entry<UUID, Integer> entry : playerRadiationLevels.entrySet()) {
            UUID uuid = entry.getKey();
            int radiation = entry.getValue();
            int gasMask = playerGasMaskLevels.getOrDefault(uuid, 0);

            ConfigurationSection section = playerDataConfig.createSection(uuid.toString());
            section.set("radiation", radiation);
            section.set("gasMaskLevel", gasMask);
        }

        try {
            playerDataConfig.save(playerDataFile);
        } catch (IOException e) {
            getLogger().severe("Не удалось сохранить playerData.yml");
            e.printStackTrace();
        }
    }

    /**
     * Загрузка маппинга эффектов из конфигурации.
     */
    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("radiation_zones");
        if (zonesSection != null) {
            for (String zoneName : zonesSection.getKeys(false)) {
                ConfigurationSection zoneConfig = zonesSection.getConfigurationSection(zoneName);
                if (zoneConfig != null) {
                    String worldName = zoneConfig.getString("world");
                    if (worldName == null || Bukkit.getWorld(worldName) == null) {
                        getLogger().warning("Некорректное или отсутствующее имя мира для зоны: " + zoneName);
                        continue;
                    }
                    World world = Bukkit.getWorld(worldName);
                    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.getWorld().equals(world) &&
                                existingZone.overlapsWith(minX, minY, minZ, maxX, maxY, maxZ)) {
                            getLogger().warning("Зона " + zoneName + " перекрывается с зоной " + existingZone.getName() + ". Зона будет пропущена.");
                            overlaps = true;
                            break;
                        }
                    }
                    if (overlaps) continue;

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

    /**
     * Сохранение радиационных зон в конфигурацию.
     */
    private void saveRadiationZones() {
        ConfigurationSection zonesSection = config.getConfigurationSection("radiation_zones");
        if (zonesSection == null) {
            zonesSection = config.createSection("radiation_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("world", zone.getWorld().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 радиации)"), 100);
        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 радиации)"), 200);
        NamespacedKey gasMaskKey2 = new NamespacedKey(this, "gas_mask_level_2");
        ShapedRecipe gasMaskRecipe2 = new ShapedRecipe(gasMaskKey2, gasMask2);
        gasMaskRecipe2.shape(" I ", "IDI", "RIR");
        gasMaskRecipe2.setIngredient('I', Material.DIAMOND);
        gasMaskRecipe2.setIngredient('D', Material.DIAMOND);
        gasMaskRecipe2.setIngredient('R', Material.REDSTONE);
        Bukkit.addRecipe(gasMaskRecipe2);

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

        getLogger().info("Рецепты противогазов зарегистрированы.");
    }

    /**
     * Вспомогательный метод для создания настраиваемого предмета с именем, лором и прочностью.
     *
     * @param material    Материал предмета
     * @param name        Отображаемое имя предмета
     * @param lore        Лор предмета (может быть null)
     * @param durability  Прочность противогаза
     * @return Настроенный ItemStack
     */
    private ItemStack createCustomItem(Material material, String name, List<String> lore, int durability) {
        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) {
                    List<String> updatedLore = new ArrayList<>(lore);
                    updatedLore.add(ChatColor.GRAY + "Прочность: " + durability);
                    meta.setLore(updatedLore);
                }
                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);
            String radiationCheckMessage = config.getString("messages.radiation_check", "Ваш суммарный уровень радиации: %radiation%");
            radiationCheckMessage = radiationCheckMessage.replace("%radiation%", String.valueOf(totalRadiation));
            player.sendMessage(ChatColor.YELLOW + radiationCheckMessage);
            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) {
                String usageMessage = config.getString("messages.zone_usage", "Использование: /radiationzone <create|delete|list|info>");
                player.sendMessage(ChatColor.RED + usageMessage);
                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:
                    String invalidSubCommand = config.getString("messages.invalid_subcommand", "Неверная подкоманда. Используйте: create, delete, list, info");
                    player.sendMessage(ChatColor.RED + invalidSubCommand);
                    return true;
            }
        }

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

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

        try {
            String name = args[1];
            String worldName = args[2];
            World world = Bukkit.getWorld(worldName);
            if (world == null) {
                player.sendMessage(ChatColor.RED + "Мир '" + worldName + "' не найден.");
                return true;
            }
            double minX = Double.parseDouble(args[3]);
            double minY = Double.parseDouble(args[4]);
            double minZ = Double.parseDouble(args[5]);
            double maxX = Double.parseDouble(args[6]);
            double maxY = Double.parseDouble(args[7]);
            double maxZ = Double.parseDouble(args[8]);
            int duration = Integer.parseInt(args[9]); // Продолжительность в секундах
            int radiation = Integer.parseInt(args[10]); // Уровень радиации

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

            // Проверка радиации
            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.getWorld().equals(world) &&
                        existingZone.overlapsWith(minX, minY, minZ, maxX, maxY, maxZ)) {
                    player.sendMessage(ChatColor.RED + "Зона перекрывается с существующей зоной: " + existingZone.getName());
                    return true;
                }
            }

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

            player.sendMessage(ChatColor.GREEN + "Радиационная зона '" + name + "' успешно создана.");
            String broadcastCreate = config.getString("messages.zone_created", "Создана новая радиационная зона: %zone%");
            broadcastCreate = broadcastCreate.replace("%zone%", name);
            Bukkit.broadcastMessage(ChatColor.GOLD + broadcastCreate);
            visualizeZone(zone.getName());

        } catch (NumberFormatException e) {
            player.sendMessage(ChatColor.RED + "Ошибка: убедитесь, что координаты, продолжительность и уровень радиации указаны числами.");
            getLogger().warning("NumberFormatException при создании зоны: " + Arrays.toString(args));
            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>
            String deleteUsage = config.getString("messages.delete_usage", "Использование: /radiationzone delete <имя>");
            player.sendMessage(ChatColor.RED + deleteUsage);
            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 + "' успешно удалена.");
        String broadcastDelete = config.getString("messages.zone_deleted", "Радиационная зона была удалена: %zone%");
        broadcastDelete = broadcastDelete.replace("%zone%", name);
        Bukkit.broadcastMessage(ChatColor.GOLD + broadcastDelete);
        return true;
    }

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

        String listHeader = config.getString("messages.list_zones_header", "Список активных радиационных зон:");
        player.sendMessage(ChatColor.GOLD + listHeader);
        for (RadiationZone zone : zones.values()) {
            String zoneInfoTemplate = config.getString("messages.zone_info_list", "- %name% (Радиация: %radiation%, Осталось: %time% сек)");
            String zoneInfo = zoneInfoTemplate
                    .replace("%name%", zone.getName())
                    .replace("%radiation%", String.valueOf(zone.radiation))
                    .replace("%time%", String.valueOf(zone.getRemainingTime()));
            player.sendMessage(ChatColor.GRAY + zoneInfo);
        }
        return true;
    }

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

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

        String infoHeader = config.getString("messages.zone_info_header", "Информация о радиационной зоне '%zone%':");
        infoHeader = infoHeader.replace("%zone%", name);
        player.sendMessage(ChatColor.GOLD + infoHeader);

        String coordinates = config.getString("messages.zone_coordinates", "Координаты: [%minX%, %minY%, %minZ%] до [%maxX%, %maxY%, %maxZ%]");
        coordinates = coordinates.replace("%minX%", String.valueOf(zone.minX))
                .replace("%minY%", String.valueOf(zone.minY))
                .replace("%minZ%", String.valueOf(zone.minZ))
                .replace("%maxX%", String.valueOf(zone.maxX))
                .replace("%maxY%", String.valueOf(zone.maxY))
                .replace("%maxZ%", String.valueOf(zone.maxZ));
        player.sendMessage(ChatColor.WHITE + coordinates);

        String radiationLevel = config.getString("messages.zone_radiation", "Уровень радиации: %radiation%");
        radiationLevel = radiationLevel.replace("%radiation%", String.valueOf(zone.radiation));
        player.sendMessage(ChatColor.WHITE + radiationLevel);

        String remainingTime = config.getString("messages.zone_remaining_time", "Осталось времени: %time% сек");
        remainingTime = remainingTime.replace("%time%", String.valueOf(zone.getRemainingTime()));
        player.sendMessage(ChatColor.WHITE + remainingTime);
        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();
                        String broadcastExpire = config.getString("messages.zone_expired", "Радиационная зона '%zone%' истекла и была удалена.");
                        broadcastExpire = broadcastExpire.replace("%zone%", zoneName);
                        Bukkit.broadcastMessage(ChatColor.GOLD + broadcastExpire);
                        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) {
                        String enterMsgTemplate = config.getString("messages.enter_zone", "Вы вошли в радиационную зону: %zone%");
                        String enterMessage = enterMsgTemplate.replace("%zone%", zoneName);
                        player.sendMessage(ChatColor.GREEN + enterMessage);
                        // Визуализация частиц при входе
                        visualizeZone(zoneName);
                    }

                    // Уведомление о выходе из зон
                    for (String zoneName : exitedZones) {
                        String exitMsgTemplate = config.getString("messages.exit_zone", "Вы покинули радиационную зону: %zone%");
                        String exitMessage = exitMsgTemplate.replace("%zone%", zoneName);
                        player.sendMessage(ChatColor.RED + exitMessage);
                    }

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

                    // Обработка радиации
                    if (totalRadiation > 0) {
                        if (isWearingGasMask(player)) {
                            int maskLevel = getPlayerGasMaskLevel(player);
                            // Абсорбация радиации
                            int absorbedRadiation = maskLevel;
                            totalRadiation -= absorbedRadiation;
                            if (totalRadiation < 0) totalRadiation = 0;
                            addPlayerRadiation(player, absorbedRadiation);
                            String maskAbsorbMsg = config.getString("messages.gas_mask_absorb", "Ваш противогаз абсорбировал %amount% ед. радиации.");
                            maskAbsorbMsg = maskAbsorbMsg.replace("%amount%", String.valueOf(absorbedRadiation));
                            player.sendMessage(ChatColor.AQUA + maskAbsorbMsg);
                            // Уменьшение прочности противогаза
                            decreaseGasMaskDurability(player);
                        } else {
                            // Увеличение радиации без противогаза
                            int radiationIncrease = getRadiationChange();
                            addPlayerRadiation(player, radiationIncrease);
                            String radiationIncreaseMsg = config.getString("messages.radiation_increase", "На вас накладывается %amount% ед. радиации.");
                            radiationIncreaseMsg = radiationIncreaseMsg.replace("%amount%", String.valueOf(radiationIncrease));
                            player.sendMessage(ChatColor.YELLOW + radiationIncreaseMsg);
                        }
                    } else {
                        // Постепенное снижение радиации, если игрок не в зоне
                        int currentRadiation = getPlayerTotalRadiation(player);
                        if (currentRadiation > 0) {
                            int radiationDecrease = getRadiationChange();
                            removePlayerRadiation(player, radiationDecrease);
                            String radiationDecreaseMsg = config.getString("messages.radiation_decrease", "Ваша радиация уменьшилась на %amount% ед.");
                            radiationDecreaseMsg = radiationDecreaseMsg.replace("%amount%", String.valueOf(radiationDecrease));
                            player.sendMessage(ChatColor.GREEN + radiationDecreaseMsg);
                        }
                    }

                    // Применение эффектов радиации
                    int playerRadiation = getPlayerTotalRadiation(player);
                    applyRadiationEffects(player, playerRadiation);
                }
            }
        }.runTaskTimer(this, 0L, 20L); // Каждую секунду (20 тиков)
    }

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

        Bukkit.getScheduler().runTaskLater(this, () -> {
            World world = zone.getWorld();
            if (world == null) return;

            // Используем разные типы частиц для более реалистичного отображения
            Particle particleType = Particle.REDSTONE;
            Particle.DustOptions dustOptions = new Particle.DustOptions(Color.fromRGB(128, 0, 128), 0.5F);

            double step = 5.0; // Шаг для уменьшения количества частиц

            // Границы зоны
            for (double y = zone.minY; y <= zone.maxY; y += step) {
                // Передняя и задняя
                Location locFront = new Location(world, zone.minX, y, zone.minZ);
                Location locBack = new Location(world, zone.maxX, y, zone.maxZ);
                world.spawnParticle(particleType, locFront, 1, dustOptions);
                world.spawnParticle(particleType, locBack, 1, dustOptions);
            }

            for (double z = zone.minZ; z <= zone.maxZ; z += step) {
                // Левая и правая
                Location locLeft = new Location(world, zone.minX, zone.minY, z);
                Location locRight = new Location(world, zone.maxX, zone.maxY, z);
                world.spawnParticle(particleType, locLeft, 1, dustOptions);
                world.spawnParticle(particleType, locRight, 1, dustOptions);
            }

            for (double x = zone.minX; x <= zone.maxX; x += step) {
                // Верхняя и нижняя
                Location locBottom = new Location(world, x, zone.minY, zone.minZ);
                Location locTop = new Location(world, x, zone.maxY, zone.maxZ);
                world.spawnParticle(particleType, locBottom, 1, dustOptions);
                world.spawnParticle(particleType, locTop, 1, dustOptions);
            }

            // Центральная область с частицами для дополнительного эффекта
            int particleDensity = 5; // Плотность частиц
            for (int i = 0; i < particleDensity; i++) {
                double x = zone.minX + Math.random() * (zone.maxX - zone.minX);
                double y = zone.minY + Math.random() * (zone.maxY - zone.minY);
                double z = zone.minZ + Math.random() * (zone.maxZ - zone.minZ);
                Location loc = new Location(world, x, y, z);
                world.spawnParticle(Particle.CRIT, loc, 0, 0, 0, 0, 1);
            }
        }, 0L); // Запускается сразу
    }

    /**
     * Обработка событий крафта для проверки наличия предыдущих уровней противогаза.
     *
     * @param event Событие крафта предмета
     */
    @EventHandler
    public void onCraftItem(CraftItemEvent event) {
        if (!(event.getInventory() instanceof CraftingInventory)) {
            return;
        }

        CraftingInventory craftingInventory = (CraftingInventory) event.getInventory();

        if (event.getRecipe() instanceof ShapedRecipe) {
            ShapedRecipe recipe = (ShapedRecipe) event.getRecipe();
            ItemStack result = recipe.getResult();
            if (result.hasItemMeta() && result.getItemMeta().hasDisplayName()) {
                String name = ChatColor.stripColor(result.getItemMeta().getDisplayName());
                if (name.equalsIgnoreCase("Противогаз II")) {
                    if (!containsItemInCraftingGrid(craftingInventory, ChatColor.AQUA + "Противогаз I")) {
                        String msg = config.getString("messages.craft_require_previous", "Для крафта Противогаза II требуется Противогаз I в сетке.");
                        event.getWhoClicked().sendMessage(ChatColor.RED + msg);
                        event.setCancelled(true);
                        return;
                    }
                } else if (name.equalsIgnoreCase("Противогаз III")) {
                    if (!containsItemInCraftingGrid(craftingInventory, ChatColor.DARK_AQUA + "Противогаз II")) {
                        String msg = config.getString("messages.craft_require_previous", "Для крафта Противогаза III требуется Противогаз II в сетке.");
                        event.getWhoClicked().sendMessage(ChatColor.RED + msg);
                        event.setCancelled(true);
                        return;
                    }
                }
            }
        }
    }

    /**
     * Проверка наличия конкретного предмета в сетке крафта.
     *
     * @param inventory Инвентарь крафта
     * @param itemName  Отображаемое имя искомого предмета
     * @return true, если предмет найден, иначе false
     */
    private boolean containsItemInCraftingGrid(CraftingInventory inventory, String itemName) {
        for (ItemStack item : inventory.getMatrix()) {
            if (item != null && item.hasItemMeta() && item.getItemMeta().hasDisplayName()) {
                String name = ChatColor.stripColor(item.getItemMeta().getDisplayName());
                if (name.equalsIgnoreCase(itemName)) {
                    return true;
                }
            }
        }
        return false;
    }

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

    /**
     * Увеличение уровня радиации игрока.
     *
     * @param player Игрок
     * @param amount Количество радиации для добавления
     */
    private void addPlayerRadiation(Player player, int amount) {
        UUID playerId = player.getUniqueId();
        int currentRadiation = playerRadiationLevels.getOrDefault(playerId, 0);
        currentRadiation += amount;
        playerRadiationLevels.put(playerId, currentRadiation);
        getLogger().info("Игрок " + player.getName() + " получил радиацию: +" + amount + " (Всего: " + currentRadiation + ")");
    }

    /**
     * Уменьшение уровня радиации игрока.
     *
     * @param player Игрок
     * @param amount Количество радиации для уменьшения
     */
    private void removePlayerRadiation(Player player, int amount) {
        UUID playerId = player.getUniqueId();
        int currentRadiation = playerRadiationLevels.getOrDefault(playerId, 0);
        currentRadiation -= amount;
        if (currentRadiation < 0) currentRadiation = 0;
        playerRadiationLevels.put(playerId, currentRadiation);
        getLogger().info("У игрока " + player.getName() + " снизилась радиация: -" + amount + " (Всего: " + currentRadiation + ")");
    }

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

    /**
     * Получение уровня противогаза игрока.
     *
     * @param player Игрок
     * @return Уровень противогаза (800, 2400, 4800), или 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 Игрок
     * @return true, если носит противогаз, иначе false
     */
    private boolean isWearingGasMask(Player player) {
        return getPlayerGasMaskLevel(player) > 0;
    }

    /**
     * Применение эффектов радиации к игроку на основе уровня радиации.
     *
     * @param player         Игрок, к которому применяются эффекты
     * @param totalRadiation Суммарный уровень радиации
     */
    private void applyRadiationEffects(Player player, int totalRadiation) {
        // Удаление всех предыдущих радиационных эффектов
        removeRadiationEffects(player);

        // Применение новых эффектов на основе текущего уровня радиации
        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 * 20, mapping.amplifier - 1, false, false);
                        player.addPotionEffect(effect, true);
                        getLogger().info("Применён эффект " + effectName + " к игроку " + player.getName());
                    } 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);
                    getLogger().info("Удалён эффект " + effectName + " у игрока " + player.getName());
                }
            }
        }
    }

    /**
     * Уменьшение прочности противогаза игрока и обновление лора.
     *
     * @param player Игрок
     */
    private void decreaseGasMaskDurability(Player player) {
        ItemStack helmet = player.getInventory().getHelmet();
        if (helmet == null || !helmet.hasItemMeta() || !helmet.getItemMeta().hasDisplayName()) {
            return;
        }

        ItemMeta meta = helmet.getItemMeta();
        if (meta == null || !meta.hasLore()) {
            return;
        }

        List<String> lore = new ArrayList<>(meta.getLore());
        if (lore.isEmpty()) return;

        // Предполагается, что последняя строка лора содержит прочность
        String durabilityLine = lore.get(lore.size() - 1);
        String[] parts = durabilityLine.split(": ");
        if (parts.length != 2) return;

        try {
            int durability = Integer.parseInt(parts[1]);
            durability -= 10; // Уменьшаем прочность на 10
            if (durability <= 0) {
                // Удаляем противогаз, если прочность истощена
                player.getInventory().setHelmet(null);
                player.sendMessage(ChatColor.RED + "Ваш противогаз сломался.");
                return;
            }

            // Обновляем прочность в лоре
            lore.set(lore.size() - 1, ChatColor.GRAY + "Прочность: " + durability);
            meta.setLore(lore);
            helmet.setItemMeta(meta);
            // Обновляем запись в map
            playerGasMaskLevels.put(player.getUniqueId(), getPlayerGasMaskLevel(player));
        } catch (NumberFormatException e) {
            // Если не удалось распарсить прочность, ничего не делаем
        }
    }

    /**
     * Класс, представляющий радиационную зону.
     */
    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; // Время окончания в секундах
        private final String worldName;

        public RadiationZone(String name, String worldName, double minX, double minY, double minZ,
                             double maxX, double maxY, double maxZ,
                             int radiation, int duration) {
            this.name = name;
            this.worldName = worldName;
            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;
        }

        public World getWorld() {
            return Bukkit.getWorld(worldName);
        }

        /**
         * Проверка, находится ли локация внутри радиационной зоны.
         *
         * @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

# Радиоактивные зоны будут храниться в секции radiation_zones
radiation_zones:

messages:
  radiation_check: "Ваш суммарный уровень радиации: %radiation%"
  zone_usage: "Использование: /radiationzone <create|delete|list|info>"
  invalid_subcommand: "Неверная подкоманда. Используйте: create, delete, list, info"
  create_usage: "Использование: /radiationzone create <название> <мир> <min.x> <min.y> <min.z> <max.x> <max.y> <max.z> <duration_sec> <radiation>"
  delete_usage: "Использование: /radiationzone delete <имя>"
  no_active_zones: "Нет активных радиационных зон."
  list_zones_header: "Список активных радиационных зон:"
  zone_info_list: "- %name% (Радиация: %radiation%, Осталось: %time% сек)"
  zone_info_header: "Информация о радиационной зоне '%zone%':"
  zone_coordinates: "Координаты: [%minX%, %minY%, %minZ%] до [%maxX%, %maxY%, %maxZ%]"
  zone_radiation: "Уровень радиации: %radiation%"
  zone_remaining_time: "Осталось времени: %time% сек"
  zone_created: "Создана новая радиационная зона: %zone%"
  zone_deleted: "Радиационная зона была удалена: %zone%"
  zone_expired: "Радиационная зона '%zone%' истекла и была удалена."
  enter_zone: "Вы вошли в радиационную зону: %zone%"
  exit_zone: "Вы покинули радиационную зону: %zone%"
  radiation_increase: "На вас накладывается %amount% ед. радиации."
  radiation_decrease: "Ваша радиация уменьшилась на %amount% ед."
  gas_mask_absorb: "Ваш противогаз абсорбировал %amount% ед. радиации."
  craft_require_previous: "Для крафта %target% требуется %required% в сетке крафта."