minecraft-source/src/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java

421 lines
20 KiB
Java

package net.minecraft.world.level.pathfinder;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.tags.FluidTags;
import net.minecraft.world.level.block.FenceGateBlock;
import net.minecraft.world.level.block.LeavesBlock;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.block.DoorBlock;
import net.minecraft.tags.BlockTags;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.BaseRailBlock;
import java.util.EnumSet;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.shapes.VoxelShape;
import javax.annotation.Nullable;
import net.minecraft.core.Direction;
import java.util.Iterator;
import java.util.Set;
import net.minecraft.world.level.block.state.BlockState;
import com.google.common.collect.Sets;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.core.BlockPos;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.level.PathNavigationRegion;
public class WalkNodeEvaluator extends NodeEvaluator {
protected float oldWaterCost;
@Override
public void prepare(final PathNavigationRegion bke, final Mob akx) {
super.prepare(bke, akx);
this.oldWaterCost = akx.getPathfindingMalus(BlockPathTypes.WATER);
}
@Override
public void done() {
this.mob.setPathfindingMalus(BlockPathTypes.WATER, this.oldWaterCost);
super.done();
}
@Override
public Node getStart() {
int integer2;
if (this.canFloat() && this.mob.isInWater()) {
integer2 = Mth.floor(this.mob.getY());
final BlockPos.MutableBlockPos a3 = new BlockPos.MutableBlockPos(this.mob.getX(), integer2, this.mob.getZ());
for (BlockState byg4 = this.level.getBlockState(a3); byg4.getBlock() == Blocks.WATER || byg4.getFluidState() == Fluids.WATER.getSource(false); byg4 = this.level.getBlockState(a3)) {
++integer2;
a3.set(this.mob.getX(), integer2, this.mob.getZ());
}
--integer2;
}
else if (this.mob.onGround) {
integer2 = Mth.floor(this.mob.getY() + 0.5);
}
else {
BlockPos fk3;
for (fk3 = new BlockPos(this.mob); (this.level.getBlockState(fk3).isAir() || this.level.getBlockState(fk3).isPathfindable(this.level, fk3, PathComputationType.LAND)) && fk3.getY() > 0; fk3 = fk3.below()) {}
integer2 = fk3.above().getY();
}
BlockPos fk3 = new BlockPos(this.mob);
final BlockPathTypes cqj4 = this.getBlockPathType(this.mob, fk3.getX(), integer2, fk3.getZ());
if (this.mob.getPathfindingMalus(cqj4) < 0.0f) {
final Set<BlockPos> set5 = Sets.newHashSet();
set5.add(new BlockPos(this.mob.getBoundingBox().minX, integer2, this.mob.getBoundingBox().minZ));
set5.add(new BlockPos(this.mob.getBoundingBox().minX, integer2, this.mob.getBoundingBox().maxZ));
set5.add(new BlockPos(this.mob.getBoundingBox().maxX, integer2, this.mob.getBoundingBox().minZ));
set5.add(new BlockPos(this.mob.getBoundingBox().maxX, integer2, this.mob.getBoundingBox().maxZ));
for (final BlockPos fk4 : set5) {
final BlockPathTypes cqj5 = this.getBlockPathType(this.mob, fk4);
if (this.mob.getPathfindingMalus(cqj5) >= 0.0f) {
return this.getNode(fk4.getX(), fk4.getY(), fk4.getZ());
}
}
}
return this.getNode(fk3.getX(), integer2, fk3.getZ());
}
@Override
public Target getGoal(final double double1, final double double2, final double double3) {
return new Target(this.getNode(Mth.floor(double1), Mth.floor(double2), Mth.floor(double3)));
}
@Override
public int getNeighbors(final Node[] arr, final Node cql) {
int integer4 = 0;
int integer5 = 0;
final BlockPathTypes cqj6 = this.getBlockPathType(this.mob, cql.x, cql.y + 1, cql.z);
if (this.mob.getPathfindingMalus(cqj6) >= 0.0f) {
final BlockPathTypes cqj7 = this.getBlockPathType(this.mob, cql.x, cql.y, cql.z);
if (cqj7 == BlockPathTypes.STICKY_HONEY) {
integer5 = 0;
}
else {
integer5 = Mth.floor(Math.max(1.0f, this.mob.maxUpStep));
}
}
final double double7 = getFloorLevel(this.level, new BlockPos(cql.x, cql.y, cql.z));
final Node cql2 = this.getLandNode(cql.x, cql.y, cql.z + 1, integer5, double7, Direction.SOUTH);
if (cql2 != null && !cql2.closed && cql2.costMalus >= 0.0f) {
arr[integer4++] = cql2;
}
final Node cql3 = this.getLandNode(cql.x - 1, cql.y, cql.z, integer5, double7, Direction.WEST);
if (cql3 != null && !cql3.closed && cql3.costMalus >= 0.0f) {
arr[integer4++] = cql3;
}
final Node cql4 = this.getLandNode(cql.x + 1, cql.y, cql.z, integer5, double7, Direction.EAST);
if (cql4 != null && !cql4.closed && cql4.costMalus >= 0.0f) {
arr[integer4++] = cql4;
}
final Node cql5 = this.getLandNode(cql.x, cql.y, cql.z - 1, integer5, double7, Direction.NORTH);
if (cql5 != null && !cql5.closed && cql5.costMalus >= 0.0f) {
arr[integer4++] = cql5;
}
final Node cql6 = this.getLandNode(cql.x - 1, cql.y, cql.z - 1, integer5, double7, Direction.NORTH);
if (this.isDiagonalValid(cql, cql3, cql5, cql6)) {
arr[integer4++] = cql6;
}
final Node cql7 = this.getLandNode(cql.x + 1, cql.y, cql.z - 1, integer5, double7, Direction.NORTH);
if (this.isDiagonalValid(cql, cql4, cql5, cql7)) {
arr[integer4++] = cql7;
}
final Node cql8 = this.getLandNode(cql.x - 1, cql.y, cql.z + 1, integer5, double7, Direction.SOUTH);
if (this.isDiagonalValid(cql, cql3, cql2, cql8)) {
arr[integer4++] = cql8;
}
final Node cql9 = this.getLandNode(cql.x + 1, cql.y, cql.z + 1, integer5, double7, Direction.SOUTH);
if (this.isDiagonalValid(cql, cql4, cql2, cql9)) {
arr[integer4++] = cql9;
}
return integer4;
}
private boolean isDiagonalValid(final Node cql1, @Nullable final Node cql2, @Nullable final Node cql3, @Nullable final Node cql4) {
return cql4 != null && cql3 != null && cql2 != null && !cql4.closed && cql3.y <= cql1.y && cql2.y <= cql1.y && cql4.costMalus >= 0.0f && (cql3.y < cql1.y || cql3.costMalus >= 0.0f) && (cql2.y < cql1.y || cql2.costMalus >= 0.0f);
}
public static double getFloorLevel(final BlockGetter bjd, final BlockPos fk) {
final BlockPos fk2 = fk.below();
final VoxelShape cwc4 = bjd.getBlockState(fk2).getCollisionShape(bjd, fk2);
return fk2.getY() + (cwc4.isEmpty() ? 0.0 : cwc4.max(Direction.Axis.Y));
}
@Nullable
private Node getLandNode(final int integer1, int integer2, final int integer3, final int integer4, final double double5, final Direction fp) {
Node cql9 = null;
final BlockPos fk10 = new BlockPos(integer1, integer2, integer3);
final double double6 = getFloorLevel(this.level, fk10);
if (double6 - double5 > 1.125) {
return null;
}
BlockPathTypes cqj13 = this.getBlockPathType(this.mob, integer1, integer2, integer3);
float float14 = this.mob.getPathfindingMalus(cqj13);
final double double7 = this.mob.getBbWidth() / 2.0;
if (float14 >= 0.0f) {
cql9 = this.getNode(integer1, integer2, integer3);
cql9.type = cqj13;
cql9.costMalus = Math.max(cql9.costMalus, float14);
}
if (cqj13 == BlockPathTypes.WALKABLE) {
return cql9;
}
if ((cql9 == null || cql9.costMalus < 0.0f) && integer4 > 0 && cqj13 != BlockPathTypes.FENCE && cqj13 != BlockPathTypes.TRAPDOOR) {
cql9 = this.getLandNode(integer1, integer2 + 1, integer3, integer4 - 1, double5, fp);
if (cql9 != null && (cql9.type == BlockPathTypes.OPEN || cql9.type == BlockPathTypes.WALKABLE) && this.mob.getBbWidth() < 1.0f) {
final double double8 = integer1 - fp.getStepX() + 0.5;
final double double9 = integer3 - fp.getStepZ() + 0.5;
final AABB cvc21 = new AABB(double8 - double7, getFloorLevel(this.level, new BlockPos(double8, integer2 + 1, double9)) + 0.001, double9 - double7, double8 + double7, this.mob.getBbHeight() + getFloorLevel(this.level, new BlockPos(cql9.x, cql9.y, cql9.z)) - 0.002, double9 + double7);
if (!this.level.noCollision(this.mob, cvc21)) {
cql9 = null;
}
}
}
if (cqj13 == BlockPathTypes.WATER && !this.canFloat()) {
if (this.getBlockPathType(this.mob, integer1, integer2 - 1, integer3) != BlockPathTypes.WATER) {
return cql9;
}
while (integer2 > 0) {
--integer2;
cqj13 = this.getBlockPathType(this.mob, integer1, integer2, integer3);
if (cqj13 != BlockPathTypes.WATER) {
return cql9;
}
cql9 = this.getNode(integer1, integer2, integer3);
cql9.type = cqj13;
cql9.costMalus = Math.max(cql9.costMalus, this.mob.getPathfindingMalus(cqj13));
}
}
if (cqj13 == BlockPathTypes.OPEN) {
final AABB cvc22 = new AABB(integer1 - double7 + 0.5, integer2 + 0.001, integer3 - double7 + 0.5, integer1 + double7 + 0.5, integer2 + this.mob.getBbHeight(), integer3 + double7 + 0.5);
if (!this.level.noCollision(this.mob, cvc22)) {
return null;
}
if (this.mob.getBbWidth() >= 1.0f) {
final BlockPathTypes cqj14 = this.getBlockPathType(this.mob, integer1, integer2 - 1, integer3);
if (cqj14 == BlockPathTypes.BLOCKED) {
cql9 = this.getNode(integer1, integer2, integer3);
cql9.type = BlockPathTypes.WALKABLE;
cql9.costMalus = Math.max(cql9.costMalus, float14);
return cql9;
}
}
int integer5 = 0;
final int integer6 = integer2;
while (cqj13 == BlockPathTypes.OPEN) {
if (--integer2 < 0) {
final Node cql10 = this.getNode(integer1, integer6, integer3);
cql10.type = BlockPathTypes.BLOCKED;
cql10.costMalus = -1.0f;
return cql10;
}
final Node cql10 = this.getNode(integer1, integer2, integer3);
if (integer5++ >= this.mob.getMaxFallDistance()) {
cql10.type = BlockPathTypes.BLOCKED;
cql10.costMalus = -1.0f;
return cql10;
}
cqj13 = this.getBlockPathType(this.mob, integer1, integer2, integer3);
float14 = this.mob.getPathfindingMalus(cqj13);
if (cqj13 != BlockPathTypes.OPEN && float14 >= 0.0f) {
cql9 = cql10;
cql9.type = cqj13;
cql9.costMalus = Math.max(cql9.costMalus, float14);
break;
}
if (float14 < 0.0f) {
cql10.type = BlockPathTypes.BLOCKED;
cql10.costMalus = -1.0f;
return cql10;
}
}
}
return cql9;
}
@Override
public BlockPathTypes getBlockPathType(final BlockGetter bjd, final int integer2, final int integer3, final int integer4, final Mob akx, final int integer6, final int integer7, final int integer8, final boolean boolean9, final boolean boolean10) {
final EnumSet<BlockPathTypes> enumSet12 = EnumSet.<BlockPathTypes>noneOf(BlockPathTypes.class);
BlockPathTypes cqj13 = BlockPathTypes.BLOCKED;
final double double14 = akx.getBbWidth() / 2.0;
final BlockPos fk16 = new BlockPos(akx);
cqj13 = this.getBlockPathTypes(bjd, integer2, integer3, integer4, integer6, integer7, integer8, boolean9, boolean10, enumSet12, cqj13, fk16);
if (enumSet12.contains(BlockPathTypes.FENCE)) {
return BlockPathTypes.FENCE;
}
BlockPathTypes cqj14 = BlockPathTypes.BLOCKED;
for (final BlockPathTypes cqj15 : enumSet12) {
if (akx.getPathfindingMalus(cqj15) < 0.0f) {
return cqj15;
}
if (akx.getPathfindingMalus(cqj15) < akx.getPathfindingMalus(cqj14)) {
continue;
}
cqj14 = cqj15;
}
if (cqj13 == BlockPathTypes.OPEN && akx.getPathfindingMalus(cqj14) == 0.0f) {
return BlockPathTypes.OPEN;
}
return cqj14;
}
public BlockPathTypes getBlockPathTypes(final BlockGetter bjd, final int integer2, final int integer3, final int integer4, final int integer5, final int integer6, final int integer7, final boolean boolean8, final boolean boolean9, final EnumSet<BlockPathTypes> enumSet, BlockPathTypes cqj, final BlockPos fk) {
for (int integer8 = 0; integer8 < integer5; ++integer8) {
for (int integer9 = 0; integer9 < integer6; ++integer9) {
for (int integer10 = 0; integer10 < integer7; ++integer10) {
final int integer11 = integer8 + integer2;
final int integer12 = integer9 + integer3;
final int integer13 = integer10 + integer4;
BlockPathTypes cqj2 = this.getBlockPathType(bjd, integer11, integer12, integer13);
cqj2 = this.evaluateBlockPathType(bjd, boolean8, boolean9, fk, cqj2);
if (integer8 == 0 && integer9 == 0 && integer10 == 0) {
cqj = cqj2;
}
enumSet.add(cqj2);
}
}
}
return cqj;
}
protected BlockPathTypes evaluateBlockPathType(final BlockGetter bjd, final boolean boolean2, final boolean boolean3, final BlockPos fk, BlockPathTypes cqj) {
if (cqj == BlockPathTypes.DOOR_WOOD_CLOSED && boolean2 && boolean3) {
cqj = BlockPathTypes.WALKABLE;
}
if (cqj == BlockPathTypes.DOOR_OPEN && !boolean3) {
cqj = BlockPathTypes.BLOCKED;
}
if (cqj == BlockPathTypes.RAIL && !(bjd.getBlockState(fk).getBlock() instanceof BaseRailBlock) && !(bjd.getBlockState(fk.below()).getBlock() instanceof BaseRailBlock)) {
cqj = BlockPathTypes.FENCE;
}
if (cqj == BlockPathTypes.LEAVES) {
cqj = BlockPathTypes.BLOCKED;
}
return cqj;
}
private BlockPathTypes getBlockPathType(final Mob akx, final BlockPos fk) {
return this.getBlockPathType(akx, fk.getX(), fk.getY(), fk.getZ());
}
private BlockPathTypes getBlockPathType(final Mob akx, final int integer2, final int integer3, final int integer4) {
return this.getBlockPathType(this.level, integer2, integer3, integer4, akx, this.entityWidth, this.entityHeight, this.entityDepth, this.canOpenDoors(), this.canPassDoors());
}
@Override
public BlockPathTypes getBlockPathType(final BlockGetter bjd, final int integer2, final int integer3, final int integer4) {
return getBlockPathTypeStatic(bjd, integer2, integer3, integer4);
}
public static BlockPathTypes getBlockPathTypeStatic(final BlockGetter bjd, final int integer2, final int integer3, final int integer4) {
BlockPathTypes cqj5 = getBlockPathTypeRaw(bjd, integer2, integer3, integer4);
if (cqj5 == BlockPathTypes.OPEN && integer3 >= 1) {
final Block bpe6 = bjd.getBlockState(new BlockPos(integer2, integer3 - 1, integer4)).getBlock();
final BlockPathTypes cqj6 = getBlockPathTypeRaw(bjd, integer2, integer3 - 1, integer4);
cqj5 = ((cqj6 == BlockPathTypes.WALKABLE || cqj6 == BlockPathTypes.OPEN || cqj6 == BlockPathTypes.WATER || cqj6 == BlockPathTypes.LAVA) ? BlockPathTypes.OPEN : BlockPathTypes.WALKABLE);
if (cqj6 == BlockPathTypes.DAMAGE_FIRE || bpe6 == Blocks.MAGMA_BLOCK || bpe6 == Blocks.CAMPFIRE) {
cqj5 = BlockPathTypes.DAMAGE_FIRE;
}
if (cqj6 == BlockPathTypes.DAMAGE_CACTUS) {
cqj5 = BlockPathTypes.DAMAGE_CACTUS;
}
if (cqj6 == BlockPathTypes.DAMAGE_OTHER) {
cqj5 = BlockPathTypes.DAMAGE_OTHER;
}
if (cqj6 == BlockPathTypes.STICKY_HONEY) {
cqj5 = BlockPathTypes.STICKY_HONEY;
}
}
if (cqj5 == BlockPathTypes.WALKABLE) {
cqj5 = checkNeighbourBlocks(bjd, integer2, integer3, integer4, cqj5);
}
return cqj5;
}
public static BlockPathTypes checkNeighbourBlocks(final BlockGetter bjd, final int integer2, final int integer3, final int integer4, BlockPathTypes cqj) {
try (final BlockPos.PooledMutableBlockPos b6 = BlockPos.PooledMutableBlockPos.acquire()) {
for (int integer5 = -1; integer5 <= 1; ++integer5) {
for (int integer6 = -1; integer6 <= 1; ++integer6) {
for (int integer7 = -1; integer7 <= 1; ++integer7) {
if (integer5 != 0 || integer7 != 0) {
final Block bpe11 = bjd.getBlockState(b6.set(integer5 + integer2, integer6 + integer3, integer7 + integer4)).getBlock();
if (bpe11 == Blocks.CACTUS) {
cqj = BlockPathTypes.DANGER_CACTUS;
}
else if (bpe11 == Blocks.FIRE || bpe11 == Blocks.LAVA) {
cqj = BlockPathTypes.DANGER_FIRE;
}
else if (bpe11 == Blocks.SWEET_BERRY_BUSH) {
cqj = BlockPathTypes.DANGER_OTHER;
}
}
}
}
}
}
return cqj;
}
protected static BlockPathTypes getBlockPathTypeRaw(final BlockGetter bjd, final int integer2, final int integer3, final int integer4) {
final BlockPos fk5 = new BlockPos(integer2, integer3, integer4);
final BlockState byg6 = bjd.getBlockState(fk5);
final Block bpe7 = byg6.getBlock();
final Material cok8 = byg6.getMaterial();
if (byg6.isAir()) {
return BlockPathTypes.OPEN;
}
if (bpe7.is(BlockTags.TRAPDOORS) || bpe7 == Blocks.LILY_PAD) {
return BlockPathTypes.TRAPDOOR;
}
if (bpe7 == Blocks.FIRE) {
return BlockPathTypes.DAMAGE_FIRE;
}
if (bpe7 == Blocks.CACTUS) {
return BlockPathTypes.DAMAGE_CACTUS;
}
if (bpe7 == Blocks.SWEET_BERRY_BUSH) {
return BlockPathTypes.DAMAGE_OTHER;
}
if (bpe7 == Blocks.HONEY_BLOCK) {
return BlockPathTypes.STICKY_HONEY;
}
if (bpe7 == Blocks.COCOA) {
return BlockPathTypes.COCOA;
}
if (bpe7 instanceof DoorBlock && cok8 == Material.WOOD && !byg6.<Boolean>getValue((Property<Boolean>)DoorBlock.OPEN)) {
return BlockPathTypes.DOOR_WOOD_CLOSED;
}
if (bpe7 instanceof DoorBlock && cok8 == Material.METAL && !byg6.<Boolean>getValue((Property<Boolean>)DoorBlock.OPEN)) {
return BlockPathTypes.DOOR_IRON_CLOSED;
}
if (bpe7 instanceof DoorBlock && byg6.<Boolean>getValue((Property<Boolean>)DoorBlock.OPEN)) {
return BlockPathTypes.DOOR_OPEN;
}
if (bpe7 instanceof BaseRailBlock) {
return BlockPathTypes.RAIL;
}
if (bpe7 instanceof LeavesBlock) {
return BlockPathTypes.LEAVES;
}
if (bpe7.is(BlockTags.FENCES) || bpe7.is(BlockTags.WALLS) || (bpe7 instanceof FenceGateBlock && !byg6.<Boolean>getValue((Property<Boolean>)FenceGateBlock.OPEN))) {
return BlockPathTypes.FENCE;
}
final FluidState cog9 = bjd.getFluidState(fk5);
if (cog9.is(FluidTags.WATER)) {
return BlockPathTypes.WATER;
}
if (cog9.is(FluidTags.LAVA)) {
return BlockPathTypes.LAVA;
}
if (byg6.isPathfindable(bjd, fk5, PathComputationType.LAND)) {
return BlockPathTypes.OPEN;
}
return BlockPathTypes.BLOCKED;
}
}