diff --git a/build.gradle b/build.gradle index 8d77da95..c6f0fc53 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ java { } group = 'me.playbosswar.com' -version = '8.11.6' +version = '8.12.0' description = 'CommandTimer' repositories { @@ -30,11 +30,14 @@ repositories { maven { url = 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' } + + maven { url 'https://jitpack.io' } } shadowJar { dependencies { - include(dependency('fr.minuskube.inv:smart-invs:1.2.7')) + // include(dependency('fr.minuskube.inv:smart-invs:1.2.7')) + include(dependency('com.github.titivermeesch:SmartInvs:feat~folia-support-SNAPSHOT')) include(dependency('com.github.cryptomorin:XSeries:8.6.2')) include(dependency('joda-time:joda-time:2.10.13')) include(dependency('org.jeasy:easy-rules-core:4.1.0')) @@ -53,7 +56,8 @@ compileJava { dependencies { implementation 'com.github.cryptomorin:XSeries:8.6.2' - implementation 'fr.minuskube.inv:smart-invs:1.2.7' + // implementation 'fr.minuskube.inv:smart-invs:1.2.7' + implementation 'com.github.titivermeesch:SmartInvs:feat~folia-support-SNAPSHOT' implementation 'joda-time:joda-time:2.10.13' implementation 'org.jeasy:easy-rules-core:4.1.0' implementation 'com.googlecode.json-simple:json-simple:1.1.1' @@ -70,7 +74,7 @@ publishing { maven(MavenPublication) { groupId = 'me.playbosswar.com' artifactId = 'commandtimer' - version = '8.11.6' + version = '8.12.0' from components.java } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index d64cd491..2c352119 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradlew b/gradlew index 1aa94a42..f5feea6d 100755 --- a/gradlew +++ b/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -84,7 +86,8 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum diff --git a/gradlew.bat b/gradlew.bat index 7101f8e4..9b42019c 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## diff --git a/java17-build.gradle b/java17-build.gradle index c3a875b8..9456a2e0 100644 --- a/java17-build.gradle +++ b/java17-build.gradle @@ -10,7 +10,7 @@ java { group = 'me.playbosswar.com' -version = '8.11.6' +version = '8.12.0' description = 'CommandTimer' repositories { @@ -63,7 +63,7 @@ publishing { maven(MavenPublication) { groupId = 'me.playbosswar.com' artifactId = 'commandtimer-java17' - version = '8.11.6' + version = '8.12.0' from components.java } diff --git a/java21-build.gradle b/java21-build.gradle index f21e03d1..66dd4063 100644 --- a/java21-build.gradle +++ b/java21-build.gradle @@ -10,7 +10,7 @@ java { group = 'me.playbosswar.com' -version = '8.11.6' +version = '8.12.0' description = 'CommandTimer' repositories { @@ -68,7 +68,7 @@ publishing { maven(MavenPublication) { groupId = 'me.playbosswar.com' artifactId = 'commandtimer-java21' - version = '8.11.6' + version = '8.12.0' from components.java } } diff --git a/src/main/java/me/playbosswar/com/CommandTimerPlugin.java b/src/main/java/me/playbosswar/com/CommandTimerPlugin.java index f16b47ac..5b08da9d 100644 --- a/src/main/java/me/playbosswar/com/CommandTimerPlugin.java +++ b/src/main/java/me/playbosswar/com/CommandTimerPlugin.java @@ -16,6 +16,9 @@ import me.playbosswar.com.hooks.HooksManager; import me.playbosswar.com.hooks.Metrics; import me.playbosswar.com.language.LanguageManager; +import me.playbosswar.com.scheduler.BukkitSchedulerAdapter; +import me.playbosswar.com.scheduler.FoliaSchedulerAdapter; +import me.playbosswar.com.scheduler.SchedulerAdapter; import me.playbosswar.com.tasks.Task; import me.playbosswar.com.tasks.TasksManager; import me.playbosswar.com.tasks.persistors.*; @@ -48,12 +51,19 @@ public class CommandTimerPlugin extends JavaPlugin implements Listener { public static Updater updater; public static LanguageManager languageManager; public static Dao taskDao; + public static SchedulerAdapter schedulerAdapter; @Override public void onEnable() { plugin = this; instance = this; + if(FoliaSchedulerAdapter.isSupported()) { + schedulerAdapter = new FoliaSchedulerAdapter(this); + } else { + schedulerAdapter = new BukkitSchedulerAdapter(this); + } + Sentry.init(options -> { options.setDsn("https://45383fac83f64e65a45d83c3059eb934@o1414814.ingest.sentry.io/6755132"); options.setTracesSampleRate(0.3); @@ -210,4 +220,8 @@ public static LanguageManager getLanguageManager() { public static Dao getTaskDao() { return taskDao; } + + public static SchedulerAdapter getScheduler() { + return schedulerAdapter; + } } diff --git a/src/main/java/me/playbosswar/com/commands/MainCommand.java b/src/main/java/me/playbosswar/com/commands/MainCommand.java index ceb810dc..d2da1f24 100644 --- a/src/main/java/me/playbosswar/com/commands/MainCommand.java +++ b/src/main/java/me/playbosswar/com/commands/MainCommand.java @@ -12,7 +12,6 @@ import me.playbosswar.com.utils.Files; import me.playbosswar.com.utils.Messages; import me.playbosswar.com.utils.Tools; -import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; @@ -150,10 +149,9 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @N } if(task.getCommandExecutionMode().equals(CommandExecutionMode.INTERVAL)) { - Bukkit.getScheduler().runTaskTimer( - CommandTimerPlugin.getPlugin(), + CommandTimerPlugin.getScheduler().runTaskTimer( new CommandIntervalExecutorRunnable(task), - 0, + 1, task.getCommandExecutionInterval().toSeconds() * 20L); Messages.sendMessage(sender, languageManager.get(LanguageKey.TASK_EXECUTION_ONGOING)); @@ -163,9 +161,9 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @N if(task.getCommandExecutionMode().equals(CommandExecutionMode.ORDERED)) { final int[] accumulatedDelaySeconds = {0}; task.getCommands().forEach(command -> { - Bukkit.getScheduler().scheduleSyncDelayedTask(CommandTimerPlugin.getPlugin(), + CommandTimerPlugin.getScheduler().runTaskLater( () -> tasksManager.processCommandExecution(task, command), - 20L * accumulatedDelaySeconds[0]); + (20L * accumulatedDelaySeconds[0]) + 1); accumulatedDelaySeconds[0] += command.getDelay().toSeconds(); }); Messages.sendMessage(sender, languageManager.get(LanguageKey.TASK_EXECUTION_ONGOING)); @@ -174,10 +172,10 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @N int selectedCommandIndex = tasksManager.getNextTaskCommandIndex(task); if(selectedCommandIndex == -1) { - Bukkit.getScheduler().runTask(CommandTimerPlugin.getPlugin(), () -> + CommandTimerPlugin.getScheduler().runTask(() -> task.getCommands().forEach(command -> tasksManager.processCommandExecution(task, command))); } else { - Bukkit.getScheduler().runTask(CommandTimerPlugin.getPlugin(), () -> + CommandTimerPlugin.getScheduler().runTask(() -> tasksManager.processCommandExecution(task, task.getCommands().get(selectedCommandIndex))); } diff --git a/src/main/java/me/playbosswar/com/hooks/Metrics.java b/src/main/java/me/playbosswar/com/hooks/Metrics.java index 37af124b..468eb3d6 100644 --- a/src/main/java/me/playbosswar/com/hooks/Metrics.java +++ b/src/main/java/me/playbosswar/com/hooks/Metrics.java @@ -3,6 +3,9 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.gson.JsonPrimitive; + +import me.playbosswar.com.CommandTimerPlugin; + import org.bukkit.Bukkit; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; @@ -179,7 +182,7 @@ public void run() { } // Nevertheless we want our code to run in the Bukkit main thread, so we have to use the Bukkit scheduler // Don't be afraid! The connection to the bStats server is still async, only the stats collection is sync ;) - Bukkit.getScheduler().runTask(plugin, () -> submitData()); + CommandTimerPlugin.getScheduler().runTask(() -> submitData()); } }, 1000 * 60 * 5, 1000 * 60 * 30); // Submit the data every 30 minutes, first time after 5 minutes to give other plugins enough time to start diff --git a/src/main/java/me/playbosswar/com/scheduler/BukkitSchedulerAdapter.java b/src/main/java/me/playbosswar/com/scheduler/BukkitSchedulerAdapter.java new file mode 100644 index 00000000..5057baf5 --- /dev/null +++ b/src/main/java/me/playbosswar/com/scheduler/BukkitSchedulerAdapter.java @@ -0,0 +1,28 @@ +package me.playbosswar.com.scheduler; + +import org.bukkit.Bukkit; +import org.bukkit.plugin.Plugin; +import org.bukkit.scheduler.BukkitTask; + +public class BukkitSchedulerAdapter implements SchedulerAdapter { + private Plugin plugin; + + public BukkitSchedulerAdapter(Plugin plugin) { + this.plugin = plugin; + } + + @Override + public BukkitTask runTaskTimer(Runnable runnable, long delay, long period) { + return Bukkit.getScheduler().runTaskTimer(plugin, runnable, delay, period); + } + + @Override + public BukkitTask runTask(Runnable runnable) { + return Bukkit.getScheduler().runTask(plugin, runnable); + } + + @Override + public BukkitTask runTaskLater(Runnable runnable, long delay) { + return Bukkit.getScheduler().runTaskLater(plugin, runnable, delay); + } +} diff --git a/src/main/java/me/playbosswar/com/scheduler/FoliaSchedulerAdapter.java b/src/main/java/me/playbosswar/com/scheduler/FoliaSchedulerAdapter.java new file mode 100644 index 00000000..c402d32f --- /dev/null +++ b/src/main/java/me/playbosswar/com/scheduler/FoliaSchedulerAdapter.java @@ -0,0 +1,157 @@ +package me.playbosswar.com.scheduler; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.invoke.MethodHandles.Lookup; +import java.util.Objects; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.bukkit.Bukkit; +import org.bukkit.Server; +import org.bukkit.plugin.Plugin; +import org.bukkit.scheduler.BukkitTask; +import org.jetbrains.annotations.Nullable; + +public class FoliaSchedulerAdapter implements SchedulerAdapter { + private static final boolean SUPPORTED; + private static final boolean HAS_IS_CANCELLED; + + private static @Nullable MethodHandle ASYNC_SCHEDULER_RUN; + private static @Nullable MethodHandle ASYNC_SCHEDULER_RUN_DELAYED; + private static @Nullable MethodHandle ASYNC_SCHEDULER_RUN_RATE; + private static @Nullable MethodHandle SCHEDULED_TASK_IS_CANCELLED; + private static @Nullable MethodHandle SCHEDULED_TASK_CANCEL; + + static { + boolean supporting = true; + boolean hasMethod = false; + try { + Lookup lookup = MethodHandles.publicLookup(); + Class scheduledTaskType = Class.forName("io.papermc.paper.threadedregions.scheduler.ScheduledTask"); + SCHEDULED_TASK_CANCEL = lookup.findVirtual(scheduledTaskType, "cancel", MethodType.methodType( + Class.forName("io.papermc.paper.threadedregions.scheduler.ScheduledTask$CancelledState") + )); + SCHEDULED_TASK_IS_CANCELLED = lookup.findVirtual(scheduledTaskType, "isCancelled", MethodType.methodType(boolean.class)); + + Class asyncSchedulerType = Class.forName("io.papermc.paper.threadedregions.scheduler.GlobalRegionScheduler"); + + MethodHandle getAsyncScheduler = lookup.findVirtual(Server.class, "getGlobalRegionScheduler", MethodType.methodType(asyncSchedulerType)); + Object asyncScheduler = getAsyncScheduler.invoke(Bukkit.getServer()); + + ASYNC_SCHEDULER_RUN = lookup.findVirtual(asyncSchedulerType, "run", MethodType.methodType( + scheduledTaskType, Plugin.class, Consumer.class + )).bindTo(asyncScheduler); + ASYNC_SCHEDULER_RUN_DELAYED = lookup.findVirtual(asyncSchedulerType, "runDelayed", MethodType.methodType( + scheduledTaskType, Plugin.class, Consumer.class, long.class + )).bindTo(asyncScheduler); + ASYNC_SCHEDULER_RUN_RATE = lookup.findVirtual(asyncSchedulerType, "runAtFixedRate", MethodType.methodType( + scheduledTaskType, Plugin.class, Consumer.class, long.class, long.class + )).bindTo(asyncScheduler); + + try { + BukkitTask.class.getMethod("isCancelled"); + hasMethod = true; + } catch (NoSuchMethodException ignored) { + } + } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException e) { + supporting = false; + } catch (Throwable throwable) { + Logger.getLogger(FoliaSchedulerAdapter.class.getName()).log(Level.WARNING, "Error in Folia scheduler adapter initialization", throwable); + } + SUPPORTED = supporting; + HAS_IS_CANCELLED = hasMethod; + } + + private final Plugin plugin; + + public FoliaSchedulerAdapter(Plugin plugin) { + this.plugin = plugin; + } + + public static boolean isSupported() { + return SUPPORTED; + } + + @Override + public BukkitTask runTaskTimer(Runnable runnable, long delay, long period) { + try { + final Consumer consumer = task -> runnable.run(); + return new ScheduledTask(Objects.requireNonNull(ASYNC_SCHEDULER_RUN_RATE).invoke(plugin, consumer, delay, period)); + } catch (Throwable e) { + plugin.getLogger().log(Level.SEVERE, "Error in task scheduling by the Folia scheduler adapter", e); + } + return new ScheduledTask(null); + } + + @Override + public BukkitTask runTask(Runnable runnable) { + try { + final Consumer consumer = task -> runnable.run(); + return new ScheduledTask(Objects.requireNonNull(ASYNC_SCHEDULER_RUN).invoke(plugin, consumer)); + } catch (Throwable e) { + plugin.getLogger().log(Level.SEVERE, "Error in task scheduling by the Folia scheduler adapter", e); + } + return new ScheduledTask(null); + } + + + @Override + public BukkitTask runTaskLater(Runnable runnable, long delay) { + try { + final Consumer consumer = task -> runnable.run(); + return new ScheduledTask(Objects.requireNonNull(ASYNC_SCHEDULER_RUN_DELAYED).invoke(plugin, consumer, delay)); + } catch (Throwable e) { + plugin.getLogger().log(Level.SEVERE, "Error in task scheduling by the Folia scheduler adapter", e); + } + return new ScheduledTask(null); + } + + private class ScheduledTask implements BukkitTask { + private final Object task; + + public ScheduledTask(Object task) { + this.task = task; + } + + @Override + public int getTaskId() { + return 0; + } + + @Override + public Plugin getOwner() { + return null; + } + + @Override + public boolean isSync() { + return false; + } + + public boolean isCancelled() { + if (!HAS_IS_CANCELLED) { + return false; + } + try { + return (boolean) Objects.requireNonNull(SCHEDULED_TASK_IS_CANCELLED).invoke(task); + } catch (Throwable e) { + plugin.getLogger().log(Level.SEVERE, "Error in task cancellation check by the Folia scheduler adapter", e); + } + return false; + } + + @Override + public void cancel() { + try { + Objects.requireNonNull(SCHEDULED_TASK_CANCEL).invoke(task); + } catch (Throwable e) { + plugin.getLogger().log(Level.SEVERE, "Error in task canceling by the Folia scheduler adapter", e); + } + } + } +} + diff --git a/src/main/java/me/playbosswar/com/scheduler/SchedulerAdapter.java b/src/main/java/me/playbosswar/com/scheduler/SchedulerAdapter.java new file mode 100644 index 00000000..6ecfd9f1 --- /dev/null +++ b/src/main/java/me/playbosswar/com/scheduler/SchedulerAdapter.java @@ -0,0 +1,11 @@ +package me.playbosswar.com.scheduler; + +import org.bukkit.scheduler.BukkitTask; + +public interface SchedulerAdapter { + BukkitTask runTaskTimer(Runnable runnable, long delay, long period); + + BukkitTask runTask(Runnable runnable); + + BukkitTask runTaskLater(Runnable runnable, long delay); +} diff --git a/src/main/java/me/playbosswar/com/tasks/TaskRunner.java b/src/main/java/me/playbosswar/com/tasks/TaskRunner.java index 9f9312c0..08eae35a 100644 --- a/src/main/java/me/playbosswar/com/tasks/TaskRunner.java +++ b/src/main/java/me/playbosswar/com/tasks/TaskRunner.java @@ -13,7 +13,6 @@ import java.time.LocalTime; import java.time.format.DateTimeFormatter; -import java.util.Date; import java.util.List; import java.util.TimerTask; @@ -138,8 +137,8 @@ private void processTask(Task task) { CommandExecutionMode executionMode = task.getCommandExecutionMode(); if(executionMode.equals(CommandExecutionMode.INTERVAL)) { - Bukkit.getScheduler().runTaskTimer(CommandTimerPlugin.getPlugin(), - new CommandIntervalExecutorRunnable(task), 0, task.getCommandExecutionInterval().toSeconds() * 20L); + CommandTimerPlugin.getScheduler().runTaskTimer( + new CommandIntervalExecutorRunnable(task), 1, task.getCommandExecutionInterval().toSeconds() * 20L); return; } @@ -147,8 +146,8 @@ private void processTask(Task task) { if(executionMode.equals(CommandExecutionMode.ORDERED) && hasDelayedCommands) { final int[] accumulatedDelaySeconds = {0}; task.getCommands().forEach(command -> { - Bukkit.getScheduler().scheduleSyncDelayedTask(CommandTimerPlugin.getPlugin(), - () -> tasksManager.processCommandExecution(task, command), 20L * accumulatedDelaySeconds[0]); + CommandTimerPlugin.getScheduler().runTaskLater( + () -> tasksManager.processCommandExecution(task, command), (20L * accumulatedDelaySeconds[0]) + 1); accumulatedDelaySeconds[0] += command.getDelay().toSeconds(); }); return; @@ -159,12 +158,12 @@ private void processTask(Task task) { if(selectedCommandIndex == -1) { task.setLastExecutedCommandIndex(0); - Bukkit.getScheduler().runTask(CommandTimerPlugin.getPlugin(), + CommandTimerPlugin.getScheduler().runTask( () -> task.getCommands().forEach(command -> tasksManager.processCommandExecution(task, command))); } else { TaskCommand taskCommand = task.getCommands().get(selectedCommandIndex); task.setLastExecutedCommandIndex(task.getCommands().indexOf(taskCommand)); - Bukkit.getScheduler().runTask(CommandTimerPlugin.getPlugin(), + CommandTimerPlugin.getScheduler().runTask( () -> tasksManager.processCommandExecution(task, taskCommand)); } @@ -173,7 +172,7 @@ private void processTask(Task task) { @Override public void run() { - Bukkit.getScheduler().runTaskTimer(CommandTimerPlugin.getPlugin(), new TimerTask() { + CommandTimerPlugin.getScheduler().runTaskTimer(new TimerTask() { @Override public void run() { if(tasksManager.stopRunner) { @@ -190,6 +189,6 @@ public void run() { }); } // Sync runner with the clock - }, System.currentTimeMillis() % 20, 20); + }, (System.currentTimeMillis() % 20) + 1, 20); } } \ No newline at end of file diff --git a/src/main/java/me/playbosswar/com/tasks/TasksManager.java b/src/main/java/me/playbosswar/com/tasks/TasksManager.java index 59b9b455..3c831795 100644 --- a/src/main/java/me/playbosswar/com/tasks/TasksManager.java +++ b/src/main/java/me/playbosswar/com/tasks/TasksManager.java @@ -142,10 +142,10 @@ private boolean runConsolePerUserCommand(Task task, TaskCommand taskCommand, Lis willExecute = true; if(delayedExecutions) { - Bukkit.getScheduler().scheduleSyncDelayedTask(CommandTimerPlugin.getPlugin(), () -> { + CommandTimerPlugin.getScheduler().runTaskLater(() -> { Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), PAPIHook.parsePAPI(command, p)); executionsSinceLastSync++; - }, 20L * i * taskCommand.getInterval().toSeconds()); + }, (20L * i * taskCommand.getInterval().toSeconds()) + 1); } else { Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), PAPIHook.parsePAPI(command, p)); executionsSinceLastSync++; @@ -164,10 +164,10 @@ private boolean runConsolePerUserOfflineCommand(TaskCommand taskCommand) throws // TODO: Caching could be used heres, Bukkit.getOfflinePlayers() is pretty expensive for(OfflinePlayer p : Bukkit.getOfflinePlayers()) { if(delayedExecutions) { - Bukkit.getScheduler().scheduleSyncDelayedTask(CommandTimerPlugin.getPlugin(), () -> { + CommandTimerPlugin.getScheduler().runTaskLater(() -> { Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), PAPIHook.parsePAPI(command, p)); executionsSinceLastSync++; - }, 20L * i * taskCommand.getInterval().toSeconds()); + }, (20L * i * taskCommand.getInterval().toSeconds()) + 1); } else { Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), PAPIHook.parsePAPI(command, p)); executionsSinceLastSync++; @@ -220,8 +220,8 @@ private boolean runPlayerCommand(Task task, TaskCommand taskCommand, List willExecute = true; if(delayedExecution) { - Bukkit.getScheduler().scheduleSyncDelayedTask(CommandTimerPlugin.getPlugin(), () -> runForPlayer(p, - command), 20L * i * taskCommand.getInterval().toSeconds()); + CommandTimerPlugin.getScheduler().runTaskLater(() -> runForPlayer(p, + command), (20L * i * taskCommand.getInterval().toSeconds()) + 1); } else { runForPlayer(p, command); } @@ -278,10 +278,10 @@ private boolean runOperatorCommand(Task task, TaskCommand taskCommand, List { + CommandTimerPlugin.getScheduler().runTaskLater(() -> { p.performCommand(PAPIHook.parsePAPI(command, p)); executionsSinceLastSync++; - }, 20L * i * taskCommand.getInterval().toSeconds()); + }, (20L * i * taskCommand.getInterval().toSeconds()) + 1); } else { p.performCommand(PAPIHook.parsePAPI(command, p)); executionsSinceLastSync++; diff --git a/src/main/java/me/playbosswar/com/utils/Futures.java b/src/main/java/me/playbosswar/com/utils/Futures.java index 3c16c90c..45125234 100644 --- a/src/main/java/me/playbosswar/com/utils/Futures.java +++ b/src/main/java/me/playbosswar/com/utils/Futures.java @@ -12,6 +12,8 @@ import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.NotNull; +import me.playbosswar.com.CommandTimerPlugin; + public final class Futures { private Futures() {} @@ -23,7 +25,7 @@ public static void onMainThread(@NotNull final Plugin plugin, if (Bukkit.isPrimaryThread()) { consumer.accept(value, exception); } else { - Bukkit.getScheduler().runTask(plugin, () -> consumer.accept(value, exception)); + CommandTimerPlugin.getScheduler().runTask(() -> consumer.accept(value, exception)); } }); } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 0121ab87..f0450114 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,9 +1,10 @@ main: me.playbosswar.com.CommandTimerPlugin name: "CommandTimer" -version: "8.11.6" +version: "8.12.0" description: "Schedule commands like you want" author: PlayBossWar api-version: 1.13 +folia-supported: true softdepend: [PlaceholderAPI] commands: