minecraft-src/net/minecraft/world/entity/vehicle/DismountHelper.java
2025-07-04 01:41:11 +03:00

108 lines
4.1 KiB
Java

package net.minecraft.world.entity.vehicle;
import java.util.function.Function;
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;
import org.jetbrains.annotations.Nullable;
public class DismountHelper {
public static int[][] offsetsForDirection(Direction direction) {
Direction direction2 = direction.getClockWise();
Direction direction3 = direction2.getOpposite();
Direction direction4 = direction.getOpposite();
return new int[][]{
{direction2.getStepX(), direction2.getStepZ()},
{direction3.getStepX(), direction3.getStepZ()},
{direction4.getStepX() + direction2.getStepX(), direction4.getStepZ() + direction2.getStepZ()},
{direction4.getStepX() + direction3.getStepX(), direction4.getStepZ() + direction3.getStepZ()},
{direction.getStepX() + direction2.getStepX(), direction.getStepZ() + direction2.getStepZ()},
{direction.getStepX() + direction3.getStepX(), direction.getStepZ() + direction3.getStepZ()},
{direction4.getStepX(), direction4.getStepZ()},
{direction.getStepX(), direction.getStepZ()}
};
}
public static boolean isBlockFloorValid(double distance) {
return !Double.isInfinite(distance) && distance < 1.0;
}
public static boolean canDismountTo(CollisionGetter level, LivingEntity passenger, AABB boundingBox) {
for (VoxelShape voxelShape : level.getBlockCollisions(passenger, boundingBox)) {
if (!voxelShape.isEmpty()) {
return false;
}
}
return level.getWorldBorder().isWithinBounds(boundingBox);
}
public static boolean canDismountTo(CollisionGetter level, Vec3 offset, LivingEntity passenger, Pose pose) {
return canDismountTo(level, passenger, passenger.getLocalBoundsForPose(pose).move(offset));
}
public static VoxelShape nonClimbableShape(BlockGetter level, BlockPos pos) {
BlockState blockState = level.getBlockState(pos);
return !blockState.is(BlockTags.CLIMBABLE) && (!(blockState.getBlock() instanceof TrapDoorBlock) || !blockState.getValue(TrapDoorBlock.OPEN))
? blockState.getCollisionShape(level, pos)
: Shapes.empty();
}
public static double findCeilingFrom(BlockPos pos, int ceiling, Function<BlockPos, VoxelShape> shapeForPos) {
BlockPos.MutableBlockPos mutableBlockPos = pos.mutable();
int i = 0;
while (i < ceiling) {
VoxelShape voxelShape = (VoxelShape)shapeForPos.apply(mutableBlockPos);
if (!voxelShape.isEmpty()) {
return pos.getY() + i + voxelShape.min(Direction.Axis.Y);
}
i++;
mutableBlockPos.move(Direction.UP);
}
return Double.POSITIVE_INFINITY;
}
@Nullable
public static Vec3 findSafeDismountLocation(EntityType<?> entityType, CollisionGetter level, BlockPos pos, boolean onlySafePositions) {
if (onlySafePositions && entityType.isBlockDangerous(level.getBlockState(pos))) {
return null;
} else {
double d = level.getBlockFloorHeight(nonClimbableShape(level, pos), () -> nonClimbableShape(level, pos.below()));
if (!isBlockFloorValid(d)) {
return null;
} else if (onlySafePositions && d <= 0.0 && entityType.isBlockDangerous(level.getBlockState(pos.below()))) {
return null;
} else {
Vec3 vec3 = Vec3.upFromBottomCenterOf(pos, d);
AABB aABB = entityType.getDimensions().makeBoundingBox(vec3);
for (VoxelShape voxelShape : level.getBlockCollisions(null, aABB)) {
if (!voxelShape.isEmpty()) {
return null;
}
}
if (entityType != EntityType.PLAYER
|| !level.getBlockState(pos).is(BlockTags.INVALID_SPAWN_INSIDE) && !level.getBlockState(pos.above()).is(BlockTags.INVALID_SPAWN_INSIDE)) {
return !level.getWorldBorder().isWithinBounds(aABB) ? null : vec3;
} else {
return null;
}
}
}
}
}