Add world border checking to teleportation safety (#3536)

Fixes #3499. Please see that issue for discussion about the bug.

Fix demonstration with `/tppos`: https://imgur.com/a/Mo4okQa
2.x
pop4959 2020-08-22 09:51:23 -07:00 committed by GitHub
parent 3351092c79
commit 98557dcecf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 47 additions and 3 deletions

View File

@ -179,8 +179,13 @@ public class AsyncTeleport implements IAsyncTeleport {
}
}
teleportee.setLastLocation();
PaperLib.getChunkAtAsync(target.getLocation()).thenAccept(chunk -> {
Location loc = target.getLocation();
final Location targetLoc = target.getLocation();
if (ess.getSettings().isTeleportSafetyEnabled() && LocationUtil.isBlockOutsideWorldBorder(targetLoc.getWorld(), targetLoc.getBlockX(), targetLoc.getBlockZ())) {
targetLoc.setX(LocationUtil.getXInsideWorldBorder(targetLoc.getWorld(), targetLoc.getBlockX()));
targetLoc.setZ(LocationUtil.getZInsideWorldBorder(targetLoc.getWorld(), targetLoc.getBlockZ()));
}
PaperLib.getChunkAtAsync(targetLoc).thenAccept(chunk -> {
Location loc = targetLoc;
if (LocationUtil.isBlockUnsafeForUser(teleportee, chunk.getWorld(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())) {
if (ess.getSettings().isTeleportSafetyEnabled()) {
if (ess.getSettings().isForceDisableTeleportSafety()) {

View File

@ -92,6 +92,38 @@ public class LocationUtil {
return y > world.getMaxHeight() || HOLLOW_MATERIALS.contains(world.getBlockAt(x, y - 1, z).getType());
}
public static boolean isBlockOutsideWorldBorder(final World world, final int x, final int z) {
final Location center = world.getWorldBorder().getCenter();
final int radius = (int) world.getWorldBorder().getSize() / 2;
final int x1 = center.getBlockX() - radius, x2 = center.getBlockX() + radius;
final int z1 = center.getBlockZ() - radius, z2 = center.getBlockZ() + radius;
return x < x1 || x > x2 || z < z1 || z > z2;
}
public static int getXInsideWorldBorder(final World world, final int x) {
final Location center = world.getWorldBorder().getCenter();
final int radius = (int) world.getWorldBorder().getSize() / 2;
final int x1 = center.getBlockX() - radius, x2 = center.getBlockX() + radius;
if (x < x1) {
return x1;
} else if (x > x2) {
return x2;
}
return x;
}
public static int getZInsideWorldBorder(final World world, final int z) {
final Location center = world.getWorldBorder().getCenter();
final int radius = (int) world.getWorldBorder().getSize() / 2;
final int z1 = center.getBlockZ() - radius, z2 = center.getBlockZ() + radius;
if (z < z1) {
return z1;
} else if (z > z2) {
return z2;
}
return z;
}
public static boolean isBlockUnsafeForUser(final IUser user, final World world, final int x, final int y, final int z) {
if (user.getBase().isOnline() && world.equals(user.getBase().getWorld()) && (user.getBase().getGameMode() == GameMode.CREATIVE || user.getBase().getGameMode() == GameMode.SPECTATOR || user.isGodModeEnabled()) && user.getBase().getAllowFlight()) {
return false;
@ -100,7 +132,10 @@ public class LocationUtil {
if (isBlockDamaging(world, x, y, z)) {
return true;
}
return isBlockAboveAir(world, x, y, z);
if (isBlockAboveAir(world, x, y, z)) {
return true;
}
return isBlockOutsideWorldBorder(world, x, z);
}
public static boolean isBlockUnsafe(final World world, final int x, final int y, final int z) {
@ -175,6 +210,10 @@ public class LocationUtil {
int x = loc.getBlockX();
int y = (int) Math.round(loc.getY());
int z = loc.getBlockZ();
if (isBlockOutsideWorldBorder(world, x, z)) {
x = getXInsideWorldBorder(world, x);
z = getZInsideWorldBorder(world, z);
}
final int origX = x;
final int origY = y;
final int origZ = z;