base mod created
This commit is contained in:
@@ -0,0 +1,359 @@
|
||||
package net.minecraft.pathfinding;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.entity.EntityLiving;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
|
||||
public class FlyingNodeProcessor extends WalkNodeProcessor
|
||||
{
|
||||
public void init(IBlockAccess sourceIn, EntityLiving mob)
|
||||
{
|
||||
super.init(sourceIn, mob);
|
||||
this.avoidsWater = mob.getPathPriority(PathNodeType.WATER);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called when all nodes have been processed and PathEntity is created.
|
||||
* {@link net.minecraft.world.pathfinder.WalkNodeProcessor WalkNodeProcessor} uses this to change its field {@link
|
||||
* net.minecraft.world.pathfinder.WalkNodeProcessor#avoidsWater avoidsWater}
|
||||
*/
|
||||
public void postProcess()
|
||||
{
|
||||
this.entity.setPathPriority(PathNodeType.WATER, this.avoidsWater);
|
||||
super.postProcess();
|
||||
}
|
||||
|
||||
public PathPoint getStart()
|
||||
{
|
||||
int i;
|
||||
|
||||
if (this.getCanSwim() && this.entity.isInWater())
|
||||
{
|
||||
i = (int)this.entity.getEntityBoundingBox().minY;
|
||||
BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos(MathHelper.floor(this.entity.posX), i, MathHelper.floor(this.entity.posZ));
|
||||
|
||||
for (Block block = this.blockaccess.getBlockState(blockpos$mutableblockpos).getBlock(); block == Blocks.FLOWING_WATER || block == Blocks.WATER; block = this.blockaccess.getBlockState(blockpos$mutableblockpos).getBlock())
|
||||
{
|
||||
++i;
|
||||
blockpos$mutableblockpos.setPos(MathHelper.floor(this.entity.posX), i, MathHelper.floor(this.entity.posZ));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
i = MathHelper.floor(this.entity.getEntityBoundingBox().minY + 0.5D);
|
||||
}
|
||||
|
||||
BlockPos blockpos1 = new BlockPos(this.entity);
|
||||
PathNodeType pathnodetype1 = this.getPathNodeType(this.entity, blockpos1.getX(), i, blockpos1.getZ());
|
||||
|
||||
if (this.entity.getPathPriority(pathnodetype1) < 0.0F)
|
||||
{
|
||||
Set<BlockPos> set = Sets.<BlockPos>newHashSet();
|
||||
set.add(new BlockPos(this.entity.getEntityBoundingBox().minX, (double)i, this.entity.getEntityBoundingBox().minZ));
|
||||
set.add(new BlockPos(this.entity.getEntityBoundingBox().minX, (double)i, this.entity.getEntityBoundingBox().maxZ));
|
||||
set.add(new BlockPos(this.entity.getEntityBoundingBox().maxX, (double)i, this.entity.getEntityBoundingBox().minZ));
|
||||
set.add(new BlockPos(this.entity.getEntityBoundingBox().maxX, (double)i, this.entity.getEntityBoundingBox().maxZ));
|
||||
|
||||
for (BlockPos blockpos : set)
|
||||
{
|
||||
PathNodeType pathnodetype = this.getPathNodeType(this.entity, blockpos);
|
||||
|
||||
if (this.entity.getPathPriority(pathnodetype) >= 0.0F)
|
||||
{
|
||||
return super.openPoint(blockpos.getX(), blockpos.getY(), blockpos.getZ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return super.openPoint(blockpos1.getX(), i, blockpos1.getZ());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns PathPoint for given coordinates
|
||||
*/
|
||||
public PathPoint getPathPointToCoords(double x, double y, double z)
|
||||
{
|
||||
return super.openPoint(MathHelper.floor(x), MathHelper.floor(y), MathHelper.floor(z));
|
||||
}
|
||||
|
||||
public int findPathOptions(PathPoint[] pathOptions, PathPoint currentPoint, PathPoint targetPoint, float maxDistance)
|
||||
{
|
||||
int i = 0;
|
||||
PathPoint pathpoint = this.openPoint(currentPoint.x, currentPoint.y, currentPoint.z + 1);
|
||||
PathPoint pathpoint1 = this.openPoint(currentPoint.x - 1, currentPoint.y, currentPoint.z);
|
||||
PathPoint pathpoint2 = this.openPoint(currentPoint.x + 1, currentPoint.y, currentPoint.z);
|
||||
PathPoint pathpoint3 = this.openPoint(currentPoint.x, currentPoint.y, currentPoint.z - 1);
|
||||
PathPoint pathpoint4 = this.openPoint(currentPoint.x, currentPoint.y + 1, currentPoint.z);
|
||||
PathPoint pathpoint5 = this.openPoint(currentPoint.x, currentPoint.y - 1, currentPoint.z);
|
||||
|
||||
if (pathpoint != null && !pathpoint.visited && pathpoint.distanceTo(targetPoint) < maxDistance)
|
||||
{
|
||||
pathOptions[i++] = pathpoint;
|
||||
}
|
||||
|
||||
if (pathpoint1 != null && !pathpoint1.visited && pathpoint1.distanceTo(targetPoint) < maxDistance)
|
||||
{
|
||||
pathOptions[i++] = pathpoint1;
|
||||
}
|
||||
|
||||
if (pathpoint2 != null && !pathpoint2.visited && pathpoint2.distanceTo(targetPoint) < maxDistance)
|
||||
{
|
||||
pathOptions[i++] = pathpoint2;
|
||||
}
|
||||
|
||||
if (pathpoint3 != null && !pathpoint3.visited && pathpoint3.distanceTo(targetPoint) < maxDistance)
|
||||
{
|
||||
pathOptions[i++] = pathpoint3;
|
||||
}
|
||||
|
||||
if (pathpoint4 != null && !pathpoint4.visited && pathpoint4.distanceTo(targetPoint) < maxDistance)
|
||||
{
|
||||
pathOptions[i++] = pathpoint4;
|
||||
}
|
||||
|
||||
if (pathpoint5 != null && !pathpoint5.visited && pathpoint5.distanceTo(targetPoint) < maxDistance)
|
||||
{
|
||||
pathOptions[i++] = pathpoint5;
|
||||
}
|
||||
|
||||
boolean flag = pathpoint3 == null || pathpoint3.costMalus != 0.0F;
|
||||
boolean flag1 = pathpoint == null || pathpoint.costMalus != 0.0F;
|
||||
boolean flag2 = pathpoint2 == null || pathpoint2.costMalus != 0.0F;
|
||||
boolean flag3 = pathpoint1 == null || pathpoint1.costMalus != 0.0F;
|
||||
boolean flag4 = pathpoint4 == null || pathpoint4.costMalus != 0.0F;
|
||||
boolean flag5 = pathpoint5 == null || pathpoint5.costMalus != 0.0F;
|
||||
|
||||
if (flag && flag3)
|
||||
{
|
||||
PathPoint pathpoint6 = this.openPoint(currentPoint.x - 1, currentPoint.y, currentPoint.z - 1);
|
||||
|
||||
if (pathpoint6 != null && !pathpoint6.visited && pathpoint6.distanceTo(targetPoint) < maxDistance)
|
||||
{
|
||||
pathOptions[i++] = pathpoint6;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag && flag2)
|
||||
{
|
||||
PathPoint pathpoint7 = this.openPoint(currentPoint.x + 1, currentPoint.y, currentPoint.z - 1);
|
||||
|
||||
if (pathpoint7 != null && !pathpoint7.visited && pathpoint7.distanceTo(targetPoint) < maxDistance)
|
||||
{
|
||||
pathOptions[i++] = pathpoint7;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag1 && flag3)
|
||||
{
|
||||
PathPoint pathpoint8 = this.openPoint(currentPoint.x - 1, currentPoint.y, currentPoint.z + 1);
|
||||
|
||||
if (pathpoint8 != null && !pathpoint8.visited && pathpoint8.distanceTo(targetPoint) < maxDistance)
|
||||
{
|
||||
pathOptions[i++] = pathpoint8;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag1 && flag2)
|
||||
{
|
||||
PathPoint pathpoint9 = this.openPoint(currentPoint.x + 1, currentPoint.y, currentPoint.z + 1);
|
||||
|
||||
if (pathpoint9 != null && !pathpoint9.visited && pathpoint9.distanceTo(targetPoint) < maxDistance)
|
||||
{
|
||||
pathOptions[i++] = pathpoint9;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag && flag4)
|
||||
{
|
||||
PathPoint pathpoint10 = this.openPoint(currentPoint.x, currentPoint.y + 1, currentPoint.z - 1);
|
||||
|
||||
if (pathpoint10 != null && !pathpoint10.visited && pathpoint10.distanceTo(targetPoint) < maxDistance)
|
||||
{
|
||||
pathOptions[i++] = pathpoint10;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag1 && flag4)
|
||||
{
|
||||
PathPoint pathpoint11 = this.openPoint(currentPoint.x, currentPoint.y + 1, currentPoint.z + 1);
|
||||
|
||||
if (pathpoint11 != null && !pathpoint11.visited && pathpoint11.distanceTo(targetPoint) < maxDistance)
|
||||
{
|
||||
pathOptions[i++] = pathpoint11;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag2 && flag4)
|
||||
{
|
||||
PathPoint pathpoint12 = this.openPoint(currentPoint.x + 1, currentPoint.y + 1, currentPoint.z);
|
||||
|
||||
if (pathpoint12 != null && !pathpoint12.visited && pathpoint12.distanceTo(targetPoint) < maxDistance)
|
||||
{
|
||||
pathOptions[i++] = pathpoint12;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag3 && flag4)
|
||||
{
|
||||
PathPoint pathpoint13 = this.openPoint(currentPoint.x - 1, currentPoint.y + 1, currentPoint.z);
|
||||
|
||||
if (pathpoint13 != null && !pathpoint13.visited && pathpoint13.distanceTo(targetPoint) < maxDistance)
|
||||
{
|
||||
pathOptions[i++] = pathpoint13;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag && flag5)
|
||||
{
|
||||
PathPoint pathpoint14 = this.openPoint(currentPoint.x, currentPoint.y - 1, currentPoint.z - 1);
|
||||
|
||||
if (pathpoint14 != null && !pathpoint14.visited && pathpoint14.distanceTo(targetPoint) < maxDistance)
|
||||
{
|
||||
pathOptions[i++] = pathpoint14;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag1 && flag5)
|
||||
{
|
||||
PathPoint pathpoint15 = this.openPoint(currentPoint.x, currentPoint.y - 1, currentPoint.z + 1);
|
||||
|
||||
if (pathpoint15 != null && !pathpoint15.visited && pathpoint15.distanceTo(targetPoint) < maxDistance)
|
||||
{
|
||||
pathOptions[i++] = pathpoint15;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag2 && flag5)
|
||||
{
|
||||
PathPoint pathpoint16 = this.openPoint(currentPoint.x + 1, currentPoint.y - 1, currentPoint.z);
|
||||
|
||||
if (pathpoint16 != null && !pathpoint16.visited && pathpoint16.distanceTo(targetPoint) < maxDistance)
|
||||
{
|
||||
pathOptions[i++] = pathpoint16;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag3 && flag5)
|
||||
{
|
||||
PathPoint pathpoint17 = this.openPoint(currentPoint.x - 1, currentPoint.y - 1, currentPoint.z);
|
||||
|
||||
if (pathpoint17 != null && !pathpoint17.visited && pathpoint17.distanceTo(targetPoint) < maxDistance)
|
||||
{
|
||||
pathOptions[i++] = pathpoint17;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a mapped point or creates and adds one
|
||||
*/
|
||||
@Nullable
|
||||
protected PathPoint openPoint(int x, int y, int z)
|
||||
{
|
||||
PathPoint pathpoint = null;
|
||||
PathNodeType pathnodetype = this.getPathNodeType(this.entity, x, y, z);
|
||||
float f = this.entity.getPathPriority(pathnodetype);
|
||||
|
||||
if (f >= 0.0F)
|
||||
{
|
||||
pathpoint = super.openPoint(x, y, z);
|
||||
pathpoint.nodeType = pathnodetype;
|
||||
pathpoint.costMalus = Math.max(pathpoint.costMalus, f);
|
||||
|
||||
if (pathnodetype == PathNodeType.WALKABLE)
|
||||
{
|
||||
++pathpoint.costMalus;
|
||||
}
|
||||
}
|
||||
|
||||
return pathnodetype != PathNodeType.OPEN && pathnodetype != PathNodeType.WALKABLE ? pathpoint : pathpoint;
|
||||
}
|
||||
|
||||
public PathNodeType getPathNodeType(IBlockAccess blockaccessIn, int x, int y, int z, EntityLiving entitylivingIn, int xSize, int ySize, int zSize, boolean canBreakDoorsIn, boolean canEnterDoorsIn)
|
||||
{
|
||||
EnumSet<PathNodeType> enumset = EnumSet.<PathNodeType>noneOf(PathNodeType.class);
|
||||
PathNodeType pathnodetype = PathNodeType.BLOCKED;
|
||||
BlockPos blockpos = new BlockPos(entitylivingIn);
|
||||
pathnodetype = this.getPathNodeType(blockaccessIn, x, y, z, xSize, ySize, zSize, canBreakDoorsIn, canEnterDoorsIn, enumset, pathnodetype, blockpos);
|
||||
|
||||
if (enumset.contains(PathNodeType.FENCE))
|
||||
{
|
||||
return PathNodeType.FENCE;
|
||||
}
|
||||
else
|
||||
{
|
||||
PathNodeType pathnodetype1 = PathNodeType.BLOCKED;
|
||||
|
||||
for (PathNodeType pathnodetype2 : enumset)
|
||||
{
|
||||
if (entitylivingIn.getPathPriority(pathnodetype2) < 0.0F)
|
||||
{
|
||||
return pathnodetype2;
|
||||
}
|
||||
|
||||
if (entitylivingIn.getPathPriority(pathnodetype2) >= entitylivingIn.getPathPriority(pathnodetype1))
|
||||
{
|
||||
pathnodetype1 = pathnodetype2;
|
||||
}
|
||||
}
|
||||
|
||||
if (pathnodetype == PathNodeType.OPEN && entitylivingIn.getPathPriority(pathnodetype1) == 0.0F)
|
||||
{
|
||||
return PathNodeType.OPEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
return pathnodetype1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PathNodeType getPathNodeType(IBlockAccess blockaccessIn, int x, int y, int z)
|
||||
{
|
||||
PathNodeType pathnodetype = this.getPathNodeTypeRaw(blockaccessIn, x, y, z);
|
||||
|
||||
if (pathnodetype == PathNodeType.OPEN && y >= 1)
|
||||
{
|
||||
Block block = blockaccessIn.getBlockState(new BlockPos(x, y - 1, z)).getBlock();
|
||||
PathNodeType pathnodetype1 = this.getPathNodeTypeRaw(blockaccessIn, x, y - 1, z);
|
||||
|
||||
if (pathnodetype1 != PathNodeType.DAMAGE_FIRE && block != Blocks.MAGMA && pathnodetype1 != PathNodeType.LAVA)
|
||||
{
|
||||
if (pathnodetype1 == PathNodeType.DAMAGE_CACTUS)
|
||||
{
|
||||
pathnodetype = PathNodeType.DAMAGE_CACTUS;
|
||||
}
|
||||
else
|
||||
{
|
||||
pathnodetype = pathnodetype1 != PathNodeType.WALKABLE && pathnodetype1 != PathNodeType.OPEN && pathnodetype1 != PathNodeType.WATER ? PathNodeType.WALKABLE : PathNodeType.OPEN;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pathnodetype = PathNodeType.DAMAGE_FIRE;
|
||||
}
|
||||
}
|
||||
|
||||
pathnodetype = this.checkNeighborBlocks(blockaccessIn, x, y, z, pathnodetype);
|
||||
return pathnodetype;
|
||||
}
|
||||
|
||||
private PathNodeType getPathNodeType(EntityLiving p_192559_1_, BlockPos p_192559_2_)
|
||||
{
|
||||
return this.getPathNodeType(p_192559_1_, p_192559_2_.getX(), p_192559_2_.getY(), p_192559_2_.getZ());
|
||||
}
|
||||
|
||||
private PathNodeType getPathNodeType(EntityLiving p_192558_1_, int p_192558_2_, int p_192558_3_, int p_192558_4_)
|
||||
{
|
||||
return this.getPathNodeType(this.blockaccess, p_192558_2_, p_192558_3_, p_192558_4_, p_192558_1_, this.entitySizeX, this.entitySizeY, this.entitySizeZ, this.getCanOpenDoors(), this.getCanEnterDoors());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package net.minecraft.pathfinding;
|
||||
|
||||
import net.minecraft.entity.EntityLiving;
|
||||
import net.minecraft.util.IntHashMap;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
|
||||
public abstract class NodeProcessor
|
||||
{
|
||||
protected IBlockAccess blockaccess;
|
||||
protected EntityLiving entity;
|
||||
protected final IntHashMap<PathPoint> pointMap = new IntHashMap<PathPoint>();
|
||||
protected int entitySizeX;
|
||||
protected int entitySizeY;
|
||||
protected int entitySizeZ;
|
||||
protected boolean canEnterDoors;
|
||||
protected boolean canOpenDoors;
|
||||
protected boolean canSwim;
|
||||
|
||||
public void init(IBlockAccess sourceIn, EntityLiving mob)
|
||||
{
|
||||
this.blockaccess = sourceIn;
|
||||
this.entity = mob;
|
||||
this.pointMap.clearMap();
|
||||
this.entitySizeX = MathHelper.floor(mob.width + 1.0F);
|
||||
this.entitySizeY = MathHelper.floor(mob.height + 1.0F);
|
||||
this.entitySizeZ = MathHelper.floor(mob.width + 1.0F);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called when all nodes have been processed and PathEntity is created.
|
||||
* {@link net.minecraft.world.pathfinder.WalkNodeProcessor WalkNodeProcessor} uses this to change its field {@link
|
||||
* net.minecraft.world.pathfinder.WalkNodeProcessor#avoidsWater avoidsWater}
|
||||
*/
|
||||
public void postProcess()
|
||||
{
|
||||
this.blockaccess = null;
|
||||
this.entity = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a mapped point or creates and adds one
|
||||
*/
|
||||
protected PathPoint openPoint(int x, int y, int z)
|
||||
{
|
||||
int i = PathPoint.makeHash(x, y, z);
|
||||
PathPoint pathpoint = this.pointMap.lookup(i);
|
||||
|
||||
if (pathpoint == null)
|
||||
{
|
||||
pathpoint = new PathPoint(x, y, z);
|
||||
this.pointMap.addKey(i, pathpoint);
|
||||
}
|
||||
|
||||
return pathpoint;
|
||||
}
|
||||
|
||||
public abstract PathPoint getStart();
|
||||
|
||||
/**
|
||||
* Returns PathPoint for given coordinates
|
||||
*/
|
||||
public abstract PathPoint getPathPointToCoords(double x, double y, double z);
|
||||
|
||||
public abstract int findPathOptions(PathPoint[] pathOptions, PathPoint currentPoint, PathPoint targetPoint, float maxDistance);
|
||||
|
||||
public abstract PathNodeType getPathNodeType(IBlockAccess blockaccessIn, int x, int y, int z, EntityLiving entitylivingIn, int xSize, int ySize, int zSize, boolean canBreakDoorsIn, boolean canEnterDoorsIn);
|
||||
|
||||
public abstract PathNodeType getPathNodeType(IBlockAccess blockaccessIn, int x, int y, int z);
|
||||
|
||||
public void setCanEnterDoors(boolean canEnterDoorsIn)
|
||||
{
|
||||
this.canEnterDoors = canEnterDoorsIn;
|
||||
}
|
||||
|
||||
public void setCanOpenDoors(boolean canOpenDoorsIn)
|
||||
{
|
||||
this.canOpenDoors = canOpenDoorsIn;
|
||||
}
|
||||
|
||||
public void setCanSwim(boolean canSwimIn)
|
||||
{
|
||||
this.canSwim = canSwimIn;
|
||||
}
|
||||
|
||||
public boolean getCanEnterDoors()
|
||||
{
|
||||
return this.canEnterDoors;
|
||||
}
|
||||
|
||||
public boolean getCanOpenDoors()
|
||||
{
|
||||
return this.canOpenDoors;
|
||||
}
|
||||
|
||||
public boolean getCanSwim()
|
||||
{
|
||||
return this.canSwim;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
package net.minecraft.pathfinding;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
public class Path
|
||||
{
|
||||
/** The actual points in the path */
|
||||
private final PathPoint[] points;
|
||||
private PathPoint[] openSet = new PathPoint[0];
|
||||
private PathPoint[] closedSet = new PathPoint[0];
|
||||
@SideOnly(Side.CLIENT)
|
||||
private PathPoint target;
|
||||
/** PathEntity Array Index the Entity is currently targeting */
|
||||
private int currentPathIndex;
|
||||
/** The total length of the path */
|
||||
private int pathLength;
|
||||
|
||||
public Path(PathPoint[] pathpoints)
|
||||
{
|
||||
this.points = pathpoints;
|
||||
this.pathLength = pathpoints.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Directs this path to the next point in its array
|
||||
*/
|
||||
public void incrementPathIndex()
|
||||
{
|
||||
++this.currentPathIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this path has reached the end
|
||||
*/
|
||||
public boolean isFinished()
|
||||
{
|
||||
return this.currentPathIndex >= this.pathLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the last PathPoint of the Array
|
||||
*/
|
||||
@Nullable
|
||||
public PathPoint getFinalPathPoint()
|
||||
{
|
||||
return this.pathLength > 0 ? this.points[this.pathLength - 1] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* return the PathPoint located at the specified PathIndex, usually the current one
|
||||
*/
|
||||
public PathPoint getPathPointFromIndex(int index)
|
||||
{
|
||||
return this.points[index];
|
||||
}
|
||||
|
||||
public void setPoint(int index, PathPoint point)
|
||||
{
|
||||
this.points[index] = point;
|
||||
}
|
||||
|
||||
public int getCurrentPathLength()
|
||||
{
|
||||
return this.pathLength;
|
||||
}
|
||||
|
||||
public void setCurrentPathLength(int length)
|
||||
{
|
||||
this.pathLength = length;
|
||||
}
|
||||
|
||||
public int getCurrentPathIndex()
|
||||
{
|
||||
return this.currentPathIndex;
|
||||
}
|
||||
|
||||
public void setCurrentPathIndex(int currentPathIndexIn)
|
||||
{
|
||||
this.currentPathIndex = currentPathIndexIn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the vector of the PathPoint associated with the given index.
|
||||
*/
|
||||
public Vec3d getVectorFromIndex(Entity entityIn, int index)
|
||||
{
|
||||
double d0 = (double)this.points[index].x + (double)((int)(entityIn.width + 1.0F)) * 0.5D;
|
||||
double d1 = (double)this.points[index].y;
|
||||
double d2 = (double)this.points[index].z + (double)((int)(entityIn.width + 1.0F)) * 0.5D;
|
||||
return new Vec3d(d0, d1, d2);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the current PathEntity target node as Vec3D
|
||||
*/
|
||||
public Vec3d getPosition(Entity entityIn)
|
||||
{
|
||||
return this.getVectorFromIndex(entityIn, this.currentPathIndex);
|
||||
}
|
||||
|
||||
public Vec3d getCurrentPos()
|
||||
{
|
||||
PathPoint pathpoint = this.points[this.currentPathIndex];
|
||||
return new Vec3d((double)pathpoint.x, (double)pathpoint.y, (double)pathpoint.z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the EntityPath are the same. Non instance related equals.
|
||||
*/
|
||||
public boolean isSamePath(Path pathentityIn)
|
||||
{
|
||||
if (pathentityIn == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (pathentityIn.points.length != this.points.length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < this.points.length; ++i)
|
||||
{
|
||||
if (this.points[i].x != pathentityIn.points[i].x || this.points[i].y != pathentityIn.points[i].y || this.points[i].z != pathentityIn.points[i].z)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public PathPoint[] getOpenSet()
|
||||
{
|
||||
return this.openSet;
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public PathPoint[] getClosedSet()
|
||||
{
|
||||
return this.closedSet;
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public PathPoint getTarget()
|
||||
{
|
||||
return this.target;
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public static Path read(PacketBuffer buf)
|
||||
{
|
||||
int i = buf.readInt();
|
||||
PathPoint pathpoint = PathPoint.createFromBuffer(buf);
|
||||
PathPoint[] apathpoint = new PathPoint[buf.readInt()];
|
||||
|
||||
for (int j = 0; j < apathpoint.length; ++j)
|
||||
{
|
||||
apathpoint[j] = PathPoint.createFromBuffer(buf);
|
||||
}
|
||||
|
||||
PathPoint[] apathpoint1 = new PathPoint[buf.readInt()];
|
||||
|
||||
for (int k = 0; k < apathpoint1.length; ++k)
|
||||
{
|
||||
apathpoint1[k] = PathPoint.createFromBuffer(buf);
|
||||
}
|
||||
|
||||
PathPoint[] apathpoint2 = new PathPoint[buf.readInt()];
|
||||
|
||||
for (int l = 0; l < apathpoint2.length; ++l)
|
||||
{
|
||||
apathpoint2[l] = PathPoint.createFromBuffer(buf);
|
||||
}
|
||||
|
||||
Path path = new Path(apathpoint);
|
||||
path.openSet = apathpoint1;
|
||||
path.closedSet = apathpoint2;
|
||||
path.target = pathpoint;
|
||||
path.currentPathIndex = i;
|
||||
return path;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
package net.minecraft.pathfinding;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLiving;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
|
||||
public class PathFinder
|
||||
{
|
||||
/** The path being generated */
|
||||
private final PathHeap path = new PathHeap();
|
||||
private final Set<PathPoint> closedSet = Sets.<PathPoint>newHashSet();
|
||||
/** Selection of path points to add to the path */
|
||||
private final PathPoint[] pathOptions = new PathPoint[32];
|
||||
private final NodeProcessor nodeProcessor;
|
||||
|
||||
public PathFinder(NodeProcessor processor)
|
||||
{
|
||||
this.nodeProcessor = processor;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Path findPath(IBlockAccess worldIn, EntityLiving entitylivingIn, Entity targetEntity, float maxDistance)
|
||||
{
|
||||
return this.findPath(worldIn, entitylivingIn, targetEntity.posX, targetEntity.getEntityBoundingBox().minY, targetEntity.posZ, maxDistance);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Path findPath(IBlockAccess worldIn, EntityLiving entitylivingIn, BlockPos targetPos, float maxDistance)
|
||||
{
|
||||
return this.findPath(worldIn, entitylivingIn, (double)((float)targetPos.getX() + 0.5F), (double)((float)targetPos.getY() + 0.5F), (double)((float)targetPos.getZ() + 0.5F), maxDistance);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Path findPath(IBlockAccess worldIn, EntityLiving entitylivingIn, double x, double y, double z, float maxDistance)
|
||||
{
|
||||
this.path.clearPath();
|
||||
this.nodeProcessor.init(worldIn, entitylivingIn);
|
||||
PathPoint pathpoint = this.nodeProcessor.getStart();
|
||||
PathPoint pathpoint1 = this.nodeProcessor.getPathPointToCoords(x, y, z);
|
||||
Path path = this.findPath(pathpoint, pathpoint1, maxDistance);
|
||||
this.nodeProcessor.postProcess();
|
||||
return path;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Path findPath(PathPoint pathFrom, PathPoint pathTo, float maxDistance)
|
||||
{
|
||||
pathFrom.totalPathDistance = 0.0F;
|
||||
pathFrom.distanceToNext = pathFrom.distanceManhattan(pathTo);
|
||||
pathFrom.distanceToTarget = pathFrom.distanceToNext;
|
||||
this.path.clearPath();
|
||||
this.closedSet.clear();
|
||||
this.path.addPoint(pathFrom);
|
||||
PathPoint pathpoint = pathFrom;
|
||||
int i = 0;
|
||||
|
||||
while (!this.path.isPathEmpty())
|
||||
{
|
||||
++i;
|
||||
|
||||
if (i >= 200)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
PathPoint pathpoint1 = this.path.dequeue();
|
||||
|
||||
if (pathpoint1.equals(pathTo))
|
||||
{
|
||||
pathpoint = pathTo;
|
||||
break;
|
||||
}
|
||||
|
||||
if (pathpoint1.distanceManhattan(pathTo) < pathpoint.distanceManhattan(pathTo))
|
||||
{
|
||||
pathpoint = pathpoint1;
|
||||
}
|
||||
|
||||
pathpoint1.visited = true;
|
||||
int j = this.nodeProcessor.findPathOptions(this.pathOptions, pathpoint1, pathTo, maxDistance);
|
||||
|
||||
for (int k = 0; k < j; ++k)
|
||||
{
|
||||
PathPoint pathpoint2 = this.pathOptions[k];
|
||||
float f = pathpoint1.distanceManhattan(pathpoint2);
|
||||
pathpoint2.distanceFromOrigin = pathpoint1.distanceFromOrigin + f;
|
||||
pathpoint2.cost = f + pathpoint2.costMalus;
|
||||
float f1 = pathpoint1.totalPathDistance + pathpoint2.cost;
|
||||
|
||||
if (pathpoint2.distanceFromOrigin < maxDistance && (!pathpoint2.isAssigned() || f1 < pathpoint2.totalPathDistance))
|
||||
{
|
||||
pathpoint2.previous = pathpoint1;
|
||||
pathpoint2.totalPathDistance = f1;
|
||||
pathpoint2.distanceToNext = pathpoint2.distanceManhattan(pathTo) + pathpoint2.costMalus;
|
||||
|
||||
if (pathpoint2.isAssigned())
|
||||
{
|
||||
this.path.changeDistance(pathpoint2, pathpoint2.totalPathDistance + pathpoint2.distanceToNext);
|
||||
}
|
||||
else
|
||||
{
|
||||
pathpoint2.distanceToTarget = pathpoint2.totalPathDistance + pathpoint2.distanceToNext;
|
||||
this.path.addPoint(pathpoint2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pathpoint == pathFrom)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
Path path = this.createPath(pathFrom, pathpoint);
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new PathEntity for a given start and end point
|
||||
*/
|
||||
private Path createPath(PathPoint start, PathPoint end)
|
||||
{
|
||||
int i = 1;
|
||||
|
||||
for (PathPoint pathpoint = end; pathpoint.previous != null; pathpoint = pathpoint.previous)
|
||||
{
|
||||
++i;
|
||||
}
|
||||
|
||||
PathPoint[] apathpoint = new PathPoint[i];
|
||||
PathPoint pathpoint1 = end;
|
||||
--i;
|
||||
|
||||
for (apathpoint[i] = end; pathpoint1.previous != null; apathpoint[i] = pathpoint1)
|
||||
{
|
||||
pathpoint1 = pathpoint1.previous;
|
||||
--i;
|
||||
}
|
||||
|
||||
return new Path(apathpoint);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
package net.minecraft.pathfinding;
|
||||
|
||||
public class PathHeap
|
||||
{
|
||||
/** Contains the points in this path */
|
||||
private PathPoint[] pathPoints = new PathPoint[128];
|
||||
/** The number of points in this path */
|
||||
private int count;
|
||||
|
||||
/**
|
||||
* Adds a point to the path
|
||||
*/
|
||||
public PathPoint addPoint(PathPoint point)
|
||||
{
|
||||
if (point.index >= 0)
|
||||
{
|
||||
throw new IllegalStateException("OW KNOWS!");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.count == this.pathPoints.length)
|
||||
{
|
||||
PathPoint[] apathpoint = new PathPoint[this.count << 1];
|
||||
System.arraycopy(this.pathPoints, 0, apathpoint, 0, this.count);
|
||||
this.pathPoints = apathpoint;
|
||||
}
|
||||
|
||||
this.pathPoints[this.count] = point;
|
||||
point.index = this.count;
|
||||
this.sortBack(this.count++);
|
||||
return point;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the path
|
||||
*/
|
||||
public void clearPath()
|
||||
{
|
||||
this.count = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns and removes the first point in the path
|
||||
*/
|
||||
public PathPoint dequeue()
|
||||
{
|
||||
PathPoint pathpoint = this.pathPoints[0];
|
||||
this.pathPoints[0] = this.pathPoints[--this.count];
|
||||
this.pathPoints[this.count] = null;
|
||||
|
||||
if (this.count > 0)
|
||||
{
|
||||
this.sortForward(0);
|
||||
}
|
||||
|
||||
pathpoint.index = -1;
|
||||
return pathpoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the provided point's distance to target
|
||||
*/
|
||||
public void changeDistance(PathPoint point, float distance)
|
||||
{
|
||||
float f = point.distanceToTarget;
|
||||
point.distanceToTarget = distance;
|
||||
|
||||
if (distance < f)
|
||||
{
|
||||
this.sortBack(point.index);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.sortForward(point.index);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts a point to the left
|
||||
*/
|
||||
private void sortBack(int index)
|
||||
{
|
||||
PathPoint pathpoint = this.pathPoints[index];
|
||||
int i;
|
||||
|
||||
for (float f = pathpoint.distanceToTarget; index > 0; index = i)
|
||||
{
|
||||
i = index - 1 >> 1;
|
||||
PathPoint pathpoint1 = this.pathPoints[i];
|
||||
|
||||
if (f >= pathpoint1.distanceToTarget)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
this.pathPoints[index] = pathpoint1;
|
||||
pathpoint1.index = index;
|
||||
}
|
||||
|
||||
this.pathPoints[index] = pathpoint;
|
||||
pathpoint.index = index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts a point to the right
|
||||
*/
|
||||
private void sortForward(int index)
|
||||
{
|
||||
PathPoint pathpoint = this.pathPoints[index];
|
||||
float f = pathpoint.distanceToTarget;
|
||||
|
||||
while (true)
|
||||
{
|
||||
int i = 1 + (index << 1);
|
||||
int j = i + 1;
|
||||
|
||||
if (i >= this.count)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
PathPoint pathpoint1 = this.pathPoints[i];
|
||||
float f1 = pathpoint1.distanceToTarget;
|
||||
PathPoint pathpoint2;
|
||||
float f2;
|
||||
|
||||
if (j >= this.count)
|
||||
{
|
||||
pathpoint2 = null;
|
||||
f2 = Float.POSITIVE_INFINITY;
|
||||
}
|
||||
else
|
||||
{
|
||||
pathpoint2 = this.pathPoints[j];
|
||||
f2 = pathpoint2.distanceToTarget;
|
||||
}
|
||||
|
||||
if (f1 < f2)
|
||||
{
|
||||
if (f1 >= f)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
this.pathPoints[index] = pathpoint1;
|
||||
pathpoint1.index = index;
|
||||
index = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (f2 >= f)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
this.pathPoints[index] = pathpoint2;
|
||||
pathpoint2.index = index;
|
||||
index = j;
|
||||
}
|
||||
}
|
||||
|
||||
this.pathPoints[index] = pathpoint;
|
||||
pathpoint.index = index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this path contains no points
|
||||
*/
|
||||
public boolean isPathEmpty()
|
||||
{
|
||||
return this.count == 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,426 @@
|
||||
package net.minecraft.pathfinding;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLiving;
|
||||
import net.minecraft.entity.SharedMonsterAttributes;
|
||||
import net.minecraft.entity.ai.attributes.IAttributeInstance;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.ChunkCache;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public abstract class PathNavigate
|
||||
{
|
||||
protected EntityLiving entity;
|
||||
protected World world;
|
||||
/** The PathEntity being followed. */
|
||||
@Nullable
|
||||
protected Path currentPath;
|
||||
protected double speed;
|
||||
/** The number of blocks (extra) +/- in each axis that get pulled out as cache for the pathfinder's search space */
|
||||
private final IAttributeInstance pathSearchRange;
|
||||
/** Time, in number of ticks, following the current path */
|
||||
protected int totalTicks;
|
||||
/** The time when the last position check was done (to detect successful movement) */
|
||||
private int ticksAtLastPos;
|
||||
/** Coordinates of the entity's position last time a check was done (part of monitoring getting 'stuck') */
|
||||
private Vec3d lastPosCheck = Vec3d.ZERO;
|
||||
private Vec3d timeoutCachedNode = Vec3d.ZERO;
|
||||
private long timeoutTimer;
|
||||
private long lastTimeoutCheck;
|
||||
private double timeoutLimit;
|
||||
protected float maxDistanceToWaypoint = 0.5F;
|
||||
protected boolean tryUpdatePath;
|
||||
private long lastTimeUpdated;
|
||||
protected NodeProcessor nodeProcessor;
|
||||
private BlockPos targetPos;
|
||||
private final PathFinder pathFinder;
|
||||
|
||||
public PathNavigate(EntityLiving entityIn, World worldIn)
|
||||
{
|
||||
this.entity = entityIn;
|
||||
this.world = worldIn;
|
||||
this.pathSearchRange = entityIn.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE);
|
||||
this.pathFinder = this.getPathFinder();
|
||||
}
|
||||
|
||||
protected abstract PathFinder getPathFinder();
|
||||
|
||||
/**
|
||||
* Sets the speed
|
||||
*/
|
||||
public void setSpeed(double speedIn)
|
||||
{
|
||||
this.speed = speedIn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the maximum distance that the path finding will search in.
|
||||
*/
|
||||
public float getPathSearchRange()
|
||||
{
|
||||
return (float)this.pathSearchRange.getAttributeValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if path can be changed by {@link net.minecraft.pathfinding.PathNavigate#onUpdateNavigation()
|
||||
* onUpdateNavigation()}
|
||||
*/
|
||||
public boolean canUpdatePathOnTimeout()
|
||||
{
|
||||
return this.tryUpdatePath;
|
||||
}
|
||||
|
||||
public void updatePath()
|
||||
{
|
||||
if (this.world.getTotalWorldTime() - this.lastTimeUpdated > 20L)
|
||||
{
|
||||
if (this.targetPos != null)
|
||||
{
|
||||
this.currentPath = null;
|
||||
this.currentPath = this.getPathToPos(this.targetPos);
|
||||
this.lastTimeUpdated = this.world.getTotalWorldTime();
|
||||
this.tryUpdatePath = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.tryUpdatePath = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path to the given coordinates. Args : x, y, z
|
||||
*/
|
||||
@Nullable
|
||||
public final Path getPathToXYZ(double x, double y, double z)
|
||||
{
|
||||
return this.getPathToPos(new BlockPos(x, y, z));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns path to given BlockPos
|
||||
*/
|
||||
@Nullable
|
||||
public Path getPathToPos(BlockPos pos)
|
||||
{
|
||||
if (!this.canNavigate())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else if (this.currentPath != null && !this.currentPath.isFinished() && pos.equals(this.targetPos))
|
||||
{
|
||||
return this.currentPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.targetPos = pos;
|
||||
float f = this.getPathSearchRange();
|
||||
this.world.profiler.startSection("pathfind");
|
||||
BlockPos blockpos = new BlockPos(this.entity);
|
||||
int i = (int)(f + 8.0F);
|
||||
ChunkCache chunkcache = new ChunkCache(this.world, blockpos.add(-i, -i, -i), blockpos.add(i, i, i), 0);
|
||||
Path path = this.pathFinder.findPath(chunkcache, this.entity, this.targetPos, f);
|
||||
this.world.profiler.endSection();
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path to the given EntityLiving. Args : entity
|
||||
*/
|
||||
@Nullable
|
||||
public Path getPathToEntityLiving(Entity entityIn)
|
||||
{
|
||||
if (!this.canNavigate())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
BlockPos blockpos = new BlockPos(entityIn);
|
||||
|
||||
if (this.currentPath != null && !this.currentPath.isFinished() && blockpos.equals(this.targetPos))
|
||||
{
|
||||
return this.currentPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.targetPos = blockpos;
|
||||
float f = this.getPathSearchRange();
|
||||
this.world.profiler.startSection("pathfind");
|
||||
BlockPos blockpos1 = (new BlockPos(this.entity)).up();
|
||||
int i = (int)(f + 16.0F);
|
||||
ChunkCache chunkcache = new ChunkCache(this.world, blockpos1.add(-i, -i, -i), blockpos1.add(i, i, i), 0);
|
||||
Path path = this.pathFinder.findPath(chunkcache, this.entity, entityIn, f);
|
||||
this.world.profiler.endSection();
|
||||
return path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to find and set a path to XYZ. Returns true if successful. Args : x, y, z, speed
|
||||
*/
|
||||
public boolean tryMoveToXYZ(double x, double y, double z, double speedIn)
|
||||
{
|
||||
return this.setPath(this.getPathToXYZ(x, y, z), speedIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to find and set a path to EntityLiving. Returns true if successful. Args : entity, speed
|
||||
*/
|
||||
public boolean tryMoveToEntityLiving(Entity entityIn, double speedIn)
|
||||
{
|
||||
Path path = this.getPathToEntityLiving(entityIn);
|
||||
return path != null && this.setPath(path, speedIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new path. If it's diferent from the old path. Checks to adjust path for sun avoiding, and stores start
|
||||
* coords. Args : path, speed
|
||||
*/
|
||||
public boolean setPath(@Nullable Path pathentityIn, double speedIn)
|
||||
{
|
||||
if (pathentityIn == null)
|
||||
{
|
||||
this.currentPath = null;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!pathentityIn.isSamePath(this.currentPath))
|
||||
{
|
||||
this.currentPath = pathentityIn;
|
||||
}
|
||||
|
||||
this.removeSunnyPath();
|
||||
|
||||
if (this.currentPath.getCurrentPathLength() <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.speed = speedIn;
|
||||
Vec3d vec3d = this.getEntityPosition();
|
||||
this.ticksAtLastPos = this.totalTicks;
|
||||
this.lastPosCheck = vec3d;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the actively used PathEntity
|
||||
*/
|
||||
@Nullable
|
||||
public Path getPath()
|
||||
{
|
||||
return this.currentPath;
|
||||
}
|
||||
|
||||
public void onUpdateNavigation()
|
||||
{
|
||||
++this.totalTicks;
|
||||
|
||||
if (this.tryUpdatePath)
|
||||
{
|
||||
this.updatePath();
|
||||
}
|
||||
|
||||
if (!this.noPath())
|
||||
{
|
||||
if (this.canNavigate())
|
||||
{
|
||||
this.pathFollow();
|
||||
}
|
||||
else if (this.currentPath != null && this.currentPath.getCurrentPathIndex() < this.currentPath.getCurrentPathLength())
|
||||
{
|
||||
Vec3d vec3d = this.getEntityPosition();
|
||||
Vec3d vec3d1 = this.currentPath.getVectorFromIndex(this.entity, this.currentPath.getCurrentPathIndex());
|
||||
|
||||
if (vec3d.y > vec3d1.y && !this.entity.onGround && MathHelper.floor(vec3d.x) == MathHelper.floor(vec3d1.x) && MathHelper.floor(vec3d.z) == MathHelper.floor(vec3d1.z))
|
||||
{
|
||||
this.currentPath.setCurrentPathIndex(this.currentPath.getCurrentPathIndex() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
this.debugPathFinding();
|
||||
|
||||
if (!this.noPath())
|
||||
{
|
||||
Vec3d vec3d2 = this.currentPath.getPosition(this.entity);
|
||||
BlockPos blockpos = (new BlockPos(vec3d2)).down();
|
||||
AxisAlignedBB axisalignedbb = this.world.getBlockState(blockpos).getBoundingBox(this.world, blockpos);
|
||||
vec3d2 = vec3d2.subtract(0.0D, 1.0D - axisalignedbb.maxY, 0.0D);
|
||||
this.entity.getMoveHelper().setMoveTo(vec3d2.x, vec3d2.y, vec3d2.z, this.speed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void debugPathFinding()
|
||||
{
|
||||
}
|
||||
|
||||
protected void pathFollow()
|
||||
{
|
||||
Vec3d vec3d = this.getEntityPosition();
|
||||
int i = this.currentPath.getCurrentPathLength();
|
||||
|
||||
for (int j = this.currentPath.getCurrentPathIndex(); j < this.currentPath.getCurrentPathLength(); ++j)
|
||||
{
|
||||
if ((double)this.currentPath.getPathPointFromIndex(j).y != Math.floor(vec3d.y))
|
||||
{
|
||||
i = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.maxDistanceToWaypoint = this.entity.width > 0.75F ? this.entity.width / 2.0F : 0.75F - this.entity.width / 2.0F;
|
||||
Vec3d vec3d1 = this.currentPath.getCurrentPos();
|
||||
|
||||
if (MathHelper.abs((float)(this.entity.posX - (vec3d1.x + 0.5D))) < this.maxDistanceToWaypoint && MathHelper.abs((float)(this.entity.posZ - (vec3d1.z + 0.5D))) < this.maxDistanceToWaypoint && Math.abs(this.entity.posY - vec3d1.y) < 1.0D)
|
||||
{
|
||||
this.currentPath.setCurrentPathIndex(this.currentPath.getCurrentPathIndex() + 1);
|
||||
}
|
||||
|
||||
int k = MathHelper.ceil(this.entity.width);
|
||||
int l = MathHelper.ceil(this.entity.height);
|
||||
int i1 = k;
|
||||
|
||||
for (int j1 = i - 1; j1 >= this.currentPath.getCurrentPathIndex(); --j1)
|
||||
{
|
||||
if (this.isDirectPathBetweenPoints(vec3d, this.currentPath.getVectorFromIndex(this.entity, j1), k, l, i1))
|
||||
{
|
||||
this.currentPath.setCurrentPathIndex(j1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.checkForStuck(vec3d);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if entity haven't been moved when last checked and if so, clears current {@link
|
||||
* net.minecraft.pathfinding.PathEntity}
|
||||
*/
|
||||
protected void checkForStuck(Vec3d positionVec3)
|
||||
{
|
||||
if (this.totalTicks - this.ticksAtLastPos > 100)
|
||||
{
|
||||
if (positionVec3.squareDistanceTo(this.lastPosCheck) < 2.25D)
|
||||
{
|
||||
this.clearPath();
|
||||
}
|
||||
|
||||
this.ticksAtLastPos = this.totalTicks;
|
||||
this.lastPosCheck = positionVec3;
|
||||
}
|
||||
|
||||
if (this.currentPath != null && !this.currentPath.isFinished())
|
||||
{
|
||||
Vec3d vec3d = this.currentPath.getCurrentPos();
|
||||
|
||||
if (vec3d.equals(this.timeoutCachedNode))
|
||||
{
|
||||
this.timeoutTimer += System.currentTimeMillis() - this.lastTimeoutCheck;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.timeoutCachedNode = vec3d;
|
||||
double d0 = positionVec3.distanceTo(this.timeoutCachedNode);
|
||||
this.timeoutLimit = this.entity.getAIMoveSpeed() > 0.0F ? d0 / (double)this.entity.getAIMoveSpeed() * 1000.0D : 0.0D;
|
||||
}
|
||||
|
||||
if (this.timeoutLimit > 0.0D && (double)this.timeoutTimer > this.timeoutLimit * 3.0D)
|
||||
{
|
||||
this.timeoutCachedNode = Vec3d.ZERO;
|
||||
this.timeoutTimer = 0L;
|
||||
this.timeoutLimit = 0.0D;
|
||||
this.clearPath();
|
||||
}
|
||||
|
||||
this.lastTimeoutCheck = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If null path or reached the end
|
||||
*/
|
||||
public boolean noPath()
|
||||
{
|
||||
return this.currentPath == null || this.currentPath.isFinished();
|
||||
}
|
||||
|
||||
/**
|
||||
* sets active PathEntity to null
|
||||
*/
|
||||
public void clearPath()
|
||||
{
|
||||
this.currentPath = null;
|
||||
}
|
||||
|
||||
protected abstract Vec3d getEntityPosition();
|
||||
|
||||
/**
|
||||
* If on ground or swimming and can swim
|
||||
*/
|
||||
protected abstract boolean canNavigate();
|
||||
|
||||
/**
|
||||
* Returns true if the entity is in water or lava, false otherwise
|
||||
*/
|
||||
protected boolean isInLiquid()
|
||||
{
|
||||
return this.entity.isInWater() || this.entity.isInLava();
|
||||
}
|
||||
|
||||
/**
|
||||
* Trims path data from the end to the first sun covered block
|
||||
*/
|
||||
protected void removeSunnyPath()
|
||||
{
|
||||
if (this.currentPath != null)
|
||||
{
|
||||
for (int i = 0; i < this.currentPath.getCurrentPathLength(); ++i)
|
||||
{
|
||||
PathPoint pathpoint = this.currentPath.getPathPointFromIndex(i);
|
||||
PathPoint pathpoint1 = i + 1 < this.currentPath.getCurrentPathLength() ? this.currentPath.getPathPointFromIndex(i + 1) : null;
|
||||
IBlockState iblockstate = this.world.getBlockState(new BlockPos(pathpoint.x, pathpoint.y, pathpoint.z));
|
||||
Block block = iblockstate.getBlock();
|
||||
|
||||
if (block == Blocks.CAULDRON)
|
||||
{
|
||||
this.currentPath.setPoint(i, pathpoint.cloneMove(pathpoint.x, pathpoint.y + 1, pathpoint.z));
|
||||
|
||||
if (pathpoint1 != null && pathpoint.y >= pathpoint1.y)
|
||||
{
|
||||
this.currentPath.setPoint(i + 1, pathpoint1.cloneMove(pathpoint1.x, pathpoint.y + 1, pathpoint1.z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified entity can safely walk to the specified location.
|
||||
*/
|
||||
protected abstract boolean isDirectPathBetweenPoints(Vec3d posVec31, Vec3d posVec32, int sizeX, int sizeY, int sizeZ);
|
||||
|
||||
public boolean canEntityStandOnPos(BlockPos pos)
|
||||
{
|
||||
return this.world.getBlockState(pos.down()).isFullBlock();
|
||||
}
|
||||
|
||||
public NodeProcessor getNodeProcessor()
|
||||
{
|
||||
return this.nodeProcessor;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package net.minecraft.pathfinding;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLiving;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class PathNavigateClimber extends PathNavigateGround
|
||||
{
|
||||
/** Current path navigation target */
|
||||
private BlockPos targetPosition;
|
||||
|
||||
public PathNavigateClimber(EntityLiving entityLivingIn, World worldIn)
|
||||
{
|
||||
super(entityLivingIn, worldIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns path to given BlockPos
|
||||
*/
|
||||
public Path getPathToPos(BlockPos pos)
|
||||
{
|
||||
this.targetPosition = pos;
|
||||
return super.getPathToPos(pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path to the given EntityLiving. Args : entity
|
||||
*/
|
||||
public Path getPathToEntityLiving(Entity entityIn)
|
||||
{
|
||||
this.targetPosition = new BlockPos(entityIn);
|
||||
return super.getPathToEntityLiving(entityIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to find and set a path to EntityLiving. Returns true if successful. Args : entity, speed
|
||||
*/
|
||||
public boolean tryMoveToEntityLiving(Entity entityIn, double speedIn)
|
||||
{
|
||||
Path path = this.getPathToEntityLiving(entityIn);
|
||||
|
||||
if (path != null)
|
||||
{
|
||||
return this.setPath(path, speedIn);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.targetPosition = new BlockPos(entityIn);
|
||||
this.speed = speedIn;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public void onUpdateNavigation()
|
||||
{
|
||||
if (!this.noPath())
|
||||
{
|
||||
super.onUpdateNavigation();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.targetPosition != null)
|
||||
{
|
||||
double d0 = (double)(this.entity.width * this.entity.width);
|
||||
|
||||
if (this.entity.getDistanceSqToCenter(this.targetPosition) >= d0 && (this.entity.posY <= (double)this.targetPosition.getY() || this.entity.getDistanceSqToCenter(new BlockPos(this.targetPosition.getX(), MathHelper.floor(this.entity.posY), this.targetPosition.getZ())) >= d0))
|
||||
{
|
||||
this.entity.getMoveHelper().setMoveTo((double)this.targetPosition.getX(), (double)this.targetPosition.getY(), (double)this.targetPosition.getZ(), this.speed);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.targetPosition = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
package net.minecraft.pathfinding;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLiving;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class PathNavigateFlying extends PathNavigate
|
||||
{
|
||||
public PathNavigateFlying(EntityLiving p_i47412_1_, World p_i47412_2_)
|
||||
{
|
||||
super(p_i47412_1_, p_i47412_2_);
|
||||
}
|
||||
|
||||
protected PathFinder getPathFinder()
|
||||
{
|
||||
this.nodeProcessor = new FlyingNodeProcessor();
|
||||
this.nodeProcessor.setCanEnterDoors(true);
|
||||
return new PathFinder(this.nodeProcessor);
|
||||
}
|
||||
|
||||
/**
|
||||
* If on ground or swimming and can swim
|
||||
*/
|
||||
protected boolean canNavigate()
|
||||
{
|
||||
return this.canFloat() && this.isInLiquid() || !this.entity.isRiding();
|
||||
}
|
||||
|
||||
protected Vec3d getEntityPosition()
|
||||
{
|
||||
return new Vec3d(this.entity.posX, this.entity.posY, this.entity.posZ);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path to the given EntityLiving. Args : entity
|
||||
*/
|
||||
public Path getPathToEntityLiving(Entity entityIn)
|
||||
{
|
||||
return this.getPathToPos(new BlockPos(entityIn));
|
||||
}
|
||||
|
||||
public void onUpdateNavigation()
|
||||
{
|
||||
++this.totalTicks;
|
||||
|
||||
if (this.tryUpdatePath)
|
||||
{
|
||||
this.updatePath();
|
||||
}
|
||||
|
||||
if (!this.noPath())
|
||||
{
|
||||
if (this.canNavigate())
|
||||
{
|
||||
this.pathFollow();
|
||||
}
|
||||
else if (this.currentPath != null && this.currentPath.getCurrentPathIndex() < this.currentPath.getCurrentPathLength())
|
||||
{
|
||||
Vec3d vec3d = this.currentPath.getVectorFromIndex(this.entity, this.currentPath.getCurrentPathIndex());
|
||||
|
||||
if (MathHelper.floor(this.entity.posX) == MathHelper.floor(vec3d.x) && MathHelper.floor(this.entity.posY) == MathHelper.floor(vec3d.y) && MathHelper.floor(this.entity.posZ) == MathHelper.floor(vec3d.z))
|
||||
{
|
||||
this.currentPath.setCurrentPathIndex(this.currentPath.getCurrentPathIndex() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
this.debugPathFinding();
|
||||
|
||||
if (!this.noPath())
|
||||
{
|
||||
Vec3d vec3d1 = this.currentPath.getPosition(this.entity);
|
||||
this.entity.getMoveHelper().setMoveTo(vec3d1.x, vec3d1.y, vec3d1.z, this.speed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified entity can safely walk to the specified location.
|
||||
*/
|
||||
protected boolean isDirectPathBetweenPoints(Vec3d posVec31, Vec3d posVec32, int sizeX, int sizeY, int sizeZ)
|
||||
{
|
||||
int i = MathHelper.floor(posVec31.x);
|
||||
int j = MathHelper.floor(posVec31.y);
|
||||
int k = MathHelper.floor(posVec31.z);
|
||||
double d0 = posVec32.x - posVec31.x;
|
||||
double d1 = posVec32.y - posVec31.y;
|
||||
double d2 = posVec32.z - posVec31.z;
|
||||
double d3 = d0 * d0 + d1 * d1 + d2 * d2;
|
||||
|
||||
if (d3 < 1.0E-8D)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
double d4 = 1.0D / Math.sqrt(d3);
|
||||
d0 = d0 * d4;
|
||||
d1 = d1 * d4;
|
||||
d2 = d2 * d4;
|
||||
double d5 = 1.0D / Math.abs(d0);
|
||||
double d6 = 1.0D / Math.abs(d1);
|
||||
double d7 = 1.0D / Math.abs(d2);
|
||||
double d8 = (double)i - posVec31.x;
|
||||
double d9 = (double)j - posVec31.y;
|
||||
double d10 = (double)k - posVec31.z;
|
||||
|
||||
if (d0 >= 0.0D)
|
||||
{
|
||||
++d8;
|
||||
}
|
||||
|
||||
if (d1 >= 0.0D)
|
||||
{
|
||||
++d9;
|
||||
}
|
||||
|
||||
if (d2 >= 0.0D)
|
||||
{
|
||||
++d10;
|
||||
}
|
||||
|
||||
d8 = d8 / d0;
|
||||
d9 = d9 / d1;
|
||||
d10 = d10 / d2;
|
||||
int l = d0 < 0.0D ? -1 : 1;
|
||||
int i1 = d1 < 0.0D ? -1 : 1;
|
||||
int j1 = d2 < 0.0D ? -1 : 1;
|
||||
int k1 = MathHelper.floor(posVec32.x);
|
||||
int l1 = MathHelper.floor(posVec32.y);
|
||||
int i2 = MathHelper.floor(posVec32.z);
|
||||
int j2 = k1 - i;
|
||||
int k2 = l1 - j;
|
||||
int l2 = i2 - k;
|
||||
|
||||
while (j2 * l > 0 || k2 * i1 > 0 || l2 * j1 > 0)
|
||||
{
|
||||
if (d8 < d10 && d8 <= d9)
|
||||
{
|
||||
d8 += d5;
|
||||
i += l;
|
||||
j2 = k1 - i;
|
||||
}
|
||||
else if (d9 < d8 && d9 <= d10)
|
||||
{
|
||||
d9 += d6;
|
||||
j += i1;
|
||||
k2 = l1 - j;
|
||||
}
|
||||
else
|
||||
{
|
||||
d10 += d7;
|
||||
k += j1;
|
||||
l2 = i2 - k;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public void setCanOpenDoors(boolean p_192879_1_)
|
||||
{
|
||||
this.nodeProcessor.setCanOpenDoors(p_192879_1_);
|
||||
}
|
||||
|
||||
public void setCanEnterDoors(boolean p_192878_1_)
|
||||
{
|
||||
this.nodeProcessor.setCanEnterDoors(p_192878_1_);
|
||||
}
|
||||
|
||||
public void setCanFloat(boolean p_192877_1_)
|
||||
{
|
||||
this.nodeProcessor.setCanSwim(p_192877_1_);
|
||||
}
|
||||
|
||||
public boolean canFloat()
|
||||
{
|
||||
return this.nodeProcessor.getCanSwim();
|
||||
}
|
||||
|
||||
public boolean canEntityStandOnPos(BlockPos pos)
|
||||
{
|
||||
return this.world.getBlockState(pos).isTopSolid();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,346 @@
|
||||
package net.minecraft.pathfinding;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLiving;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class PathNavigateGround extends PathNavigate
|
||||
{
|
||||
private boolean shouldAvoidSun;
|
||||
|
||||
public PathNavigateGround(EntityLiving entitylivingIn, World worldIn)
|
||||
{
|
||||
super(entitylivingIn, worldIn);
|
||||
}
|
||||
|
||||
protected PathFinder getPathFinder()
|
||||
{
|
||||
this.nodeProcessor = new WalkNodeProcessor();
|
||||
this.nodeProcessor.setCanEnterDoors(true);
|
||||
return new PathFinder(this.nodeProcessor);
|
||||
}
|
||||
|
||||
/**
|
||||
* If on ground or swimming and can swim
|
||||
*/
|
||||
protected boolean canNavigate()
|
||||
{
|
||||
return this.entity.onGround || this.getCanSwim() && this.isInLiquid() || this.entity.isRiding();
|
||||
}
|
||||
|
||||
protected Vec3d getEntityPosition()
|
||||
{
|
||||
return new Vec3d(this.entity.posX, (double)this.getPathablePosY(), this.entity.posZ);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns path to given BlockPos
|
||||
*/
|
||||
public Path getPathToPos(BlockPos pos)
|
||||
{
|
||||
if (this.world.getBlockState(pos).getMaterial() == Material.AIR)
|
||||
{
|
||||
BlockPos blockpos;
|
||||
|
||||
for (blockpos = pos.down(); blockpos.getY() > 0 && this.world.getBlockState(blockpos).getMaterial() == Material.AIR; blockpos = blockpos.down())
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
if (blockpos.getY() > 0)
|
||||
{
|
||||
return super.getPathToPos(blockpos.up());
|
||||
}
|
||||
|
||||
while (blockpos.getY() < this.world.getHeight() && this.world.getBlockState(blockpos).getMaterial() == Material.AIR)
|
||||
{
|
||||
blockpos = blockpos.up();
|
||||
}
|
||||
|
||||
pos = blockpos;
|
||||
}
|
||||
|
||||
if (!this.world.getBlockState(pos).getMaterial().isSolid())
|
||||
{
|
||||
return super.getPathToPos(pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
BlockPos blockpos1;
|
||||
|
||||
for (blockpos1 = pos.up(); blockpos1.getY() < this.world.getHeight() && this.world.getBlockState(blockpos1).getMaterial().isSolid(); blockpos1 = blockpos1.up())
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
return super.getPathToPos(blockpos1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path to the given EntityLiving. Args : entity
|
||||
*/
|
||||
public Path getPathToEntityLiving(Entity entityIn)
|
||||
{
|
||||
return this.getPathToPos(new BlockPos(entityIn));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the safe pathing Y position for the entity depending on if it can path swim or not
|
||||
*/
|
||||
private int getPathablePosY()
|
||||
{
|
||||
if (this.entity.isInWater() && this.getCanSwim())
|
||||
{
|
||||
int i = (int)this.entity.getEntityBoundingBox().minY;
|
||||
Block block = this.world.getBlockState(new BlockPos(MathHelper.floor(this.entity.posX), i, MathHelper.floor(this.entity.posZ))).getBlock();
|
||||
int j = 0;
|
||||
|
||||
while (block == Blocks.FLOWING_WATER || block == Blocks.WATER)
|
||||
{
|
||||
++i;
|
||||
block = this.world.getBlockState(new BlockPos(MathHelper.floor(this.entity.posX), i, MathHelper.floor(this.entity.posZ))).getBlock();
|
||||
++j;
|
||||
|
||||
if (j > 16)
|
||||
{
|
||||
return (int)this.entity.getEntityBoundingBox().minY;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (int)(this.entity.getEntityBoundingBox().minY + 0.5D);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Trims path data from the end to the first sun covered block
|
||||
*/
|
||||
protected void removeSunnyPath()
|
||||
{
|
||||
super.removeSunnyPath();
|
||||
|
||||
if (this.shouldAvoidSun)
|
||||
{
|
||||
if (this.world.canSeeSky(new BlockPos(MathHelper.floor(this.entity.posX), (int)(this.entity.getEntityBoundingBox().minY + 0.5D), MathHelper.floor(this.entity.posZ))))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < this.currentPath.getCurrentPathLength(); ++i)
|
||||
{
|
||||
PathPoint pathpoint = this.currentPath.getPathPointFromIndex(i);
|
||||
|
||||
if (this.world.canSeeSky(new BlockPos(pathpoint.x, pathpoint.y, pathpoint.z)))
|
||||
{
|
||||
this.currentPath.setCurrentPathLength(i - 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified entity can safely walk to the specified location.
|
||||
*/
|
||||
protected boolean isDirectPathBetweenPoints(Vec3d posVec31, Vec3d posVec32, int sizeX, int sizeY, int sizeZ)
|
||||
{
|
||||
int i = MathHelper.floor(posVec31.x);
|
||||
int j = MathHelper.floor(posVec31.z);
|
||||
double d0 = posVec32.x - posVec31.x;
|
||||
double d1 = posVec32.z - posVec31.z;
|
||||
double d2 = d0 * d0 + d1 * d1;
|
||||
|
||||
if (d2 < 1.0E-8D)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
double d3 = 1.0D / Math.sqrt(d2);
|
||||
d0 = d0 * d3;
|
||||
d1 = d1 * d3;
|
||||
sizeX = sizeX + 2;
|
||||
sizeZ = sizeZ + 2;
|
||||
|
||||
if (!this.isSafeToStandAt(i, (int)posVec31.y, j, sizeX, sizeY, sizeZ, posVec31, d0, d1))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
sizeX = sizeX - 2;
|
||||
sizeZ = sizeZ - 2;
|
||||
double d4 = 1.0D / Math.abs(d0);
|
||||
double d5 = 1.0D / Math.abs(d1);
|
||||
double d6 = (double)i - posVec31.x;
|
||||
double d7 = (double)j - posVec31.z;
|
||||
|
||||
if (d0 >= 0.0D)
|
||||
{
|
||||
++d6;
|
||||
}
|
||||
|
||||
if (d1 >= 0.0D)
|
||||
{
|
||||
++d7;
|
||||
}
|
||||
|
||||
d6 = d6 / d0;
|
||||
d7 = d7 / d1;
|
||||
int k = d0 < 0.0D ? -1 : 1;
|
||||
int l = d1 < 0.0D ? -1 : 1;
|
||||
int i1 = MathHelper.floor(posVec32.x);
|
||||
int j1 = MathHelper.floor(posVec32.z);
|
||||
int k1 = i1 - i;
|
||||
int l1 = j1 - j;
|
||||
|
||||
while (k1 * k > 0 || l1 * l > 0)
|
||||
{
|
||||
if (d6 < d7)
|
||||
{
|
||||
d6 += d4;
|
||||
i += k;
|
||||
k1 = i1 - i;
|
||||
}
|
||||
else
|
||||
{
|
||||
d7 += d5;
|
||||
j += l;
|
||||
l1 = j1 - j;
|
||||
}
|
||||
|
||||
if (!this.isSafeToStandAt(i, (int)posVec31.y, j, sizeX, sizeY, sizeZ, posVec31, d0, d1))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true when an entity could stand at a position, including solid blocks under the entire entity.
|
||||
*/
|
||||
private boolean isSafeToStandAt(int x, int y, int z, int sizeX, int sizeY, int sizeZ, Vec3d vec31, double p_179683_8_, double p_179683_10_)
|
||||
{
|
||||
int i = x - sizeX / 2;
|
||||
int j = z - sizeZ / 2;
|
||||
|
||||
if (!this.isPositionClear(i, y, j, sizeX, sizeY, sizeZ, vec31, p_179683_8_, p_179683_10_))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int k = i; k < i + sizeX; ++k)
|
||||
{
|
||||
for (int l = j; l < j + sizeZ; ++l)
|
||||
{
|
||||
double d0 = (double)k + 0.5D - vec31.x;
|
||||
double d1 = (double)l + 0.5D - vec31.z;
|
||||
|
||||
if (d0 * p_179683_8_ + d1 * p_179683_10_ >= 0.0D)
|
||||
{
|
||||
PathNodeType pathnodetype = this.nodeProcessor.getPathNodeType(this.world, k, y - 1, l, this.entity, sizeX, sizeY, sizeZ, true, true);
|
||||
|
||||
if (pathnodetype == PathNodeType.WATER)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pathnodetype == PathNodeType.LAVA)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pathnodetype == PathNodeType.OPEN)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
pathnodetype = this.nodeProcessor.getPathNodeType(this.world, k, y, l, this.entity, sizeX, sizeY, sizeZ, true, true);
|
||||
float f = this.entity.getPathPriority(pathnodetype);
|
||||
|
||||
if (f < 0.0F || f >= 8.0F)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pathnodetype == PathNodeType.DAMAGE_FIRE || pathnodetype == PathNodeType.DANGER_FIRE || pathnodetype == PathNodeType.DAMAGE_OTHER)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if an entity does not collide with any solid blocks at the position.
|
||||
*/
|
||||
private boolean isPositionClear(int x, int y, int z, int sizeX, int sizeY, int sizeZ, Vec3d p_179692_7_, double p_179692_8_, double p_179692_10_)
|
||||
{
|
||||
for (BlockPos blockpos : BlockPos.getAllInBox(new BlockPos(x, y, z), new BlockPos(x + sizeX - 1, y + sizeY - 1, z + sizeZ - 1)))
|
||||
{
|
||||
double d0 = (double)blockpos.getX() + 0.5D - p_179692_7_.x;
|
||||
double d1 = (double)blockpos.getZ() + 0.5D - p_179692_7_.z;
|
||||
|
||||
if (d0 * p_179692_8_ + d1 * p_179692_10_ >= 0.0D)
|
||||
{
|
||||
Block block = this.world.getBlockState(blockpos).getBlock();
|
||||
|
||||
if (!block.isPassable(this.world, blockpos))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setBreakDoors(boolean canBreakDoors)
|
||||
{
|
||||
this.nodeProcessor.setCanOpenDoors(canBreakDoors);
|
||||
}
|
||||
|
||||
public void setEnterDoors(boolean enterDoors)
|
||||
{
|
||||
this.nodeProcessor.setCanEnterDoors(enterDoors);
|
||||
}
|
||||
|
||||
public boolean getEnterDoors()
|
||||
{
|
||||
return this.nodeProcessor.getCanEnterDoors();
|
||||
}
|
||||
|
||||
public void setCanSwim(boolean canSwim)
|
||||
{
|
||||
this.nodeProcessor.setCanSwim(canSwim);
|
||||
}
|
||||
|
||||
public boolean getCanSwim()
|
||||
{
|
||||
return this.nodeProcessor.getCanSwim();
|
||||
}
|
||||
|
||||
public void setAvoidSun(boolean avoidSun)
|
||||
{
|
||||
this.shouldAvoidSun = avoidSun;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package net.minecraft.pathfinding;
|
||||
|
||||
import net.minecraft.entity.EntityLiving;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class PathNavigateSwimmer extends PathNavigate
|
||||
{
|
||||
public PathNavigateSwimmer(EntityLiving entitylivingIn, World worldIn)
|
||||
{
|
||||
super(entitylivingIn, worldIn);
|
||||
}
|
||||
|
||||
protected PathFinder getPathFinder()
|
||||
{
|
||||
return new PathFinder(new SwimNodeProcessor());
|
||||
}
|
||||
|
||||
/**
|
||||
* If on ground or swimming and can swim
|
||||
*/
|
||||
protected boolean canNavigate()
|
||||
{
|
||||
return this.isInLiquid();
|
||||
}
|
||||
|
||||
protected Vec3d getEntityPosition()
|
||||
{
|
||||
return new Vec3d(this.entity.posX, this.entity.posY + (double)this.entity.height * 0.5D, this.entity.posZ);
|
||||
}
|
||||
|
||||
protected void pathFollow()
|
||||
{
|
||||
Vec3d vec3d = this.getEntityPosition();
|
||||
float f = this.entity.width * this.entity.width;
|
||||
int i = 6;
|
||||
|
||||
if (vec3d.squareDistanceTo(this.currentPath.getVectorFromIndex(this.entity, this.currentPath.getCurrentPathIndex())) < (double)f)
|
||||
{
|
||||
this.currentPath.incrementPathIndex();
|
||||
}
|
||||
|
||||
for (int j = Math.min(this.currentPath.getCurrentPathIndex() + 6, this.currentPath.getCurrentPathLength() - 1); j > this.currentPath.getCurrentPathIndex(); --j)
|
||||
{
|
||||
Vec3d vec3d1 = this.currentPath.getVectorFromIndex(this.entity, j);
|
||||
|
||||
if (vec3d1.squareDistanceTo(vec3d) <= 36.0D && this.isDirectPathBetweenPoints(vec3d, vec3d1, 0, 0, 0))
|
||||
{
|
||||
this.currentPath.setCurrentPathIndex(j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.checkForStuck(vec3d);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified entity can safely walk to the specified location.
|
||||
*/
|
||||
protected boolean isDirectPathBetweenPoints(Vec3d posVec31, Vec3d posVec32, int sizeX, int sizeY, int sizeZ)
|
||||
{
|
||||
RayTraceResult raytraceresult = this.world.rayTraceBlocks(posVec31, new Vec3d(posVec32.x, posVec32.y + (double)this.entity.height * 0.5D, posVec32.z), false, true, false);
|
||||
return raytraceresult == null || raytraceresult.typeOfHit == RayTraceResult.Type.MISS;
|
||||
}
|
||||
|
||||
public boolean canEntityStandOnPos(BlockPos pos)
|
||||
{
|
||||
return !this.world.getBlockState(pos).isFullBlock();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package net.minecraft.pathfinding;
|
||||
|
||||
public enum PathNodeType
|
||||
{
|
||||
BLOCKED(-1.0F),
|
||||
OPEN(0.0F),
|
||||
WALKABLE(0.0F),
|
||||
TRAPDOOR(0.0F),
|
||||
FENCE(-1.0F),
|
||||
LAVA(-1.0F),
|
||||
WATER(8.0F),
|
||||
RAIL(0.0F),
|
||||
DANGER_FIRE(8.0F),
|
||||
DAMAGE_FIRE(16.0F),
|
||||
DANGER_CACTUS(8.0F),
|
||||
DAMAGE_CACTUS(-1.0F),
|
||||
DANGER_OTHER(8.0F),
|
||||
DAMAGE_OTHER(-1.0F),
|
||||
DOOR_OPEN(0.0F),
|
||||
DOOR_WOOD_CLOSED(-1.0F),
|
||||
DOOR_IRON_CLOSED(-1.0F);
|
||||
|
||||
private final float priority;
|
||||
|
||||
private PathNodeType(float priorityIn)
|
||||
{
|
||||
this.priority = priorityIn;
|
||||
}
|
||||
|
||||
public float getPriority()
|
||||
{
|
||||
return this.priority;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
package net.minecraft.pathfinding;
|
||||
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
public class PathPoint
|
||||
{
|
||||
/** The x coordinate of this point */
|
||||
public final int x;
|
||||
/** The y coordinate of this point */
|
||||
public final int y;
|
||||
/** The z coordinate of this point */
|
||||
public final int z;
|
||||
/** A hash of the coordinates used to identify this point */
|
||||
private final int hash;
|
||||
/** The index of this point in its assigned path */
|
||||
public int index = -1;
|
||||
/** The distance along the path to this point */
|
||||
public float totalPathDistance;
|
||||
/** The linear distance to the next point */
|
||||
public float distanceToNext;
|
||||
/** The distance to the target */
|
||||
public float distanceToTarget;
|
||||
/** The point preceding this in its assigned path */
|
||||
public PathPoint previous;
|
||||
/** True if the pathfinder has already visited this point */
|
||||
public boolean visited;
|
||||
public float distanceFromOrigin;
|
||||
public float cost;
|
||||
public float costMalus;
|
||||
public PathNodeType nodeType = PathNodeType.BLOCKED;
|
||||
|
||||
public PathPoint(int x, int y, int z)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.hash = makeHash(x, y, z);
|
||||
}
|
||||
|
||||
public PathPoint cloneMove(int x, int y, int z)
|
||||
{
|
||||
PathPoint pathpoint = new PathPoint(x, y, z);
|
||||
pathpoint.index = this.index;
|
||||
pathpoint.totalPathDistance = this.totalPathDistance;
|
||||
pathpoint.distanceToNext = this.distanceToNext;
|
||||
pathpoint.distanceToTarget = this.distanceToTarget;
|
||||
pathpoint.previous = this.previous;
|
||||
pathpoint.visited = this.visited;
|
||||
pathpoint.distanceFromOrigin = this.distanceFromOrigin;
|
||||
pathpoint.cost = this.cost;
|
||||
pathpoint.costMalus = this.costMalus;
|
||||
pathpoint.nodeType = this.nodeType;
|
||||
return pathpoint;
|
||||
}
|
||||
|
||||
public static int makeHash(int x, int y, int z)
|
||||
{
|
||||
return y & 255 | (x & 32767) << 8 | (z & 32767) << 24 | (x < 0 ? Integer.MIN_VALUE : 0) | (z < 0 ? 32768 : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the linear distance to another path point
|
||||
*/
|
||||
public float distanceTo(PathPoint pathpointIn)
|
||||
{
|
||||
float f = (float)(pathpointIn.x - this.x);
|
||||
float f1 = (float)(pathpointIn.y - this.y);
|
||||
float f2 = (float)(pathpointIn.z - this.z);
|
||||
return MathHelper.sqrt(f * f + f1 * f1 + f2 * f2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the squared distance to another path point
|
||||
*/
|
||||
public float distanceToSquared(PathPoint pathpointIn)
|
||||
{
|
||||
float f = (float)(pathpointIn.x - this.x);
|
||||
float f1 = (float)(pathpointIn.y - this.y);
|
||||
float f2 = (float)(pathpointIn.z - this.z);
|
||||
return f * f + f1 * f1 + f2 * f2;
|
||||
}
|
||||
|
||||
public float distanceManhattan(PathPoint p_186281_1_)
|
||||
{
|
||||
float f = (float)Math.abs(p_186281_1_.x - this.x);
|
||||
float f1 = (float)Math.abs(p_186281_1_.y - this.y);
|
||||
float f2 = (float)Math.abs(p_186281_1_.z - this.z);
|
||||
return f + f1 + f2;
|
||||
}
|
||||
|
||||
public boolean equals(Object p_equals_1_)
|
||||
{
|
||||
if (!(p_equals_1_ instanceof PathPoint))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
PathPoint pathpoint = (PathPoint)p_equals_1_;
|
||||
return this.hash == pathpoint.hash && this.x == pathpoint.x && this.y == pathpoint.y && this.z == pathpoint.z;
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode()
|
||||
{
|
||||
return this.hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this point has already been assigned to a path
|
||||
*/
|
||||
public boolean isAssigned()
|
||||
{
|
||||
return this.index >= 0;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return this.x + ", " + this.y + ", " + this.z;
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public static PathPoint createFromBuffer(PacketBuffer buf)
|
||||
{
|
||||
PathPoint pathpoint = new PathPoint(buf.readInt(), buf.readInt(), buf.readInt());
|
||||
pathpoint.distanceFromOrigin = buf.readFloat();
|
||||
pathpoint.cost = buf.readFloat();
|
||||
pathpoint.costMalus = buf.readFloat();
|
||||
pathpoint.visited = buf.readBoolean();
|
||||
pathpoint.nodeType = PathNodeType.values()[buf.readInt()];
|
||||
pathpoint.distanceToTarget = buf.readFloat();
|
||||
return pathpoint;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
package net.minecraft.pathfinding;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLiving;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.util.SoundCategory;
|
||||
import net.minecraft.util.SoundEvent;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IWorldEventListener;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class PathWorldListener implements IWorldEventListener
|
||||
{
|
||||
private final List<PathNavigate> navigations = Lists.<PathNavigate>newArrayList();
|
||||
|
||||
public void notifyBlockUpdate(World worldIn, BlockPos pos, IBlockState oldState, IBlockState newState, int flags)
|
||||
{
|
||||
if (this.didBlockChange(worldIn, pos, oldState, newState))
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for (int j = this.navigations.size(); i < j; ++i)
|
||||
{
|
||||
PathNavigate pathnavigate = this.navigations.get(i);
|
||||
|
||||
if (pathnavigate != null && !pathnavigate.canUpdatePathOnTimeout())
|
||||
{
|
||||
Path path = pathnavigate.getPath();
|
||||
|
||||
if (path != null && !path.isFinished() && path.getCurrentPathLength() != 0)
|
||||
{
|
||||
PathPoint pathpoint = pathnavigate.currentPath.getFinalPathPoint();
|
||||
double d0 = pos.distanceSq(((double)pathpoint.x + pathnavigate.entity.posX) / 2.0D, ((double)pathpoint.y + pathnavigate.entity.posY) / 2.0D, ((double)pathpoint.z + pathnavigate.entity.posZ) / 2.0D);
|
||||
int k = (path.getCurrentPathLength() - path.getCurrentPathIndex()) * (path.getCurrentPathLength() - path.getCurrentPathIndex());
|
||||
|
||||
if (d0 < (double)k)
|
||||
{
|
||||
pathnavigate.updatePath();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean didBlockChange(World worldIn, BlockPos pos, IBlockState oldState, IBlockState newState)
|
||||
{
|
||||
AxisAlignedBB axisalignedbb = oldState.getCollisionBoundingBox(worldIn, pos);
|
||||
AxisAlignedBB axisalignedbb1 = newState.getCollisionBoundingBox(worldIn, pos);
|
||||
return axisalignedbb != axisalignedbb1 && (axisalignedbb == null || !axisalignedbb.equals(axisalignedbb1));
|
||||
}
|
||||
|
||||
public void notifyLightSet(BlockPos pos)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* On the client, re-renders all blocks in this range, inclusive. On the server, does nothing.
|
||||
*/
|
||||
public void markBlockRangeForRenderUpdate(int x1, int y1, int z1, int x2, int y2, int z2)
|
||||
{
|
||||
}
|
||||
|
||||
public void playSoundToAllNearExcept(@Nullable EntityPlayer player, SoundEvent soundIn, SoundCategory category, double x, double y, double z, float volume, float pitch)
|
||||
{
|
||||
}
|
||||
|
||||
public void spawnParticle(int particleID, boolean ignoreRange, double xCoord, double yCoord, double zCoord, double xSpeed, double ySpeed, double zSpeed, int... parameters)
|
||||
{
|
||||
}
|
||||
|
||||
public void spawnParticle(int id, boolean ignoreRange, boolean p_190570_3_, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed, int... parameters)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called on all IWorldAccesses when an entity is created or loaded. On client worlds, starts downloading any
|
||||
* necessary textures. On server worlds, adds the entity to the entity tracker.
|
||||
*/
|
||||
public void onEntityAdded(Entity entityIn)
|
||||
{
|
||||
if (entityIn instanceof EntityLiving)
|
||||
{
|
||||
this.navigations.add(((EntityLiving)entityIn).getNavigator());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called on all IWorldAccesses when an entity is unloaded or destroyed. On client worlds, releases any downloaded
|
||||
* textures. On server worlds, removes the entity from the entity tracker.
|
||||
*/
|
||||
public void onEntityRemoved(Entity entityIn)
|
||||
{
|
||||
if (entityIn instanceof EntityLiving)
|
||||
{
|
||||
this.navigations.remove(((EntityLiving)entityIn).getNavigator());
|
||||
}
|
||||
}
|
||||
|
||||
public void playRecord(SoundEvent soundIn, BlockPos pos)
|
||||
{
|
||||
}
|
||||
|
||||
public void broadcastSound(int soundID, BlockPos pos, int data)
|
||||
{
|
||||
}
|
||||
|
||||
public void playEvent(EntityPlayer player, int type, BlockPos blockPosIn, int data)
|
||||
{
|
||||
}
|
||||
|
||||
public void sendBlockBreakProgress(int breakerId, BlockPos pos, int progress)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package net.minecraft.pathfinding;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.EntityLiving;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
|
||||
public class SwimNodeProcessor extends NodeProcessor
|
||||
{
|
||||
public PathPoint getStart()
|
||||
{
|
||||
return this.openPoint(MathHelper.floor(this.entity.getEntityBoundingBox().minX), MathHelper.floor(this.entity.getEntityBoundingBox().minY + 0.5D), MathHelper.floor(this.entity.getEntityBoundingBox().minZ));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns PathPoint for given coordinates
|
||||
*/
|
||||
public PathPoint getPathPointToCoords(double x, double y, double z)
|
||||
{
|
||||
return this.openPoint(MathHelper.floor(x - (double)(this.entity.width / 2.0F)), MathHelper.floor(y + 0.5D), MathHelper.floor(z - (double)(this.entity.width / 2.0F)));
|
||||
}
|
||||
|
||||
public int findPathOptions(PathPoint[] pathOptions, PathPoint currentPoint, PathPoint targetPoint, float maxDistance)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for (EnumFacing enumfacing : EnumFacing.values())
|
||||
{
|
||||
PathPoint pathpoint = this.getWaterNode(currentPoint.x + enumfacing.getFrontOffsetX(), currentPoint.y + enumfacing.getFrontOffsetY(), currentPoint.z + enumfacing.getFrontOffsetZ());
|
||||
|
||||
if (pathpoint != null && !pathpoint.visited && pathpoint.distanceTo(targetPoint) < maxDistance)
|
||||
{
|
||||
pathOptions[i++] = pathpoint;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
public PathNodeType getPathNodeType(IBlockAccess blockaccessIn, int x, int y, int z, EntityLiving entitylivingIn, int xSize, int ySize, int zSize, boolean canBreakDoorsIn, boolean canEnterDoorsIn)
|
||||
{
|
||||
return PathNodeType.WATER;
|
||||
}
|
||||
|
||||
public PathNodeType getPathNodeType(IBlockAccess blockaccessIn, int x, int y, int z)
|
||||
{
|
||||
return PathNodeType.WATER;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private PathPoint getWaterNode(int p_186328_1_, int p_186328_2_, int p_186328_3_)
|
||||
{
|
||||
PathNodeType pathnodetype = this.isFree(p_186328_1_, p_186328_2_, p_186328_3_);
|
||||
return pathnodetype == PathNodeType.WATER ? this.openPoint(p_186328_1_, p_186328_2_, p_186328_3_) : null;
|
||||
}
|
||||
|
||||
private PathNodeType isFree(int p_186327_1_, int p_186327_2_, int p_186327_3_)
|
||||
{
|
||||
BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos();
|
||||
|
||||
for (int i = p_186327_1_; i < p_186327_1_ + this.entitySizeX; ++i)
|
||||
{
|
||||
for (int j = p_186327_2_; j < p_186327_2_ + this.entitySizeY; ++j)
|
||||
{
|
||||
for (int k = p_186327_3_; k < p_186327_3_ + this.entitySizeZ; ++k)
|
||||
{
|
||||
IBlockState iblockstate = this.blockaccess.getBlockState(blockpos$mutableblockpos.setPos(i, j, k));
|
||||
|
||||
if (iblockstate.getMaterial() != Material.WATER)
|
||||
{
|
||||
return PathNodeType.BLOCKED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return PathNodeType.WATER;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,516 @@
|
||||
package net.minecraft.pathfinding;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockDoor;
|
||||
import net.minecraft.block.BlockFence;
|
||||
import net.minecraft.block.BlockFenceGate;
|
||||
import net.minecraft.block.BlockRailBase;
|
||||
import net.minecraft.block.BlockWall;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.EntityLiving;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
|
||||
public class WalkNodeProcessor extends NodeProcessor
|
||||
{
|
||||
protected float avoidsWater;
|
||||
|
||||
public void init(IBlockAccess sourceIn, EntityLiving mob)
|
||||
{
|
||||
super.init(sourceIn, mob);
|
||||
this.avoidsWater = mob.getPathPriority(PathNodeType.WATER);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called when all nodes have been processed and PathEntity is created.
|
||||
* {@link net.minecraft.world.pathfinder.WalkNodeProcessor WalkNodeProcessor} uses this to change its field {@link
|
||||
* net.minecraft.world.pathfinder.WalkNodeProcessor#avoidsWater avoidsWater}
|
||||
*/
|
||||
public void postProcess()
|
||||
{
|
||||
this.entity.setPathPriority(PathNodeType.WATER, this.avoidsWater);
|
||||
super.postProcess();
|
||||
}
|
||||
|
||||
public PathPoint getStart()
|
||||
{
|
||||
int i;
|
||||
|
||||
if (this.getCanSwim() && this.entity.isInWater())
|
||||
{
|
||||
i = (int)this.entity.getEntityBoundingBox().minY;
|
||||
BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos(MathHelper.floor(this.entity.posX), i, MathHelper.floor(this.entity.posZ));
|
||||
|
||||
for (Block block = this.blockaccess.getBlockState(blockpos$mutableblockpos).getBlock(); block == Blocks.FLOWING_WATER || block == Blocks.WATER; block = this.blockaccess.getBlockState(blockpos$mutableblockpos).getBlock())
|
||||
{
|
||||
++i;
|
||||
blockpos$mutableblockpos.setPos(MathHelper.floor(this.entity.posX), i, MathHelper.floor(this.entity.posZ));
|
||||
}
|
||||
}
|
||||
else if (this.entity.onGround)
|
||||
{
|
||||
i = MathHelper.floor(this.entity.getEntityBoundingBox().minY + 0.5D);
|
||||
}
|
||||
else
|
||||
{
|
||||
BlockPos blockpos;
|
||||
|
||||
for (blockpos = new BlockPos(this.entity); (this.blockaccess.getBlockState(blockpos).getMaterial() == Material.AIR || this.blockaccess.getBlockState(blockpos).getBlock().isPassable(this.blockaccess, blockpos)) && blockpos.getY() > 0; blockpos = blockpos.down())
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
i = blockpos.up().getY();
|
||||
}
|
||||
|
||||
BlockPos blockpos2 = new BlockPos(this.entity);
|
||||
PathNodeType pathnodetype1 = this.getPathNodeType(this.entity, blockpos2.getX(), i, blockpos2.getZ());
|
||||
|
||||
if (this.entity.getPathPriority(pathnodetype1) < 0.0F)
|
||||
{
|
||||
Set<BlockPos> set = Sets.<BlockPos>newHashSet();
|
||||
set.add(new BlockPos(this.entity.getEntityBoundingBox().minX, (double)i, this.entity.getEntityBoundingBox().minZ));
|
||||
set.add(new BlockPos(this.entity.getEntityBoundingBox().minX, (double)i, this.entity.getEntityBoundingBox().maxZ));
|
||||
set.add(new BlockPos(this.entity.getEntityBoundingBox().maxX, (double)i, this.entity.getEntityBoundingBox().minZ));
|
||||
set.add(new BlockPos(this.entity.getEntityBoundingBox().maxX, (double)i, this.entity.getEntityBoundingBox().maxZ));
|
||||
|
||||
for (BlockPos blockpos1 : set)
|
||||
{
|
||||
PathNodeType pathnodetype = this.getPathNodeType(this.entity, blockpos1);
|
||||
|
||||
if (this.entity.getPathPriority(pathnodetype) >= 0.0F)
|
||||
{
|
||||
return this.openPoint(blockpos1.getX(), blockpos1.getY(), blockpos1.getZ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this.openPoint(blockpos2.getX(), i, blockpos2.getZ());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns PathPoint for given coordinates
|
||||
*/
|
||||
public PathPoint getPathPointToCoords(double x, double y, double z)
|
||||
{
|
||||
return this.openPoint(MathHelper.floor(x), MathHelper.floor(y), MathHelper.floor(z));
|
||||
}
|
||||
|
||||
public int findPathOptions(PathPoint[] pathOptions, PathPoint currentPoint, PathPoint targetPoint, float maxDistance)
|
||||
{
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
PathNodeType pathnodetype = this.getPathNodeType(this.entity, currentPoint.x, currentPoint.y + 1, currentPoint.z);
|
||||
|
||||
if (this.entity.getPathPriority(pathnodetype) >= 0.0F)
|
||||
{
|
||||
j = MathHelper.floor(Math.max(1.0F, this.entity.stepHeight));
|
||||
}
|
||||
|
||||
BlockPos blockpos = (new BlockPos(currentPoint.x, currentPoint.y, currentPoint.z)).down();
|
||||
double d0 = (double)currentPoint.y - (1.0D - this.blockaccess.getBlockState(blockpos).getBoundingBox(this.blockaccess, blockpos).maxY);
|
||||
PathPoint pathpoint = this.getSafePoint(currentPoint.x, currentPoint.y, currentPoint.z + 1, j, d0, EnumFacing.SOUTH);
|
||||
PathPoint pathpoint1 = this.getSafePoint(currentPoint.x - 1, currentPoint.y, currentPoint.z, j, d0, EnumFacing.WEST);
|
||||
PathPoint pathpoint2 = this.getSafePoint(currentPoint.x + 1, currentPoint.y, currentPoint.z, j, d0, EnumFacing.EAST);
|
||||
PathPoint pathpoint3 = this.getSafePoint(currentPoint.x, currentPoint.y, currentPoint.z - 1, j, d0, EnumFacing.NORTH);
|
||||
|
||||
if (pathpoint != null && !pathpoint.visited && pathpoint.distanceTo(targetPoint) < maxDistance)
|
||||
{
|
||||
pathOptions[i++] = pathpoint;
|
||||
}
|
||||
|
||||
if (pathpoint1 != null && !pathpoint1.visited && pathpoint1.distanceTo(targetPoint) < maxDistance)
|
||||
{
|
||||
pathOptions[i++] = pathpoint1;
|
||||
}
|
||||
|
||||
if (pathpoint2 != null && !pathpoint2.visited && pathpoint2.distanceTo(targetPoint) < maxDistance)
|
||||
{
|
||||
pathOptions[i++] = pathpoint2;
|
||||
}
|
||||
|
||||
if (pathpoint3 != null && !pathpoint3.visited && pathpoint3.distanceTo(targetPoint) < maxDistance)
|
||||
{
|
||||
pathOptions[i++] = pathpoint3;
|
||||
}
|
||||
|
||||
boolean flag = pathpoint3 == null || pathpoint3.nodeType == PathNodeType.OPEN || pathpoint3.costMalus != 0.0F;
|
||||
boolean flag1 = pathpoint == null || pathpoint.nodeType == PathNodeType.OPEN || pathpoint.costMalus != 0.0F;
|
||||
boolean flag2 = pathpoint2 == null || pathpoint2.nodeType == PathNodeType.OPEN || pathpoint2.costMalus != 0.0F;
|
||||
boolean flag3 = pathpoint1 == null || pathpoint1.nodeType == PathNodeType.OPEN || pathpoint1.costMalus != 0.0F;
|
||||
|
||||
if (flag && flag3)
|
||||
{
|
||||
PathPoint pathpoint4 = this.getSafePoint(currentPoint.x - 1, currentPoint.y, currentPoint.z - 1, j, d0, EnumFacing.NORTH);
|
||||
|
||||
if (pathpoint4 != null && !pathpoint4.visited && pathpoint4.distanceTo(targetPoint) < maxDistance)
|
||||
{
|
||||
pathOptions[i++] = pathpoint4;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag && flag2)
|
||||
{
|
||||
PathPoint pathpoint5 = this.getSafePoint(currentPoint.x + 1, currentPoint.y, currentPoint.z - 1, j, d0, EnumFacing.NORTH);
|
||||
|
||||
if (pathpoint5 != null && !pathpoint5.visited && pathpoint5.distanceTo(targetPoint) < maxDistance)
|
||||
{
|
||||
pathOptions[i++] = pathpoint5;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag1 && flag3)
|
||||
{
|
||||
PathPoint pathpoint6 = this.getSafePoint(currentPoint.x - 1, currentPoint.y, currentPoint.z + 1, j, d0, EnumFacing.SOUTH);
|
||||
|
||||
if (pathpoint6 != null && !pathpoint6.visited && pathpoint6.distanceTo(targetPoint) < maxDistance)
|
||||
{
|
||||
pathOptions[i++] = pathpoint6;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag1 && flag2)
|
||||
{
|
||||
PathPoint pathpoint7 = this.getSafePoint(currentPoint.x + 1, currentPoint.y, currentPoint.z + 1, j, d0, EnumFacing.SOUTH);
|
||||
|
||||
if (pathpoint7 != null && !pathpoint7.visited && pathpoint7.distanceTo(targetPoint) < maxDistance)
|
||||
{
|
||||
pathOptions[i++] = pathpoint7;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a point that the entity can safely move to
|
||||
*/
|
||||
@Nullable
|
||||
private PathPoint getSafePoint(int x, int y, int z, int p_186332_4_, double p_186332_5_, EnumFacing facing)
|
||||
{
|
||||
PathPoint pathpoint = null;
|
||||
BlockPos blockpos = new BlockPos(x, y, z);
|
||||
BlockPos blockpos1 = blockpos.down();
|
||||
double d0 = (double)y - (1.0D - this.blockaccess.getBlockState(blockpos1).getBoundingBox(this.blockaccess, blockpos1).maxY);
|
||||
|
||||
if (d0 - p_186332_5_ > 1.125D)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
PathNodeType pathnodetype = this.getPathNodeType(this.entity, x, y, z);
|
||||
float f = this.entity.getPathPriority(pathnodetype);
|
||||
double d1 = (double)this.entity.width / 2.0D;
|
||||
|
||||
if (f >= 0.0F)
|
||||
{
|
||||
pathpoint = this.openPoint(x, y, z);
|
||||
pathpoint.nodeType = pathnodetype;
|
||||
pathpoint.costMalus = Math.max(pathpoint.costMalus, f);
|
||||
}
|
||||
|
||||
if (pathnodetype == PathNodeType.WALKABLE)
|
||||
{
|
||||
return pathpoint;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pathpoint == null && p_186332_4_ > 0 && pathnodetype != PathNodeType.FENCE && pathnodetype != PathNodeType.TRAPDOOR)
|
||||
{
|
||||
pathpoint = this.getSafePoint(x, y + 1, z, p_186332_4_ - 1, p_186332_5_, facing);
|
||||
|
||||
if (pathpoint != null && (pathpoint.nodeType == PathNodeType.OPEN || pathpoint.nodeType == PathNodeType.WALKABLE) && this.entity.width < 1.0F)
|
||||
{
|
||||
double d2 = (double)(x - facing.getFrontOffsetX()) + 0.5D;
|
||||
double d3 = (double)(z - facing.getFrontOffsetZ()) + 0.5D;
|
||||
AxisAlignedBB axisalignedbb = new AxisAlignedBB(d2 - d1, (double)y + 0.001D, d3 - d1, d2 + d1, (double)((float)y + this.entity.height), d3 + d1);
|
||||
AxisAlignedBB axisalignedbb1 = this.blockaccess.getBlockState(blockpos).getBoundingBox(this.blockaccess, blockpos);
|
||||
AxisAlignedBB axisalignedbb2 = axisalignedbb.expand(0.0D, axisalignedbb1.maxY - 0.002D, 0.0D);
|
||||
|
||||
if (this.entity.world.collidesWithAnyBlock(axisalignedbb2))
|
||||
{
|
||||
pathpoint = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pathnodetype == PathNodeType.OPEN)
|
||||
{
|
||||
AxisAlignedBB axisalignedbb3 = new AxisAlignedBB((double)x - d1 + 0.5D, (double)y + 0.001D, (double)z - d1 + 0.5D, (double)x + d1 + 0.5D, (double)((float)y + this.entity.height), (double)z + d1 + 0.5D);
|
||||
|
||||
if (this.entity.world.collidesWithAnyBlock(axisalignedbb3))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (this.entity.width >= 1.0F)
|
||||
{
|
||||
PathNodeType pathnodetype1 = this.getPathNodeType(this.entity, x, y - 1, z);
|
||||
|
||||
if (pathnodetype1 == PathNodeType.BLOCKED)
|
||||
{
|
||||
pathpoint = this.openPoint(x, y, z);
|
||||
pathpoint.nodeType = PathNodeType.WALKABLE;
|
||||
pathpoint.costMalus = Math.max(pathpoint.costMalus, f);
|
||||
return pathpoint;
|
||||
}
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
|
||||
while (y > 0 && pathnodetype == PathNodeType.OPEN)
|
||||
{
|
||||
--y;
|
||||
|
||||
if (i++ >= this.entity.getMaxFallHeight())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
pathnodetype = this.getPathNodeType(this.entity, x, y, z);
|
||||
f = this.entity.getPathPriority(pathnodetype);
|
||||
|
||||
if (pathnodetype != PathNodeType.OPEN && f >= 0.0F)
|
||||
{
|
||||
pathpoint = this.openPoint(x, y, z);
|
||||
pathpoint.nodeType = pathnodetype;
|
||||
pathpoint.costMalus = Math.max(pathpoint.costMalus, f);
|
||||
break;
|
||||
}
|
||||
|
||||
if (f < 0.0F)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pathpoint;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PathNodeType getPathNodeType(IBlockAccess blockaccessIn, int x, int y, int z, EntityLiving entitylivingIn, int xSize, int ySize, int zSize, boolean canBreakDoorsIn, boolean canEnterDoorsIn)
|
||||
{
|
||||
EnumSet<PathNodeType> enumset = EnumSet.<PathNodeType>noneOf(PathNodeType.class);
|
||||
PathNodeType pathnodetype = PathNodeType.BLOCKED;
|
||||
double d0 = (double)entitylivingIn.width / 2.0D;
|
||||
BlockPos blockpos = new BlockPos(entitylivingIn);
|
||||
pathnodetype = this.getPathNodeType(blockaccessIn, x, y, z, xSize, ySize, zSize, canBreakDoorsIn, canEnterDoorsIn, enumset, pathnodetype, blockpos);
|
||||
|
||||
if (enumset.contains(PathNodeType.FENCE))
|
||||
{
|
||||
return PathNodeType.FENCE;
|
||||
}
|
||||
else
|
||||
{
|
||||
PathNodeType pathnodetype1 = PathNodeType.BLOCKED;
|
||||
|
||||
for (PathNodeType pathnodetype2 : enumset)
|
||||
{
|
||||
if (entitylivingIn.getPathPriority(pathnodetype2) < 0.0F)
|
||||
{
|
||||
return pathnodetype2;
|
||||
}
|
||||
|
||||
if (entitylivingIn.getPathPriority(pathnodetype2) >= entitylivingIn.getPathPriority(pathnodetype1))
|
||||
{
|
||||
pathnodetype1 = pathnodetype2;
|
||||
}
|
||||
}
|
||||
|
||||
if (pathnodetype == PathNodeType.OPEN && entitylivingIn.getPathPriority(pathnodetype1) == 0.0F)
|
||||
{
|
||||
return PathNodeType.OPEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
return pathnodetype1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PathNodeType getPathNodeType(IBlockAccess p_193577_1_, int x, int y, int z, int xSize, int ySize, int zSize, boolean canOpenDoorsIn, boolean canEnterDoorsIn, EnumSet<PathNodeType> p_193577_10_, PathNodeType p_193577_11_, BlockPos p_193577_12_)
|
||||
{
|
||||
for (int i = 0; i < xSize; ++i)
|
||||
{
|
||||
for (int j = 0; j < ySize; ++j)
|
||||
{
|
||||
for (int k = 0; k < zSize; ++k)
|
||||
{
|
||||
int l = i + x;
|
||||
int i1 = j + y;
|
||||
int j1 = k + z;
|
||||
PathNodeType pathnodetype = this.getPathNodeType(p_193577_1_, l, i1, j1);
|
||||
|
||||
if (pathnodetype == PathNodeType.DOOR_WOOD_CLOSED && canOpenDoorsIn && canEnterDoorsIn)
|
||||
{
|
||||
pathnodetype = PathNodeType.WALKABLE;
|
||||
}
|
||||
|
||||
if (pathnodetype == PathNodeType.DOOR_OPEN && !canEnterDoorsIn)
|
||||
{
|
||||
pathnodetype = PathNodeType.BLOCKED;
|
||||
}
|
||||
|
||||
if (pathnodetype == PathNodeType.RAIL && !(p_193577_1_.getBlockState(p_193577_12_).getBlock() instanceof BlockRailBase) && !(p_193577_1_.getBlockState(p_193577_12_.down()).getBlock() instanceof BlockRailBase))
|
||||
{
|
||||
pathnodetype = PathNodeType.FENCE;
|
||||
}
|
||||
|
||||
if (i == 0 && j == 0 && k == 0)
|
||||
{
|
||||
p_193577_11_ = pathnodetype;
|
||||
}
|
||||
|
||||
p_193577_10_.add(pathnodetype);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return p_193577_11_;
|
||||
}
|
||||
|
||||
private PathNodeType getPathNodeType(EntityLiving entitylivingIn, BlockPos pos)
|
||||
{
|
||||
return this.getPathNodeType(entitylivingIn, pos.getX(), pos.getY(), pos.getZ());
|
||||
}
|
||||
|
||||
private PathNodeType getPathNodeType(EntityLiving entitylivingIn, int x, int y, int z)
|
||||
{
|
||||
return this.getPathNodeType(this.blockaccess, x, y, z, entitylivingIn, this.entitySizeX, this.entitySizeY, this.entitySizeZ, this.getCanOpenDoors(), this.getCanEnterDoors());
|
||||
}
|
||||
|
||||
public PathNodeType getPathNodeType(IBlockAccess blockaccessIn, int x, int y, int z)
|
||||
{
|
||||
PathNodeType pathnodetype = this.getPathNodeTypeRaw(blockaccessIn, x, y, z);
|
||||
|
||||
if (pathnodetype == PathNodeType.OPEN && y >= 1)
|
||||
{
|
||||
Block block = blockaccessIn.getBlockState(new BlockPos(x, y - 1, z)).getBlock();
|
||||
PathNodeType pathnodetype1 = this.getPathNodeTypeRaw(blockaccessIn, x, y - 1, z);
|
||||
pathnodetype = pathnodetype1 != PathNodeType.WALKABLE && pathnodetype1 != PathNodeType.OPEN && pathnodetype1 != PathNodeType.WATER && pathnodetype1 != PathNodeType.LAVA ? PathNodeType.WALKABLE : PathNodeType.OPEN;
|
||||
|
||||
if (pathnodetype1 == PathNodeType.DAMAGE_FIRE || block == Blocks.MAGMA)
|
||||
{
|
||||
pathnodetype = PathNodeType.DAMAGE_FIRE;
|
||||
}
|
||||
|
||||
if (pathnodetype1 == PathNodeType.DAMAGE_CACTUS)
|
||||
{
|
||||
pathnodetype = PathNodeType.DAMAGE_CACTUS;
|
||||
}
|
||||
}
|
||||
|
||||
pathnodetype = this.checkNeighborBlocks(blockaccessIn, x, y, z, pathnodetype);
|
||||
return pathnodetype;
|
||||
}
|
||||
|
||||
public PathNodeType checkNeighborBlocks(IBlockAccess p_193578_1_, int p_193578_2_, int p_193578_3_, int p_193578_4_, PathNodeType p_193578_5_)
|
||||
{
|
||||
BlockPos.PooledMutableBlockPos blockpos$pooledmutableblockpos = BlockPos.PooledMutableBlockPos.retain();
|
||||
|
||||
if (p_193578_5_ == PathNodeType.WALKABLE)
|
||||
{
|
||||
for (int i = -1; i <= 1; ++i)
|
||||
{
|
||||
for (int j = -1; j <= 1; ++j)
|
||||
{
|
||||
if (i != 0 || j != 0)
|
||||
{
|
||||
Block block = p_193578_1_.getBlockState(blockpos$pooledmutableblockpos.setPos(i + p_193578_2_, p_193578_3_, j + p_193578_4_)).getBlock();
|
||||
|
||||
if (block == Blocks.CACTUS)
|
||||
{
|
||||
p_193578_5_ = PathNodeType.DANGER_CACTUS;
|
||||
}
|
||||
else if (block == Blocks.FIRE)
|
||||
{
|
||||
p_193578_5_ = PathNodeType.DANGER_FIRE;
|
||||
}
|
||||
else if(block.isBurning(p_193578_1_,blockpos$pooledmutableblockpos)) p_193578_5_ = PathNodeType.DAMAGE_FIRE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
blockpos$pooledmutableblockpos.release();
|
||||
return p_193578_5_;
|
||||
}
|
||||
|
||||
protected PathNodeType getPathNodeTypeRaw(IBlockAccess p_189553_1_, int p_189553_2_, int p_189553_3_, int p_189553_4_)
|
||||
{
|
||||
BlockPos blockpos = new BlockPos(p_189553_2_, p_189553_3_, p_189553_4_);
|
||||
IBlockState iblockstate = p_189553_1_.getBlockState(blockpos);
|
||||
Block block = iblockstate.getBlock();
|
||||
Material material = iblockstate.getMaterial();
|
||||
|
||||
PathNodeType type = block.getAiPathNodeType(iblockstate, p_189553_1_, blockpos);
|
||||
if (type != null) return type;
|
||||
|
||||
if (material == Material.AIR)
|
||||
{
|
||||
return PathNodeType.OPEN;
|
||||
}
|
||||
else if (block != Blocks.TRAPDOOR && block != Blocks.IRON_TRAPDOOR && block != Blocks.WATERLILY)
|
||||
{
|
||||
if (block == Blocks.FIRE)
|
||||
{
|
||||
return PathNodeType.DAMAGE_FIRE;
|
||||
}
|
||||
else if (block == Blocks.CACTUS)
|
||||
{
|
||||
return PathNodeType.DAMAGE_CACTUS;
|
||||
}
|
||||
else if (block instanceof BlockDoor && material == Material.WOOD && !((Boolean)iblockstate.getValue(BlockDoor.OPEN)).booleanValue())
|
||||
{
|
||||
return PathNodeType.DOOR_WOOD_CLOSED;
|
||||
}
|
||||
else if (block instanceof BlockDoor && material == Material.IRON && !((Boolean)iblockstate.getValue(BlockDoor.OPEN)).booleanValue())
|
||||
{
|
||||
return PathNodeType.DOOR_IRON_CLOSED;
|
||||
}
|
||||
else if (block instanceof BlockDoor && ((Boolean)iblockstate.getValue(BlockDoor.OPEN)).booleanValue())
|
||||
{
|
||||
return PathNodeType.DOOR_OPEN;
|
||||
}
|
||||
else if (block instanceof BlockRailBase)
|
||||
{
|
||||
return PathNodeType.RAIL;
|
||||
}
|
||||
else if (!(block instanceof BlockFence) && !(block instanceof BlockWall) && (!(block instanceof BlockFenceGate) || ((Boolean)iblockstate.getValue(BlockFenceGate.OPEN)).booleanValue()))
|
||||
{
|
||||
if (material == Material.WATER)
|
||||
{
|
||||
return PathNodeType.WATER;
|
||||
}
|
||||
else if (material == Material.LAVA)
|
||||
{
|
||||
return PathNodeType.LAVA;
|
||||
}
|
||||
else
|
||||
{
|
||||
return block.isPassable(p_189553_1_, blockpos) ? PathNodeType.OPEN : PathNodeType.BLOCKED;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return PathNodeType.FENCE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return PathNodeType.TRAPDOOR;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// Auto generated package-info by MCP
|
||||
@ParametersAreNonnullByDefault
|
||||
@MethodsReturnNonnullByDefault
|
||||
package net.minecraft.pathfinding;
|
||||
|
||||
import mcp.MethodsReturnNonnullByDefault;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
Reference in New Issue
Block a user