package net.minecraft.world.entity.vehicle; import java.util.function.Function; import javax.annotation.Nullable; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.tags.BlockTags; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.Pose; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.CollisionGetter; import net.minecraft.world.level.block.TrapDoorBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; public class DismountHelper { public static int[][] offsetsForDirection(Direction p_38468_) { Direction direction = p_38468_.getClockWise(); Direction direction1 = direction.getOpposite(); Direction direction2 = p_38468_.getOpposite(); return new int[][]{ {direction.getStepX(), direction.getStepZ()}, {direction1.getStepX(), direction1.getStepZ()}, {direction2.getStepX() + direction.getStepX(), direction2.getStepZ() + direction.getStepZ()}, {direction2.getStepX() + direction1.getStepX(), direction2.getStepZ() + direction1.getStepZ()}, {p_38468_.getStepX() + direction.getStepX(), p_38468_.getStepZ() + direction.getStepZ()}, {p_38468_.getStepX() + direction1.getStepX(), p_38468_.getStepZ() + direction1.getStepZ()}, {direction2.getStepX(), direction2.getStepZ()}, {p_38468_.getStepX(), p_38468_.getStepZ()} }; } public static boolean isBlockFloorValid(double p_38440_) { return !Double.isInfinite(p_38440_) && p_38440_ < 1.0; } public static boolean canDismountTo(CollisionGetter p_38457_, LivingEntity p_38458_, AABB p_38459_) { for (VoxelShape voxelshape : p_38457_.getBlockCollisions(p_38458_, p_38459_)) { if (!voxelshape.isEmpty()) { return false; } } return p_38457_.getWorldBorder().isWithinBounds(p_38459_); } public static boolean canDismountTo(CollisionGetter p_150280_, Vec3 p_150281_, LivingEntity p_150282_, Pose p_150283_) { return canDismountTo(p_150280_, p_150282_, p_150282_.getLocalBoundsForPose(p_150283_).move(p_150281_)); } public static VoxelShape nonClimbableShape(BlockGetter p_38447_, BlockPos p_38448_) { BlockState blockstate = p_38447_.getBlockState(p_38448_); return !blockstate.is(BlockTags.CLIMBABLE) && (!(blockstate.getBlock() instanceof TrapDoorBlock) || !blockstate.getValue(TrapDoorBlock.OPEN)) ? blockstate.getCollisionShape(p_38447_, p_38448_) : Shapes.empty(); } public static double findCeilingFrom(BlockPos p_38464_, int p_38465_, Function p_38466_) { BlockPos.MutableBlockPos blockpos$mutableblockpos = p_38464_.mutable(); int i = 0; while (i < p_38465_) { VoxelShape voxelshape = p_38466_.apply(blockpos$mutableblockpos); if (!voxelshape.isEmpty()) { return p_38464_.getY() + i + voxelshape.min(Direction.Axis.Y); } i++; blockpos$mutableblockpos.move(Direction.UP); } return Double.POSITIVE_INFINITY; } @Nullable public static Vec3 findSafeDismountLocation(EntityType p_38442_, CollisionGetter p_38443_, BlockPos p_38444_, boolean p_38445_) { if (p_38445_ && p_38442_.isBlockDangerous(p_38443_.getBlockState(p_38444_))) { return null; } else { double d0 = p_38443_.getBlockFloorHeight(nonClimbableShape(p_38443_, p_38444_), () -> nonClimbableShape(p_38443_, p_38444_.below())); if (!isBlockFloorValid(d0)) { return null; } else if (p_38445_ && d0 <= 0.0 && p_38442_.isBlockDangerous(p_38443_.getBlockState(p_38444_.below()))) { return null; } else { Vec3 vec3 = Vec3.upFromBottomCenterOf(p_38444_, d0); AABB aabb = p_38442_.getDimensions().makeBoundingBox(vec3); for (VoxelShape voxelshape : p_38443_.getBlockCollisions(null, aabb)) { if (!voxelshape.isEmpty()) { return null; } } if (p_38442_ != EntityType.PLAYER || !p_38443_.getBlockState(p_38444_).is(BlockTags.INVALID_SPAWN_INSIDE) && !p_38443_.getBlockState(p_38444_.above()).is(BlockTags.INVALID_SPAWN_INSIDE)) { return !p_38443_.getWorldBorder().isWithinBounds(aabb) ? null : vec3; } else { return null; } } } } }