package net.minecraft.world.level.pathfinder;

import net.minecraft.world.level.block.CampfireBlock;
import net.minecraft.world.level.block.FenceGateBlock;
import net.minecraft.world.level.block.LeavesBlock;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.block.DoorBlock;
import net.minecraft.world.level.block.Block;
import net.minecraft.tags.BlockTags;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.tags.Tag;
import net.minecraft.tags.FluidTags;
import net.minecraft.world.level.block.BaseRailBlock;
import java.util.Iterator;
import java.util.EnumSet;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraft.world.phys.Vec3;
import javax.annotation.Nullable;
import net.minecraft.core.Direction;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.util.Mth;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.level.PathNavigationRegion;
import it.unimi.dsi.fastutil.objects.Object2BooleanOpenHashMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import net.minecraft.world.phys.AABB;
import it.unimi.dsi.fastutil.objects.Object2BooleanMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;

public class WalkNodeEvaluator extends NodeEvaluator {
    protected float oldWaterCost;
    private final Long2ObjectMap<BlockPathTypes> pathTypesByPosCache;
    private final Object2BooleanMap<AABB> collisionCache;
    
    public WalkNodeEvaluator() {
        this.pathTypesByPosCache = (Long2ObjectMap<BlockPathTypes>)new Long2ObjectOpenHashMap();
        this.collisionCache = (Object2BooleanMap<AABB>)new Object2BooleanOpenHashMap();
    }
    
    @Override
    public void prepare(final PathNavigationRegion bql, final Mob aoz) {
        super.prepare(bql, aoz);
        this.oldWaterCost = aoz.getPathfindingMalus(BlockPathTypes.WATER);
    }
    
    @Override
    public void done() {
        this.mob.setPathfindingMalus(BlockPathTypes.WATER, this.oldWaterCost);
        this.pathTypesByPosCache.clear();
        this.collisionCache.clear();
        super.done();
    }
    
    @Override
    public Node getStart() {
        final BlockPos.MutableBlockPos a3 = new BlockPos.MutableBlockPos();
        int integer2 = Mth.floor(this.mob.getY());
        BlockState cfj4 = this.level.getBlockState(a3.set(this.mob.getX(), integer2, this.mob.getZ()));
        if (this.mob.canStandOnFluid(cfj4.getFluidState().getType())) {
            while (this.mob.canStandOnFluid(cfj4.getFluidState().getType())) {
                ++integer2;
                cfj4 = this.level.getBlockState(a3.set(this.mob.getX(), integer2, this.mob.getZ()));
            }
            --integer2;
        }
        else if (this.canFloat() && this.mob.isInWater()) {
            while (cfj4.getBlock() == Blocks.WATER || cfj4.getFluidState() == Fluids.WATER.getSource(false)) {
                ++integer2;
                cfj4 = this.level.getBlockState(a3.set(this.mob.getX(), integer2, this.mob.getZ()));
            }
            --integer2;
        }
        else if (this.mob.isOnGround()) {
            integer2 = Mth.floor(this.mob.getY() + 0.5);
        }
        else {
            BlockPos fu5;
            for (fu5 = this.mob.blockPosition(); (this.level.getBlockState(fu5).isAir() || this.level.getBlockState(fu5).isPathfindable(this.level, fu5, PathComputationType.LAND)) && fu5.getY() > 0; fu5 = fu5.below()) {}
            integer2 = fu5.above().getY();
        }
        BlockPos fu5 = this.mob.blockPosition();
        final BlockPathTypes czb6 = this.getCachedBlockType(this.mob, fu5.getX(), integer2, fu5.getZ());
        if (this.mob.getPathfindingMalus(czb6) < 0.0f) {
            final AABB deg7 = this.mob.getBoundingBox();
            if (this.hasPositiveMalus(a3.set(deg7.minX, integer2, deg7.minZ)) || this.hasPositiveMalus(a3.set(deg7.minX, integer2, deg7.maxZ)) || this.hasPositiveMalus(a3.set(deg7.maxX, integer2, deg7.minZ)) || this.hasPositiveMalus(a3.set(deg7.maxX, integer2, deg7.maxZ))) {
                final Node czd8 = this.getNode(a3);
                czd8.type = this.getBlockPathType(this.mob, czd8.asBlockPos());
                czd8.costMalus = this.mob.getPathfindingMalus(czd8.type);
                return czd8;
            }
        }
        final Node czd9 = this.getNode(fu5.getX(), integer2, fu5.getZ());
        czd9.type = this.getBlockPathType(this.mob, czd9.asBlockPos());
        czd9.costMalus = this.mob.getPathfindingMalus(czd9.type);
        return czd9;
    }
    
    private boolean hasPositiveMalus(final BlockPos fu) {
        final BlockPathTypes czb3 = this.getBlockPathType(this.mob, fu);
        return this.mob.getPathfindingMalus(czb3) >= 0.0f;
    }
    
    @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 czd) {
        int integer4 = 0;
        int integer5 = 0;
        final BlockPathTypes czb6 = this.getCachedBlockType(this.mob, czd.x, czd.y + 1, czd.z);
        final BlockPathTypes czb7 = this.getCachedBlockType(this.mob, czd.x, czd.y, czd.z);
        if (this.mob.getPathfindingMalus(czb6) >= 0.0f && czb7 != BlockPathTypes.STICKY_HONEY) {
            integer5 = Mth.floor(Math.max(1.0f, this.mob.maxUpStep));
        }
        final double double8 = getFloorLevel(this.level, new BlockPos(czd.x, czd.y, czd.z));
        final Node czd2 = this.getLandNode(czd.x, czd.y, czd.z + 1, integer5, double8, Direction.SOUTH, czb7);
        if (this.isNeighborValid(czd2, czd)) {
            arr[integer4++] = czd2;
        }
        final Node czd3 = this.getLandNode(czd.x - 1, czd.y, czd.z, integer5, double8, Direction.WEST, czb7);
        if (this.isNeighborValid(czd3, czd)) {
            arr[integer4++] = czd3;
        }
        final Node czd4 = this.getLandNode(czd.x + 1, czd.y, czd.z, integer5, double8, Direction.EAST, czb7);
        if (this.isNeighborValid(czd4, czd)) {
            arr[integer4++] = czd4;
        }
        final Node czd5 = this.getLandNode(czd.x, czd.y, czd.z - 1, integer5, double8, Direction.NORTH, czb7);
        if (this.isNeighborValid(czd5, czd)) {
            arr[integer4++] = czd5;
        }
        final Node czd6 = this.getLandNode(czd.x - 1, czd.y, czd.z - 1, integer5, double8, Direction.NORTH, czb7);
        if (this.isDiagonalValid(czd, czd3, czd5, czd6)) {
            arr[integer4++] = czd6;
        }
        final Node czd7 = this.getLandNode(czd.x + 1, czd.y, czd.z - 1, integer5, double8, Direction.NORTH, czb7);
        if (this.isDiagonalValid(czd, czd4, czd5, czd7)) {
            arr[integer4++] = czd7;
        }
        final Node czd8 = this.getLandNode(czd.x - 1, czd.y, czd.z + 1, integer5, double8, Direction.SOUTH, czb7);
        if (this.isDiagonalValid(czd, czd3, czd2, czd8)) {
            arr[integer4++] = czd8;
        }
        final Node czd9 = this.getLandNode(czd.x + 1, czd.y, czd.z + 1, integer5, double8, Direction.SOUTH, czb7);
        if (this.isDiagonalValid(czd, czd4, czd2, czd9)) {
            arr[integer4++] = czd9;
        }
        return integer4;
    }
    
    private boolean isNeighborValid(final Node czd1, final Node czd2) {
        return czd1 != null && !czd1.closed && (czd1.costMalus >= 0.0f || czd2.costMalus < 0.0f);
    }
    
    private boolean isDiagonalValid(final Node czd1, @Nullable final Node czd2, @Nullable final Node czd3, @Nullable final Node czd4) {
        if (czd4 == null || czd3 == null || czd2 == null) {
            return false;
        }
        if (czd4.closed) {
            return false;
        }
        if (czd3.y > czd1.y || czd2.y > czd1.y) {
            return false;
        }
        final boolean boolean6 = czd3.type == BlockPathTypes.FENCE && czd2.type == BlockPathTypes.FENCE && this.mob.getBbWidth() < 0.5;
        return czd4.costMalus >= 0.0f && (czd3.y < czd1.y || czd3.costMalus >= 0.0f || boolean6) && (czd2.y < czd1.y || czd2.costMalus >= 0.0f || boolean6);
    }
    
    private boolean canReachWithoutCollision(final Node czd) {
        Vec3 dem3 = new Vec3(czd.x - this.mob.getX(), czd.y - this.mob.getY(), czd.z - this.mob.getZ());
        AABB deg4 = this.mob.getBoundingBox();
        final int integer5 = Mth.ceil(dem3.length() / deg4.getSize());
        dem3 = dem3.scale(1.0f / integer5);
        for (int integer6 = 1; integer6 <= integer5; ++integer6) {
            deg4 = deg4.move(dem3);
            if (this.hasCollisions(deg4)) {
                return false;
            }
        }
        return true;
    }
    
    public static double getFloorLevel(final BlockGetter bpg, final BlockPos fu) {
        final BlockPos fu2 = fu.below();
        final VoxelShape dfg4 = bpg.getBlockState(fu2).getCollisionShape(bpg, fu2);
        return fu2.getY() + (dfg4.isEmpty() ? 0.0 : dfg4.max(Direction.Axis.Y));
    }
    
    @Nullable
    private Node getLandNode(final int integer1, int integer2, final int integer3, final int integer4, final double double5, final Direction fz, final BlockPathTypes czb) {
        Node czd10 = null;
        final BlockPos.MutableBlockPos a11 = new BlockPos.MutableBlockPos();
        final double double6 = getFloorLevel(this.level, a11.set(integer1, integer2, integer3));
        if (double6 - double5 > 1.125) {
            return null;
        }
        BlockPathTypes czb2 = this.getCachedBlockType(this.mob, integer1, integer2, integer3);
        float float15 = this.mob.getPathfindingMalus(czb2);
        final double double7 = this.mob.getBbWidth() / 2.0;
        if (float15 >= 0.0f) {
            czd10 = this.getNode(integer1, integer2, integer3);
            czd10.type = czb2;
            czd10.costMalus = Math.max(czd10.costMalus, float15);
        }
        if (czb == BlockPathTypes.FENCE && czd10 != null && czd10.costMalus >= 0.0f && !this.canReachWithoutCollision(czd10)) {
            czd10 = null;
        }
        if (czb2 == BlockPathTypes.WALKABLE) {
            return czd10;
        }
        if ((czd10 == null || czd10.costMalus < 0.0f) && integer4 > 0 && czb2 != BlockPathTypes.FENCE && czb2 != BlockPathTypes.UNPASSABLE_RAIL && czb2 != BlockPathTypes.TRAPDOOR) {
            czd10 = this.getLandNode(integer1, integer2 + 1, integer3, integer4 - 1, double5, fz, czb);
            if (czd10 != null && (czd10.type == BlockPathTypes.OPEN || czd10.type == BlockPathTypes.WALKABLE) && this.mob.getBbWidth() < 1.0f) {
                final double double8 = integer1 - fz.getStepX() + 0.5;
                final double double9 = integer3 - fz.getStepZ() + 0.5;
                final AABB deg22 = new AABB(double8 - double7, getFloorLevel(this.level, a11.set(double8, integer2 + 1, double9)) + 0.001, double9 - double7, double8 + double7, this.mob.getBbHeight() + getFloorLevel(this.level, a11.set(czd10.x, czd10.y, (double)czd10.z)) - 0.002, double9 + double7);
                if (this.hasCollisions(deg22)) {
                    czd10 = null;
                }
            }
        }
        if (czb2 == BlockPathTypes.WATER && !this.canFloat()) {
            if (this.getCachedBlockType(this.mob, integer1, integer2 - 1, integer3) != BlockPathTypes.WATER) {
                return czd10;
            }
            while (integer2 > 0) {
                --integer2;
                czb2 = this.getCachedBlockType(this.mob, integer1, integer2, integer3);
                if (czb2 != BlockPathTypes.WATER) {
                    return czd10;
                }
                czd10 = this.getNode(integer1, integer2, integer3);
                czd10.type = czb2;
                czd10.costMalus = Math.max(czd10.costMalus, this.mob.getPathfindingMalus(czb2));
            }
        }
        if (czb2 == BlockPathTypes.OPEN) {
            final AABB deg23 = 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.hasCollisions(deg23)) {
                return null;
            }
            if (this.mob.getBbWidth() >= 1.0f) {
                final BlockPathTypes czb3 = this.getCachedBlockType(this.mob, integer1, integer2 - 1, integer3);
                if (czb3 == BlockPathTypes.BLOCKED) {
                    czd10 = this.getNode(integer1, integer2, integer3);
                    czd10.type = BlockPathTypes.WALKABLE;
                    czd10.costMalus = Math.max(czd10.costMalus, float15);
                    return czd10;
                }
            }
            int integer5 = 0;
            final int integer6 = integer2;
            while (czb2 == BlockPathTypes.OPEN) {
                if (--integer2 < 0) {
                    final Node czd11 = this.getNode(integer1, integer6, integer3);
                    czd11.type = BlockPathTypes.BLOCKED;
                    czd11.costMalus = -1.0f;
                    return czd11;
                }
                final Node czd11 = this.getNode(integer1, integer2, integer3);
                if (integer5++ >= this.mob.getMaxFallDistance()) {
                    czd11.type = BlockPathTypes.BLOCKED;
                    czd11.costMalus = -1.0f;
                    return czd11;
                }
                czb2 = this.getCachedBlockType(this.mob, integer1, integer2, integer3);
                float15 = this.mob.getPathfindingMalus(czb2);
                if (czb2 != BlockPathTypes.OPEN && float15 >= 0.0f) {
                    czd10 = czd11;
                    czd10.type = czb2;
                    czd10.costMalus = Math.max(czd10.costMalus, float15);
                    break;
                }
                if (float15 < 0.0f) {
                    czd11.type = BlockPathTypes.BLOCKED;
                    czd11.costMalus = -1.0f;
                    return czd11;
                }
            }
        }
        if (czb2 == BlockPathTypes.FENCE) {
            czd10 = this.getNode(integer1, integer2, integer3);
            czd10.closed = true;
            czd10.type = czb2;
            czd10.costMalus = czb2.getMalus();
        }
        return czd10;
    }
    
    private boolean hasCollisions(final AABB deg) {
        return (boolean)this.collisionCache.computeIfAbsent(deg, deg2 -> !this.level.noCollision(this.mob, deg));
    }
    
    @Override
    public BlockPathTypes getBlockPathType(final BlockGetter bpg, final int integer2, final int integer3, final int integer4, final Mob aoz, 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 czb13 = BlockPathTypes.BLOCKED;
        final BlockPos fu14 = aoz.blockPosition();
        czb13 = this.getBlockPathTypes(bpg, integer2, integer3, integer4, integer6, integer7, integer8, boolean9, boolean10, enumSet12, czb13, fu14);
        if (enumSet12.contains(BlockPathTypes.FENCE)) {
            return BlockPathTypes.FENCE;
        }
        if (enumSet12.contains(BlockPathTypes.UNPASSABLE_RAIL)) {
            return BlockPathTypes.UNPASSABLE_RAIL;
        }
        BlockPathTypes czb14 = BlockPathTypes.BLOCKED;
        for (final BlockPathTypes czb15 : enumSet12) {
            if (aoz.getPathfindingMalus(czb15) < 0.0f) {
                return czb15;
            }
            if (aoz.getPathfindingMalus(czb15) < aoz.getPathfindingMalus(czb14)) {
                continue;
            }
            czb14 = czb15;
        }
        if (czb13 == BlockPathTypes.OPEN && aoz.getPathfindingMalus(czb14) == 0.0f) {
            return BlockPathTypes.OPEN;
        }
        return czb14;
    }
    
    public BlockPathTypes getBlockPathTypes(final BlockGetter bpg, 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 czb, final BlockPos fu) {
        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 czb2 = this.getBlockPathType(bpg, integer11, integer12, integer13);
                    czb2 = this.evaluateBlockPathType(bpg, boolean8, boolean9, fu, czb2);
                    if (integer8 == 0 && integer9 == 0 && integer10 == 0) {
                        czb = czb2;
                    }
                    enumSet.add(czb2);
                }
            }
        }
        return czb;
    }
    
    protected BlockPathTypes evaluateBlockPathType(final BlockGetter bpg, final boolean boolean2, final boolean boolean3, final BlockPos fu, BlockPathTypes czb) {
        if (czb == BlockPathTypes.DOOR_WOOD_CLOSED && boolean2 && boolean3) {
            czb = BlockPathTypes.WALKABLE;
        }
        if (czb == BlockPathTypes.DOOR_OPEN && !boolean3) {
            czb = BlockPathTypes.BLOCKED;
        }
        if (czb == BlockPathTypes.RAIL && !(bpg.getBlockState(fu).getBlock() instanceof BaseRailBlock) && !(bpg.getBlockState(fu.below()).getBlock() instanceof BaseRailBlock)) {
            czb = BlockPathTypes.UNPASSABLE_RAIL;
        }
        if (czb == BlockPathTypes.LEAVES) {
            czb = BlockPathTypes.BLOCKED;
        }
        return czb;
    }
    
    private BlockPathTypes getBlockPathType(final Mob aoz, final BlockPos fu) {
        return this.getCachedBlockType(aoz, fu.getX(), fu.getY(), fu.getZ());
    }
    
    private BlockPathTypes getCachedBlockType(final Mob aoz, final int integer2, final int integer3, final int integer4) {
        return (BlockPathTypes)this.pathTypesByPosCache.computeIfAbsent(BlockPos.asLong(integer2, integer3, integer4), long5 -> this.getBlockPathType(this.level, integer2, integer3, integer4, aoz, this.entityWidth, this.entityHeight, this.entityDepth, this.canOpenDoors(), this.canPassDoors()));
    }
    
    @Override
    public BlockPathTypes getBlockPathType(final BlockGetter bpg, final int integer2, final int integer3, final int integer4) {
        return getBlockPathTypeStatic(bpg, new BlockPos.MutableBlockPos(integer2, integer3, integer4));
    }
    
    public static BlockPathTypes getBlockPathTypeStatic(final BlockGetter bpg, final BlockPos.MutableBlockPos a) {
        final int integer3 = a.getX();
        final int integer4 = a.getY();
        final int integer5 = a.getZ();
        BlockPathTypes czb6 = getBlockPathTypeRaw(bpg, a);
        if (czb6 == BlockPathTypes.OPEN && integer4 >= 1) {
            final BlockPathTypes czb7 = getBlockPathTypeRaw(bpg, a.set(integer3, integer4 - 1, integer5));
            czb6 = ((czb7 == BlockPathTypes.WALKABLE || czb7 == BlockPathTypes.OPEN || czb7 == BlockPathTypes.WATER || czb7 == BlockPathTypes.LAVA) ? BlockPathTypes.OPEN : BlockPathTypes.WALKABLE);
            if (czb7 == BlockPathTypes.DAMAGE_FIRE) {
                czb6 = BlockPathTypes.DAMAGE_FIRE;
            }
            if (czb7 == BlockPathTypes.DAMAGE_CACTUS) {
                czb6 = BlockPathTypes.DAMAGE_CACTUS;
            }
            if (czb7 == BlockPathTypes.DAMAGE_OTHER) {
                czb6 = BlockPathTypes.DAMAGE_OTHER;
            }
            if (czb7 == BlockPathTypes.STICKY_HONEY) {
                czb6 = BlockPathTypes.STICKY_HONEY;
            }
        }
        if (czb6 == BlockPathTypes.WALKABLE) {
            czb6 = checkNeighbourBlocks(bpg, a.set(integer3, integer4, integer5), czb6);
        }
        return czb6;
    }
    
    public static BlockPathTypes checkNeighbourBlocks(final BlockGetter bpg, final BlockPos.MutableBlockPos a, final BlockPathTypes czb) {
        final int integer4 = a.getX();
        final int integer5 = a.getY();
        final int integer6 = a.getZ();
        for (int integer7 = -1; integer7 <= 1; ++integer7) {
            for (int integer8 = -1; integer8 <= 1; ++integer8) {
                for (int integer9 = -1; integer9 <= 1; ++integer9) {
                    if (integer7 != 0 || integer9 != 0) {
                        a.set(integer4 + integer7, integer5 + integer8, integer6 + integer9);
                        final BlockState cfj10 = bpg.getBlockState(a);
                        if (cfj10.is(Blocks.CACTUS)) {
                            return BlockPathTypes.DANGER_CACTUS;
                        }
                        if (cfj10.is(Blocks.SWEET_BERRY_BUSH)) {
                            return BlockPathTypes.DANGER_OTHER;
                        }
                        if (isBurningBlock(cfj10)) {
                            return BlockPathTypes.DANGER_FIRE;
                        }
                        final FluidState cxa11 = bpg.getFluidState(a);
                        if (cxa11.is(FluidTags.WATER)) {
                            return BlockPathTypes.WATER_BORDER;
                        }
                        if (cxa11.is(FluidTags.LAVA)) {
                            return BlockPathTypes.LAVA;
                        }
                    }
                }
            }
        }
        return czb;
    }
    
    protected static BlockPathTypes getBlockPathTypeRaw(final BlockGetter bpg, final BlockPos fu) {
        final BlockState cfj3 = bpg.getBlockState(fu);
        final Block bvr4 = cfj3.getBlock();
        final Material cxd5 = cfj3.getMaterial();
        if (cfj3.isAir()) {
            return BlockPathTypes.OPEN;
        }
        if (cfj3.is(BlockTags.TRAPDOORS) || cfj3.is(Blocks.LILY_PAD)) {
            return BlockPathTypes.TRAPDOOR;
        }
        if (cfj3.is(Blocks.CACTUS)) {
            return BlockPathTypes.DAMAGE_CACTUS;
        }
        if (cfj3.is(Blocks.SWEET_BERRY_BUSH)) {
            return BlockPathTypes.DAMAGE_OTHER;
        }
        if (cfj3.is(Blocks.HONEY_BLOCK)) {
            return BlockPathTypes.STICKY_HONEY;
        }
        if (cfj3.is(Blocks.COCOA)) {
            return BlockPathTypes.COCOA;
        }
        if (isBurningBlock(cfj3)) {
            return BlockPathTypes.DAMAGE_FIRE;
        }
        if (DoorBlock.isWoodenDoor(cfj3) && !cfj3.<Boolean>getValue((Property<Boolean>)DoorBlock.OPEN)) {
            return BlockPathTypes.DOOR_WOOD_CLOSED;
        }
        if (bvr4 instanceof DoorBlock && cxd5 == Material.METAL && !cfj3.<Boolean>getValue((Property<Boolean>)DoorBlock.OPEN)) {
            return BlockPathTypes.DOOR_IRON_CLOSED;
        }
        if (bvr4 instanceof DoorBlock && cfj3.<Boolean>getValue((Property<Boolean>)DoorBlock.OPEN)) {
            return BlockPathTypes.DOOR_OPEN;
        }
        if (bvr4 instanceof BaseRailBlock) {
            return BlockPathTypes.RAIL;
        }
        if (bvr4 instanceof LeavesBlock) {
            return BlockPathTypes.LEAVES;
        }
        if (bvr4.is(BlockTags.FENCES) || bvr4.is(BlockTags.WALLS) || (bvr4 instanceof FenceGateBlock && !cfj3.<Boolean>getValue((Property<Boolean>)FenceGateBlock.OPEN))) {
            return BlockPathTypes.FENCE;
        }
        if (!cfj3.isPathfindable(bpg, fu, PathComputationType.LAND)) {
            return BlockPathTypes.BLOCKED;
        }
        final FluidState cxa6 = bpg.getFluidState(fu);
        if (cxa6.is(FluidTags.WATER)) {
            return BlockPathTypes.WATER;
        }
        if (cxa6.is(FluidTags.LAVA)) {
            return BlockPathTypes.LAVA;
        }
        return BlockPathTypes.OPEN;
    }
    
    private static boolean isBurningBlock(final BlockState cfj) {
        return cfj.is(BlockTags.FIRE) || cfj.is(Blocks.MAGMA_BLOCK) || CampfireBlock.isLitCampfire(cfj);
    }
}
