// Path: api/src/main/java/net/techcable/npclib/ai/AIEnvironment.java
// @RequiredArgsConstructor
// public class AIEnvironment {
//     private final Set<AITask> tasks = new HashSet<>();
//     private final List<Runnable> callbacks = new ArrayList<>();
// 
//     protected void tick() {
//         for (final AITask task : tasks) {
//             try {
//                 task.tick(this);
//             } catch (Throwable t) {
//                 NPCLog.warn("AI task " + task.getClass().getSimpleName() + " threw an exception", t);
//             }
//         }
//         for (Runnable callback : callbacks) {
//             try {
//                 callback.run();
//             } catch (Throwable t) {
//                 NPCLog.warn("Callback " + callback.getClass().getSimpleName() + " threw an exception", t);
//             }
//         }
//         callbacks.clear();
//     }
// 
//     /**
//      * Add a callback to be ticked as soon as possible
//      * <p>
//      * Tasks are guaranteed to be ticked before callbacks
//      *
//      * @param callback the callback to run
//      */
//     public void addCallback(Runnable callback) {
//         Preconditions.checkNotNull(callback, "Null callback");
//         callbacks.add(callback);
//     }
// 
//     /**
//      * Remove this task from the ai environment
//      *
//      * @param task the task to remove
//      */
//     public void addTask(AITask task) {
//         Preconditions.checkNotNull(task, "Null task");
//         tasks.add(task);
//     }
// 
//     /**
//      * Remove this task from the ai environment
//      * <p>
//      * Does nothing if the task isn't there
//      *
//      * @param task the task to remove
//      */
//     public void removeTask(AITask task) {
//         Preconditions.checkNotNull(task, "Null task to remove");
//         tasks.remove(task);
//     }
// }
// 
// Path: api/src/main/java/net/techcable/npclib/ai/AITask.java
// public interface AITask {
// 
//     /**
//      * Run this task in the given ai environment
//      *
//      * @param environment the ai environment
//      */
//     public void tick(AIEnvironment environment);
// }


import java.util.UUID;
import net.techcable.npclib.ai.AIEnvironment;
import net.techcable.npclib.ai.AITask;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
package net.techcable.npclib;




/**
 * Represents a non player controlled nmsEntity
 *
 * @author Techcable
 * @version 2.0
 * @since 1.0
 */
public interface NPC {

    /**
     * Despawn this npc
     * <p/>
     * Once despawned it can not be respawned
     * It will be deregistered from the registry
     *
     * @return true if was able to despawn
     *
     * @throws java.lang.IllegalStateException if the npc is already despawned
     */
    public void despawn();

    /**
     * Get the nmsEntity associated with this npc
     *
     * @return the nmsEntity
     */
    public Entity getEntity();

    /**
     * Get this npc's uuid
     *
     * @return the uuid of this npc
     */
    public UUID getUUID();

    /**
     * Returns whether the npc is spawned
     *
     * @return true if the npc is spawned
     */
    public boolean isSpawned();

    /**
     * Returns whether the npc has been destroyed
     * <p>
     * NPCs that are destroyed can never be respawned
     * </p>
     *
     * @return true if the npc has been destroyed
     */
    public boolean isDestroyed();

    /**
     * Spawn this npc
     *
     * @param toSpawn location to spawn this npc
     *
     * @return true if the npc was able to spawn
     *
     * @throws java.lang.NullPointerException if location is null
     * @throws java.lang.IllegalArgumentException if already or spawned or {@link #despawn()} has been called
     */
    public void spawn(Location toSpawn);

    /**
     * Set the protected status of this NPC
     * true by default
     *
     * @param protect whether or not this npc is invincible
     */
    public void setProtected(boolean protect);

    /**
     * Check if the NPC is protected from damage
     *
     * @return The protected status of the NPC
     */
    public boolean isProtected();

    /**
     * Add the specified task to the npc
     *
     * @param task the task to add
     */
// Path: api/src/main/java/net/techcable/npclib/ai/AIEnvironment.java
// @RequiredArgsConstructor
// public class AIEnvironment {
//     private final Set<AITask> tasks = new HashSet<>();
//     private final List<Runnable> callbacks = new ArrayList<>();
// 
//     protected void tick() {
//         for (final AITask task : tasks) {
//             try {
//                 task.tick(this);
//             } catch (Throwable t) {
//                 NPCLog.warn("AI task " + task.getClass().getSimpleName() + " threw an exception", t);
//             }
//         }
//         for (Runnable callback : callbacks) {
//             try {
//                 callback.run();
//             } catch (Throwable t) {
//                 NPCLog.warn("Callback " + callback.getClass().getSimpleName() + " threw an exception", t);
//             }
//         }
//         callbacks.clear();
//     }
// 
//     /**
//      * Add a callback to be ticked as soon as possible
//      * <p>
//      * Tasks are guaranteed to be ticked before callbacks
//      *
//      * @param callback the callback to run
//      */
//     public void addCallback(Runnable callback) {
//         Preconditions.checkNotNull(callback, "Null callback");
//         callbacks.add(callback);
//     }
// 
//     /**
//      * Remove this task from the ai environment
//      *
//      * @param task the task to remove
//      */
//     public void addTask(AITask task) {
//         Preconditions.checkNotNull(task, "Null task");
//         tasks.add(task);
//     }
// 
//     /**
//      * Remove this task from the ai environment
//      * <p>
//      * Does nothing if the task isn't there
//      *
//      * @param task the task to remove
//      */
//     public void removeTask(AITask task) {
//         Preconditions.checkNotNull(task, "Null task to remove");
//         tasks.remove(task);
//     }
// }
// 
// Path: api/src/main/java/net/techcable/npclib/ai/AITask.java
// public interface AITask {
// 
//     /**
//      * Run this task in the given ai environment
//      *
//      * @param environment the ai environment
//      */
//     public void tick(AIEnvironment environment);
// }


// Path: api/src/main/java/net/techcable/npclib/NPC.java
import java.util.UUID;
import net.techcable.npclib.ai.AIEnvironment;
import net.techcable.npclib.ai.AITask;
import org.bukkit.Location;
import org.bukkit.entity.Entity;

package net.techcable.npclib;




/**
 * Represents a non player controlled nmsEntity
 *
 * @author Techcable
 * @version 2.0
 * @since 1.0
 */
public interface NPC {

    /**
     * Despawn this npc
     * <p/>
     * Once despawned it can not be respawned
     * It will be deregistered from the registry
     *
     * @return true if was able to despawn
     *
     * @throws java.lang.IllegalStateException if the npc is already despawned
     */
    public void despawn();

    /**
     * Get the nmsEntity associated with this npc
     *
     * @return the nmsEntity
     */
    public Entity getEntity();

    /**
     * Get this npc's uuid
     *
     * @return the uuid of this npc
     */
    public UUID getUUID();

    /**
     * Returns whether the npc is spawned
     *
     * @return true if the npc is spawned
     */
    public boolean isSpawned();

    /**
     * Returns whether the npc has been destroyed
     * <p>
     * NPCs that are destroyed can never be respawned
     * </p>
     *
     * @return true if the npc has been destroyed
     */
    public boolean isDestroyed();

    /**
     * Spawn this npc
     *
     * @param toSpawn location to spawn this npc
     *
     * @return true if the npc was able to spawn
     *
     * @throws java.lang.NullPointerException if location is null
     * @throws java.lang.IllegalArgumentException if already or spawned or {@link #despawn()} has been called
     */
    public void spawn(Location toSpawn);

    /**
     * Set the protected status of this NPC
     * true by default
     *
     * @param protect whether or not this npc is invincible
     */
    public void setProtected(boolean protect);

    /**
     * Check if the NPC is protected from damage
     *
     * @return The protected status of the NPC
     */
    public boolean isProtected();

    /**
     * Add the specified task to the npc
     *
     * @param task the task to add
     */
    public void addTask(AITask task);