// Path: src/main/java/com/endercrest/voidspawn/detectors/NetherDetector.java
// public class NetherDetector extends VoidDetector {
//     public static final OptionIdentifier<Integer> OPTION_ROOF = new OptionIdentifier<>(Integer.class, "roof_height", "The height to detect at on the roof (default 128)");
// 
//     public NetherDetector() {
//         attachOption(new IntegerOption(OPTION_ROOF, 128));
//     }
// 
//     @Override
//     public boolean isDetected(Mode mode, Player player, World world) {
//         Option<Integer> voidOption = getOption(OPTION_ROOF);
//         int checkHeight = voidOption.getValue(world).orElse(128);
// 
//         return player.getLocation().getBlockY() > checkHeight || super.isDetected(mode, player, world);
//     }
// 
//     @Override
//     public String getDescription() {
//         return "Activated when entering the void or going above nether bedrock level.";
//     }
// 
//     @Override
//     public String getName() {
//         return "Nether";
//     }
// }
// 
// Path: src/main/java/com/endercrest/voidspawn/detectors/Detector.java
// public interface Detector extends OptionContainer {
// 
//     /**
//      * Checks if the current player is within the 'detected' region. This is used to signal to the mode whether it
//      * should activate
//      * @param mode The current mode
//      * @param player The player
//      * @param world The world
//      */
//     boolean isDetected(Mode mode, Player player, World world);
// 
//     String getDescription();
// 
//     /**
//      * Get the name of the detector.
//      *
//      * @return The string version of the mode.
//      */
//     String getName();
// }
// 
// Path: src/main/java/com/endercrest/voidspawn/detectors/VoidDetector.java
// public class VoidDetector extends BaseDetector {
//     @Override
//     public boolean isDetected(Mode mode, Player player, World world) {
//         Option<Integer> voidOption = getOption(BaseDetector.OPTION_VOID);
//         int checkHeight = voidOption.getValue(world).orElse(world.getMinHeight());
// 
//         return player.getLocation().getBlockY() < checkHeight;
//     }
// 
//     @Override
//     public String getDescription() {
//         return "Activated by entering the void. [Default]";
//     }
// 
//     @Override
//     public String getName() {
//         return "Void";
//     }
// }


import com.endercrest.voidspawn.detectors.NetherDetector;
import com.endercrest.voidspawn.detectors.Detector;
import com.endercrest.voidspawn.detectors.VoidDetector;
import javax.naming.NameAlreadyBoundException;
import java.util.HashMap;
package com.endercrest.voidspawn;



public class DetectorManager {

    private static DetectorManager instance = new DetectorManager();

    public static DetectorManager getInstance() {
        return instance;
    }

    private Detector defaultDetector;
    private HashMap<String, Detector> detectors;

    /**
     * Setup the DetectorManager, should only be called once.
     */
    public void setUp() {
        defaultDetector = new VoidDetector();

        detectors = new HashMap<String, Detector>() {{
            put("void", defaultDetector);
            put("nether", new NetherDetector());
        }};
    }

    /**
     * Gets a HashMap of the detectors.
     *
     * @return A clone of the detectors HashMap where string is the key of the detector and SubDetector is detector class.
     */
    public HashMap<String, Detector> getDetectors() {
        return new HashMap<>(detectors);
    }

    /**
     * Add a new detector that can be accessed in-game and be set for worlds.
     *
     * @param name     The name of the detector.
     * @param detector The class definition.
     * @throws NameAlreadyBoundException Thrown when the detector has already been set with that name.
     */
    public void addDetector(String name, Detector detector) throws NameAlreadyBoundException {
        name = name.toLowerCase();

        if (detectors.containsKey(name))
            throw new NameAlreadyBoundException(String.format("A detector with the name %s has already been set.", name));

        detectors.put(name, detector);
    }

    /**
     * Removes detector, from being selectable and stops world from using this detector.
     *
     * @param name The name of the detector.
     */
// Path: src/main/java/com/endercrest/voidspawn/detectors/NetherDetector.java
// public class NetherDetector extends VoidDetector {
//     public static final OptionIdentifier<Integer> OPTION_ROOF = new OptionIdentifier<>(Integer.class, "roof_height", "The height to detect at on the roof (default 128)");
// 
//     public NetherDetector() {
//         attachOption(new IntegerOption(OPTION_ROOF, 128));
//     }
// 
//     @Override
//     public boolean isDetected(Mode mode, Player player, World world) {
//         Option<Integer> voidOption = getOption(OPTION_ROOF);
//         int checkHeight = voidOption.getValue(world).orElse(128);
// 
//         return player.getLocation().getBlockY() > checkHeight || super.isDetected(mode, player, world);
//     }
// 
//     @Override
//     public String getDescription() {
//         return "Activated when entering the void or going above nether bedrock level.";
//     }
// 
//     @Override
//     public String getName() {
//         return "Nether";
//     }
// }
// 
// Path: src/main/java/com/endercrest/voidspawn/detectors/Detector.java
// public interface Detector extends OptionContainer {
// 
//     /**
//      * Checks if the current player is within the 'detected' region. This is used to signal to the mode whether it
//      * should activate
//      * @param mode The current mode
//      * @param player The player
//      * @param world The world
//      */
//     boolean isDetected(Mode mode, Player player, World world);
// 
//     String getDescription();
// 
//     /**
//      * Get the name of the detector.
//      *
//      * @return The string version of the mode.
//      */
//     String getName();
// }
// 
// Path: src/main/java/com/endercrest/voidspawn/detectors/VoidDetector.java
// public class VoidDetector extends BaseDetector {
//     @Override
//     public boolean isDetected(Mode mode, Player player, World world) {
//         Option<Integer> voidOption = getOption(BaseDetector.OPTION_VOID);
//         int checkHeight = voidOption.getValue(world).orElse(world.getMinHeight());
// 
//         return player.getLocation().getBlockY() < checkHeight;
//     }
// 
//     @Override
//     public String getDescription() {
//         return "Activated by entering the void. [Default]";
//     }
// 
//     @Override
//     public String getName() {
//         return "Void";
//     }
// }


// Path: src/main/java/com/endercrest/voidspawn/DetectorManager.java
import com.endercrest.voidspawn.detectors.NetherDetector;
import com.endercrest.voidspawn.detectors.Detector;
import com.endercrest.voidspawn.detectors.VoidDetector;
import javax.naming.NameAlreadyBoundException;
import java.util.HashMap;

package com.endercrest.voidspawn;



public class DetectorManager {

    private static DetectorManager instance = new DetectorManager();

    public static DetectorManager getInstance() {
        return instance;
    }

    private Detector defaultDetector;
    private HashMap<String, Detector> detectors;

    /**
     * Setup the DetectorManager, should only be called once.
     */
    public void setUp() {
        defaultDetector = new VoidDetector();

        detectors = new HashMap<String, Detector>() {{
            put("void", defaultDetector);
            put("nether", new NetherDetector());
        }};
    }

    /**
     * Gets a HashMap of the detectors.
     *
     * @return A clone of the detectors HashMap where string is the key of the detector and SubDetector is detector class.
     */
    public HashMap<String, Detector> getDetectors() {
        return new HashMap<>(detectors);
    }

    /**
     * Add a new detector that can be accessed in-game and be set for worlds.
     *
     * @param name     The name of the detector.
     * @param detector The class definition.
     * @throws NameAlreadyBoundException Thrown when the detector has already been set with that name.
     */
    public void addDetector(String name, Detector detector) throws NameAlreadyBoundException {
        name = name.toLowerCase();

        if (detectors.containsKey(name))
            throw new NameAlreadyBoundException(String.format("A detector with the name %s has already been set.", name));

        detectors.put(name, detector);
    }

    /**
     * Removes detector, from being selectable and stops world from using this detector.
     *
     * @param name The name of the detector.
     */
    public void removeDetector(String name) {