flan/common/src/main/java/io/github/flemmli97/flan/player/TeleportUtils.java

79 lines
3.7 KiB
Java

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<Claim, BlockPos, Boolean> 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<Claim, BlockPos, Boolean> check) {
Tuple<Direction, Vec3> 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<Direction, Vec3> 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));
}
}