diff --git a/pom.xml b/pom.xml
index 121bb06..4875cad 100644
--- a/pom.xml
+++ b/pom.xml
@@ -46,8 +46,6 @@
2.7.12
6.2.1
2.5.0
- 1.4
- 6.7.3
1.10.0
3.16.1.0
3.0.0
@@ -117,12 +115,6 @@
-
-
- phoenix
- https://nexus.phoenixdevt.fr/repository/maven-public/
-
-
papermc
@@ -213,6 +205,12 @@
https://repo.maven.apache.org/maven2/
+
+
+ phoenix
+ https://nexus.phoenixdevt.fr/repository/maven-public/
+
+
@@ -272,17 +270,20 @@
io.lumine
- MythicLib
- ${ver.mythiclib}
+ MythicLib-dist
+ 1.6.2-SNAPSHOT
provided
+ true
+
net.Indyuce
MMOItems-API
- ${ver.mmoitems_api}
+ 6.9.5-SNAPSHOT
provided
+
su.nightexpress.nightcore
@@ -303,11 +304,11 @@
provided
-
+
com.wolfyscript.wolfyutilities
wolfyutilities
- ${ver.wolfyutilities}
+ 4.19.0.0
provided
diff --git a/src/io/github/stumper66/lm_items/LM_Items.java b/src/io/github/stumper66/lm_items/LM_Items.java
index e95d2bb..e390695 100644
--- a/src/io/github/stumper66/lm_items/LM_Items.java
+++ b/src/io/github/stumper66/lm_items/LM_Items.java
@@ -1,6 +1,6 @@
package io.github.stumper66.lm_items;
-import org.bukkit.Bukkit;
+import io.github.stumper66.lm_items.plugins.helpers.SchedulerCompat;
import org.bukkit.command.PluginCommand;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
@@ -28,7 +28,7 @@ public void onEnable() {
registerCommands();
- Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, this::buildApiClasses, 0L);
+ SchedulerCompat.runLater(this, this::buildApiClasses, 1L);
Utils.logger.info(String.format("LM_Items: start-up complete, took %s ms",
(System.currentTimeMillis() - startedTime)));
diff --git a/src/io/github/stumper66/lm_items/plugins/helpers/SchedulerCompat.java b/src/io/github/stumper66/lm_items/plugins/helpers/SchedulerCompat.java
new file mode 100644
index 0000000..a0666b9
--- /dev/null
+++ b/src/io/github/stumper66/lm_items/plugins/helpers/SchedulerCompat.java
@@ -0,0 +1,289 @@
+package io.github.stumper66.lm_items.plugins.helpers;
+
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.entity.Player;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.scheduler.BukkitTask;
+
+import java.time.Duration;
+import java.util.Objects;
+import java.util.concurrent.atomic.AtomicReference;
+
+/** Minimal Folia/Paper/Spigot scheduler bridge. */
+public final class SchedulerCompat {
+ private SchedulerCompat() {}
+
+ public static boolean isFolia() {
+ // Folia servers expose getGlobalRegionScheduler()
+ try {
+ Bukkit.getServer().getClass().getMethod("getGlobalRegionScheduler");
+ return true;
+ } catch (NoSuchMethodException e) {
+ return false;
+ }
+ }
+
+ /* ---------------- Handle ---------------- */
+
+ /** Minimal cancel handle that works across implementations. */
+ public interface CancelHandle {
+ void cancel();
+ boolean isCancelled();
+ }
+
+ private static Duration ticksToDuration(long ticks) {
+ if (ticks < 0) ticks = 0;
+ return Duration.ofMillis(ticks * 50L);
+ }
+
+ /* ---------------- Global (main-thread) scheduling ---------------- */
+
+ /** Run next tick (or ASAP) on the main thread. */
+ static CancelHandle runNow(Plugin plugin, Runnable task) {
+ Objects.requireNonNull(plugin);
+ Objects.requireNonNull(task);
+ if (isFolia()) {
+ final var ref = new AtomicReference();
+ var t = Bukkit.getGlobalRegionScheduler().run(plugin, st -> task.run());
+ ref.set(t);
+ return new CancelHandle() {
+ public void cancel() { var s = ref.getAndSet(null); if (s != null) s.cancel(); }
+ public boolean isCancelled() { return ref.get() == null || ref.get().isCancelled(); }
+ };
+ } else {
+ BukkitTask t = Bukkit.getScheduler().runTask(plugin, task);
+ return bukkitHandle(t);
+ }
+ }
+
+ /**
+ * Run after a delay (ticks) on the main thread.
+ */
+ public static void runLater(Plugin plugin, Runnable task, long delayTicks) {
+ Objects.requireNonNull(plugin);
+ Objects.requireNonNull(task);
+ if (isFolia()) {
+ final var ref = new AtomicReference();
+ var t = Bukkit.getGlobalRegionScheduler().runDelayed(plugin, st -> task.run(), delayTicks);
+ ref.set(t);
+ } else {
+ BukkitTask t = Bukkit.getScheduler().runTaskLater(plugin, task, Math.max(0L, delayTicks));
+ bukkitHandle(t);
+ }
+ }
+
+ /** Run repeating on the main thread. */
+ static CancelHandle runRepeating(Plugin plugin, Runnable task, long initialDelayTicks, long periodTicks) {
+ Objects.requireNonNull(plugin);
+ Objects.requireNonNull(task);
+ if (periodTicks <= 0) periodTicks = 1;
+ if (isFolia()) {
+ final var ref = new AtomicReference();
+ var t = Bukkit.getGlobalRegionScheduler().runAtFixedRate(
+ plugin, st -> task.run(), initialDelayTicks, periodTicks);
+ ref.set(t);
+ return new CancelHandle() {
+ public void cancel() { var s = ref.getAndSet(null); if (s != null) s.cancel(); }
+ public boolean isCancelled() { return ref.get() == null || ref.get().isCancelled(); }
+ };
+ } else {
+ BukkitTask t = Bukkit.getScheduler().runTaskTimer(plugin, task,
+ Math.max(0L, initialDelayTicks), Math.max(1L, periodTicks));
+ return bukkitHandle(t);
+ }
+ }
+
+ /* ---------------- Region / Player (Folia main-thread safe) ---------------- */
+
+ /** Run at a location’s region next tick. On non-Folia, this falls back to normal main thread. */
+ static CancelHandle runAtLocation(Plugin plugin, Location where, Runnable task) {
+ Objects.requireNonNull(plugin);
+ Objects.requireNonNull(where);
+ Objects.requireNonNull(task);
+ if (isFolia()) {
+ final var ref = new AtomicReference();
+ var t = Bukkit.getRegionScheduler().run(plugin, where, st -> task.run());
+ ref.set(t);
+ return new CancelHandle() {
+ public void cancel() { var s = ref.getAndSet(null); if (s != null) s.cancel(); }
+ public boolean isCancelled() { return ref.get() == null || ref.get().isCancelled(); }
+ };
+ } else {
+ BukkitTask t = Bukkit.getScheduler().runTask(plugin, task);
+ return bukkitHandle(t);
+ }
+ }
+
+ /** Run repeating in the player’s region. On non-Folia, normal repeating main-thread. */
+ static CancelHandle runPlayerRepeating(Plugin plugin, Player player, Runnable task,
+ long initialDelayTicks, long periodTicks) {
+ Objects.requireNonNull(plugin);
+ Objects.requireNonNull(player);
+ Objects.requireNonNull(task);
+ if (isFolia()) {
+ final var ref = new AtomicReference();
+ var t = player.getScheduler().runAtFixedRate(
+ plugin, st -> task.run(), () -> {}, initialDelayTicks, periodTicks);
+ ref.set(t);
+ return new CancelHandle() {
+ public void cancel() { var s = ref.getAndSet(null); if (s != null) s.cancel(); }
+ public boolean isCancelled() { return ref.get() == null || ref.get().isCancelled(); }
+ };
+ } else {
+ BukkitTask t = Bukkit.getScheduler().runTaskTimer(plugin, task,
+ Math.max(0L, initialDelayTicks), Math.max(1L, periodTicks));
+ return bukkitHandle(t);
+ }
+ }
+
+ /* ---------------- Async scheduling (compat: Duration or TimeUnit) ---------------- */
+
+ @SuppressWarnings("unchecked")
+ static CancelHandle runAsync(Plugin plugin, Runnable task) {
+ Objects.requireNonNull(plugin);
+ Objects.requireNonNull(task);
+
+ if (isFolia()) {
+ try {
+ // Prefer: AsyncScheduler.runNow(Plugin, Consumer)
+ var m = Bukkit.getAsyncScheduler().getClass()
+ .getMethod("runNow", Plugin.class, java.util.function.Consumer.class);
+ final var ref = new AtomicReference