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 @@ -29,6 +29,9 @@
import com.sk89q.worldguard.config.WorldConfiguration;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.RegionContainer;
import com.sk89q.worldguard.bukkit.util.task.SchedulerAdapter;
import com.sk89q.worldguard.bukkit.util.task.SchedulerAdapterFactory;
import com.sk89q.worldguard.bukkit.util.task.ScheduledTask;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.event.EventHandler;
Expand All @@ -51,6 +54,7 @@ public class BukkitRegionContainer extends RegionContainer {
private static final int CACHE_INVALIDATION_INTERVAL = 2;

private final WorldGuardPlugin plugin;
private ScheduledTask cacheInvalidationTask;

/**
* Create a new instance.
Expand Down Expand Up @@ -94,11 +98,16 @@ public void onChunkUnload(ChunkUnloadEvent event) {
}
}, plugin);

Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, cache::invalidateAll, CACHE_INVALIDATION_INTERVAL, CACHE_INVALIDATION_INTERVAL);
SchedulerAdapter scheduler = SchedulerAdapterFactory.getAdapter();
cacheInvalidationTask = scheduler.runTaskTimer(plugin, cache::invalidateAll,
CACHE_INVALIDATION_INTERVAL, CACHE_INVALIDATION_INTERVAL);
}

public void shutdown() {
container.shutdown();
if (cacheInvalidationTask != null) {
cacheInvalidationTask.cancel();
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@
import com.sk89q.worldguard.bukkit.listener.RegionFlagsListener;
import com.sk89q.worldguard.bukkit.listener.RegionProtectionListener;
import com.sk89q.worldguard.bukkit.listener.WorldGuardBlockListener;
import com.sk89q.worldguard.bukkit.util.task.SchedulerAdapter;
import com.sk89q.worldguard.bukkit.util.task.SchedulerAdapterFactory;
import com.sk89q.worldguard.bukkit.util.task.ScheduledTask;
import com.sk89q.worldguard.bukkit.listener.WorldGuardCommandBookListener;
import com.sk89q.worldguard.bukkit.listener.WorldGuardEntityListener;
import com.sk89q.worldguard.bukkit.listener.WorldGuardHangingListener;
Expand Down Expand Up @@ -107,6 +110,8 @@ public class WorldGuardPlugin extends JavaPlugin {
private static BukkitWorldGuardPlatform platform;
private final CommandsManager<Actor> commands;
private PlayerMoveListener playerMoveListener;
private SchedulerAdapter scheduler;
private ScheduledTask sessionTask;

private static final int BSTATS_PLUGIN_ID = 3283;

Expand Down Expand Up @@ -145,6 +150,10 @@ public void onEnable() {

getDataFolder().mkdirs(); // Need to create the plugins/WorldGuard folder

// Initialize scheduler adapter for Folia compatibility
scheduler = SchedulerAdapterFactory.getAdapter(this);
getLogger().info("Server platform: " + SchedulerAdapterFactory.getPlatformInfo());

PermissionsResolverManager.initialize(this);

WorldGuard.getInstance().setPlatform(platform = new BukkitWorldGuardPlatform()); // Initialise WorldGuard
Expand All @@ -163,7 +172,7 @@ public void onEnable() {
reg.register(GeneralCommands.class);
}

getServer().getScheduler().scheduleSyncRepeatingTask(this, sessionManager, BukkitSessionManager.RUN_DELAY, BukkitSessionManager.RUN_DELAY);
sessionTask = scheduler.runTaskTimer(this, sessionManager, BukkitSessionManager.RUN_DELAY, BukkitSessionManager.RUN_DELAY);

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

Bukkit.getScheduler().runTask(this, () -> {
scheduler.runTask(this, () -> {
for (Player player : Bukkit.getServer().getOnlinePlayers()) {
ProcessPlayerEvent event = new ProcessPlayerEvent(player);
Events.fire(event);
Expand Down Expand Up @@ -264,7 +273,13 @@ private void setupCustomCharts(Metrics metrics) {
@Override
public void onDisable() {
WorldGuard.getInstance().disable();
this.getServer().getScheduler().cancelTasks(this);
if (scheduler != null) {
scheduler.cancelTasks(this);
// Properly shutdown fallback scheduler if it's being used
if (scheduler instanceof com.sk89q.worldguard.bukkit.util.task.FallbackSchedulerAdapter) {
((com.sk89q.worldguard.bukkit.util.task.FallbackSchedulerAdapter) scheduler).shutdown();
}
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import com.sk89q.worldguard.bukkit.util.Entities;
import com.sk89q.worldguard.bukkit.util.Events;
import com.sk89q.worldguard.bukkit.util.Materials;
import com.sk89q.worldguard.bukkit.util.task.SchedulerAdapterFactory;
import com.sk89q.worldguard.config.WorldConfiguration;
import com.sk89q.worldguard.protection.flags.Flags;
import io.papermc.lib.PaperLib;
Expand Down Expand Up @@ -1045,8 +1046,10 @@ public void onInventoryMoveItem(InventoryMoveItemEvent event) {
}

if (event.isCancelled() && causeHolder instanceof Hopper && wcfg.breakDeniedHoppers) {
Bukkit.getScheduler().scheduleSyncDelayedTask(getPlugin(),
() -> ((Hopper) causeHolder).getBlock().breakNaturally());
// Use location-aware scheduler for Folia compatibility
Location hopperLocation = ((Hopper) causeHolder).getBlock().getLocation();
SchedulerAdapterFactory.getAdapter().runTaskAtLater(getPlugin(), hopperLocation,
() -> ((Hopper) causeHolder).getBlock().breakNaturally(), 1);
} else {
entry.setCancelled(event.isCancelled());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.util.task.SchedulerAdapterFactory;
import com.sk89q.worldguard.session.MoveType;
import com.sk89q.worldguard.session.Session;
import org.bukkit.Bukkit;
Expand Down Expand Up @@ -127,7 +128,10 @@ public void onPlayerMove(PlayerMoveEvent event) {

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

Bukkit.getScheduler().runTaskLater(getPlugin(), () -> player.teleport(override.clone().add(0, 1, 0)), 1);
// Schedule a follow-up teleport using location-aware scheduler for Folia compatibility
Location teleportLoc = override.clone().add(0, 1, 0);
SchedulerAdapterFactory.getAdapter().runTaskAtLater(getPlugin(), teleportLoc,
() -> player.teleport(teleportLoc), 1);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,32 +99,13 @@ public RegionProtectionListener(WorldGuardPlugin plugin) {
* @param what what was done
*/
private void tellErrorMessage(DelegateEvent event, Cause cause, Location location, String what) {
if (event.isSilent() || cause.isIndirect()) {
return;
}

Object rootCause = cause.getRootCause();

if (rootCause instanceof Player) {
Player player = (Player) rootCause;

long now = System.currentTimeMillis();
Long lastTime = WGMetadata.getIfPresent(player, DENY_MESSAGE_KEY, Long.class);
if (lastTime == null || now - lastTime >= LAST_MESSAGE_DELAY) {
RegionQuery query = WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery();
LocalPlayer localPlayer = getPlugin().wrapPlayer(player);
String message = query.queryValue(BukkitAdapter.adapt(location), localPlayer, Flags.DENY_MESSAGE);
formatAndSendDenyMessage(what, localPlayer, message);
WGMetadata.put(player, DENY_MESSAGE_KEY, now);
}
}
// Messages disabled - no chat messages will be sent for protection violations
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't just remove the messages

return;
}

static void formatAndSendDenyMessage(String what, LocalPlayer localPlayer, String message) {
if (message == null || message.isEmpty()) return;
message = WorldGuard.getInstance().getPlatform().getMatcher().replaceMacros(localPlayer, message);
message = CommandUtils.replaceColorMacros(message);
localPlayer.printRaw(message.replace("%what%", what));
// Messages disabled - no denial messages will be sent
return;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above

}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -613,63 +613,108 @@ public void onExplosionPrime(ExplosionPrimeEvent event) {

@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onCreatureSpawn(CreatureSpawnEvent event) {
ConfigurationManager cfg = getConfig();
try {
ConfigurationManager cfg = getConfig();

if (cfg.activityHaltToggle) {
event.setCancelled(true);
return;
if (cfg.activityHaltToggle) {
event.setCancelled(true);
return;
}

WorldConfiguration wcfg = getWorldConfig(event.getEntity().getWorld());

// allow spawning of creatures from plugins
if (!wcfg.blockPluginSpawning && Entities.isPluginSpawning(event.getSpawnReason())) {
return;
}

// armor stands are living entities, but we check them as blocks/non-living entities, so ignore them here
if (Entities.isConsideredBuildingIfUsed(event.getEntity())) {
return;
}

if (wcfg.allowTamedSpawns
&& event.getEntity() instanceof Tameable // nullsafe check
&& ((Tameable) event.getEntity()).isTamed()) {
return;
}

EntityType entityType = event.getEntityType();

com.sk89q.worldedit.world.entity.EntityType weEntityType = BukkitAdapter.adapt(entityType);

if (weEntityType != null && wcfg.blockCreatureSpawn.contains(weEntityType)) {
event.setCancelled(true);
return;
}

Location eventLoc = event.getLocation();

if (wcfg.useRegions && cfg.useRegionsCreatureSpawnEvent) {
ApplicableRegionSet set =
WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery().getApplicableRegions(BukkitAdapter.adapt(eventLoc));

if (!set.testState(null, Flags.MOB_SPAWNING)) {
event.setCancelled(true);
return;
}

Set<com.sk89q.worldedit.world.entity.EntityType> entityTypes = set.queryValue(null, Flags.DENY_SPAWN);
if (entityTypes != null && weEntityType != null && entityTypes.contains(weEntityType)) {
event.setCancelled(true);
return;
}
}

if (wcfg.blockGroundSlimes && entityType == EntityType.SLIME
&& eventLoc.getY() >= 60
&& event.getSpawnReason() == SpawnReason.NATURAL) {
event.setCancelled(true);
return;
}
} catch (Exception e) {
WorldGuard.logger.warning("[WorldGuard] Exception in creature spawn handler at "
+ event.getLocation() + ": " + e.getMessage());
}
}

/**
* MONITOR-priority fallback for threaded servers (Canvas/Folia) where event
* cancellation from the HIGH handler may not be reliably respected due to
* async entity spawning. If the entity still spawned in a MOB_SPAWNING=DENY
* region, forcefully remove it.
*/
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onCreatureSpawnMonitor(CreatureSpawnEvent event) {
WorldConfiguration wcfg = getWorldConfig(event.getEntity().getWorld());
ConfigurationManager cfg = getConfig();

// allow spawning of creatures from plugins
if (!wcfg.useRegions || !cfg.useRegionsCreatureSpawnEvent) {
return;
}
if (!wcfg.blockPluginSpawning && Entities.isPluginSpawning(event.getSpawnReason())) {
return;
}

// armor stands are living entities, but we check them as blocks/non-living entities, so ignore them here
if (Entities.isConsideredBuildingIfUsed(event.getEntity())) {
return;
}

if (wcfg.allowTamedSpawns
&& event.getEntity() instanceof Tameable // nullsafe check
&& event.getEntity() instanceof Tameable
&& ((Tameable) event.getEntity()).isTamed()) {
return;
}

EntityType entityType = event.getEntityType();

com.sk89q.worldedit.world.entity.EntityType weEntityType = BukkitAdapter.adapt(entityType);

if (weEntityType != null && wcfg.blockCreatureSpawn.contains(weEntityType)) {
event.setCancelled(true);
return;
}

Location eventLoc = event.getLocation();

if (wcfg.useRegions && cfg.useRegionsCreatureSpawnEvent) {
ApplicableRegionSet set =
WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery().getApplicableRegions(BukkitAdapter.adapt(eventLoc));
try {
ApplicableRegionSet set = WorldGuard.getInstance().getPlatform().getRegionContainer()
.createQuery().getApplicableRegions(BukkitAdapter.adapt(event.getLocation()));

if (!set.testState(null, Flags.MOB_SPAWNING)) {
event.setCancelled(true);
return;
event.getEntity().remove();
}

Set<com.sk89q.worldedit.world.entity.EntityType> entityTypes = set.queryValue(null, Flags.DENY_SPAWN);
if (entityTypes != null && weEntityType != null && entityTypes.contains(weEntityType)) {
event.setCancelled(true);
return;
}
}

if (wcfg.blockGroundSlimes && entityType == EntityType.SLIME
&& eventLoc.getY() >= 60
&& event.getSpawnReason() == SpawnReason.NATURAL) {
event.setCancelled(true);
return;
} catch (Exception e) {
WorldGuard.logger.warning("[WorldGuard] Exception in creature spawn monitor handler at "
+ event.getLocation() + ": " + e.getMessage());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.event.player.ProcessPlayerEvent;
import com.sk89q.worldguard.bukkit.util.Entities;
import com.sk89q.worldguard.bukkit.util.task.SchedulerAdapterFactory;
import com.sk89q.worldguard.session.AbstractSessionManager;
import com.sk89q.worldguard.session.Session;
import org.bukkit.Bukkit;
Expand Down Expand Up @@ -66,9 +67,22 @@ public void onPlayerProcess(ProcessPlayerEvent event) {

@Override
public void run() {
for (Player player : Bukkit.getServer().getOnlinePlayers()) {
LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer(player);
get(localPlayer).tick(localPlayer);
WorldGuardPlugin plugin = WorldGuardPlugin.inst();
if (SchedulerAdapterFactory.isFolia()) {
// On Folia, player.getLocation() and region access must happen on the
// player's own region thread, not the global region thread this timer
// runs on. Dispatch each player's tick to their entity scheduler.
for (Player player : Bukkit.getServer().getOnlinePlayers()) {
LocalPlayer localPlayer = plugin.wrapPlayer(player);
SchedulerAdapterFactory.getAdapter().runTaskFor(plugin, player, () -> {
get(localPlayer).tick(localPlayer);
});
}
} else {
for (Player player : Bukkit.getServer().getOnlinePlayers()) {
LocalPlayer localPlayer = plugin.wrapPlayer(player);
get(localPlayer).tick(localPlayer);
}
}
}

Expand Down
Loading