From 98557dcecf081fb19d7c5b50b55a065a65945ac2 Mon Sep 17 00:00:00 2001 From: pop4959 Date: Sat, 22 Aug 2020 09:51:23 -0700 Subject: [PATCH] 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 --- .../earth2me/essentials/AsyncTeleport.java | 9 +++- .../essentials/utils/LocationUtil.java | 41 ++++++++++++++++++- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/Essentials/src/com/earth2me/essentials/AsyncTeleport.java b/Essentials/src/com/earth2me/essentials/AsyncTeleport.java index 43cf1dd8d..860e56036 100644 --- a/Essentials/src/com/earth2me/essentials/AsyncTeleport.java +++ b/Essentials/src/com/earth2me/essentials/AsyncTeleport.java @@ -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()) { diff --git a/Essentials/src/com/earth2me/essentials/utils/LocationUtil.java b/Essentials/src/com/earth2me/essentials/utils/LocationUtil.java index 307b0ea65..dc04ff991 100644 --- a/Essentials/src/com/earth2me/essentials/utils/LocationUtil.java +++ b/Essentials/src/com/earth2me/essentials/utils/LocationUtil.java @@ -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;