// Path: api/src/main/java/net/techcable/npclib/Animation.java
// @RequiredArgsConstructor
// public enum Animation {
//     /**
//      * Makes the npc act hurt
//      * <p/>
//      * Only applicable to living entities
//      */
//     HURT,
//     /**
//      * Makes the npc lie on the ground
//      * <p/>
//      * Only applicable to living entities
//      */
//     DEAD,
// 
//     // Human Animations
// 
//     /**
//      * Makes the npc swing its arm
//      * <p/>
//      * Only applicable to human entities
//      */
//     ARM_SWING(HumanNPC.class),
//     /**
//      * Makes the npc eat the item it is holding
//      * <p/>
//      * Only applicable to human entities
//      */
//     EAT(HumanNPC.class),
//     /**
//      * A critical hit animation
//      * <p/>
//      * Only applicable to human entities
//      */
//     CRITICAL(HumanNPC.class),
//     /**
//      * A 'magic' critical hit animation
//      * <p/>
//      * Only applicable to human entities
//      */
//     MAGIC_CRITICAL(HumanNPC.class);
// 
// 
//     private final Class<? extends NPC> appliesTo;
// 
//     /**
//      * Get the type of npc this animation can be applied to
//      *
//      * @return the type of npc this animation can be applied to
//      */
//     public Class<? extends NPC> getAppliesTo() {
//         return appliesTo;
//     }
// 
//     private Animation() {
//         this(LivingNPC.class);
//     }
// }
// 
// Path: api/src/main/java/net/techcable/npclib/LivingNPC.java
// public interface LivingNPC extends NPC {
// 
//     /**
//      * Set the current name of the npc
//      *
//      * @param name the new name
//      */
//     public void setName(String name);
// 
//     /**
//      * Retrieve the name of this npc
//      *
//      * @return this npc's name
//      */
//     public String getName();
// 
//     /**
//      * Get the nmsEntity associated with this npc
//      *
//      * @return the nmsEntity
//      */
//     @Override
//     public LivingEntity getEntity();
// 
//     /**
//      * The npc's head will look in this direction
//      *
//      * @param toFace the direction to look
//      */
//     public void faceLocation(Location toFace);
// 
//     /**
//      * Returns if the npc is an a condition to walk
//      *
//      * @return if the npc is an a condition to walk
//      */
//     public boolean isAbleToWalk();
// 
//     /**
//      * Walk to the specified location
//      *
//      * @param l the location to walk to
//      *
//      * @throws java.lang.IllegalStateException if not in a condition to walk
//      * @throws PathNotFoundException if the NPC could not walk to the specified location
//      * @throws NullPointerException if the location is null
//      */
//     public void walkTo(Location l) throws PathNotFoundException;
// 
//     /**
//      * Play the specified animation to all clients
//      *
//      * @param animation the animation to play
//      *
//      * @throws java.lang.IllegalArgumentException if the annotation can't be played on this type of npc
//      * @throws java.lang.IllegalStateException if the npc is not spawned
//      * @throws java.lang.UnsupportedOperationException if this implementation doesn't support the specified animation
//      */
//     public void animate(Animation animation);
// 
// }
// 
// Path: api/src/main/java/net/techcable/npclib/PathNotFoundException.java
// public class PathNotFoundException extends Exception {
//     public PathNotFoundException(Location to, Location from) {
//         super(String.format("Could not find a path to %s, %s, %s from %s, %s, %s", to.getX(), to.getY(), to.getZ(), from.getX(), from.getY(), from.getZ()));
//     }
// }
// 
// 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: nms/src/main/java/net/techcable/npclib/nms/ai/NMSAIEnvironment.java
// public class NMSAIEnvironment extends AIEnvironment {
// 
//     private final NMSNPC npc;
// 
//     public NMSAIEnvironment(final NMSNPC npc) {
//         this.npc = npc;
//         new BukkitRunnable() {
// 
//             @Override
//             public void run() {
//                 if (npc.isDestroyed()) cancel();
//                 if (!npc.isSpawned()) return;
//                 tick();
//             }
//         }.runTaskTimer(npc.getRegistry().getPlugin(), 0, 1);
//     }
// }


import lombok.*;
import java.util.UUID;
import net.techcable.npclib.Animation;
import net.techcable.npclib.LivingNPC;
import net.techcable.npclib.PathNotFoundException;
import net.techcable.npclib.ai.AITask;
import net.techcable.npclib.nms.ai.NMSAIEnvironment;
import org.bukkit.Location;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.LivingEntity;
import com.google.common.base.Preconditions;
package net.techcable.npclib.nms;






public abstract class NMSLivingNPC<T extends ILivingNPCHook> extends NMSNPC<T> implements LivingNPC {

    private final EntityType entityType;

    public NMSLivingNPC(NMSRegistry registry, UUID id, String name, EntityType entityType) {
        super(registry, id, name);
        this.entityType = entityType;
    }

    @Override
    public void setName(String s) {
        super.setName(s);
        if (isSpawned()) getHook().setName(s);
    }

    @Override
    public LivingEntity getEntity() {
        return (LivingEntity) super.getEntity();
    }

    @Override
// Path: api/src/main/java/net/techcable/npclib/Animation.java
// @RequiredArgsConstructor
// public enum Animation {
//     /**
//      * Makes the npc act hurt
//      * <p/>
//      * Only applicable to living entities
//      */
//     HURT,
//     /**
//      * Makes the npc lie on the ground
//      * <p/>
//      * Only applicable to living entities
//      */
//     DEAD,
// 
//     // Human Animations
// 
//     /**
//      * Makes the npc swing its arm
//      * <p/>
//      * Only applicable to human entities
//      */
//     ARM_SWING(HumanNPC.class),
//     /**
//      * Makes the npc eat the item it is holding
//      * <p/>
//      * Only applicable to human entities
//      */
//     EAT(HumanNPC.class),
//     /**
//      * A critical hit animation
//      * <p/>
//      * Only applicable to human entities
//      */
//     CRITICAL(HumanNPC.class),
//     /**
//      * A 'magic' critical hit animation
//      * <p/>
//      * Only applicable to human entities
//      */
//     MAGIC_CRITICAL(HumanNPC.class);
// 
// 
//     private final Class<? extends NPC> appliesTo;
// 
//     /**
//      * Get the type of npc this animation can be applied to
//      *
//      * @return the type of npc this animation can be applied to
//      */
//     public Class<? extends NPC> getAppliesTo() {
//         return appliesTo;
//     }
// 
//     private Animation() {
//         this(LivingNPC.class);
//     }
// }
// 
// Path: api/src/main/java/net/techcable/npclib/LivingNPC.java
// public interface LivingNPC extends NPC {
// 
//     /**
//      * Set the current name of the npc
//      *
//      * @param name the new name
//      */
//     public void setName(String name);
// 
//     /**
//      * Retrieve the name of this npc
//      *
//      * @return this npc's name
//      */
//     public String getName();
// 
//     /**
//      * Get the nmsEntity associated with this npc
//      *
//      * @return the nmsEntity
//      */
//     @Override
//     public LivingEntity getEntity();
// 
//     /**
//      * The npc's head will look in this direction
//      *
//      * @param toFace the direction to look
//      */
//     public void faceLocation(Location toFace);
// 
//     /**
//      * Returns if the npc is an a condition to walk
//      *
//      * @return if the npc is an a condition to walk
//      */
//     public boolean isAbleToWalk();
// 
//     /**
//      * Walk to the specified location
//      *
//      * @param l the location to walk to
//      *
//      * @throws java.lang.IllegalStateException if not in a condition to walk
//      * @throws PathNotFoundException if the NPC could not walk to the specified location
//      * @throws NullPointerException if the location is null
//      */
//     public void walkTo(Location l) throws PathNotFoundException;
// 
//     /**
//      * Play the specified animation to all clients
//      *
//      * @param animation the animation to play
//      *
//      * @throws java.lang.IllegalArgumentException if the annotation can't be played on this type of npc
//      * @throws java.lang.IllegalStateException if the npc is not spawned
//      * @throws java.lang.UnsupportedOperationException if this implementation doesn't support the specified animation
//      */
//     public void animate(Animation animation);
// 
// }
// 
// Path: api/src/main/java/net/techcable/npclib/PathNotFoundException.java
// public class PathNotFoundException extends Exception {
//     public PathNotFoundException(Location to, Location from) {
//         super(String.format("Could not find a path to %s, %s, %s from %s, %s, %s", to.getX(), to.getY(), to.getZ(), from.getX(), from.getY(), from.getZ()));
//     }
// }
// 
// 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: nms/src/main/java/net/techcable/npclib/nms/ai/NMSAIEnvironment.java
// public class NMSAIEnvironment extends AIEnvironment {
// 
//     private final NMSNPC npc;
// 
//     public NMSAIEnvironment(final NMSNPC npc) {
//         this.npc = npc;
//         new BukkitRunnable() {
// 
//             @Override
//             public void run() {
//                 if (npc.isDestroyed()) cancel();
//                 if (!npc.isSpawned()) return;
//                 tick();
//             }
//         }.runTaskTimer(npc.getRegistry().getPlugin(), 0, 1);
//     }
// }


// Path: nms/src/main/java/net/techcable/npclib/nms/NMSLivingNPC.java
import lombok.*;
import java.util.UUID;
import net.techcable.npclib.Animation;
import net.techcable.npclib.LivingNPC;
import net.techcable.npclib.PathNotFoundException;
import net.techcable.npclib.ai.AITask;
import net.techcable.npclib.nms.ai.NMSAIEnvironment;
import org.bukkit.Location;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.LivingEntity;
import com.google.common.base.Preconditions;

package net.techcable.npclib.nms;






public abstract class NMSLivingNPC<T extends ILivingNPCHook> extends NMSNPC<T> implements LivingNPC {

    private final EntityType entityType;

    public NMSLivingNPC(NMSRegistry registry, UUID id, String name, EntityType entityType) {
        super(registry, id, name);
        this.entityType = entityType;
    }

    @Override
    public void setName(String s) {
        super.setName(s);
        if (isSpawned()) getHook().setName(s);
    }

    @Override
    public LivingEntity getEntity() {
        return (LivingEntity) super.getEntity();
    }

    @Override
    public void walkTo(Location l) throws PathNotFoundException {