// Path: src/main/java/crazypants/enderzoo/entity/SpawnUtil.java
// public class SpawnUtil {
// 
//   public static boolean findClearGround(World world, Point3i startingLocation, Point3i clearLocation) {
//     return findClearGround(world, startingLocation, clearLocation, 2, 10, false);
//   }
//   
//   public static boolean findClearGround(World world, Point3i startingLocation, Point3i clearLocation, int horizRange, int vertRange,
//       boolean checkForLivingEntities) {
//     //first find some air in the y
//     boolean foundTargetSpace = false;
//     for (int xOff = -horizRange; xOff <= horizRange && !foundTargetSpace; xOff++) {
//       clearLocation.x = startingLocation.x + xOff;
//       for (int zOff = -horizRange; zOff <= horizRange && !foundTargetSpace; zOff++) {
//         clearLocation.z = startingLocation.z + zOff;
//         foundTargetSpace = SpawnUtil.seachYForClearGround(clearLocation, world, vertRange, checkForLivingEntities);
//         if(!foundTargetSpace) {
//           clearLocation.y = startingLocation.y;
//         }
//       }
//     }
//     return foundTargetSpace;
//   }
//   
//   public static boolean seachYForClearGround(Point3i target, World world) {
//     return seachYForClearGround(target, world, 10, false);
//   }
//   
//   public static boolean seachYForClearGround(Point3i target, World world, int searchRange, boolean checkForLivingEntities) {
//     boolean foundY = false;
//     for (int i = 0; i < searchRange && !foundY; i++) {
//       if(world.isAirBlock(VecUtil.bpos(target.x, target.y, target.z))) {
//         foundY = true;
//       } else {
//         target.y++;
//       }
//     }
//     boolean onGround = false;
//     if(foundY) {
//       for (int i = 0; i < searchRange && !onGround; i++) {
//         onGround = !world.isAirBlock(VecUtil.bpos(target.x, target.y - 1, target.z)) && !isLiquid(world, target.x, target.y - 1, target.z);
//         if(!onGround) {
//           target.y--;
//         } else if(checkForLivingEntities && containsLiving(world, target)) {
//           return false;
//         }
//       }
//     }
//     return foundY && onGround;
//   }
// 
//   public static boolean containsLiving(World world, Point3i blockCoord) {
//     AxisAlignedBB bb = new AxisAlignedBB(blockCoord.x, blockCoord.y, blockCoord.z, blockCoord.x + 1, blockCoord.y + 1, blockCoord.z + 1);
//     List<?> ents = world.getEntitiesWithinAABB(EntityLivingBase.class, bb);
//     return ents != null && !ents.isEmpty();
//   }
// 
//   public static boolean isLiquid(World world, int x, int y, int z) {
// 	IBlockState bs = world.getBlockState(VecUtil.bpos(x, y, z));
// 	if(bs == null || bs.getBlock() == null) {
// 		return false;
// 	}
//     if(bs.getMaterial().isLiquid()) {
//       return true;
//     }
//     return false;
//   }
// 
//   public static boolean isSpaceAvailableForSpawn(World worldObj, EntityLiving entity, EntityCreature asCreature, boolean checkEntityCollisions, boolean canSpawnInLiquid) {
//     if(asCreature != null && asCreature.getBlockPathWeight(entity.getPosition()) < 0) {
//       return false;
//     }
//     if(checkEntityCollisions && !worldObj.checkNoEntityCollision(entity.getEntityBoundingBox())) {
//       return false;
//     }
//     if(!worldObj.getCollisionBoxes(entity, entity.getEntityBoundingBox()).isEmpty()) {
//       return false;
//     }    
//     if(!canSpawnInLiquid && worldObj.containsAnyLiquid(entity.getEntityBoundingBox())) {
//       return false;
//     }    
//     return true;
//   }
// 
//   public static boolean isSpaceAvailableForSpawn(World worldObj, EntityCreature entityCreature, boolean checkEntityCollisions, boolean canSpawnInLiquid) {
//     return isSpaceAvailableForSpawn(worldObj, entityCreature, entityCreature, checkEntityCollisions, false);
//   }
//   public static boolean isSpaceAvailableForSpawn(World worldObj, EntityLiving entity, boolean checkEntityCollisions, boolean canSpawnInLiquid) {
//     return isSpaceAvailableForSpawn(worldObj, entity, entity instanceof EntityCreature ? ((EntityCreature)entity) : null, checkEntityCollisions, canSpawnInLiquid);
//   }
//   
//   public static boolean isSpaceAvailableForSpawn(World worldObj, EntityLiving spawn, boolean checkEntityCollisions) {
//     return isSpaceAvailableForSpawn(worldObj, spawn, checkEntityCollisions, false);
//   }
// 
//   
// }


import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import crazypants.enderzoo.entity.SpawnUtil;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.pathfinding.NodeProcessor;
import net.minecraft.pathfinding.Path;
import net.minecraft.pathfinding.PathFinder;
import net.minecraft.pathfinding.PathHeap;
import net.minecraft.pathfinding.PathPoint;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.IBlockAccess;
    this.path.clearPath();
    this.nodeProcessor.initProcessor(blockaccess, entityIn);
    
//    PathPoint pathpoint1 =nodeProcessor.getPathPointToCoords(entityIn, x, y, z);    
    PathPoint pathpoint = nodeProcessor.getStart();
    PathPoint pathpoint1 = nodeProcessor.getPathPointToCoords(x, y, z);
    
    PathPoint[] p = addToPath(entityIn, pathpoint, pathpoint1, distance);
    Path res;
    if(p == null) {
      res = null;
    } else {
      res = new Path(p);  
    }     
    this.nodeProcessor.postProcess();
    return res;
  }
  
  private static PathPoint[] createEntityPath(PathPoint start, PathPoint end) {
    int i = 1;

    
    for (PathPoint pathpoint = end; PPUtil.getPrevious(pathpoint) != null; pathpoint = PPUtil.getPrevious(pathpoint)) {
      ++i;
    }

    PathPoint[] apathpoint = new PathPoint[i];
    PathPoint pathpoint1 = end;
    --i;
    for (apathpoint[i] = end; PPUtil.getPrevious(pathpoint1) != null; apathpoint[i] = pathpoint1) {
// Path: src/main/java/crazypants/enderzoo/entity/SpawnUtil.java
// public class SpawnUtil {
// 
//   public static boolean findClearGround(World world, Point3i startingLocation, Point3i clearLocation) {
//     return findClearGround(world, startingLocation, clearLocation, 2, 10, false);
//   }
//   
//   public static boolean findClearGround(World world, Point3i startingLocation, Point3i clearLocation, int horizRange, int vertRange,
//       boolean checkForLivingEntities) {
//     //first find some air in the y
//     boolean foundTargetSpace = false;
//     for (int xOff = -horizRange; xOff <= horizRange && !foundTargetSpace; xOff++) {
//       clearLocation.x = startingLocation.x + xOff;
//       for (int zOff = -horizRange; zOff <= horizRange && !foundTargetSpace; zOff++) {
//         clearLocation.z = startingLocation.z + zOff;
//         foundTargetSpace = SpawnUtil.seachYForClearGround(clearLocation, world, vertRange, checkForLivingEntities);
//         if(!foundTargetSpace) {
//           clearLocation.y = startingLocation.y;
//         }
//       }
//     }
//     return foundTargetSpace;
//   }
//   
//   public static boolean seachYForClearGround(Point3i target, World world) {
//     return seachYForClearGround(target, world, 10, false);
//   }
//   
//   public static boolean seachYForClearGround(Point3i target, World world, int searchRange, boolean checkForLivingEntities) {
//     boolean foundY = false;
//     for (int i = 0; i < searchRange && !foundY; i++) {
//       if(world.isAirBlock(VecUtil.bpos(target.x, target.y, target.z))) {
//         foundY = true;
//       } else {
//         target.y++;
//       }
//     }
//     boolean onGround = false;
//     if(foundY) {
//       for (int i = 0; i < searchRange && !onGround; i++) {
//         onGround = !world.isAirBlock(VecUtil.bpos(target.x, target.y - 1, target.z)) && !isLiquid(world, target.x, target.y - 1, target.z);
//         if(!onGround) {
//           target.y--;
//         } else if(checkForLivingEntities && containsLiving(world, target)) {
//           return false;
//         }
//       }
//     }
//     return foundY && onGround;
//   }
// 
//   public static boolean containsLiving(World world, Point3i blockCoord) {
//     AxisAlignedBB bb = new AxisAlignedBB(blockCoord.x, blockCoord.y, blockCoord.z, blockCoord.x + 1, blockCoord.y + 1, blockCoord.z + 1);
//     List<?> ents = world.getEntitiesWithinAABB(EntityLivingBase.class, bb);
//     return ents != null && !ents.isEmpty();
//   }
// 
//   public static boolean isLiquid(World world, int x, int y, int z) {
// 	IBlockState bs = world.getBlockState(VecUtil.bpos(x, y, z));
// 	if(bs == null || bs.getBlock() == null) {
// 		return false;
// 	}
//     if(bs.getMaterial().isLiquid()) {
//       return true;
//     }
//     return false;
//   }
// 
//   public static boolean isSpaceAvailableForSpawn(World worldObj, EntityLiving entity, EntityCreature asCreature, boolean checkEntityCollisions, boolean canSpawnInLiquid) {
//     if(asCreature != null && asCreature.getBlockPathWeight(entity.getPosition()) < 0) {
//       return false;
//     }
//     if(checkEntityCollisions && !worldObj.checkNoEntityCollision(entity.getEntityBoundingBox())) {
//       return false;
//     }
//     if(!worldObj.getCollisionBoxes(entity, entity.getEntityBoundingBox()).isEmpty()) {
//       return false;
//     }    
//     if(!canSpawnInLiquid && worldObj.containsAnyLiquid(entity.getEntityBoundingBox())) {
//       return false;
//     }    
//     return true;
//   }
// 
//   public static boolean isSpaceAvailableForSpawn(World worldObj, EntityCreature entityCreature, boolean checkEntityCollisions, boolean canSpawnInLiquid) {
//     return isSpaceAvailableForSpawn(worldObj, entityCreature, entityCreature, checkEntityCollisions, false);
//   }
//   public static boolean isSpaceAvailableForSpawn(World worldObj, EntityLiving entity, boolean checkEntityCollisions, boolean canSpawnInLiquid) {
//     return isSpaceAvailableForSpawn(worldObj, entity, entity instanceof EntityCreature ? ((EntityCreature)entity) : null, checkEntityCollisions, canSpawnInLiquid);
//   }
//   
//   public static boolean isSpaceAvailableForSpawn(World worldObj, EntityLiving spawn, boolean checkEntityCollisions) {
//     return isSpaceAvailableForSpawn(worldObj, spawn, checkEntityCollisions, false);
//   }
// 
//   
// }


// Path: src/main/java/crazypants/enderzoo/entity/navigate/FlyingPathFinder.java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import crazypants.enderzoo.entity.SpawnUtil;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.pathfinding.NodeProcessor;
import net.minecraft.pathfinding.Path;
import net.minecraft.pathfinding.PathFinder;
import net.minecraft.pathfinding.PathHeap;
import net.minecraft.pathfinding.PathPoint;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.IBlockAccess;

    this.path.clearPath();
    this.nodeProcessor.initProcessor(blockaccess, entityIn);
    
//    PathPoint pathpoint1 =nodeProcessor.getPathPointToCoords(entityIn, x, y, z);    
    PathPoint pathpoint = nodeProcessor.getStart();
    PathPoint pathpoint1 = nodeProcessor.getPathPointToCoords(x, y, z);
    
    PathPoint[] p = addToPath(entityIn, pathpoint, pathpoint1, distance);
    Path res;
    if(p == null) {
      res = null;
    } else {
      res = new Path(p);  
    }     
    this.nodeProcessor.postProcess();
    return res;
  }
  
  private static PathPoint[] createEntityPath(PathPoint start, PathPoint end) {
    int i = 1;

    
    for (PathPoint pathpoint = end; PPUtil.getPrevious(pathpoint) != null; pathpoint = PPUtil.getPrevious(pathpoint)) {
      ++i;
    }

    PathPoint[] apathpoint = new PathPoint[i];
    PathPoint pathpoint1 = end;
    --i;
    for (apathpoint[i] = end; PPUtil.getPrevious(pathpoint1) != null; apathpoint[i] = pathpoint1) {
      pathpoint1 = PPUtil.getPrevious(pathpoint1);