From 70ef567d22cadb33faacd360b0dfe4862c2ac264 Mon Sep 17 00:00:00 2001 From: Warrior <50800980+Warriorrrr@users.noreply.github.com> Date: Sat, 29 Aug 2026 13:45:34 +0200 Subject: [PATCH] Fix wrong coords being read by check task during dimension change on Folia --- .../chunkyborder/ChunkyBorderBukkit.java | 20 +++- .../chunkyborder/BorderCheckTask.java | 113 +++++++----------- 2 files changed, 62 insertions(+), 71 deletions(-) diff --git a/bukkit/src/main/java/org/popcraft/chunkyborder/ChunkyBorderBukkit.java b/bukkit/src/main/java/org/popcraft/chunkyborder/ChunkyBorderBukkit.java index 47c9d80..b6d0592 100644 --- a/bukkit/src/main/java/org/popcraft/chunkyborder/ChunkyBorderBukkit.java +++ b/bukkit/src/main/java/org/popcraft/chunkyborder/ChunkyBorderBukkit.java @@ -11,6 +11,7 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerRegisterChannelEvent; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.ServicePriority; @@ -67,6 +68,7 @@ public final class ChunkyBorderBukkit extends JavaPlugin implements Listener { .valueOf(Particle.class, "REDSTONE") // 1.20.4 and prior .orElseGet(() -> Particle.DUST); // 1.20.5 and above private ChunkyBorder chunkyBorder; + private BorderCheckTask borderCheckTask; @Override public void onEnable() { @@ -98,10 +100,9 @@ public void onEnable() { getServer().getScheduler().scheduleSyncDelayedTask(this, borderInitTask); } final long checkInterval = chunkyBorder.getConfig().checkInterval(); - final Runnable borderCheckTask = new BorderCheckTask(chunkyBorder); - if (Folia.isFolia()) { - Folia.scheduleFixedGlobal(this, borderCheckTask, checkInterval, checkInterval); - } else { + this.borderCheckTask = new BorderCheckTask(chunkyBorder); + // Border check task is started per-player in the join event on Folia + if (!Folia.isFolia()) { getServer().getScheduler().scheduleSyncRepeatingTask(this, borderCheckTask, checkInterval, checkInterval); } chunkyBorder.getChunky().getCommands().put("border", new BorderCommand(chunkyBorder)); @@ -221,6 +222,17 @@ public void onDisable() { chunkyBorder.disable(); } + @EventHandler(priority = EventPriority.MONITOR) + public void onPlayerJoin(final PlayerJoinEvent event) { + if (!Folia.isFolia()) { + return; + } + + final long borderCheckInterval = chunkyBorder.getConfig().checkInterval(); + final Player player = new BukkitPlayer(event.getPlayer()); + Folia.scheduleFixed(this, event.getPlayer(), () -> borderCheckTask.check(player), borderCheckInterval, borderCheckInterval); + } + @EventHandler(priority = EventPriority.MONITOR) public void onWorldLoad(final org.bukkit.event.world.WorldLoadEvent e) { chunkyBorder.getChunky().getEventBus().call(new WorldLoadEvent(new BukkitWorld(e.getWorld()))); diff --git a/common/src/main/java/org/popcraft/chunkyborder/BorderCheckTask.java b/common/src/main/java/org/popcraft/chunkyborder/BorderCheckTask.java index 54c55b3..3ddf8c5 100644 --- a/common/src/main/java/org/popcraft/chunkyborder/BorderCheckTask.java +++ b/common/src/main/java/org/popcraft/chunkyborder/BorderCheckTask.java @@ -1,7 +1,6 @@ package org.popcraft.chunkyborder; import org.popcraft.chunky.platform.Player; -import org.popcraft.chunky.platform.World; import org.popcraft.chunky.platform.util.Location; import org.popcraft.chunky.platform.util.Vector2; import org.popcraft.chunky.platform.util.Vector3; @@ -26,50 +25,54 @@ public BorderCheckTask(final ChunkyBorder chunkyBorder) { @Override public void run() { for (final Player player : chunkyBorder.getChunky().getServer().getPlayers()) { - final PlayerData playerData = chunkyBorder.getPlayerData(player.getUUID()); - chunkyBorder.getBorder(player.getWorld().getName()).ifPresent(borderData -> { - final Location location = player.getLocation(); - if (borderData.getBorder().isBounding(location.getX(), location.getZ())) { - playerData.setLastLocation(location); - } else if (!playerData.isBypassing() && !player.hasPermission("chunkyborder.bypass.move")) { - final CompletableFuture redirectFuture; - final BorderWrapType borderWrapType = borderData.getWrapType(); - if (!BorderWrapType.NONE.equals(borderWrapType)) { - redirectFuture = wrap(borderData, borderWrapType, player, playerData); - redirectFuture.thenAccept(redirect -> { - playerData.setLastLocation(redirect); - chunkyBorder.getChunky().getEventBus().call(new BorderWrapEvent(player, location, redirect)); - }); - } else { - final Location lastLocation = playerData.getLastLocation().orElse(location.getWorld().getSpawn()); - lastLocation.setYaw(location.getYaw()); - lastLocation.setPitch(location.getPitch()); - redirectFuture = CompletableFuture.completedFuture(lastLocation); - } + check(player); + } + } + public void check(final Player player) { + final PlayerData playerData = chunkyBorder.getPlayerData(player.getUUID()); + chunkyBorder.getBorder(player.getWorld().getName()).ifPresent(borderData -> { + final Location location = player.getLocation(); + if (borderData.getBorder().isBounding(location.getX(), location.getZ())) { + playerData.setLastLocation(location); + } else if (!playerData.isBypassing() && !player.hasPermission("chunkyborder.bypass.move")) { + final CompletableFuture redirectFuture; + final BorderWrapType borderWrapType = borderData.getWrapType(); + if (!BorderWrapType.NONE.equals(borderWrapType)) { + redirectFuture = wrap(borderData, borderWrapType, player, playerData); redirectFuture.thenAccept(redirect -> { - if (chunkyBorder.getConfig().hasEffect()) { - location.getWorld().playEffect(player, chunkyBorder.getConfig().effect()); - } - if (chunkyBorder.getConfig().hasSound()) { - location.getWorld().playSound(player, chunkyBorder.getConfig().sound()); - } - player.teleport(redirect); - if (chunkyBorder.getConfig().hasMessage()) { - if (chunkyBorder.getConfig().useActionBar()) { - player.sendActionBar("custom_border_message"); - } else { - player.sendMessage("custom_border_message"); - } - } - }).whenComplete(((unused, throwable) -> { - if (throwable != null) { - chunkyBorder.getLogger().warn("An exception occurred while redirecting {}", player.getName(), throwable); - } - })); + playerData.setLastLocation(redirect); + chunkyBorder.getChunky().getEventBus().call(new BorderWrapEvent(player, location, redirect)); + }); + } else { + final Location lastLocation = playerData.getLastLocation().orElse(location.getWorld().getSpawn()); + lastLocation.setYaw(location.getYaw()); + lastLocation.setPitch(location.getPitch()); + redirectFuture = CompletableFuture.completedFuture(lastLocation); } - }); - } + + redirectFuture.thenAccept(redirect -> { + if (chunkyBorder.getConfig().hasEffect()) { + location.getWorld().playEffect(player, chunkyBorder.getConfig().effect()); + } + if (chunkyBorder.getConfig().hasSound()) { + location.getWorld().playSound(player, chunkyBorder.getConfig().sound()); + } + player.teleport(redirect); + if (chunkyBorder.getConfig().hasMessage()) { + if (chunkyBorder.getConfig().useActionBar()) { + player.sendActionBar("custom_border_message"); + } else { + player.sendMessage("custom_border_message"); + } + } + }).whenComplete(((unused, throwable) -> { + if (throwable != null) { + chunkyBorder.getLogger().warn("An exception occurred while redirecting {}", player.getName(), throwable); + } + })); + } + }); } private CompletableFuture wrap(final BorderData borderData, final BorderWrapType borderWrapType, final Player player, final PlayerData playerData) { @@ -85,7 +88,7 @@ private CompletableFuture wrap(final BorderData borderData, final Bord case EARTH -> rectangle && wrapEarth(borderData, location); }; if (wrapped) { - return this.getElevationAtAsync(location.getWorld(), (int) location.getX(), (int) location.getZ()).thenApply(elevation -> { + return location.getWorld().getElevationAtAsync((int) location.getX(), (int) location.getZ()).thenApply(elevation -> { if (elevation >= location.getWorld().getMaxElevation()) { return location.getWorld().getSpawn(); } @@ -193,28 +196,4 @@ private boolean wrapEarth(final BorderData borderData, final Location location) } return true; } - - // FIXME: replace when chunky dependency is bumped - private static final java.lang.invoke.MethodHandle GET_ELEVATION_AT_ASYNC; - - static { - java.lang.invoke.MethodHandle temp; - - try { - temp = java.lang.invoke.MethodHandles.publicLookup().unreflect(World.class.getMethod("getElevationAtAsync", int.class, int.class)); - } catch (ReflectiveOperationException e) { - throw new RuntimeException(e); - } - - GET_ELEVATION_AT_ASYNC = temp; - } - - @SuppressWarnings("unchecked") - private CompletableFuture getElevationAtAsync(final World world, final int x, final int z) { - try { - return (CompletableFuture) GET_ELEVATION_AT_ASYNC.invokeExact(world, x, z); - } catch (Throwable e) { - return CompletableFuture.failedFuture(e); - } - } }