package io.github.flemmli97.flan.player; import io.github.flemmli97.flan.claim.Claim; import io.github.flemmli97.flan.claim.ClaimStorage; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.server.level.ServerPlayer; import net.minecraft.util.Tuple; import net.minecraft.world.level.chunk.ChunkStatus; import net.minecraft.world.level.levelgen.Heightmap; import net.minecraft.world.phys.Vec3; import java.util.function.BiFunction; public class TeleportUtils { public static BlockPos roundedBlockPos(Vec3 pos) { return BlockPos.containing(pos); } public static Vec3 getTeleportPos(ServerPlayer player, Vec3 playerPos, ClaimStorage storage, int[] dim, BlockPos.MutableBlockPos bPos, BiFunction check) { return getTeleportPos(player, playerPos, storage, dim, false, bPos, check); } public static Vec3 getTeleportPos(ServerPlayer player, Vec3 playerPos, ClaimStorage storage, int[] dim, boolean checkSub, BlockPos.MutableBlockPos bPos, BiFunction check) { Tuple pos = nearestOutside(dim, playerPos); bPos.set(pos.getB().x(), pos.getB().y(), pos.getB().z()); Claim claim = storage.getClaimAt(bPos); if (checkSub) { Claim sub = claim != null ? claim.getSubClaim(bPos) : null; if (sub != null) claim = sub; } if (claim == null || check.apply(claim, bPos)) { Vec3 ret = pos.getB(); BlockPos rounded = roundedBlockPos(ret); int y = player.level().getChunk(rounded.getX() >> 4, rounded.getZ() >> 4, ChunkStatus.FULL) .getHeight(Heightmap.Types.MOTION_BLOCKING, rounded.getX() & 15, rounded.getZ() & 15); Vec3 dest = new Vec3(ret.x, y + 1, ret.z); if (player.level().noCollision(player, player.getBoundingBox().move(dest.subtract(player.position())))) return dest; return new Vec3(rounded.getX() + 0.5, y + 1, rounded.getZ() + 0.5); } int[] newDim = claim.getDimensions(); switch (pos.getA()) { case NORTH -> dim[2] = newDim[2]; case SOUTH -> dim[3] = newDim[3]; case EAST -> dim[1] = newDim[1]; default -> dim[0] = newDim[0]; } return getTeleportPos(player, playerPos, storage, dim, checkSub, bPos, check); } private static Tuple nearestOutside(int[] dim, Vec3 from) { double northDist = Math.abs(from.z() - dim[2]); double southDist = Math.abs(dim[3] - from.z()); double westDist = Math.abs(from.x() - dim[0]); double eastDist = Math.abs(dim[1] - from.x()); if (northDist > southDist) { if (eastDist > westDist) { if (southDist > westDist) return new Tuple<>(Direction.WEST, new Vec3(dim[0] - 1.5, from.y(), from.z())); return new Tuple<>(Direction.SOUTH, new Vec3(from.x(), from.y(), dim[3] + 1.5)); } if (southDist > eastDist) return new Tuple<>(Direction.EAST, new Vec3(dim[1] + 1.5, from.y(), from.z())); return new Tuple<>(Direction.SOUTH, new Vec3(from.x(), from.y(), dim[3] + 1.5)); } if (eastDist > westDist) { if (northDist > westDist) return new Tuple<>(Direction.WEST, new Vec3(dim[0] - 1.5, from.y(), from.z())); return new Tuple<>(Direction.NORTH, new Vec3(from.x(), from.y(), dim[2] - 1.5)); } if (northDist > eastDist) return new Tuple<>(Direction.EAST, new Vec3(dim[1] + 1.5, from.y(), from.z())); return new Tuple<>(Direction.NORTH, new Vec3(from.x(), from.y(), dim[2] - 1.5)); } }