Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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())));
Expand Down
113 changes: 46 additions & 67 deletions common/src/main/java/org/popcraft/chunkyborder/BorderCheckTask.java
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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<Location> 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<Location> 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<Location> wrap(final BorderData borderData, final BorderWrapType borderWrapType, final Player player, final PlayerData playerData) {
Expand All @@ -85,7 +88,7 @@ private CompletableFuture<Location> 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();
}
Expand Down Expand Up @@ -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<Integer> getElevationAtAsync(final World world, final int x, final int z) {
try {
return (CompletableFuture<Integer>) GET_ELEVATION_AT_ASYNC.invokeExact(world, x, z);
} catch (Throwable e) {
return CompletableFuture.failedFuture(e);
}
}
}
Loading