diff --git a/multiverse-core.jar b/multiverse-core.jar new file mode 100644 index 000000000..4598c8bf9 Binary files /dev/null and b/multiverse-core.jar differ diff --git a/src/main/java/org/mvplugins/multiverse/core/command/queue/CommandQueueManager.java b/src/main/java/org/mvplugins/multiverse/core/command/queue/CommandQueueManager.java index abdbd6b14..1b15f4a46 100644 --- a/src/main/java/org/mvplugins/multiverse/core/command/queue/CommandQueueManager.java +++ b/src/main/java/org/mvplugins/multiverse/core/command/queue/CommandQueueManager.java @@ -28,6 +28,7 @@ import org.mvplugins.multiverse.core.command.MVCommandIssuer; import org.mvplugins.multiverse.core.config.CoreConfig; import org.mvplugins.multiverse.core.locale.MVCorei18n; +import org.mvplugins.multiverse.core.utils.FoliaUtil; import org.mvplugins.multiverse.core.utils.result.Attempt; import static org.mvplugins.multiverse.core.locale.message.MessageReplacement.*; @@ -108,6 +109,13 @@ private boolean canRunImmediately(@NotNull String senderName) { */ @NotNull private BukkitTask runExpireLater(@NotNull String senderName, int validDuration) { + if (FoliaUtil.isFolia()) { + return new FoliaUtil.TaskAdapter( + Bukkit.getServer().getGlobalRegionScheduler().runDelayed( + this.plugin, + t -> expireRunnable(senderName).run(), + validDuration * TICKS_PER_SECOND)); + } return Bukkit.getScheduler().runTaskLater( this.plugin, expireRunnable(senderName), diff --git a/src/main/java/org/mvplugins/multiverse/core/commands/DumpsService.java b/src/main/java/org/mvplugins/multiverse/core/commands/DumpsService.java index 7f3b8b103..424be9738 100644 --- a/src/main/java/org/mvplugins/multiverse/core/commands/DumpsService.java +++ b/src/main/java/org/mvplugins/multiverse/core/commands/DumpsService.java @@ -11,8 +11,10 @@ import org.jetbrains.annotations.NotNull; import org.jvnet.hk2.annotations.Service; +import org.bukkit.Bukkit; import org.mvplugins.multiverse.core.MultiverseCore; import org.mvplugins.multiverse.core.locale.MVCorei18n; +import org.mvplugins.multiverse.core.utils.FoliaUtil; import org.mvplugins.multiverse.core.module.MultiverseModulesRegistry; import org.mvplugins.multiverse.core.commands.DumpsLogPoster.UploadType; import org.mvplugins.multiverse.core.command.MVCommandIssuer; @@ -42,8 +44,12 @@ void postLogs(MVCommandIssuer issuer, UploadType servicesType) { // Initialise and add info to the debug event MVDumpsDebugInfoEvent versionEvent = createAndCallDebugInfoEvent(); - new DumpsLogPoster(plugin, issuer, servicesType, getLogs(), versionEvent) - .runTaskAsynchronously(plugin); + DumpsLogPoster poster = new DumpsLogPoster(plugin, issuer, servicesType, getLogs(), versionEvent); + if (FoliaUtil.isFolia()) { + Bukkit.getServer().getAsyncScheduler().runNow(plugin, t -> poster.run()); + } else { + poster.runTaskAsynchronously(plugin); + } } /** diff --git a/src/main/java/org/mvplugins/multiverse/core/listeners/MVPlayerListener.java b/src/main/java/org/mvplugins/multiverse/core/listeners/MVPlayerListener.java index 6d2582680..bd2a3bcf5 100644 --- a/src/main/java/org/mvplugins/multiverse/core/listeners/MVPlayerListener.java +++ b/src/main/java/org/mvplugins/multiverse/core/listeners/MVPlayerListener.java @@ -25,8 +25,10 @@ import org.bukkit.event.player.PlayerPortalEvent; import org.bukkit.event.player.PlayerRespawnEvent; import org.bukkit.event.player.PlayerTeleportEvent; +import org.bukkit.Bukkit; import org.bukkit.plugin.Plugin; import org.jvnet.hk2.annotations.Service; +import org.mvplugins.multiverse.core.utils.FoliaUtil; import org.mvplugins.multiverse.core.MultiverseCore; import org.mvplugins.multiverse.core.command.MVCommandManager; @@ -432,11 +434,17 @@ private void handleGameModeAndFlight(final Player player, World world) { doGameModeAndFlightEnforcement(player, world); return; } - server.getScheduler().runTaskLater( - this.plugin, - () -> doGameModeAndFlightEnforcement(player, world), - config.getGamemodeAndFlightEnforceDelay() - ); + if (FoliaUtil.isFolia()) { + player.getScheduler().runDelayed(this.plugin, + t -> doGameModeAndFlightEnforcement(player, world), + null, + config.getGamemodeAndFlightEnforceDelay()); + } else { + server.getScheduler().runTaskLater( + this.plugin, + () -> doGameModeAndFlightEnforcement(player, world), + config.getGamemodeAndFlightEnforceDelay()); + } } private void doGameModeAndFlightEnforcement(Player player, World world) { diff --git a/src/main/java/org/mvplugins/multiverse/core/teleportation/AsyncSafetyTeleporterAction.java b/src/main/java/org/mvplugins/multiverse/core/teleportation/AsyncSafetyTeleporterAction.java index 1e70de926..de05da29b 100644 --- a/src/main/java/org/mvplugins/multiverse/core/teleportation/AsyncSafetyTeleporterAction.java +++ b/src/main/java/org/mvplugins/multiverse/core/teleportation/AsyncSafetyTeleporterAction.java @@ -17,6 +17,7 @@ import org.mvplugins.multiverse.core.MultiverseCore; import org.mvplugins.multiverse.core.destination.DestinationInstance; import org.mvplugins.multiverse.core.event.MVTeleportDestinationEvent; +import org.mvplugins.multiverse.core.utils.FoliaUtil; import org.mvplugins.multiverse.core.utils.result.AsyncAttempt; import org.mvplugins.multiverse.core.utils.result.AsyncAttemptsAggregate; import org.mvplugins.multiverse.core.utils.result.Attempt; @@ -244,10 +245,19 @@ private AsyncAttemptsAggregate doPassengersTeleport return AsyncAttemptsAggregate.allOfAggregate(toTeleport.stream() .map(passenger -> doAsyncTeleport(passenger, location)) .toList()) - .onSuccess(() -> Bukkit.getScheduler().runTask(multiverseCore, () -> { - passengers.forEach(teleportee::addPassenger); - Logging.finer("Mounted %d passengers to %s", passengers.size(), teleportee.getName()); - })); + .onSuccess(() -> { + if (FoliaUtil.isFolia()) { + Bukkit.getServer().getGlobalRegionScheduler().run(multiverseCore, t -> { + passengers.forEach(teleportee::addPassenger); + Logging.finer("Mounted %d passengers to %s", passengers.size(), teleportee.getName()); + }); + } else { + Bukkit.getScheduler().runTask(multiverseCore, () -> { + passengers.forEach(teleportee::addPassenger); + Logging.finer("Mounted %d passengers to %s", passengers.size(), teleportee.getName()); + }); + } + }); } private AsyncAttempt doSingleTeleport( @@ -271,7 +281,14 @@ private AsyncAttempt doSingleTeleport( private void applyPostTeleportVelocity(@NotNull Entity teleportee) { locationOrDestination.peek(destination -> - destination.getVelocity(teleportee).peek(velocity -> - Bukkit.getScheduler().runTaskLater(multiverseCore, () -> teleportee.setVelocity(velocity), 1L))); + destination.getVelocity(teleportee).peek(velocity -> { + if (FoliaUtil.isFolia()) { + teleportee.getScheduler().runDelayed(multiverseCore, + t -> teleportee.setVelocity(velocity), null, 1L); + } else { + Bukkit.getScheduler().runTaskLater(multiverseCore, + () -> teleportee.setVelocity(velocity), 1L); + } + })); } } diff --git a/src/main/java/org/mvplugins/multiverse/core/utils/FoliaUtil.java b/src/main/java/org/mvplugins/multiverse/core/utils/FoliaUtil.java new file mode 100644 index 000000000..ae7359320 --- /dev/null +++ b/src/main/java/org/mvplugins/multiverse/core/utils/FoliaUtil.java @@ -0,0 +1,33 @@ +package org.mvplugins.multiverse.core.utils; + +import io.papermc.paper.threadedregions.scheduler.ScheduledTask; +import org.bukkit.plugin.Plugin; +import org.bukkit.scheduler.BukkitTask; + +public final class FoliaUtil { + private FoliaUtil() {} + + public static boolean isFolia() { + try { + Class.forName("io.papermc.paper.threadedregions.RegionizedServer"); + return true; + } catch (ClassNotFoundException e) { + return false; + } + } + + /** Wraps a Folia {@link ScheduledTask} so it can be used wherever {@link BukkitTask} is expected. */ + public static class TaskAdapter implements BukkitTask { + private final ScheduledTask handle; + + public TaskAdapter(ScheduledTask handle) { + this.handle = handle; + } + + @Override public int getTaskId() { return -1; } + @Override public Plugin getOwner() { return handle.getOwningPlugin(); } + @Override public boolean isSync() { return false; } + @Override public boolean isCancelled() { return handle.isCancelled(); } + @Override public void cancel() { handle.cancel(); } + } +} diff --git a/src/main/java/org/mvplugins/multiverse/core/utils/WorldTickDeferrer.java b/src/main/java/org/mvplugins/multiverse/core/utils/WorldTickDeferrer.java index 7d5c0f484..94d0c8540 100644 --- a/src/main/java/org/mvplugins/multiverse/core/utils/WorldTickDeferrer.java +++ b/src/main/java/org/mvplugins/multiverse/core/utils/WorldTickDeferrer.java @@ -3,6 +3,7 @@ import com.dumptruckman.minecraft.util.Logging; import io.vavr.control.Option; import jakarta.inject.Inject; +import org.bukkit.Bukkit; import org.bukkit.Server; import org.bukkit.scheduler.BukkitRunnable; import org.jetbrains.annotations.NotNull; @@ -48,12 +49,16 @@ public void deferWorldTick(Runnable action) { return; } Logging.fine("Deferring world tick..."); - new BukkitRunnable() { - @Override - public void run() { - action.run(); - } - }.runTaskLater(this.plugin, 1L); + if (FoliaUtil.isFolia()) { + Bukkit.getServer().getGlobalRegionScheduler().runDelayed(this.plugin, t -> action.run(), 1L); + } else { + new BukkitRunnable() { + @Override + public void run() { + action.run(); + } + }.runTaskLater(this.plugin, 1L); + } } /** diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 113598775..480d92f6d 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -5,4 +5,5 @@ website: 'https://modrinth.com/plugin/multiverse-core' description: 'The original Bukkit Multi-World Plugin!' softdepend: ['Vault', 'PlaceholderAPI'] api-version: 1.13 +folia-supported: true version: ${version}