// Path: src/main/java/com/endercrest/voidspawn/modes/BaseMode.java
// public abstract class BaseMode extends BasicOptionContainer implements Mode {
//     public static final OptionIdentifier<Sound> OPTION_SOUND = new OptionIdentifier<>(Sound.class, "sound", "The sound played when detected in void");
//     public static final OptionIdentifier<Float> OPTION_SOUND_VOLUME = new OptionIdentifier<>(Float.class, "sound_volume", "The sound volume");
//     public static final OptionIdentifier<Float> OPTION_SOUND_PITCH = new OptionIdentifier<>(Float.class, "sound_pitch", "The sound pitch");
//     public static final OptionIdentifier<Boolean> OPTION_HYBRID = new OptionIdentifier<>(Boolean.class, "hybrid", "Whether to run in hybrid mode (mode and command)");
//     public static final OptionIdentifier<Boolean> OPTION_KEEP_INVENTORY = new OptionIdentifier<>(Boolean.class, "keep_inventory", "Whether players keep inventory");
//     public static final OptionIdentifier<String> OPTION_MESSAGE = new OptionIdentifier<>(String.class, "message", "Message sent when detected in void");
//     public static final OptionIdentifier<String> OPTION_COMMAND = new OptionIdentifier<>(String.class, "command", "The command(s) for either command mode or hybrid");
//     public static final OptionIdentifier<Boolean> OPTION_INC_DEATH_STAT = new OptionIdentifier<>(Boolean.class, "inc_death_stat", "Whether to increment the death statistic");
//     public static final OptionIdentifier<Integer> OPTION_DAMAGE = new OptionIdentifier<>(Integer.class, "damage", "Amount of damage applied upon entering the void");
//     public static final OptionIdentifier<Integer> OPTION_BOUNCE = new OptionIdentifier<>(Integer.class, "bounce", "Number of times to bounce from the void before activating mode");
//     public static final OptionIdentifier<Float> OPTION_MIN_BOUNCE_VELOCITY = new OptionIdentifier<>(Float.class, "min_bounce_velocity", "The minimum bounce velocity");
// 
//     public BaseMode() {
//         attachOption(new SoundOption(OPTION_SOUND));
//         attachOption(new FloatOption(OPTION_SOUND_VOLUME, 1f));
//         attachOption(new FloatOption(OPTION_SOUND_PITCH, 1f));
//         attachOption(new BooleanOption(OPTION_HYBRID, false));
//         attachOption(new BooleanOption(OPTION_KEEP_INVENTORY, true));
//         attachOption(new StringOption(OPTION_MESSAGE));
//         attachOption(new StringOption(OPTION_COMMAND));
//         attachOption(new BooleanOption(OPTION_INC_DEATH_STAT, false));
//         attachOption(new IntegerOption(OPTION_DAMAGE, 0));
//         attachOption(new IntegerOption(OPTION_BOUNCE, 0));
//         attachOption(new FloatOption(OPTION_MIN_BOUNCE_VELOCITY, 2.0f));
//     }
// }
// 
// Path: src/main/java/com/endercrest/voidspawn/options/OptionIdentifier.java
// public class OptionIdentifier<T> {
//     private final Class<T> type;
//     private final String name;
//     private final String description;
// 
//     public OptionIdentifier(Class<T> type, String name, String description) {
//         this.type = type;
//         this.name = name;
//         this.description = description;
//     }
// 
//     public Class<T> getType() {
//         return type;
//     }
// 
//     public String getName() {
//         return name;
//     }
// 
//     public String getDescription() {
//         return description;
//     }
// }
// 
// Path: src/main/java/com/endercrest/voidspawn/utils/WorldUtil.java
// public class WorldUtil {
// 
//     public static String configSafe(String worldName){
//         return worldName.replace(" ", "_");
//     }
// 
//     /**
//      * Checks if the selected world is a valid world.
//      *
//      * @param worldName The world name that will be checked.
//      * @return True if the world does not return null.
//      */
//     public static boolean isValidWorld(String worldName){
//         return Bukkit.getWorld(worldName) != null;
//     }
// 
//     /**
//      * get a list of world names that begin with partial. If partial is
//      * empty, all worlds are returned.
//      * @param partial String to compare against.
//      * @return List of world names.
//      */
//     public static List<String> getMatchingWorlds(String partial) {
//         return Bukkit.getWorlds().stream()
//                 .map(World::getName)
//                 .filter(world -> world.toLowerCase().startsWith(partial.toLowerCase()))
//                 .collect(Collectors.toList());
//     }
// }


import com.endercrest.voidspawn.modes.BaseMode;
import com.endercrest.voidspawn.options.OptionIdentifier;
import com.endercrest.voidspawn.utils.WorldUtil;
import java.io.File;
import java.io.IOException;
import java.time.Instant;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
        set(world + ".spawn.y", loc.getY());
        set(world + ".spawn.z", loc.getZ());
        set(world + ".spawn.pitch", loc.getPitch());
        set(world + ".spawn.yaw", loc.getYaw());
        set(world + ".spawn.world", loc.getWorld().getName());
        saveConfig();
    }

    @Nullable
    public Location getSpawn(String world) {
        if(!isWorldSpawnSet(world))
            return null;

        world = WorldUtil.configSafe(world);


        return new Location(Bukkit.getWorld(getString(world + ".spawn.world", null)),
                getDouble(world + ".spawn.x", 0.0),
                getDouble(world + ".spawn.y", 0.0),
                getDouble(world + ".spawn.z", 0.0),
                getFloat(world + ".spawn.pitch", 0.0f),
                getFloat(world + ".spawn.yaw", 0.0f));
    }

    /**
     * Removes the spawn of a world based on the world name.
     *
     * @param world The world name.
     */
    public void removeSpawn(String world) {
// Path: src/main/java/com/endercrest/voidspawn/modes/BaseMode.java
// public abstract class BaseMode extends BasicOptionContainer implements Mode {
//     public static final OptionIdentifier<Sound> OPTION_SOUND = new OptionIdentifier<>(Sound.class, "sound", "The sound played when detected in void");
//     public static final OptionIdentifier<Float> OPTION_SOUND_VOLUME = new OptionIdentifier<>(Float.class, "sound_volume", "The sound volume");
//     public static final OptionIdentifier<Float> OPTION_SOUND_PITCH = new OptionIdentifier<>(Float.class, "sound_pitch", "The sound pitch");
//     public static final OptionIdentifier<Boolean> OPTION_HYBRID = new OptionIdentifier<>(Boolean.class, "hybrid", "Whether to run in hybrid mode (mode and command)");
//     public static final OptionIdentifier<Boolean> OPTION_KEEP_INVENTORY = new OptionIdentifier<>(Boolean.class, "keep_inventory", "Whether players keep inventory");
//     public static final OptionIdentifier<String> OPTION_MESSAGE = new OptionIdentifier<>(String.class, "message", "Message sent when detected in void");
//     public static final OptionIdentifier<String> OPTION_COMMAND = new OptionIdentifier<>(String.class, "command", "The command(s) for either command mode or hybrid");
//     public static final OptionIdentifier<Boolean> OPTION_INC_DEATH_STAT = new OptionIdentifier<>(Boolean.class, "inc_death_stat", "Whether to increment the death statistic");
//     public static final OptionIdentifier<Integer> OPTION_DAMAGE = new OptionIdentifier<>(Integer.class, "damage", "Amount of damage applied upon entering the void");
//     public static final OptionIdentifier<Integer> OPTION_BOUNCE = new OptionIdentifier<>(Integer.class, "bounce", "Number of times to bounce from the void before activating mode");
//     public static final OptionIdentifier<Float> OPTION_MIN_BOUNCE_VELOCITY = new OptionIdentifier<>(Float.class, "min_bounce_velocity", "The minimum bounce velocity");
// 
//     public BaseMode() {
//         attachOption(new SoundOption(OPTION_SOUND));
//         attachOption(new FloatOption(OPTION_SOUND_VOLUME, 1f));
//         attachOption(new FloatOption(OPTION_SOUND_PITCH, 1f));
//         attachOption(new BooleanOption(OPTION_HYBRID, false));
//         attachOption(new BooleanOption(OPTION_KEEP_INVENTORY, true));
//         attachOption(new StringOption(OPTION_MESSAGE));
//         attachOption(new StringOption(OPTION_COMMAND));
//         attachOption(new BooleanOption(OPTION_INC_DEATH_STAT, false));
//         attachOption(new IntegerOption(OPTION_DAMAGE, 0));
//         attachOption(new IntegerOption(OPTION_BOUNCE, 0));
//         attachOption(new FloatOption(OPTION_MIN_BOUNCE_VELOCITY, 2.0f));
//     }
// }
// 
// Path: src/main/java/com/endercrest/voidspawn/options/OptionIdentifier.java
// public class OptionIdentifier<T> {
//     private final Class<T> type;
//     private final String name;
//     private final String description;
// 
//     public OptionIdentifier(Class<T> type, String name, String description) {
//         this.type = type;
//         this.name = name;
//         this.description = description;
//     }
// 
//     public Class<T> getType() {
//         return type;
//     }
// 
//     public String getName() {
//         return name;
//     }
// 
//     public String getDescription() {
//         return description;
//     }
// }
// 
// Path: src/main/java/com/endercrest/voidspawn/utils/WorldUtil.java
// public class WorldUtil {
// 
//     public static String configSafe(String worldName){
//         return worldName.replace(" ", "_");
//     }
// 
//     /**
//      * Checks if the selected world is a valid world.
//      *
//      * @param worldName The world name that will be checked.
//      * @return True if the world does not return null.
//      */
//     public static boolean isValidWorld(String worldName){
//         return Bukkit.getWorld(worldName) != null;
//     }
// 
//     /**
//      * get a list of world names that begin with partial. If partial is
//      * empty, all worlds are returned.
//      * @param partial String to compare against.
//      * @return List of world names.
//      */
//     public static List<String> getMatchingWorlds(String partial) {
//         return Bukkit.getWorlds().stream()
//                 .map(World::getName)
//                 .filter(world -> world.toLowerCase().startsWith(partial.toLowerCase()))
//                 .collect(Collectors.toList());
//     }
// }


// Path: src/main/java/com/endercrest/voidspawn/ConfigManager.java
import com.endercrest.voidspawn.modes.BaseMode;
import com.endercrest.voidspawn.options.OptionIdentifier;
import com.endercrest.voidspawn.utils.WorldUtil;
import java.io.File;
import java.io.IOException;
import java.time.Instant;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;

        set(world + ".spawn.y", loc.getY());
        set(world + ".spawn.z", loc.getZ());
        set(world + ".spawn.pitch", loc.getPitch());
        set(world + ".spawn.yaw", loc.getYaw());
        set(world + ".spawn.world", loc.getWorld().getName());
        saveConfig();
    }

    @Nullable
    public Location getSpawn(String world) {
        if(!isWorldSpawnSet(world))
            return null;

        world = WorldUtil.configSafe(world);


        return new Location(Bukkit.getWorld(getString(world + ".spawn.world", null)),
                getDouble(world + ".spawn.x", 0.0),
                getDouble(world + ".spawn.y", 0.0),
                getDouble(world + ".spawn.z", 0.0),
                getFloat(world + ".spawn.pitch", 0.0f),
                getFloat(world + ".spawn.yaw", 0.0f));
    }

    /**
     * Removes the spawn of a world based on the world name.
     *
     * @param world The world name.
     */
    public void removeSpawn(String world) {
        world = WorldUtil.configSafe(world);