/**
  * Damages an entity with as cause another entity
  *
  * @param entity to be damaged
  * @param damager that damages
  * @param damage to deal
  */
 public static void damageBy(
     org.bukkit.entity.Entity entity, org.bukkit.entity.Entity damager, double damage) {
   DamageSource source;
   if (damager instanceof Player) {
     source = DamageSource.playerAttack(CommonNMS.getNative((Player) damager));
   } else if (damager instanceof LivingEntity) {
     source = DamageSource.mobAttack(CommonNMS.getNative((LivingEntity) damager));
   } else {
     source = DamageSource.GENERIC;
   }
   CommonNMS.getNative(entity).damageEntity(source, (float) damage);
 }
 /**
  * Damages an entity
  *
  * @param entity to be damagedd
  * @param cause of the damage
  * @param damage to deal
  */
 public static void damage(org.bukkit.entity.Entity entity, DamageCause cause, int damage) {
   DamageSource source;
   if (cause == DamageCause.BLOCK_EXPLOSION) {
     source = DamageSource.EXPLOSION;
   } else if (cause == DamageCause.CONTACT) {
     source = DamageSource.CACTUS;
   } else if (cause == DamageCause.DROWNING) {
     source = DamageSource.DROWN;
   } else if (cause == DamageCause.FALL) {
     source = DamageSource.FALL;
   } else if (cause == DamageCause.FALLING_BLOCK) {
     source = DamageSource.FALLING_BLOCK;
   } else if (cause == DamageCause.FIRE) {
     source = DamageSource.FIRE;
   } else if (cause == DamageCause.LAVA) {
     source = DamageSource.LAVA;
   } else if (cause == DamageCause.MAGIC) {
     source = DamageSource.MAGIC;
   } else if (cause == DamageCause.VOID) {
     source = DamageSource.OUT_OF_WORLD;
   } else if (cause == DamageCause.STARVATION) {
     source = DamageSource.STARVE;
   } else if (cause == DamageCause.SUFFOCATION) {
     source = DamageSource.STUCK;
   } else if (cause == DamageCause.WITHER) {
     source = DamageSource.WITHER;
   } else {
     source = DamageSource.GENERIC;
   }
   CommonNMS.getNative(entity).damageEntity(source, damage);
 }
 public static Object newInstance(Material type, int data, int amount) {
   // Why is Bukkit unable to create proper constructors? Really? -,-
   Object instance = constructor1.newInstance(Blocks.STONE, 1, 1);
   ItemStackRef.type.set(instance, CommonNMS.getItem(type));
   ItemStackRef.data.set(instance, data);
   ItemStackRef.amount.set(instance, amount);
   return instance;
 }
 /**
  * Damages an entity
  *
  * @param entity to be damagedd
  * @param cause of the damage
  * @param damage to deal
  */
 public static void damage(org.bukkit.entity.Entity entity, DamageCause cause, double damage) {
   DamageSource source;
   if (cause == DamageCause.BLOCK_EXPLOSION) {
     Location loc = entity.getLocation();
     World worldhandle = CommonNMS.getNative(loc.getWorld());
     Explosion ex =
         new Explosion(
             worldhandle, null, loc.getX(), loc.getY(), loc.getZ(), (float) 4.0, true, true);
     source = DamageSource.explosion(ex);
   } else if (cause == DamageCause.CONTACT) {
     source = DamageSource.CACTUS;
   } else if (cause == DamageCause.DROWNING) {
     source = DamageSource.DROWN;
   } else if (cause == DamageCause.FALL) {
     source = DamageSource.FALL;
   } else if (cause == DamageCause.FALLING_BLOCK) {
     source = DamageSource.FALLING_BLOCK;
   } else if (cause == DamageCause.FIRE) {
     source = DamageSource.FIRE;
   } else if (cause == DamageCause.LAVA) {
     source = DamageSource.LAVA;
   } else if (cause == DamageCause.MAGIC) {
     source = DamageSource.MAGIC;
   } else if (cause == DamageCause.VOID) {
     source = DamageSource.OUT_OF_WORLD;
   } else if (cause == DamageCause.STARVATION) {
     source = DamageSource.STARVE;
   } else if (cause == DamageCause.SUFFOCATION) {
     source = DamageSource.STUCK;
   } else if (cause == DamageCause.WITHER) {
     source = DamageSource.WITHER;
   } else {
     source = DamageSource.GENERIC;
   }
   CommonNMS.getNative(entity).damageEntity(source, (float) damage);
 }
/**
 * Takes care of NMS Entity class creation, allowing multiple callback methods to be implemented.
 * All methods provided by a callback Class that are supposed to be inherited by the produced Entity
 * class instance, should be in a separate interface Class implemented by the callback class.<br>
 * <br>
 * For example, an 'InventoryHookImpl' class implementing 'InventoryHook', with InventoryHook
 * declaring the methods 'setItem' and 'super_setItem'.<br>
 * <br>
 * To call super methods, add methods in the interface starting with <i>super_</i>. These methods
 * are automatically redirected to the base Entity class.<br>
 * <br>
 * All callback classes must have a constructor that accepts a single CommonEntity instance.
 */
public class NMSEntityClassBuilder extends ClassBuilder {
  private static final Class<?>[] DEFAULT_CONSTRUCTOR_TYPES = {WorldRef.TEMPLATE.getType()};
  private static final Object[] DEFAULT_CONSTRUCTOR_ARGS = {
    CommonNMS.getWorlds().iterator().next()
  };
  private final List<Constructor<?>> callbackConstructors = new ArrayList<Constructor<?>>();

  public NMSEntityClassBuilder(Class<?> superClass, Collection<Class<?>> callbackClasses) {
    super(superClass, callbackClasses);
    for (Class<?> callbackClass : this.getCallbackClasses()) {
      try {
        callbackConstructors.add(callbackClass.getConstructor(CommonEntity.class));
      } catch (Throwable t) {
        throw new RuntimeException(
            "Callback class '"
                + callbackClass.getName()
                + "' is invalid: No one-argument 'CommonEntity' constructor");
      }
    }
  }

  /**
   * Creates a new Entity instance
   *
   * @return new Entiy instance
   */
  public synchronized Object create(CommonEntity<?> entity, Object... args) {
    // Prepare new Callback instances
    List<Object> instances = new ArrayList<Object>(callbackConstructors.size());
    for (Constructor<?> callbackConstructor : callbackConstructors) {
      try {
        instances.add(callbackConstructor.newInstance(entity));
      } catch (Throwable t) {
        throw new RuntimeException("Unable to construct Callback Class:", t);
      }
    }

    // Create and return
    return create(DEFAULT_CONSTRUCTOR_TYPES, DEFAULT_CONSTRUCTOR_ARGS, instances);
  }
}
 public static void setLastY(Entity entity, double value) {
   CommonNMS.getNative(entity).lastY = value;
 }
 public static double getLastY(Entity entity) {
   return CommonNMS.getNative(entity).lastY;
 }
 public static void setMotZ(Entity entity, double value) {
   CommonNMS.getNative(entity).motZ = value;
 }
 public static double getMotZ(Entity entity) {
   return CommonNMS.getNative(entity).motZ;
 }
 public static void setLocZ(Entity entity, double value) {
   CommonNMS.getNative(entity).locZ = value;
 }
 public static double getLocZ(Entity entity) {
   return CommonNMS.getNative(entity).locZ;
 }
 /**
  * Gets the maximum portal cooldown ticks. This is the value applied right after entering a
  * portal.
  *
  * @param entity to get it for
  * @return entity maximum portal cooldown ticks
  */
 public static int getPortalCooldownMaximum(Entity entity) {
   return CommonNMS.getNative(entity).aq();
 }
 /**
  * Gets the entity portal enter cooldown ticks
  *
  * @param entity to get it for
  * @return entity cooldown ticks
  */
 public static int getPortalCooldown(Entity entity) {
   return CommonNMS.getNative(entity).portalCooldown;
 }
 /**
  * Sets the entity portal enter cooldown ticks
  *
  * @param entity to set it for
  * @param cooldownTicks to set to
  */
 public static void setPortalCooldown(Entity entity, int cooldownTicks) {
   CommonNMS.getNative(entity).portalCooldown = cooldownTicks;
 }
 /**
  * Damages an entity with the reason of an explosion
  *
  * @param entity to be demaged
  * @param damage of the damage
  * @param explosion wich has damaged the player
  */
 public static void damage_explode(
     org.bukkit.entity.Entity entity, double damage, Explosion explosion) {
   CommonNMS.getNative(entity).damageEntity(DamageSource.explosion(explosion), (float) damage);
 }
 public static void setDead(Entity entity, boolean dead) {
   CommonNMS.getNative(entity).dead = dead;
 }