2023-03-04 22:13:23 +01:00
|
|
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
|
|
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
|
|
|
Date: Sat, 4 Mar 2023 12:48:43 -0800
|
|
|
|
Subject: [PATCH] Region scheduler API
|
|
|
|
|
2023-03-20 00:43:34 +01:00
|
|
|
Add both a location based scheduler, an entity based scheduler,
|
|
|
|
and a global region scheduler.
|
2023-03-04 22:13:23 +01:00
|
|
|
|
2023-03-23 10:51:04 +01:00
|
|
|
diff --git a/src/main/java/io/papermc/paper/threadedregions/scheduler/AsyncScheduler.java b/src/main/java/io/papermc/paper/threadedregions/scheduler/AsyncScheduler.java
|
|
|
|
new file mode 100644
|
2023-03-25 18:40:20 +01:00
|
|
|
index 0000000000000000000000000000000000000000..66232a9f5cea31dc8046817c3c2a91695930e53f
|
2023-03-23 10:51:04 +01:00
|
|
|
--- /dev/null
|
|
|
|
+++ b/src/main/java/io/papermc/paper/threadedregions/scheduler/AsyncScheduler.java
|
|
|
|
@@ -0,0 +1,50 @@
|
|
|
|
+package io.papermc.paper.threadedregions.scheduler;
|
|
|
|
+
|
|
|
|
+import org.bukkit.plugin.Plugin;
|
|
|
|
+import org.jetbrains.annotations.NotNull;
|
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
|
+import java.util.function.Consumer;
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * Scheduler that may be used by plugins to schedule tasks to execute asynchronously from the server tick process.
|
|
|
|
+ */
|
|
|
|
+public interface AsyncScheduler {
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Schedules the specified task to be executed asynchronously immediately.
|
|
|
|
+ * @param plugin Plugin which owns the specified task.
|
|
|
|
+ * @param task Specified task.
|
|
|
|
+ * @return The {@link ScheduledTask} that represents the scheduled task.
|
|
|
|
+ */
|
2023-03-25 18:40:20 +01:00
|
|
|
+ @NotNull ScheduledTask runNow(@NotNull Plugin plugin, @NotNull Consumer<ScheduledTask> task);
|
2023-03-23 10:51:04 +01:00
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Schedules the specified task to be executed asynchronously after the time delay has passed.
|
|
|
|
+ * @param plugin Plugin which owns the specified task.
|
|
|
|
+ * @param task Specified task.
|
|
|
|
+ * @param delay The time delay to pass before the task should be executed.
|
|
|
|
+ * @param unit The time unit for the time delay.
|
|
|
|
+ * @return The {@link ScheduledTask} that represents the scheduled task.
|
|
|
|
+ */
|
2023-03-25 18:40:20 +01:00
|
|
|
+ @NotNull ScheduledTask runDelayed(@NotNull Plugin plugin, @NotNull Consumer<ScheduledTask> task, long delay,
|
2023-03-23 10:51:04 +01:00
|
|
|
+ @NotNull TimeUnit unit);
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Schedules the specified task to be executed asynchronously after the initial delay has passed,
|
|
|
|
+ * and then periodically executed with the specified period.
|
|
|
|
+ * @param plugin Plugin which owns the specified task.
|
|
|
|
+ * @param task Specified task.
|
|
|
|
+ * @param initialDelay The time delay to pass before the first execution of the task.
|
|
|
|
+ * @param period The time between task executions after the first execution of the task.
|
|
|
|
+ * @param unit The time unit for the initial delay and period.
|
|
|
|
+ * @return The {@link ScheduledTask} that represents the scheduled task.
|
|
|
|
+ */
|
2023-03-25 18:40:20 +01:00
|
|
|
+ @NotNull ScheduledTask runAtFixedRate(@NotNull Plugin plugin, @NotNull Consumer<ScheduledTask> task,
|
2023-03-23 10:51:04 +01:00
|
|
|
+ long initialDelay, long period, @NotNull TimeUnit unit);
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Attempts to cancel all tasks scheduled by the specified plugin.
|
|
|
|
+ * @param plugin Specified plugin.
|
|
|
|
+ */
|
2023-03-25 18:40:20 +01:00
|
|
|
+ void cancelTasks(@NotNull Plugin plugin);
|
2023-03-23 10:51:04 +01:00
|
|
|
+}
|
2023-03-04 22:13:23 +01:00
|
|
|
diff --git a/src/main/java/io/papermc/paper/threadedregions/scheduler/EntityScheduler.java b/src/main/java/io/papermc/paper/threadedregions/scheduler/EntityScheduler.java
|
|
|
|
new file mode 100644
|
2023-03-26 06:48:28 +02:00
|
|
|
index 0000000000000000000000000000000000000000..01fc5d440ee96a2b00fadaf304cedf418a946b21
|
2023-03-04 22:13:23 +01:00
|
|
|
--- /dev/null
|
|
|
|
+++ b/src/main/java/io/papermc/paper/threadedregions/scheduler/EntityScheduler.java
|
2023-03-23 10:51:04 +01:00
|
|
|
@@ -0,0 +1,103 @@
|
2023-03-04 22:13:23 +01:00
|
|
|
+package io.papermc.paper.threadedregions.scheduler;
|
|
|
|
+
|
|
|
|
+import org.bukkit.plugin.Plugin;
|
|
|
|
+import org.jetbrains.annotations.NotNull;
|
|
|
|
+import org.jetbrains.annotations.Nullable;
|
2023-03-23 10:51:04 +01:00
|
|
|
+import java.util.function.Consumer;
|
2023-03-04 22:13:23 +01:00
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * An entity can move between worlds with an arbitrary tick delay, be temporarily removed
|
|
|
|
+ * for players (i.e end credits), be partially removed from world state (i.e inactive but not removed),
|
|
|
|
+ * teleport between ticking regions, teleport between worlds, and even be removed entirely from the server.
|
|
|
|
+ * The uncertainty of an entity's state can make it difficult to schedule tasks without worrying about undefined
|
|
|
|
+ * behaviors resulting from any of the states listed previously.
|
|
|
|
+ *
|
|
|
|
+ * <p>
|
|
|
|
+ * This class is designed to eliminate those states by providing an interface to run tasks only when an entity
|
|
|
|
+ * is contained in a world, on the owning thread for the region, and by providing the current Entity object.
|
|
|
|
+ * The scheduler also allows a task to provide a callback, the "retired" callback, that will be invoked
|
|
|
|
+ * if the entity is removed before a task that was scheduled could be executed. The scheduler is also
|
|
|
|
+ * completely thread-safe, allowing tasks to be scheduled from any thread context. The scheduler also indicates
|
|
|
|
+ * properly whether a task was scheduled successfully (i.e scheduler not retired), thus the code scheduling any task
|
|
|
|
+ * knows whether the given callbacks will be invoked eventually or not - which may be critical for off-thread
|
|
|
|
+ * contexts.
|
|
|
|
+ * </p>
|
|
|
|
+ */
|
|
|
|
+public interface EntityScheduler {
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 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 run and retired callback are invoked on the region which owns the entity.
|
|
|
|
+ * </p>
|
|
|
|
+ * @param run The callback to run after the specified delay, may not be null.
|
|
|
|
+ * @param retired Retire callback to run if the entity is retired before the run callback can be invoked, may be null.
|
|
|
|
+ * @param delay The delay in ticks before the run callback is invoked. Any value less-than 1 is treated as 1.
|
|
|
|
+ * @return {@code true} if the task was scheduled, which means that either the run function or the retired function
|
|
|
|
+ * will be invoked (but never both), or {@code false} indicating neither the run nor retired function will be invoked
|
|
|
|
+ * since the scheduler has been retired.
|
|
|
|
+ */
|
2023-03-25 18:40:20 +01:00
|
|
|
+ boolean execute(@NotNull Plugin plugin, @NotNull Runnable run, @Nullable Runnable retired, long delay);
|
2023-03-04 22:13:23 +01:00
|
|
|
+
|
2023-03-23 10:51:04 +01:00
|
|
|
+ /**
|
|
|
|
+ * Schedules a task to execute on the next tick. If the task failed to schedule because the scheduler is retired (entity
|
|
|
|
+ * removed), then returns {@code null}. Otherwise, either the task 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 plugin The plugin that owns the task
|
|
|
|
+ * @param task The task to execute
|
|
|
|
+ * @param retired Retire callback to run if the entity is retired before the run callback can be invoked, may be null.
|
|
|
|
+ * @return The {@link ScheduledTask} that represents the scheduled task, or {@code null} if the entity has been removed.
|
|
|
|
+ */
|
2023-03-25 18:40:20 +01:00
|
|
|
+ @Nullable ScheduledTask run(@NotNull Plugin plugin, @NotNull Consumer<ScheduledTask> task,
|
2023-03-23 10:51:04 +01:00
|
|
|
+ @Nullable Runnable retired);
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Schedules a task with the given delay. If the task failed to schedule because the scheduler is retired (entity
|
|
|
|
+ * removed), then returns {@code null}. Otherwise, either the task 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 plugin The plugin that owns the task
|
|
|
|
+ * @param task The task to execute
|
|
|
|
+ * @param retired Retire callback to run if the entity is retired before the run callback can be invoked, may be null.
|
|
|
|
+ * @param delayTicks The delay, in ticks.
|
|
|
|
+ * @return The {@link ScheduledTask} that represents the scheduled task, or {@code null} if the entity has been removed.
|
|
|
|
+ */
|
2023-03-25 18:40:20 +01:00
|
|
|
+ @Nullable ScheduledTask runDelayed(@NotNull Plugin plugin, @NotNull Consumer<ScheduledTask> task,
|
2023-03-26 06:48:28 +02:00
|
|
|
+ @Nullable Runnable retired, long delayTicks);
|
2023-03-23 10:51:04 +01:00
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Schedules a repeating task with the given delay and period. If the task failed to schedule because the scheduler
|
|
|
|
+ * is retired (entity removed), then returns {@code null}. Otherwise, either the task 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 plugin The plugin that owns the task
|
|
|
|
+ * @param task The task to execute
|
|
|
|
+ * @param retired Retire callback to run if the entity is retired before the run callback can be invoked, may be null.
|
|
|
|
+ * @param initialDelayTicks The initial delay, in ticks.
|
|
|
|
+ * @param periodTicks The period, in ticks.
|
|
|
|
+ * @return The {@link ScheduledTask} that represents the scheduled task, or {@code null} if the entity has been removed.
|
|
|
|
+ */
|
2023-03-25 18:40:20 +01:00
|
|
|
+ @Nullable ScheduledTask runAtFixedRate(@NotNull Plugin plugin, @NotNull Consumer<ScheduledTask> task,
|
2023-03-26 06:48:28 +02:00
|
|
|
+ @Nullable Runnable retired, long initialDelayTicks, long periodTicks);
|
2023-03-04 22:13:23 +01:00
|
|
|
+}
|
2023-03-20 00:43:34 +01:00
|
|
|
diff --git a/src/main/java/io/papermc/paper/threadedregions/scheduler/GlobalRegionScheduler.java b/src/main/java/io/papermc/paper/threadedregions/scheduler/GlobalRegionScheduler.java
|
|
|
|
new file mode 100644
|
2023-03-26 06:48:28 +02:00
|
|
|
index 0000000000000000000000000000000000000000..712af8218d5a81f731a227bcaccd7a1dc54628be
|
2023-03-20 00:43:34 +01:00
|
|
|
--- /dev/null
|
|
|
|
+++ b/src/main/java/io/papermc/paper/threadedregions/scheduler/GlobalRegionScheduler.java
|
2023-03-23 10:51:04 +01:00
|
|
|
@@ -0,0 +1,57 @@
|
2023-03-20 00:43:34 +01:00
|
|
|
+package io.papermc.paper.threadedregions.scheduler;
|
|
|
|
+
|
|
|
|
+import org.bukkit.plugin.Plugin;
|
|
|
|
+import org.jetbrains.annotations.NotNull;
|
2023-03-23 10:51:04 +01:00
|
|
|
+import java.util.function.Consumer;
|
2023-03-20 00:43:34 +01:00
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * The global region task scheduler may be used to schedule tasks that will execute on the global region.
|
|
|
|
+ * <p>
|
|
|
|
+ * The global region is responsible for maintaining world day time, world game time, weather cycle,
|
|
|
|
+ * sleep night skipping, executing commands for console, and other misc. tasks that do not belong to any specific region.
|
|
|
|
+ * </p>
|
|
|
|
+ */
|
|
|
|
+public interface GlobalRegionScheduler {
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Schedules a task to be executed on the global region.
|
|
|
|
+ * @param plugin The plugin that owns the task
|
|
|
|
+ * @param run The task to execute
|
|
|
|
+ */
|
2023-03-25 18:40:20 +01:00
|
|
|
+ void execute(@NotNull Plugin plugin, @NotNull Runnable run);
|
2023-03-23 10:51:04 +01:00
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Schedules a task to be executed on the global region on the next tick.
|
|
|
|
+ * @param plugin The plugin that owns the task
|
|
|
|
+ * @param task The task to execute
|
|
|
|
+ * @return The {@link ScheduledTask} that represents the scheduled task.
|
|
|
|
+ */
|
2023-03-25 18:40:20 +01:00
|
|
|
+ @NotNull ScheduledTask run(@NotNull Plugin plugin, @NotNull Consumer<ScheduledTask> task);
|
2023-03-23 10:51:04 +01:00
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Schedules a task to be executed on the global region after the specified delay in ticks.
|
|
|
|
+ * @param plugin The plugin that owns the task
|
|
|
|
+ * @param task The task to execute
|
|
|
|
+ * @param delayTicks The delay, in ticks.
|
|
|
|
+ * @return The {@link ScheduledTask} that represents the scheduled task.
|
|
|
|
+ */
|
2023-03-26 06:48:28 +02:00
|
|
|
+ @NotNull ScheduledTask runDelayed(@NotNull Plugin plugin, @NotNull Consumer<ScheduledTask> task, long delayTicks);
|
2023-03-23 10:51:04 +01:00
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Schedules a repeating task to be executed on the global region after the initial delay with the
|
|
|
|
+ * specified period.
|
|
|
|
+ * @param plugin The plugin that owns the task
|
|
|
|
+ * @param task The task to execute
|
|
|
|
+ * @param initialDelayTicks The initial delay, in ticks.
|
|
|
|
+ * @param periodTicks The period, in ticks.
|
|
|
|
+ * @return The {@link ScheduledTask} that represents the scheduled task.
|
|
|
|
+ */
|
2023-03-25 18:40:20 +01:00
|
|
|
+ @NotNull ScheduledTask runAtFixedRate(@NotNull Plugin plugin, @NotNull Consumer<ScheduledTask> task,
|
2023-03-26 06:48:28 +02:00
|
|
|
+ long initialDelayTicks, long periodTicks);
|
2023-03-20 00:43:34 +01:00
|
|
|
+
|
2023-03-23 10:51:04 +01:00
|
|
|
+ /**
|
|
|
|
+ * Attempts to cancel all tasks scheduled by the specified plugin.
|
|
|
|
+ * @param plugin Specified plugin.
|
|
|
|
+ */
|
2023-03-25 18:40:20 +01:00
|
|
|
+ void cancelTasks(@NotNull Plugin plugin);
|
2023-03-20 00:43:34 +01:00
|
|
|
+}
|
2023-03-25 00:22:47 +01:00
|
|
|
diff --git a/src/main/java/io/papermc/paper/threadedregions/scheduler/RegionScheduler.java b/src/main/java/io/papermc/paper/threadedregions/scheduler/RegionScheduler.java
|
2023-03-04 22:13:23 +01:00
|
|
|
new file mode 100644
|
2023-03-26 06:48:28 +02:00
|
|
|
index 0000000000000000000000000000000000000000..7a7afd4ffb323dd55db13ef1a49c6594aeb5ffea
|
2023-03-04 22:13:23 +01:00
|
|
|
--- /dev/null
|
2023-03-25 00:22:47 +01:00
|
|
|
+++ b/src/main/java/io/papermc/paper/threadedregions/scheduler/RegionScheduler.java
|
2023-03-25 18:40:20 +01:00
|
|
|
@@ -0,0 +1,126 @@
|
2023-03-04 22:13:23 +01:00
|
|
|
+package io.papermc.paper.threadedregions.scheduler;
|
|
|
|
+
|
|
|
|
+import org.bukkit.Location;
|
2023-03-25 18:40:20 +01:00
|
|
|
+import org.bukkit.World;
|
2023-03-04 22:13:23 +01:00
|
|
|
+import org.bukkit.entity.Entity;
|
|
|
|
+import org.bukkit.plugin.Plugin;
|
|
|
|
+import org.jetbrains.annotations.NotNull;
|
2023-03-23 10:51:04 +01:00
|
|
|
+import java.util.function.Consumer;
|
2023-03-04 22:13:23 +01:00
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * The region task scheduler can be used to schedule tasks by location to be executed on the region which owns the location.
|
|
|
|
+ * <p>
|
|
|
|
+ * <b>Note</b>: It is entirely inappropriate to use the region scheduler to schedule tasks for entities.
|
|
|
|
+ * If you wish to schedule tasks to perform actions on entities, you should be using {@link Entity#getScheduler()}
|
|
|
|
+ * as the entity scheduler will "follow" an entity if it is teleported, whereas the region task scheduler
|
|
|
|
+ * will not.
|
|
|
|
+ * </p>
|
|
|
|
+ */
|
2023-03-25 00:22:47 +01:00
|
|
|
+public interface RegionScheduler {
|
2023-03-04 22:13:23 +01:00
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Schedules a task to be executed on the region which owns the location.
|
2023-03-25 18:40:20 +01:00
|
|
|
+ *
|
2023-03-04 22:13:23 +01:00
|
|
|
+ * @param plugin The plugin that owns the task
|
2023-03-25 18:40:20 +01:00
|
|
|
+ * @param world The world of the region that owns the task
|
|
|
|
+ * @param chunkX The chunk X coordinate of the region that owns the task
|
|
|
|
+ * @param chunkZ The chunk Z coordinate of the region that owns the task
|
|
|
|
+ * @param run The task to execute
|
|
|
|
+ */
|
|
|
|
+ void execute(@NotNull Plugin plugin, @NotNull World world, int chunkX, int chunkZ, @NotNull Runnable run);
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Schedules a task to be executed on the region which owns the location.
|
|
|
|
+ *
|
|
|
|
+ * @param plugin The plugin that owns the task
|
2023-03-04 22:13:23 +01:00
|
|
|
+ * @param location The location at which the region executing should own
|
2023-03-25 18:40:20 +01:00
|
|
|
+ * @param run The task to execute
|
2023-03-04 22:13:23 +01:00
|
|
|
+ */
|
2023-03-25 18:40:20 +01:00
|
|
|
+ default void execute(@NotNull Plugin plugin, @NotNull Location location, @NotNull Runnable run) {
|
|
|
|
+ this.execute(plugin, location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4, run);
|
|
|
|
+ }
|
2023-03-23 10:51:04 +01:00
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Schedules a task to be executed on the region which owns the location on the next tick.
|
2023-03-25 18:40:20 +01:00
|
|
|
+ *
|
2023-03-23 10:51:04 +01:00
|
|
|
+ * @param plugin The plugin that owns the task
|
2023-03-25 18:40:20 +01:00
|
|
|
+ * @param world The world of the region that owns the task
|
|
|
|
+ * @param chunkX The chunk X coordinate of the region that owns the task
|
|
|
|
+ * @param chunkZ The chunk Z coordinate of the region that owns the task
|
|
|
|
+ * @param task The task to execute
|
|
|
|
+ * @return The {@link ScheduledTask} that represents the scheduled task.
|
|
|
|
+ */
|
|
|
|
+ @NotNull ScheduledTask run(@NotNull Plugin plugin, @NotNull World world, int chunkX, int chunkZ, @NotNull Consumer<ScheduledTask> task);
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Schedules a task to be executed on the region which owns the location on the next tick.
|
|
|
|
+ *
|
|
|
|
+ * @param plugin The plugin that owns the task
|
2023-03-23 10:51:04 +01:00
|
|
|
+ * @param location The location at which the region executing should own
|
2023-03-25 18:40:20 +01:00
|
|
|
+ * @param task The task to execute
|
2023-03-23 10:51:04 +01:00
|
|
|
+ * @return The {@link ScheduledTask} that represents the scheduled task.
|
|
|
|
+ */
|
2023-03-25 18:40:20 +01:00
|
|
|
+ default @NotNull ScheduledTask run(@NotNull Plugin plugin, @NotNull Location location, @NotNull Consumer<ScheduledTask> task) {
|
|
|
|
+ return this.run(plugin, location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4, task);
|
|
|
|
+ }
|
2023-03-23 10:51:04 +01:00
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Schedules a task to be executed on the region which owns the location after the specified delay in ticks.
|
2023-03-25 18:40:20 +01:00
|
|
|
+ *
|
|
|
|
+ * @param plugin The plugin that owns the task
|
|
|
|
+ * @param world The world of the region that owns the task
|
|
|
|
+ * @param chunkX The chunk X coordinate of the region that owns the task
|
|
|
|
+ * @param chunkZ The chunk Z coordinate of the region that owns the task
|
|
|
|
+ * @param task The task to execute
|
|
|
|
+ * @param delayTicks The delay, in ticks.
|
|
|
|
+ * @return The {@link ScheduledTask} that represents the scheduled task.
|
|
|
|
+ */
|
|
|
|
+ @NotNull ScheduledTask runDelayed(@NotNull Plugin plugin, @NotNull World world, int chunkX, int chunkZ, @NotNull Consumer<ScheduledTask> task,
|
2023-03-26 06:48:28 +02:00
|
|
|
+ long delayTicks);
|
2023-03-25 18:40:20 +01:00
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Schedules a task to be executed on the region which owns the location after the specified delay in ticks.
|
|
|
|
+ *
|
|
|
|
+ * @param plugin The plugin that owns the task
|
|
|
|
+ * @param location The location at which the region executing should own
|
|
|
|
+ * @param task The task to execute
|
2023-03-23 10:51:04 +01:00
|
|
|
+ * @param delayTicks The delay, in ticks.
|
|
|
|
+ * @return The {@link ScheduledTask} that represents the scheduled task.
|
|
|
|
+ */
|
2023-03-25 18:40:20 +01:00
|
|
|
+ default @NotNull ScheduledTask runDelayed(@NotNull Plugin plugin, @NotNull Location location, @NotNull Consumer<ScheduledTask> task,
|
2023-03-26 06:48:28 +02:00
|
|
|
+ long delayTicks) {
|
2023-03-25 18:40:20 +01:00
|
|
|
+ return this.runDelayed(plugin, location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4, task, delayTicks);
|
|
|
|
+ }
|
2023-03-23 10:51:04 +01:00
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Schedules a repeating task to be executed on the region which owns the location after the initial delay with the
|
|
|
|
+ * specified period.
|
2023-03-25 18:40:20 +01:00
|
|
|
+ *
|
|
|
|
+ * @param plugin The plugin that owns the task
|
|
|
|
+ * @param world The world of the region that owns the task
|
|
|
|
+ * @param chunkX The chunk X coordinate of the region that owns the task
|
|
|
|
+ * @param chunkZ The chunk Z coordinate of the region that owns the task
|
|
|
|
+ * @param task The task to execute
|
2023-03-23 10:51:04 +01:00
|
|
|
+ * @param initialDelayTicks The initial delay, in ticks.
|
2023-03-25 18:40:20 +01:00
|
|
|
+ * @param periodTicks The period, in ticks.
|
2023-03-23 10:51:04 +01:00
|
|
|
+ * @return The {@link ScheduledTask} that represents the scheduled task.
|
|
|
|
+ */
|
2023-03-25 18:40:20 +01:00
|
|
|
+ @NotNull ScheduledTask runAtFixedRate(@NotNull Plugin plugin, @NotNull World world, int chunkX, int chunkZ, @NotNull Consumer<ScheduledTask> task,
|
2023-03-26 06:48:28 +02:00
|
|
|
+ long initialDelayTicks, long periodTicks);
|
2023-03-25 18:40:20 +01:00
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Schedules a repeating task to be executed on the region which owns the location after the initial delay with the
|
|
|
|
+ * specified period.
|
|
|
|
+ *
|
|
|
|
+ * @param plugin The plugin that owns the task
|
|
|
|
+ * @param location The location at which the region executing should own
|
|
|
|
+ * @param task The task to execute
|
|
|
|
+ * @param initialDelayTicks The initial delay, in ticks.
|
|
|
|
+ * @param periodTicks The period, in ticks.
|
|
|
|
+ * @return The {@link ScheduledTask} that represents the scheduled task.
|
|
|
|
+ */
|
|
|
|
+ default @NotNull ScheduledTask runAtFixedRate(@NotNull Plugin plugin, @NotNull Location location, @NotNull Consumer<ScheduledTask> task,
|
2023-03-26 06:48:28 +02:00
|
|
|
+ long initialDelayTicks, long periodTicks) {
|
2023-03-25 18:40:20 +01:00
|
|
|
+ return this.runAtFixedRate(plugin, location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4, task, initialDelayTicks, periodTicks);
|
|
|
|
+ }
|
2023-03-23 10:51:04 +01:00
|
|
|
+}
|
|
|
|
diff --git a/src/main/java/io/papermc/paper/threadedregions/scheduler/ScheduledTask.java b/src/main/java/io/papermc/paper/threadedregions/scheduler/ScheduledTask.java
|
|
|
|
new file mode 100644
|
2023-03-25 18:40:20 +01:00
|
|
|
index 0000000000000000000000000000000000000000..a6b50c9d8af589cc4747e14d343d2045216c249c
|
2023-03-23 10:51:04 +01:00
|
|
|
--- /dev/null
|
|
|
|
+++ b/src/main/java/io/papermc/paper/threadedregions/scheduler/ScheduledTask.java
|
|
|
|
@@ -0,0 +1,112 @@
|
|
|
|
+package io.papermc.paper.threadedregions.scheduler;
|
|
|
|
+
|
|
|
|
+import org.bukkit.plugin.Plugin;
|
|
|
|
+import org.jetbrains.annotations.NotNull;
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * Represents a task scheduled to a scheduler.
|
|
|
|
+ */
|
|
|
|
+public interface ScheduledTask {
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Returns the plugin that scheduled this task.
|
|
|
|
+ * @return the plugin that scheduled this task.
|
|
|
|
+ */
|
2023-03-25 18:40:20 +01:00
|
|
|
+ @NotNull Plugin getOwningPlugin();
|
2023-03-23 10:51:04 +01:00
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Returns whether this task executes on a fixed period, as opposed to executing only once.
|
|
|
|
+ * @return whether this task executes on a fixed period, as opposed to executing only once.
|
|
|
|
+ */
|
2023-03-25 18:40:20 +01:00
|
|
|
+ boolean isRepeatingTask();
|
2023-03-23 10:51:04 +01:00
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Attempts to cancel this task, returning the result of the attempt. In all cases, if the task is currently
|
|
|
|
+ * being executed no attempt is made to halt the task, however any executions in the future are halted.
|
|
|
|
+ * @return the result of the cancellation attempt.
|
|
|
|
+ */
|
2023-03-25 18:40:20 +01:00
|
|
|
+ @NotNull CancelledState cancel();
|
2023-03-23 10:51:04 +01:00
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Returns the current execution state of this task.
|
|
|
|
+ * @return the current execution state of this task.
|
|
|
|
+ */
|
2023-03-25 18:40:20 +01:00
|
|
|
+ @NotNull ExecutionState getExecutionState();
|
2023-03-23 10:51:04 +01:00
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Returns whether the current execution state is {@link ExecutionState#CANCELLED} or {@link ExecutionState#CANCELLED_RUNNING}.
|
|
|
|
+ * @return whether the current execution state is {@link ExecutionState#CANCELLED} or {@link ExecutionState#CANCELLED_RUNNING}.
|
|
|
|
+ */
|
2023-03-25 18:40:20 +01:00
|
|
|
+ default boolean isCancelled() {
|
2023-03-23 10:51:04 +01:00
|
|
|
+ final ExecutionState state = this.getExecutionState();
|
|
|
|
+ return state == ExecutionState.CANCELLED || state == ExecutionState.CANCELLED_RUNNING;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Represents the result of attempting to cancel a task.
|
|
|
|
+ */
|
2023-03-25 18:40:20 +01:00
|
|
|
+ enum CancelledState {
|
2023-03-23 10:51:04 +01:00
|
|
|
+ /**
|
|
|
|
+ * The task (repeating or not) has been successfully cancelled by the caller thread. The task is not executing
|
|
|
|
+ * currently, and it will not begin execution in the future.
|
|
|
|
+ */
|
|
|
|
+ CANCELLED_BY_CALLER,
|
|
|
|
+ /**
|
|
|
|
+ * The task (repeating or not) is already cancelled. The task is not executing currently, and it will not
|
|
|
|
+ * begin execution in the future.
|
|
|
|
+ */
|
|
|
|
+ CANCELLED_ALREADY,
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * The task is not a repeating task, and could not be cancelled because the task is being executed.
|
|
|
|
+ */
|
|
|
|
+ RUNNING,
|
|
|
|
+ /**
|
|
|
|
+ * The task is not a repeating task, and could not be cancelled because the task has already finished execution.
|
|
|
|
+ */
|
|
|
|
+ ALREADY_EXECUTED,
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * The caller thread successfully stopped future executions of a repeating task, but the task is currently
|
|
|
|
+ * being executed.
|
|
|
|
+ */
|
|
|
|
+ NEXT_RUNS_CANCELLED,
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * The repeating task's future executions are cancelled already, but the task is currently
|
|
|
|
+ * being executed.
|
|
|
|
+ */
|
|
|
|
+ NEXT_RUNS_CANCELLED_ALREADY,
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Represents the current execution state of the task.
|
|
|
|
+ */
|
2023-03-25 18:40:20 +01:00
|
|
|
+ enum ExecutionState {
|
2023-03-23 10:51:04 +01:00
|
|
|
+ /**
|
|
|
|
+ * The task is currently not executing, but may begin execution in the future.
|
|
|
|
+ */
|
|
|
|
+ IDLE,
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * The task is currently executing.
|
|
|
|
+ */
|
|
|
|
+ RUNNING,
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * The task is not repeating, and the task finished executing.
|
|
|
|
+ */
|
|
|
|
+ FINISHED,
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * The task is not executing and will not begin execution in the future. If this task is not repeating, then
|
|
|
|
+ * this task was never executed.
|
|
|
|
+ */
|
|
|
|
+ CANCELLED,
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * The task is repeating and currently executing, but future executions are cancelled and will not occur.
|
|
|
|
+ */
|
|
|
|
+ CANCELLED_RUNNING;
|
|
|
|
+ }
|
2023-03-04 22:13:23 +01:00
|
|
|
+}
|
|
|
|
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
|
2023-03-30 03:26:03 +02:00
|
|
|
index a6bdd42b38454fe481f9210e1a0f5f94023a0543..aa2d0af0b0a783000e993fa622dd14e32b1914e3 100644
|
2023-03-04 22:13:23 +01:00
|
|
|
--- a/src/main/java/org/bukkit/Bukkit.java
|
|
|
|
+++ b/src/main/java/org/bukkit/Bukkit.java
|
2023-03-23 10:51:04 +01:00
|
|
|
@@ -2459,6 +2459,44 @@ public final class Bukkit {
|
2023-03-04 22:13:23 +01:00
|
|
|
return server.getPotionBrewer();
|
|
|
|
}
|
|
|
|
// Paper end
|
|
|
|
+ // Folia start - region threading API
|
|
|
|
+ /**
|
|
|
|
+ * Returns the region task scheduler. The region task scheduler can be used to schedule
|
|
|
|
+ * tasks by location to be executed on the region which owns the location.
|
|
|
|
+ * <p>
|
|
|
|
+ * <b>Note</b>: It is entirely inappropriate to use the region scheduler to schedule tasks for entities.
|
|
|
|
+ * If you wish to schedule tasks to perform actions on entities, you should be using {@link Entity#getScheduler()}
|
|
|
|
+ * as the entity scheduler will "follow" an entity if it is teleported, whereas the region task scheduler
|
|
|
|
+ * will not.
|
|
|
|
+ * </p>
|
|
|
|
+ * @return the region task scheduler
|
|
|
|
+ */
|
2023-03-25 00:22:47 +01:00
|
|
|
+ public static @NotNull io.papermc.paper.threadedregions.scheduler.RegionScheduler getRegionScheduler() {
|
2023-03-04 22:13:23 +01:00
|
|
|
+ return server.getRegionScheduler();
|
|
|
|
+ }
|
2023-03-20 00:43:34 +01:00
|
|
|
+
|
|
|
|
+ /**
|
2023-03-23 10:51:04 +01:00
|
|
|
+ * Returns the async task scheduler. The async task scheduler can be used to schedule tasks
|
|
|
|
+ * that execute asynchronously from the server tick process.
|
|
|
|
+ * @return the async task scheduler
|
|
|
|
+ */
|
|
|
|
+ public static @NotNull io.papermc.paper.threadedregions.scheduler.AsyncScheduler getAsyncScheduler() {
|
|
|
|
+ return server.getAsyncScheduler();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
2023-03-20 00:43:34 +01:00
|
|
|
+ * Returns the global region task scheduler. The global task scheduler can be used to schedule
|
|
|
|
+ * tasks to execute on the global region.
|
|
|
|
+ * <p>
|
|
|
|
+ * The global region is responsible for maintaining world day time, world game time, weather cycle,
|
|
|
|
+ * sleep night skipping, executing commands for console, and other misc. tasks that do not belong to any specific region.
|
|
|
|
+ * </p>
|
|
|
|
+ * @return the global region scheduler
|
|
|
|
+ */
|
|
|
|
+ public static @NotNull io.papermc.paper.threadedregions.scheduler.GlobalRegionScheduler getGlobalRegionScheduler() {
|
|
|
|
+ return server.getGlobalRegionScheduler();
|
|
|
|
+ }
|
2023-03-04 22:13:23 +01:00
|
|
|
+ // Folia end - region threading API
|
|
|
|
|
|
|
|
@NotNull
|
|
|
|
public static Server.Spigot spigot() {
|
|
|
|
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
|
2023-03-30 03:26:03 +02:00
|
|
|
index ce2ef5cff6ad10b64791e67f6d3cff328c2cf7dc..2f1d1edbe802f66962e2763d49a025fbc657c99f 100644
|
2023-03-04 22:13:23 +01:00
|
|
|
--- a/src/main/java/org/bukkit/Server.java
|
|
|
|
+++ b/src/main/java/org/bukkit/Server.java
|
2023-03-23 10:51:04 +01:00
|
|
|
@@ -2139,4 +2139,36 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
|
2023-03-04 22:13:23 +01:00
|
|
|
*/
|
|
|
|
@NotNull org.bukkit.potion.PotionBrewer getPotionBrewer();
|
|
|
|
// Paper end
|
|
|
|
+ // Folia start - region threading API
|
|
|
|
+ /**
|
|
|
|
+ * Returns the region task scheduler. The region task scheduler can be used to schedule
|
|
|
|
+ * tasks by location to be executed on the region which owns the location.
|
|
|
|
+ * <p>
|
|
|
|
+ * <b>Note</b>: It is entirely inappropriate to use the region scheduler to schedule tasks for entities.
|
|
|
|
+ * If you wish to schedule tasks to perform actions on entities, you should be using {@link Entity#getScheduler()}
|
|
|
|
+ * as the entity scheduler will "follow" an entity if it is teleported, whereas the region task scheduler
|
|
|
|
+ * will not.
|
|
|
|
+ * </p>
|
|
|
|
+ * @return the region task scheduler
|
|
|
|
+ */
|
2023-03-25 00:22:47 +01:00
|
|
|
+ public @NotNull io.papermc.paper.threadedregions.scheduler.RegionScheduler getRegionScheduler();
|
2023-03-23 10:51:04 +01:00
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Returns the async task scheduler. The async task scheduler can be used to schedule tasks
|
|
|
|
+ * that execute asynchronously from the server tick process.
|
|
|
|
+ * @return the async task scheduler
|
|
|
|
+ */
|
|
|
|
+ public @NotNull io.papermc.paper.threadedregions.scheduler.AsyncScheduler getAsyncScheduler();
|
2023-03-20 00:43:34 +01:00
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Returns the global region task scheduler. The global task scheduler can be used to schedule
|
|
|
|
+ * tasks to execute on the global region.
|
|
|
|
+ * <p>
|
|
|
|
+ * The global region is responsible for maintaining world day time, world game time, weather cycle,
|
|
|
|
+ * sleep night skipping, executing commands for console, and other misc. tasks that do not belong to any specific region.
|
|
|
|
+ * </p>
|
|
|
|
+ * @return the global region scheduler
|
|
|
|
+ */
|
|
|
|
+ public @NotNull io.papermc.paper.threadedregions.scheduler.GlobalRegionScheduler getGlobalRegionScheduler();
|
2023-03-04 22:13:23 +01:00
|
|
|
+ // Folia end - region threading API
|
|
|
|
}
|
|
|
|
diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java
|
2023-03-30 03:26:03 +02:00
|
|
|
index 8c58018b155c52a7b2a139f784abceb6aa00a268..d8c447b4c01e82efab6f68b0c668fc10404ef202 100644
|
2023-03-04 22:13:23 +01:00
|
|
|
--- a/src/main/java/org/bukkit/entity/Entity.java
|
|
|
|
+++ b/src/main/java/org/bukkit/entity/Entity.java
|
2023-03-23 14:55:09 +01:00
|
|
|
@@ -953,4 +953,13 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent
|
2023-03-04 22:13:23 +01:00
|
|
|
*/
|
|
|
|
boolean wouldCollideUsing(@NotNull BoundingBox boundingBox);
|
|
|
|
// Paper End - Collision API
|
|
|
|
+ // Folia start - region threading API
|
|
|
|
+ /**
|
|
|
|
+ * Returns the task scheduler for this entity. The entity scheduler can be used to schedule tasks
|
|
|
|
+ * that are guaranteed to always execute on the tick thread that owns the entity.
|
|
|
|
+ * @return the task scheduler for this entity.
|
|
|
|
+ * @see io.papermc.paper.threadedregions.scheduler.EntityScheduler
|
|
|
|
+ */
|
|
|
|
+ @NotNull io.papermc.paper.threadedregions.scheduler.EntityScheduler getScheduler();
|
|
|
|
+ // Folia end - region threading API
|
|
|
|
}
|
2023-03-06 21:57:29 +01:00
|
|
|
diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java
|
2023-03-23 14:55:09 +01:00
|
|
|
index 2b8308989fce7f8a16907f8711b362e671fdbfb6..800f954161886ca4f6332f8e0cbc4d4e8f9cbb74 100644
|
2023-03-06 21:57:29 +01:00
|
|
|
--- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java
|
|
|
|
+++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java
|
2023-03-23 14:55:09 +01:00
|
|
|
@@ -544,9 +544,9 @@ public final class SimplePluginManager implements PluginManager {
|
2023-03-06 21:57:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
- server.getScheduler().cancelTasks(plugin);
|
2023-03-23 10:51:04 +01:00
|
|
|
+ server.getAsyncScheduler().cancelTasks(plugin); // Folia - new schedulers
|
2023-03-06 21:57:29 +01:00
|
|
|
} catch (Throwable ex) {
|
2023-03-23 10:51:04 +01:00
|
|
|
- handlePluginException("Error occurred (in the plugin loader) while cancelling tasks for "
|
|
|
|
+ handlePluginException("Error occurred (in the plugin loader) while cancelling async tasks for " // Folia - new schedulers
|
2023-03-06 21:57:29 +01:00
|
|
|
+ plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); // Paper
|
2023-03-23 10:51:04 +01:00
|
|
|
}
|
|
|
|
|
2023-03-26 00:29:07 +01:00
|
|
|
diff --git a/src/main/java/org/bukkit/scheduler/BukkitScheduler.java b/src/main/java/org/bukkit/scheduler/BukkitScheduler.java
|
|
|
|
index d2ab2ee1e1e8fbaac4edef5b3ee313ee4ceb6991..8476504e3d54721c64f02eddd5b48193ac8f366b 100644
|
|
|
|
--- a/src/main/java/org/bukkit/scheduler/BukkitScheduler.java
|
|
|
|
+++ b/src/main/java/org/bukkit/scheduler/BukkitScheduler.java
|
|
|
|
@@ -7,6 +7,15 @@ import java.util.function.Consumer;
|
|
|
|
import org.bukkit.plugin.Plugin;
|
|
|
|
import org.jetbrains.annotations.NotNull;
|
|
|
|
|
|
|
|
+// Folia start - add new schedulers
|
|
|
|
+/**
|
|
|
|
+ * @deprecated Use one of {@link io.papermc.paper.threadedregions.scheduler.RegionScheduler},
|
|
|
|
+ * {@link io.papermc.paper.threadedregions.scheduler.AsyncScheduler},
|
|
|
|
+ * {@link io.papermc.paper.threadedregions.scheduler.EntityScheduler},
|
|
|
|
+ * or {@link io.papermc.paper.threadedregions.scheduler.GlobalRegionScheduler}
|
|
|
|
+ */
|
|
|
|
+// Folia end - add new schedulers
|
|
|
|
+@Deprecated
|
|
|
|
public interface BukkitScheduler {
|
|
|
|
|
|
|
|
/**
|