Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public void onChunkUnload(ChunkUnloadEvent event) {
}
}, plugin);

Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, cache::invalidateAll, CACHE_INVALIDATION_INTERVAL, CACHE_INVALIDATION_INTERVAL);
plugin.getScheduler().runAsyncRate(cache::invalidateAll, CACHE_INVALIDATION_INTERVAL, CACHE_INVALIDATION_INTERVAL);
}

public void shutdown() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import com.sk89q.worldedit.world.gamemode.GameModes;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.bukkit.scheduler.FoliaSchedulerAdapter;
import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.util.profile.resolver.PaperPlayerService;
Expand Down Expand Up @@ -235,7 +236,7 @@ public void stackPlayerInventory(LocalPlayer localPlayer) {
public void addPlatformReports(ReportList report) {
report.add(new ServerReport());
report.add(new PluginReport());
report.add(new SchedulerReport());
if (!FoliaSchedulerAdapter.isSupported()) report.add(new SchedulerReport());
report.add(new ServicesReport());
report.add(new WorldReport());
report.add(new PerformanceReport());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@
import com.sk89q.worldguard.bukkit.listener.WorldGuardWeatherListener;
import com.sk89q.worldguard.bukkit.listener.WorldGuardWorldListener;
import com.sk89q.worldguard.bukkit.listener.WorldRulesListener;
import com.sk89q.worldguard.bukkit.scheduler.BukkitSchedulerAdapter;
import com.sk89q.worldguard.bukkit.scheduler.FoliaSchedulerAdapter;
import com.sk89q.worldguard.bukkit.scheduler.SchedulerAdapter;
import com.sk89q.worldguard.bukkit.session.BukkitSessionManager;
import com.sk89q.worldguard.bukkit.util.ClassSourceValidator;
import com.sk89q.worldguard.bukkit.util.Entities;
Expand Down Expand Up @@ -107,6 +110,8 @@ public class WorldGuardPlugin extends JavaPlugin {
private static WorldGuardPlugin inst;
private static BukkitWorldGuardPlatform platform;
private final CommandsManager<Actor> commands;
private final SchedulerAdapter scheduler = FoliaSchedulerAdapter.isSupported()
? new FoliaSchedulerAdapter(this) : new BukkitSchedulerAdapter(this);
private PlayerMoveListener playerMoveListener;

private static final int BSTATS_PLUGIN_ID = 3283;
Expand Down Expand Up @@ -164,7 +169,7 @@ public void onEnable() {
reg.register(GeneralCommands.class);
}

getServer().getScheduler().scheduleSyncRepeatingTask(this, sessionManager, BukkitSessionManager.RUN_DELAY, BukkitSessionManager.RUN_DELAY);
getScheduler().runAsyncRate(sessionManager, BukkitSessionManager.RUN_DELAY, BukkitSessionManager.RUN_DELAY);

// Register events
getServer().getPluginManager().registerEvents(sessionManager, this);
Expand Down Expand Up @@ -205,12 +210,12 @@ public void onEnable() {
}
worldListener.registerEvents();

Bukkit.getScheduler().runTask(this, () -> {
for (Player player : Bukkit.getServer().getOnlinePlayers()) {
for (Player player : Bukkit.getServer().getOnlinePlayers()) {
getScheduler().executeAtEntity(player, () -> {
ProcessPlayerEvent event = new ProcessPlayerEvent(player);
Events.fire(event);
}
});
});
}

((SimpleFlagRegistry) WorldGuard.getInstance().getFlagRegistry()).setInitialized(true);
((SimpleDomainRegistry) WorldGuard.getInstance().getDomainRegistry()).setInitialized(true);
Expand Down Expand Up @@ -266,7 +271,7 @@ private void setupCustomCharts(Metrics metrics) {
@Override
public void onDisable() {
WorldGuard.getInstance().disable();
this.getServer().getScheduler().cancelTasks(this);
getScheduler().cancelTasks();
}

@Override
Expand Down Expand Up @@ -526,4 +531,7 @@ public PlayerMoveListener getPlayerMoveListener() {
return playerMoveListener;
}

public SchedulerAdapter getScheduler() {
return scheduler;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -990,8 +990,7 @@ public void onInventoryMoveItem(InventoryMoveItemEvent event) {
handleInventoryHolderUse(event, cause, targetHolder);

if (event.isCancelled() && causeHolder instanceof Hopper && wcfg.breakDeniedHoppers) {
Bukkit.getScheduler().scheduleSyncDelayedTask(getPlugin(),
() -> ((Hopper) causeHolder).getBlock().breakNaturally());
getPlugin().getScheduler().executeAtRegion(((Hopper) causeHolder).getLocation(), () -> ((Hopper) causeHolder).getBlock().breakNaturally());
} else {
entry.setCancelled(event.isCancelled());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.session.MoveType;
import com.sk89q.worldguard.session.Session;
import org.bukkit.Bukkit;
import io.papermc.lib.PaperLib;
import org.bukkit.Location;
import org.bukkit.entity.AbstractHorse;
import org.bukkit.entity.Entity;
Expand Down Expand Up @@ -118,16 +118,16 @@ public void onPlayerMove(PlayerMoveEvent event) {
current.eject();
vehicle.setVelocity(new Vector());
if (vehicle instanceof LivingEntity) {
vehicle.teleport(override.clone());
PaperLib.teleportAsync(vehicle, override.clone());
} else {
vehicle.teleport(override.clone().add(0, 1, 0));
PaperLib.teleportAsync(vehicle, override.clone().add(0, 1, 0));
}
current = current.getVehicle();
}

player.teleport(override.clone().add(0, 1, 0));
PaperLib.teleportAsync(player, override.clone().add(0, 1, 0));

Bukkit.getScheduler().runTaskLater(getPlugin(), () -> player.teleport(override.clone().add(0, 1, 0)), 1);
getPlugin().getScheduler().runAtEntityDelayed(player, () -> PaperLib.teleportAsync(player, override.clone().add(0, 1, 0)), 1);
}
}
}
Expand All @@ -141,7 +141,7 @@ public void onPlayerQuit(PlayerQuitEvent event) {
com.sk89q.worldedit.util.Location loc = session.testMoveTo(localPlayer,
BukkitAdapter.adapt(event.getPlayer().getLocation()), MoveType.OTHER_CANCELLABLE); // white lie
if (loc != null) {
player.teleport(BukkitAdapter.adapt(loc));
PaperLib.teleportAsync(player, BukkitAdapter.adapt(loc));
}

session.uninitialize(localPlayer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import com.sk89q.worldguard.config.WorldConfiguration;
import com.sk89q.worldguard.session.MoveType;
import com.sk89q.worldguard.util.Locations;
import io.papermc.lib.PaperLib;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.entity.Vehicle;
Expand Down Expand Up @@ -66,10 +67,10 @@ public void onVehicleMove(VehicleMoveEvent event) {
if ((lastValid = WorldGuard.getInstance().getPlatform().getSessionManager().get(localPlayer)
.testMoveTo(localPlayer, BukkitAdapter.adapt(event.getTo()), MoveType.RIDE)) != null) {
vehicle.setVelocity(new Vector(0, 0, 0));
vehicle.teleport(event.getFrom());
PaperLib.teleportAsync(vehicle, event.getFrom());
if (Locations.isDifferentBlock(lastValid, BukkitAdapter.adapt(event.getFrom()))) {
Vector dir = player.getLocation().getDirection();
player.teleport(BukkitAdapter.adapt(lastValid).setDirection(dir));
PaperLib.teleportAsync(player, BukkitAdapter.adapt(lastValid).setDirection(dir));
}
return;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package com.sk89q.worldguard.bukkit.scheduler;

import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitScheduler;

public class BukkitSchedulerAdapter implements SchedulerAdapter {

private final Plugin plugin;
@SuppressWarnings("deprecation")
private final BukkitScheduler scheduler;

public BukkitSchedulerAdapter(final Plugin plugin) {
this.plugin = plugin;
this.scheduler = plugin.getServer().getScheduler();
}

@Override
public void runAsyncRate(Runnable runnable, long delay, long period) {
scheduler.runTaskTimerAsynchronously(plugin, runnable, delay, period);
}

@Override
public void executeAtEntity(Entity entity, Runnable runnable) {
scheduler.runTask(plugin, runnable);
}

@Override
public void runAtEntityDelayed(final Entity entity, final Runnable runnable, final long delay) {
scheduler.runTaskLater(plugin, runnable, delay);
}

@Override
public void executeAtRegion(Location location, Runnable runnable) {
scheduler.runTask(plugin, runnable);
}

@Override
public void cancelTasks() {
scheduler.cancelTasks(plugin);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package com.sk89q.worldguard.bukkit.scheduler;

import io.papermc.paper.threadedregions.scheduler.AsyncScheduler;
import io.papermc.paper.threadedregions.scheduler.RegionScheduler;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.plugin.Plugin;

import java.util.concurrent.TimeUnit;

public class FoliaSchedulerAdapter implements SchedulerAdapter {
private static final boolean SUPPORTED = checkSupport();

private final Plugin plugin;
private final AsyncScheduler asyncScheduler;
private final RegionScheduler regionScheduler;

public FoliaSchedulerAdapter(final Plugin plugin) {
this.plugin = plugin;
this.asyncScheduler = plugin.getServer().getAsyncScheduler();
this.regionScheduler = plugin.getServer().getRegionScheduler();
}

public static boolean isSupported() {
return SUPPORTED;
}

private static boolean checkSupport() {
try {
Class.forName("io.papermc.paper.threadedregions.RegionizedServer");
return true;
} catch (ClassNotFoundException e) {
return false;
}
}

@Override
public void runAsyncRate(final Runnable runnable, final long delay, final long period) {
asyncScheduler.runAtFixedRate(plugin, task -> runnable.run(), delay * 50, period * 50, TimeUnit.MILLISECONDS);
}

@Override
public void executeAtEntity(final Entity entity, final Runnable runnable) {
entity.getScheduler().run(plugin, task -> runnable.run(), null);
}

@Override
public void runAtEntityDelayed(final Entity entity, final Runnable runnable, final long delay) {
entity.getScheduler().execute(plugin, runnable, null, delay);
}

@Override
public void executeAtRegion(final Location location, final Runnable runnable) {
regionScheduler.execute(plugin, location, runnable);
}

@Override
public void cancelTasks() {
asyncScheduler.cancelTasks(plugin);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package com.sk89q.worldguard.bukkit.scheduler;

import org.bukkit.Location;
import org.bukkit.entity.Entity;

public interface SchedulerAdapter {

/**
* Schedules the specified task to be executed asynchronously after the delay has passed,
* and then periodically executed with the specified period.
*
* @param runnable The task to execute.
* @param delay The time delay to pass before the task should be executed.
* @param period The time between task executions after the first execution of the task.
*/
void runAsyncRate(Runnable runnable, long delay, long period);

/**
* Schedules a task. If the task failed to schedule because the scheduler is retired (entity removed),
* then returns {@code false}. Otherwise, either the run callback will be invoked after the specified delay,
* or the retired callback will be invoked if the scheduler is retired.
* Note that the retired callback is invoked in critical code, so it should not attempt to remove the entity,
* remove other entities, load chunks, load worlds, modify ticket levels, etc.
*
* <p>
* It is guaranteed that the task and retired callback are invoked on the region which owns the entity.
* </p>
*
* @param entity The entity relative to which the scheduler is obtained.
* @param runnable The task to execute.
*/
void executeAtEntity(Entity entity, Runnable runnable);

/**
* Schedules a task with the given delay. If the task failed to schedule because the scheduler is retired (entity removed),
* then returns {@code false}. Otherwise, either the run callback will be invoked after the specified delay,
* or the retired callback will be invoked if the scheduler is retired.
* Note that the retired callback is invoked in critical code, so it should not attempt to remove the entity,
* remove other entities, load chunks, load worlds, modify ticket levels, etc.
*
* <p>
* It is guaranteed that the task and retired callback are invoked on the region which owns the entity.
* </p>
*
* @param entity The entity relative to which the scheduler is obtained.
* @param runnable The task to execute.
* @param delay The time delay to pass before the task should be executed, in ticks.
*/
void runAtEntityDelayed(Entity entity, Runnable runnable, long delay);

/**
* Schedules a task to be executed on the region which owns the location.
*
* @param location The location at which the region executing should own.
* @param runnable The task to execute.
*/
void executeAtRegion(Location location, Runnable runnable);

/**
* Attempts to cancel all tasks scheduled by the plugin.
*/
void cancelTasks();
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,7 @@ public void resetAllStates() {
@EventHandler
public void onPlayerProcess(ProcessPlayerEvent event) {
// Pre-load a session
LocalPlayer player = WorldGuardPlugin.inst().wrapPlayer(event.getPlayer());
get(player).initialize(player);
get(WorldGuardPlugin.inst().wrapPlayer(event.getPlayer()));
}

@Override
Expand Down
Loading