package net.minecraft.server; import com.google.common.collect.Sets; import java.util.EnumSet; import java.util.Iterator; import java.util.Set; import javax.annotation.Nullable; public class PathfinderNormal extends PathfinderAbstract { protected float j; public PathfinderNormal() {} @Override public void a(ChunkCache chunkcache, EntityInsentient entityinsentient) { super.a(chunkcache, entityinsentient); this.j = entityinsentient.a(PathType.WATER); } @Override public void a() { this.b.a(PathType.WATER, this.j); super.a(); } @Override public PathPoint b() { int i; BlockPosition blockposition; if (this.e() && this.b.isInWater()) { i = MathHelper.floor(this.b.locY()); BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition(this.b.locX(), (double) i, this.b.locZ()); for (IBlockData iblockdata = this.a.getType(blockposition_mutableblockposition); iblockdata.getBlock() == Blocks.WATER || iblockdata.getFluid() == FluidTypes.WATER.a(false); iblockdata = this.a.getType(blockposition_mutableblockposition)) { ++i; blockposition_mutableblockposition.c(this.b.locX(), (double) i, this.b.locZ()); } --i; } else if (this.b.onGround) { i = MathHelper.floor(this.b.locY() + 0.5D); } else { for (blockposition = new BlockPosition(this.b); (this.a.getType(blockposition).isAir() || this.a.getType(blockposition).a((IBlockAccess) this.a, blockposition, PathMode.LAND)) && blockposition.getY() > 0; blockposition = blockposition.down()) { ; } i = blockposition.up().getY(); } blockposition = new BlockPosition(this.b); PathType pathtype = this.a(this.b, blockposition.getX(), i, blockposition.getZ()); if (this.b.a(pathtype) < 0.0F) { Set<BlockPosition> set = Sets.newHashSet(); set.add(new BlockPosition(this.b.getBoundingBox().minX, (double) i, this.b.getBoundingBox().minZ)); set.add(new BlockPosition(this.b.getBoundingBox().minX, (double) i, this.b.getBoundingBox().maxZ)); set.add(new BlockPosition(this.b.getBoundingBox().maxX, (double) i, this.b.getBoundingBox().minZ)); set.add(new BlockPosition(this.b.getBoundingBox().maxX, (double) i, this.b.getBoundingBox().maxZ)); Iterator iterator = set.iterator(); while (iterator.hasNext()) { BlockPosition blockposition1 = (BlockPosition) iterator.next(); PathType pathtype1 = this.a(this.b, blockposition1); if (this.b.a(pathtype1) >= 0.0F) { return this.a(blockposition1.getX(), blockposition1.getY(), blockposition1.getZ()); } } } return this.a(blockposition.getX(), i, blockposition.getZ()); } @Override public PathDestination a(double d0, double d1, double d2) { return new PathDestination(this.a(MathHelper.floor(d0), MathHelper.floor(d1), MathHelper.floor(d2))); } @Override public int a(PathPoint[] apathpoint, PathPoint pathpoint) { int i = 0; int j = 0; PathType pathtype = this.a(this.b, pathpoint.a, pathpoint.b + 1, pathpoint.c); if (this.b.a(pathtype) >= 0.0F) { PathType pathtype1 = this.a(this.b, pathpoint.a, pathpoint.b, pathpoint.c); if (pathtype1 == PathType.STICKY_HONEY) { j = 0; } else { j = MathHelper.d(Math.max(1.0F, this.b.H)); } } double d0 = a((IBlockAccess) this.a, new BlockPosition(pathpoint.a, pathpoint.b, pathpoint.c)); PathPoint pathpoint1 = this.a(pathpoint.a, pathpoint.b, pathpoint.c + 1, j, d0, EnumDirection.SOUTH); if (pathpoint1 != null && !pathpoint1.i && pathpoint1.k >= 0.0F) { apathpoint[i++] = pathpoint1; } PathPoint pathpoint2 = this.a(pathpoint.a - 1, pathpoint.b, pathpoint.c, j, d0, EnumDirection.WEST); if (pathpoint2 != null && !pathpoint2.i && pathpoint2.k >= 0.0F) { apathpoint[i++] = pathpoint2; } PathPoint pathpoint3 = this.a(pathpoint.a + 1, pathpoint.b, pathpoint.c, j, d0, EnumDirection.EAST); if (pathpoint3 != null && !pathpoint3.i && pathpoint3.k >= 0.0F) { apathpoint[i++] = pathpoint3; } PathPoint pathpoint4 = this.a(pathpoint.a, pathpoint.b, pathpoint.c - 1, j, d0, EnumDirection.NORTH); if (pathpoint4 != null && !pathpoint4.i && pathpoint4.k >= 0.0F) { apathpoint[i++] = pathpoint4; } PathPoint pathpoint5 = this.a(pathpoint.a - 1, pathpoint.b, pathpoint.c - 1, j, d0, EnumDirection.NORTH); if (this.a(pathpoint, pathpoint2, pathpoint4, pathpoint5)) { apathpoint[i++] = pathpoint5; } PathPoint pathpoint6 = this.a(pathpoint.a + 1, pathpoint.b, pathpoint.c - 1, j, d0, EnumDirection.NORTH); if (this.a(pathpoint, pathpoint3, pathpoint4, pathpoint6)) { apathpoint[i++] = pathpoint6; } PathPoint pathpoint7 = this.a(pathpoint.a - 1, pathpoint.b, pathpoint.c + 1, j, d0, EnumDirection.SOUTH); if (this.a(pathpoint, pathpoint2, pathpoint1, pathpoint7)) { apathpoint[i++] = pathpoint7; } PathPoint pathpoint8 = this.a(pathpoint.a + 1, pathpoint.b, pathpoint.c + 1, j, d0, EnumDirection.SOUTH); if (this.a(pathpoint, pathpoint3, pathpoint1, pathpoint8)) { apathpoint[i++] = pathpoint8; } return i; } private boolean a(PathPoint pathpoint, @Nullable PathPoint pathpoint1, @Nullable PathPoint pathpoint2, @Nullable PathPoint pathpoint3) { return pathpoint3 != null && pathpoint2 != null && pathpoint1 != null ? (pathpoint3.i ? false : (pathpoint2.b <= pathpoint.b && pathpoint1.b <= pathpoint.b ? pathpoint3.k >= 0.0F && (pathpoint2.b < pathpoint.b || pathpoint2.k >= 0.0F) && (pathpoint1.b < pathpoint.b || pathpoint1.k >= 0.0F) : false)) : false; } public static double a(IBlockAccess iblockaccess, BlockPosition blockposition) { BlockPosition blockposition1 = blockposition.down(); VoxelShape voxelshape = iblockaccess.getType(blockposition1).getCollisionShape(iblockaccess, blockposition1); return (double) blockposition1.getY() + (voxelshape.isEmpty() ? 0.0D : voxelshape.c(EnumDirection.EnumAxis.Y)); } @Nullable private PathPoint a(int i, int j, int k, int l, double d0, EnumDirection enumdirection) { PathPoint pathpoint = null; BlockPosition blockposition = new BlockPosition(i, j, k); double d1 = a((IBlockAccess) this.a, blockposition); if (d1 - d0 > 1.125D) { return null; } else { PathType pathtype = this.a(this.b, i, j, k); float f = this.b.a(pathtype); double d2 = (double) this.b.getWidth() / 2.0D; if (f >= 0.0F) { pathpoint = this.a(i, j, k); pathpoint.l = pathtype; pathpoint.k = Math.max(pathpoint.k, f); } if (pathtype == PathType.WALKABLE) { return pathpoint; } else { if ((pathpoint == null || pathpoint.k < 0.0F) && l > 0 && pathtype != PathType.FENCE && pathtype != PathType.TRAPDOOR) { pathpoint = this.a(i, j + 1, k, l - 1, d0, enumdirection); if (pathpoint != null && (pathpoint.l == PathType.OPEN || pathpoint.l == PathType.WALKABLE) && this.b.getWidth() < 1.0F) { double d3 = (double) (i - enumdirection.getAdjacentX()) + 0.5D; double d4 = (double) (k - enumdirection.getAdjacentZ()) + 0.5D; AxisAlignedBB axisalignedbb = new AxisAlignedBB(d3 - d2, a((IBlockAccess) this.a, new BlockPosition(d3, (double) (j + 1), d4)) + 0.001D, d4 - d2, d3 + d2, (double) this.b.getHeight() + a((IBlockAccess) this.a, new BlockPosition(pathpoint.a, pathpoint.b, pathpoint.c)) - 0.002D, d4 + d2); if (!this.a.getCubes(this.b, axisalignedbb)) { pathpoint = null; } } } if (pathtype == PathType.WATER && !this.e()) { if (this.a(this.b, i, j - 1, k) != PathType.WATER) { return pathpoint; } while (j > 0) { --j; pathtype = this.a(this.b, i, j, k); if (pathtype != PathType.WATER) { return pathpoint; } pathpoint = this.a(i, j, k); pathpoint.l = pathtype; pathpoint.k = Math.max(pathpoint.k, this.b.a(pathtype)); } } if (pathtype == PathType.OPEN) { AxisAlignedBB axisalignedbb1 = new AxisAlignedBB((double) i - d2 + 0.5D, (double) j + 0.001D, (double) k - d2 + 0.5D, (double) i + d2 + 0.5D, (double) ((float) j + this.b.getHeight()), (double) k + d2 + 0.5D); if (!this.a.getCubes(this.b, axisalignedbb1)) { return null; } if (this.b.getWidth() >= 1.0F) { PathType pathtype1 = this.a(this.b, i, j - 1, k); if (pathtype1 == PathType.BLOCKED) { pathpoint = this.a(i, j, k); pathpoint.l = PathType.WALKABLE; pathpoint.k = Math.max(pathpoint.k, f); return pathpoint; } } int i1 = 0; int j1 = j; while (pathtype == PathType.OPEN) { --j; PathPoint pathpoint1; if (j < 0) { pathpoint1 = this.a(i, j1, k); pathpoint1.l = PathType.BLOCKED; pathpoint1.k = -1.0F; return pathpoint1; } pathpoint1 = this.a(i, j, k); if (i1++ >= this.b.bD()) { pathpoint1.l = PathType.BLOCKED; pathpoint1.k = -1.0F; return pathpoint1; } pathtype = this.a(this.b, i, j, k); f = this.b.a(pathtype); if (pathtype != PathType.OPEN && f >= 0.0F) { pathpoint = pathpoint1; pathpoint1.l = pathtype; pathpoint1.k = Math.max(pathpoint1.k, f); break; } if (f < 0.0F) { pathpoint1.l = PathType.BLOCKED; pathpoint1.k = -1.0F; return pathpoint1; } } } return pathpoint; } } } @Override public PathType a(IBlockAccess iblockaccess, int i, int j, int k, EntityInsentient entityinsentient, int l, int i1, int j1, boolean flag, boolean flag1) { EnumSet<PathType> enumset = EnumSet.noneOf(PathType.class); PathType pathtype = PathType.BLOCKED; double d0 = (double) entityinsentient.getWidth() / 2.0D; BlockPosition blockposition = new BlockPosition(entityinsentient); pathtype = this.a(iblockaccess, i, j, k, l, i1, j1, flag, flag1, enumset, pathtype, blockposition); if (enumset.contains(PathType.FENCE)) { return PathType.FENCE; } else { PathType pathtype1 = PathType.BLOCKED; Iterator iterator = enumset.iterator(); while (iterator.hasNext()) { PathType pathtype2 = (PathType) iterator.next(); if (entityinsentient.a(pathtype2) < 0.0F) { return pathtype2; } if (entityinsentient.a(pathtype2) >= entityinsentient.a(pathtype1)) { pathtype1 = pathtype2; } } if (pathtype == PathType.OPEN && entityinsentient.a(pathtype1) == 0.0F) { return PathType.OPEN; } else { return pathtype1; } } } public PathType a(IBlockAccess iblockaccess, int i, int j, int k, int l, int i1, int j1, boolean flag, boolean flag1, EnumSet<PathType> enumset, PathType pathtype, BlockPosition blockposition) { for (int k1 = 0; k1 < l; ++k1) { for (int l1 = 0; l1 < i1; ++l1) { for (int i2 = 0; i2 < j1; ++i2) { int j2 = k1 + i; int k2 = l1 + j; int l2 = i2 + k; PathType pathtype1 = this.a(iblockaccess, j2, k2, l2); pathtype1 = this.a(iblockaccess, flag, flag1, blockposition, pathtype1); if (k1 == 0 && l1 == 0 && i2 == 0) { pathtype = pathtype1; } enumset.add(pathtype1); } } } return pathtype; } protected PathType a(IBlockAccess iblockaccess, boolean flag, boolean flag1, BlockPosition blockposition, PathType pathtype) { if (pathtype == PathType.DOOR_WOOD_CLOSED && flag && flag1) { pathtype = PathType.WALKABLE; } if (pathtype == PathType.DOOR_OPEN && !flag1) { pathtype = PathType.BLOCKED; } if (pathtype == PathType.RAIL && !(iblockaccess.getType(blockposition).getBlock() instanceof BlockMinecartTrackAbstract) && !(iblockaccess.getType(blockposition.down()).getBlock() instanceof BlockMinecartTrackAbstract)) { pathtype = PathType.FENCE; } if (pathtype == PathType.LEAVES) { pathtype = PathType.BLOCKED; } return pathtype; } private PathType a(EntityInsentient entityinsentient, BlockPosition blockposition) { return this.a(entityinsentient, blockposition.getX(), blockposition.getY(), blockposition.getZ()); } private PathType a(EntityInsentient entityinsentient, int i, int j, int k) { return this.a(this.a, i, j, k, entityinsentient, this.d, this.e, this.f, this.d(), this.c()); } @Override public PathType a(IBlockAccess iblockaccess, int i, int j, int k) { return b(iblockaccess, i, j, k); } public static PathType b(IBlockAccess iblockaccess, int i, int j, int k) { PathType pathtype = c(iblockaccess, i, j, k); if (pathtype == PathType.OPEN && j >= 1) { Block block = iblockaccess.getType(new BlockPosition(i, j - 1, k)).getBlock(); PathType pathtype1 = c(iblockaccess, i, j - 1, k); pathtype = pathtype1 != PathType.WALKABLE && pathtype1 != PathType.OPEN && pathtype1 != PathType.WATER && pathtype1 != PathType.LAVA ? PathType.WALKABLE : PathType.OPEN; if (pathtype1 == PathType.DAMAGE_FIRE || block == Blocks.MAGMA_BLOCK || block == Blocks.CAMPFIRE) { pathtype = PathType.DAMAGE_FIRE; } if (pathtype1 == PathType.DAMAGE_CACTUS) { pathtype = PathType.DAMAGE_CACTUS; } if (pathtype1 == PathType.DAMAGE_OTHER) { pathtype = PathType.DAMAGE_OTHER; } if (pathtype1 == PathType.STICKY_HONEY) { pathtype = PathType.STICKY_HONEY; } } if (pathtype == PathType.WALKABLE) { pathtype = a(iblockaccess, i, j, k, pathtype); } return pathtype; } public static PathType a(IBlockAccess iblockaccess, int i, int j, int k, PathType pathtype) { BlockPosition.PooledBlockPosition blockposition_pooledblockposition = BlockPosition.PooledBlockPosition.r(); Throwable throwable = null; try { for (int l = -1; l <= 1; ++l) { for (int i1 = -1; i1 <= 1; ++i1) { for (int j1 = -1; j1 <= 1; ++j1) { if (l != 0 || j1 != 0) { Block block = iblockaccess.getType(blockposition_pooledblockposition.d(l + i, i1 + j, j1 + k)).getBlock(); if (block == Blocks.CACTUS) { pathtype = PathType.DANGER_CACTUS; } else if (block != Blocks.FIRE && block != Blocks.LAVA) { if (block == Blocks.SWEET_BERRY_BUSH) { pathtype = PathType.DANGER_OTHER; } } else { pathtype = PathType.DANGER_FIRE; } } } } } } catch (Throwable throwable1) { throwable = throwable1; throw throwable1; } finally { if (blockposition_pooledblockposition != null) { if (throwable != null) { try { blockposition_pooledblockposition.close(); } catch (Throwable throwable2) { throwable.addSuppressed(throwable2); } } else { blockposition_pooledblockposition.close(); } } } return pathtype; } protected static PathType c(IBlockAccess iblockaccess, int i, int j, int k) { BlockPosition blockposition = new BlockPosition(i, j, k); IBlockData iblockdata = iblockaccess.getType(blockposition); Block block = iblockdata.getBlock(); Material material = iblockdata.getMaterial(); if (iblockdata.isAir()) { return PathType.OPEN; } else if (!block.a(TagsBlock.TRAPDOORS) && block != Blocks.LILY_PAD) { if (block == Blocks.FIRE) { return PathType.DAMAGE_FIRE; } else if (block == Blocks.CACTUS) { return PathType.DAMAGE_CACTUS; } else if (block == Blocks.SWEET_BERRY_BUSH) { return PathType.DAMAGE_OTHER; } else if (block == Blocks.HONEY_BLOCK) { return PathType.STICKY_HONEY; } else if (block == Blocks.COCOA) { return PathType.COCOA; } else if (block instanceof BlockDoor && material == Material.WOOD && !(Boolean) iblockdata.get(BlockDoor.OPEN)) { return PathType.DOOR_WOOD_CLOSED; } else if (block instanceof BlockDoor && material == Material.ORE && !(Boolean) iblockdata.get(BlockDoor.OPEN)) { return PathType.DOOR_IRON_CLOSED; } else if (block instanceof BlockDoor && (Boolean) iblockdata.get(BlockDoor.OPEN)) { return PathType.DOOR_OPEN; } else if (block instanceof BlockMinecartTrackAbstract) { return PathType.RAIL; } else if (block instanceof BlockLeaves) { return PathType.LEAVES; } else if (!block.a(TagsBlock.FENCES) && !block.a(TagsBlock.WALLS) && (!(block instanceof BlockFenceGate) || (Boolean) iblockdata.get(BlockFenceGate.OPEN))) { Fluid fluid = iblockaccess.getFluid(blockposition); return fluid.a(TagsFluid.WATER) ? PathType.WATER : (fluid.a(TagsFluid.LAVA) ? PathType.LAVA : (iblockdata.a(iblockaccess, blockposition, PathMode.LAND) ? PathType.OPEN : PathType.BLOCKED)); } else { return PathType.FENCE; } } else { return PathType.TRAPDOOR; } } }