// 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: citizens/src/main/java/net/techcable/npclib/citizens/CitizensNPC.java
// public class CitizensNPC implements net.techcable.npclib.NPC {
// 
//     public CitizensNPC(NPC handle) {
//         this.handle = new WeakReference<NPC>(handle);
//     }
// 
//     public NPC getHandle() {
//         return handle.get();
//     }
// 
//     private final WeakReference<NPC> handle;
// 
//     private boolean destroyed;
// 
//     @Override
//     public void despawn() {
//         Preconditions.checkState(isSpawned(), "Already despawned");
//         getHandle().despawn();
//         getHandle().destroy();
//         destroyed = true;
//     }
// 
//     @Override
//     public Entity getEntity() {
//         if (getHandle() == null) return null;
//         return getHandle().getEntity();
//     }
// 
//     @Override
//     public UUID getUUID() {
//         return getHandle().getUniqueId();
//     }
// 
//     @Override
//     public boolean isSpawned() {
//         return getHandle() != null && getHandle().isSpawned();
//     }
// 
//     @Override
//     public boolean isDestroyed() {
//         return getHandle() == null || destroyed;
//     }
// 
//     @Override
//     public void spawn(Location toSpawn) {
//         Preconditions.checkNotNull(toSpawn, "Null location");
//         Preconditions.checkState(getHandle() != null, "This npc has been destroyed");
//         Preconditions.checkState(!isSpawned(), "Already spawned");
//         getHandle().spawn(toSpawn);
//     }
// 
//     @Override
//     public void setProtected(boolean protect) {
//         Preconditions.checkState(getHandle() != null, "This npc has been destroyed");
//         getHandle().setProtected(protect);
//     }
// 
//     @Override
//     public boolean isProtected() {
//         if (getHandle() == null) return false;
//         return getHandle().isProtected();
//     }
// 
//     @Override
//     public void addTask(AITask task) {
//         getAIEnvironment().addTask(task);
//     }
// 
//     @Getter(lazy = true)
//     private final CitizensAIEnvironment aIEnvironment = new CitizensAIEnvironment(this);
// }


import net.citizensnpcs.api.CitizensAPI;
import net.techcable.npclib.ai.AIEnvironment;
import net.techcable.npclib.citizens.CitizensNPC;
import org.bukkit.scheduler.BukkitRunnable;
package net.techcable.npclib.citizens.ai;



public class CitizensAIEnvironment extends AIEnvironment {

    private final CitizensNPC npc;

    public CitizensAIEnvironment(CitizensNPC npc) {
// 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: citizens/src/main/java/net/techcable/npclib/citizens/CitizensNPC.java
// public class CitizensNPC implements net.techcable.npclib.NPC {
// 
//     public CitizensNPC(NPC handle) {
//         this.handle = new WeakReference<NPC>(handle);
//     }
// 
//     public NPC getHandle() {
//         return handle.get();
//     }
// 
//     private final WeakReference<NPC> handle;
// 
//     private boolean destroyed;
// 
//     @Override
//     public void despawn() {
//         Preconditions.checkState(isSpawned(), "Already despawned");
//         getHandle().despawn();
//         getHandle().destroy();
//         destroyed = true;
//     }
// 
//     @Override
//     public Entity getEntity() {
//         if (getHandle() == null) return null;
//         return getHandle().getEntity();
//     }
// 
//     @Override
//     public UUID getUUID() {
//         return getHandle().getUniqueId();
//     }
// 
//     @Override
//     public boolean isSpawned() {
//         return getHandle() != null && getHandle().isSpawned();
//     }
// 
//     @Override
//     public boolean isDestroyed() {
//         return getHandle() == null || destroyed;
//     }
// 
//     @Override
//     public void spawn(Location toSpawn) {
//         Preconditions.checkNotNull(toSpawn, "Null location");
//         Preconditions.checkState(getHandle() != null, "This npc has been destroyed");
//         Preconditions.checkState(!isSpawned(), "Already spawned");
//         getHandle().spawn(toSpawn);
//     }
// 
//     @Override
//     public void setProtected(boolean protect) {
//         Preconditions.checkState(getHandle() != null, "This npc has been destroyed");
//         getHandle().setProtected(protect);
//     }
// 
//     @Override
//     public boolean isProtected() {
//         if (getHandle() == null) return false;
//         return getHandle().isProtected();
//     }
// 
//     @Override
//     public void addTask(AITask task) {
//         getAIEnvironment().addTask(task);
//     }
// 
//     @Getter(lazy = true)
//     private final CitizensAIEnvironment aIEnvironment = new CitizensAIEnvironment(this);
// }


// Path: citizens/src/main/java/net/techcable/npclib/citizens/ai/CitizensAIEnvironment.java
import net.citizensnpcs.api.CitizensAPI;
import net.techcable.npclib.ai.AIEnvironment;
import net.techcable.npclib.citizens.CitizensNPC;
import org.bukkit.scheduler.BukkitRunnable;

package net.techcable.npclib.citizens.ai;



public class CitizensAIEnvironment extends AIEnvironment {

    private final CitizensNPC npc;

    public CitizensAIEnvironment(CitizensNPC npc) {
        this.npc = npc;