mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-07-03 00:17:15 +00:00
implement platform specific schedulers
This commit is contained in:
parent
851ac18f0d
commit
2577344ac0
@ -70,6 +70,7 @@ dependencies {
|
|||||||
implementation("net.kyori:adventure-platform-bukkit:4.3.4")
|
implementation("net.kyori:adventure-platform-bukkit:4.3.4")
|
||||||
implementation("net.kyori:adventure-api:4.17.0")
|
implementation("net.kyori:adventure-api:4.17.0")
|
||||||
implementation("org.bstats:bstats-bukkit:3.1.0")
|
implementation("org.bstats:bstats-bukkit:3.1.0")
|
||||||
|
implementation(project(":scheduler"))
|
||||||
|
|
||||||
//implementation("org.bytedeco:javacpp:1.5.10")
|
//implementation("org.bytedeco:javacpp:1.5.10")
|
||||||
//implementation("org.bytedeco:cuda-platform:12.3-8.9-1.5.10")
|
//implementation("org.bytedeco:cuda-platform:12.3-8.9-1.5.10")
|
||||||
|
7
scheduler/build.gradle.kts
Normal file
7
scheduler/build.gradle.kts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
plugins {
|
||||||
|
java
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compileOnly("dev.folia:folia-api:1.20.1-R0.1-SNAPSHOT")
|
||||||
|
}
|
@ -0,0 +1,190 @@
|
|||||||
|
package com.volmit.iris.util.scheduling;
|
||||||
|
|
||||||
|
import com.volmit.iris.util.scheduling.paper.PaperPlatform;
|
||||||
|
import com.volmit.iris.util.scheduling.spigot.SpigotPlatform;
|
||||||
|
import com.volmit.iris.util.scheduling.split.IAsyncScheduler;
|
||||||
|
import com.volmit.iris.util.scheduling.split.IEntityScheduler;
|
||||||
|
import com.volmit.iris.util.scheduling.split.IGlobalScheduler;
|
||||||
|
import com.volmit.iris.util.scheduling.split.IRegionScheduler;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Server;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public interface Platform {
|
||||||
|
/**
|
||||||
|
* Folia: Returns whether the current thread is ticking a region and that
|
||||||
|
* the region being ticked owns the chunk at the specified world and block
|
||||||
|
* position as included in the specified location.
|
||||||
|
* Paper/Spigot: Returns {@link Server#isPrimaryThread()}
|
||||||
|
*
|
||||||
|
* @param location Specified location, must have a non-null world
|
||||||
|
* @return true if the current thread is ticking the region that owns the chunk at the specified location
|
||||||
|
*/
|
||||||
|
boolean isOwnedByCurrentRegion(@NotNull Location location);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Folia: Returns whether the current thread is ticking a region and that
|
||||||
|
* the region being ticked owns the chunks centered at the specified world
|
||||||
|
* and block position as included in the specified location within the
|
||||||
|
* specified square radius. Specifically, this function checks that every
|
||||||
|
* chunk with position x in [centerX - radius, centerX + radius] and
|
||||||
|
* position z in [centerZ - radius, centerZ + radius] is owned by the
|
||||||
|
* current ticking region.
|
||||||
|
* Paper/Spigot: Returns {@link Server#isPrimaryThread()}
|
||||||
|
*
|
||||||
|
* @param location Specified location, must have a non-null world
|
||||||
|
* @param squareRadiusChunks Specified square radius. Must be >= 0. Note that this parameter is not a squared radius, but rather a Chebyshev Distance
|
||||||
|
* @return true if the current thread is ticking the region that owns the chunks centered at the specified location within the specified square radius
|
||||||
|
*/
|
||||||
|
boolean isOwnedByCurrentRegion(@NotNull Location location, int squareRadiusChunks);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Folia: Returns whether the current thread is ticking a region and that
|
||||||
|
* the region being ticked owns the chunk at the specified block position.
|
||||||
|
* Paper/Spigot: Returns {@link Server#isPrimaryThread()}
|
||||||
|
*
|
||||||
|
* @param block Specified block position
|
||||||
|
* @return true if the current thread is ticking the region that owns the chunk at the specified block position
|
||||||
|
*/
|
||||||
|
boolean isOwnedByCurrentRegion(@NotNull Block block);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Folia: Returns whether the current thread is ticking a region and that
|
||||||
|
* the region being ticked owns the chunk at the specified world and chunk
|
||||||
|
* position.
|
||||||
|
* Paper/Spigot: Returns {@link Server#isPrimaryThread()}
|
||||||
|
*
|
||||||
|
* @param world Specified world
|
||||||
|
* @param chunkX Specified x-coordinate of the chunk position
|
||||||
|
* @param chunkZ Specified z-coordinate of the chunk position
|
||||||
|
* @return true if the current thread is ticking the region that owns the chunk at the specified world and chunk position
|
||||||
|
*/
|
||||||
|
boolean isOwnedByCurrentRegion(@NotNull World world, int chunkX, int chunkZ);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Folia: Returns whether the current thread is ticking a region and that
|
||||||
|
* the region being ticked owns the chunks centered at the specified world
|
||||||
|
* and chunk position within the specified square radius. Specifically,
|
||||||
|
* this function checks that every chunk with position x in [centerX -
|
||||||
|
* radius, centerX + radius] and position z in [centerZ - radius, centerZ +
|
||||||
|
* radius] is owned by the current ticking region.
|
||||||
|
* Paper/Spigot: Returns {@link Server#isPrimaryThread()}
|
||||||
|
*
|
||||||
|
* @param world Specified world
|
||||||
|
* @param chunkX Specified x-coordinate of the chunk position
|
||||||
|
* @param chunkZ Specified z-coordinate of the chunk position
|
||||||
|
* @param squareRadiusChunks Specified square radius. Must be >= 0. Note that this parameter is not a squared radius, but rather a Chebyshev Distance.
|
||||||
|
* @return true if the current thread is ticking the region that owns the chunks centered at the specified world and chunk position within the specified square radius
|
||||||
|
*/
|
||||||
|
boolean isOwnedByCurrentRegion(@NotNull World world, int chunkX, int chunkZ, int squareRadiusChunks);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Folia: Returns whether the current thread is ticking a region and that
|
||||||
|
* the region being ticked owns the specified entity. Note that this
|
||||||
|
* function is the only appropriate method of checking for ownership of an
|
||||||
|
* entity, as retrieving the entity's location is undefined unless the
|
||||||
|
* entity is owned by the current region.
|
||||||
|
* Paper/Spigot: Returns {@link Server#isPrimaryThread()}
|
||||||
|
*
|
||||||
|
* @param entity Specified entity
|
||||||
|
* @return true if the current thread is ticking the region that owns the specified entity
|
||||||
|
*/
|
||||||
|
boolean isOwnedByCurrentRegion(@NotNull Entity entity);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Folia: Returns whether the current thread is ticking the global region.
|
||||||
|
* Paper/Spigot: Returns {@link Server#isPrimaryThread()}
|
||||||
|
*
|
||||||
|
* @return true if the current thread is ticking the global region
|
||||||
|
*/
|
||||||
|
boolean isGlobalTickThread();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scheduler that may be used by plugins to schedule tasks to execute asynchronously from the server tick process.
|
||||||
|
*/
|
||||||
|
@NotNull IAsyncScheduler async();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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>
|
||||||
|
*/
|
||||||
|
@NotNull IEntityScheduler entity(@NotNull Entity entity);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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>
|
||||||
|
*/
|
||||||
|
@NotNull IGlobalScheduler global();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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>
|
||||||
|
*/
|
||||||
|
@NotNull IRegionScheduler region();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Teleport an entity to a location async
|
||||||
|
* @param entity Entity to teleport
|
||||||
|
* @param location Location to teleport to
|
||||||
|
* @return Future when the teleport is completed or failed
|
||||||
|
*/
|
||||||
|
default @NotNull CompletableFuture<@NotNull Boolean> teleportAsync(@NotNull Entity entity, @NotNull Location location) {
|
||||||
|
return teleportAsync(entity, location, PlayerTeleportEvent.TeleportCause.PLUGIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Teleport an entity to a location async with a cause
|
||||||
|
* @param entity Entity to teleport
|
||||||
|
* @param location Location to teleport to
|
||||||
|
* @param cause Cause of the teleport
|
||||||
|
* @return Future when the teleport is completed or failed
|
||||||
|
*/
|
||||||
|
@NotNull CompletableFuture<@NotNull Boolean> teleportAsync(@NotNull Entity entity, @NotNull Location location, @NotNull PlayerTeleportEvent.TeleportCause cause);
|
||||||
|
|
||||||
|
static @NotNull Platform create(@NotNull Plugin plugin) {
|
||||||
|
if (hasClass("com.destroystokyo.paper.PaperConfig") || hasClass("io.papermc.paper.configuration.Configuration"))
|
||||||
|
return new PaperPlatform(plugin);
|
||||||
|
if (hasClass("org.spigotmc.SpigotConfig"))
|
||||||
|
return new SpigotPlatform(plugin);
|
||||||
|
throw new IllegalStateException("Unsupported platform!");
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean hasClass(String name) {
|
||||||
|
try {
|
||||||
|
Class.forName(name);
|
||||||
|
return true;
|
||||||
|
} catch (Throwable e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
package com.volmit.iris.util.scheduling;
|
||||||
|
|
||||||
|
public final class Ref<T> {
|
||||||
|
public transient T value;
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package com.volmit.iris.util.scheduling;
|
||||||
|
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public interface Task {
|
||||||
|
void cancel();
|
||||||
|
boolean cancelled();
|
||||||
|
@NotNull Plugin owner();
|
||||||
|
boolean async();
|
||||||
|
|
||||||
|
interface Completable<T> extends Task {
|
||||||
|
@NotNull CompletableFuture<T> result();
|
||||||
|
|
||||||
|
default void complete(Function<Completable<T>, T> function) {
|
||||||
|
var future = result();
|
||||||
|
try {
|
||||||
|
future.complete(function.apply(this));
|
||||||
|
} catch (Throwable e) {
|
||||||
|
future.completeExceptionally(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,107 @@
|
|||||||
|
package com.volmit.iris.util.scheduling.paper;
|
||||||
|
|
||||||
|
import com.volmit.iris.util.scheduling.Platform;
|
||||||
|
import com.volmit.iris.util.scheduling.paper.split.PaperAsyncScheduler;
|
||||||
|
import com.volmit.iris.util.scheduling.paper.split.PaperEntityScheduler;
|
||||||
|
import com.volmit.iris.util.scheduling.paper.split.PaperGlobalScheduler;
|
||||||
|
import com.volmit.iris.util.scheduling.paper.split.PaperRegionScheduler;
|
||||||
|
import com.volmit.iris.util.scheduling.split.IAsyncScheduler;
|
||||||
|
import com.volmit.iris.util.scheduling.split.IEntityScheduler;
|
||||||
|
import com.volmit.iris.util.scheduling.split.IGlobalScheduler;
|
||||||
|
import com.volmit.iris.util.scheduling.split.IRegionScheduler;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Server;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.function.BooleanSupplier;
|
||||||
|
|
||||||
|
public class PaperPlatform implements Platform {
|
||||||
|
private final Plugin plugin;
|
||||||
|
private final Server server;
|
||||||
|
private final IAsyncScheduler async;
|
||||||
|
private final IGlobalScheduler global;
|
||||||
|
private final IRegionScheduler region;
|
||||||
|
private final BooleanSupplier globalTickThread;
|
||||||
|
|
||||||
|
public PaperPlatform(@NotNull Plugin plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.server = plugin.getServer();
|
||||||
|
async = new PaperAsyncScheduler(plugin, server.getAsyncScheduler());
|
||||||
|
global = new PaperGlobalScheduler(plugin, server.getGlobalRegionScheduler());
|
||||||
|
region = new PaperRegionScheduler(plugin, server.getRegionScheduler());
|
||||||
|
|
||||||
|
BooleanSupplier method;
|
||||||
|
try {
|
||||||
|
method = server::isGlobalTickThread;
|
||||||
|
} catch (Throwable e) {
|
||||||
|
method = server::isPrimaryThread;
|
||||||
|
}
|
||||||
|
globalTickThread = method;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOwnedByCurrentRegion(@NotNull Location location) {
|
||||||
|
return server.isOwnedByCurrentRegion(location);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOwnedByCurrentRegion(@NotNull Location location, int squareRadiusChunks) {
|
||||||
|
return server.isOwnedByCurrentRegion(location, squareRadiusChunks);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOwnedByCurrentRegion(@NotNull Block block) {
|
||||||
|
return server.isOwnedByCurrentRegion(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOwnedByCurrentRegion(@NotNull World world, int chunkX, int chunkZ) {
|
||||||
|
return server.isOwnedByCurrentRegion(world, chunkX, chunkZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOwnedByCurrentRegion(@NotNull World world, int chunkX, int chunkZ, int squareRadiusChunks) {
|
||||||
|
return server.isOwnedByCurrentRegion(world, chunkX, chunkZ, squareRadiusChunks);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOwnedByCurrentRegion(@NotNull Entity entity) {
|
||||||
|
return server.isOwnedByCurrentRegion(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isGlobalTickThread() {
|
||||||
|
return globalTickThread.getAsBoolean();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull IAsyncScheduler async() {
|
||||||
|
return async;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull IEntityScheduler entity(@NotNull Entity entity) {
|
||||||
|
return new PaperEntityScheduler(plugin, entity.getScheduler());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull IGlobalScheduler global() {
|
||||||
|
return global;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull IRegionScheduler region() {
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull CompletableFuture<@NotNull Boolean> teleportAsync(@NotNull Entity entity, @NotNull Location location, PlayerTeleportEvent.@NotNull TeleportCause cause) {
|
||||||
|
return entity.teleportAsync(location, cause);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
package com.volmit.iris.util.scheduling.paper;
|
||||||
|
|
||||||
|
import com.volmit.iris.util.scheduling.Task;
|
||||||
|
import io.papermc.paper.threadedregions.scheduler.ScheduledTask;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
public class PaperTask implements Task {
|
||||||
|
protected final ScheduledTask task;
|
||||||
|
protected final boolean async;
|
||||||
|
|
||||||
|
public PaperTask(@NotNull ScheduledTask task, boolean async) {
|
||||||
|
this.task = task;
|
||||||
|
this.async = async;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancel() {
|
||||||
|
task.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean cancelled() {
|
||||||
|
return task.isCancelled();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Plugin owner() {
|
||||||
|
return task.getOwningPlugin();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean async() {
|
||||||
|
return async;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Completable<T> extends PaperTask implements Task.Completable<T> {
|
||||||
|
private final CompletableFuture<T> result = new CompletableFuture<>();
|
||||||
|
|
||||||
|
public Completable(@NotNull ScheduledTask task, boolean async) {
|
||||||
|
super(task, async);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancel() {
|
||||||
|
ScheduledTask.CancelledState cancel = task.cancel();
|
||||||
|
if (cancel == ScheduledTask.CancelledState.CANCELLED_BY_CALLER || cancel == ScheduledTask.CancelledState.NEXT_RUNS_CANCELLED || cancel == ScheduledTask.CancelledState.CANCELLED_ALREADY) {
|
||||||
|
result.cancel(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull CompletableFuture<T> result() {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
package com.volmit.iris.util.scheduling.paper.split;
|
||||||
|
|
||||||
|
import com.volmit.iris.util.scheduling.Ref;
|
||||||
|
import com.volmit.iris.util.scheduling.Task;
|
||||||
|
import com.volmit.iris.util.scheduling.Task.Completable;
|
||||||
|
import com.volmit.iris.util.scheduling.paper.PaperTask;
|
||||||
|
import com.volmit.iris.util.scheduling.split.IAsyncScheduler;
|
||||||
|
import io.papermc.paper.threadedregions.scheduler.AsyncScheduler;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Range;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class PaperAsyncScheduler implements IAsyncScheduler {
|
||||||
|
private final Plugin plugin;
|
||||||
|
private final AsyncScheduler scheduler;
|
||||||
|
|
||||||
|
public PaperAsyncScheduler(Plugin plugin, AsyncScheduler scheduler) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.scheduler = scheduler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull <R> Completable<R> run(@NotNull Function<Completable<R>, R> task) {
|
||||||
|
Ref<Completable<R>> ref = new Ref<>();
|
||||||
|
return ref.value = new PaperTask.Completable<>(scheduler.runNow(plugin, t -> ref.value.complete(task)), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull <R> Completable<R> runDelayed(@NotNull Function<Completable<R>, R> task,
|
||||||
|
@Range(from = 1, to = Long.MAX_VALUE) long delay,
|
||||||
|
@NotNull TimeUnit unit) {
|
||||||
|
Ref<Completable<R>> ref = new Ref<>();
|
||||||
|
return ref.value = new PaperTask.Completable<>(scheduler.runDelayed(plugin, t -> ref.value.complete(task), delay, unit), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Task runAtFixedRate(@NotNull Consumer<Task> task,
|
||||||
|
@Range(from = 1, to = Long.MAX_VALUE) long initialDelay,
|
||||||
|
@Range(from = 1, to = Long.MAX_VALUE) long period,
|
||||||
|
@NotNull TimeUnit unit) {
|
||||||
|
Ref<Task> ref = new Ref<>();
|
||||||
|
return ref.value = new PaperTask(scheduler.runAtFixedRate(plugin, t -> task.accept(ref.value), initialDelay, period, unit), true);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
package com.volmit.iris.util.scheduling.paper.split;
|
||||||
|
|
||||||
|
import com.volmit.iris.util.scheduling.Ref;
|
||||||
|
import com.volmit.iris.util.scheduling.Task;
|
||||||
|
import com.volmit.iris.util.scheduling.Task.Completable;
|
||||||
|
import com.volmit.iris.util.scheduling.paper.PaperTask;
|
||||||
|
import com.volmit.iris.util.scheduling.split.IEntityScheduler;
|
||||||
|
import io.papermc.paper.threadedregions.scheduler.EntityScheduler;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.annotations.Range;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class PaperEntityScheduler implements IEntityScheduler {
|
||||||
|
private final Plugin plugin;
|
||||||
|
private final EntityScheduler scheduler;
|
||||||
|
|
||||||
|
public PaperEntityScheduler(Plugin plugin, EntityScheduler scheduler) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.scheduler = scheduler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable <R> Completable<R> runDelayed(@NotNull Function<Completable<R>, R> task,
|
||||||
|
@Nullable Runnable retired,
|
||||||
|
@Range(from = 1, to = Long.MAX_VALUE) long delayTicks) {
|
||||||
|
Ref<Completable<R>> ref = new Ref<>();
|
||||||
|
var raw = scheduler.runDelayed(plugin, t -> ref.value.complete(task), () -> {
|
||||||
|
if (retired != null) retired.run();
|
||||||
|
ref.value.cancel();
|
||||||
|
}, delayTicks);
|
||||||
|
if (raw == null) return null;
|
||||||
|
return ref.value = new PaperTask.Completable<>(raw, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable Task runAtFixedRate(@NotNull Consumer<Task> task,
|
||||||
|
@Nullable Runnable retired,
|
||||||
|
@Range(from = 1, to = Long.MAX_VALUE) long initialDelayTicks,
|
||||||
|
@Range(from = 1, to = Long.MAX_VALUE) long periodTicks) {
|
||||||
|
Ref<Task> ref = new Ref<>();
|
||||||
|
var raw = scheduler.runAtFixedRate(plugin, t -> task.accept(ref.value), retired, initialDelayTicks, periodTicks);
|
||||||
|
if (raw == null) return null;
|
||||||
|
return ref.value = new PaperTask(raw, false);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
package com.volmit.iris.util.scheduling.paper.split;
|
||||||
|
|
||||||
|
import com.volmit.iris.util.scheduling.Ref;
|
||||||
|
import com.volmit.iris.util.scheduling.Task;
|
||||||
|
import com.volmit.iris.util.scheduling.Task.Completable;
|
||||||
|
import com.volmit.iris.util.scheduling.paper.PaperTask;
|
||||||
|
import com.volmit.iris.util.scheduling.split.IGlobalScheduler;
|
||||||
|
import io.papermc.paper.threadedregions.scheduler.GlobalRegionScheduler;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Range;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class PaperGlobalScheduler implements IGlobalScheduler {
|
||||||
|
private final Plugin plugin;
|
||||||
|
private final GlobalRegionScheduler scheduler;
|
||||||
|
|
||||||
|
public PaperGlobalScheduler(Plugin plugin, GlobalRegionScheduler scheduler) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.scheduler = scheduler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull <R> Completable<R> runDelayed(@NotNull Function<Completable<R>, R> task,
|
||||||
|
@Range(from = 1, to = Long.MAX_VALUE) long delayTicks) {
|
||||||
|
Ref<Completable<R>> ref = new Ref<>();
|
||||||
|
return ref.value = new PaperTask.Completable<>(scheduler.runDelayed(plugin, t -> ref.value.complete(task), delayTicks), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Task runAtFixedRate(@NotNull Consumer<Task> task,
|
||||||
|
@Range(from = 1, to = Long.MAX_VALUE) long initialDelayTicks,
|
||||||
|
@Range(from = 1, to = Long.MAX_VALUE) long periodTicks) {
|
||||||
|
Ref<Task> ref = new Ref<>();
|
||||||
|
return ref.value = new PaperTask(scheduler.runAtFixedRate(plugin, t -> task.accept(ref.value), initialDelayTicks, periodTicks), false);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
package com.volmit.iris.util.scheduling.paper.split;
|
||||||
|
|
||||||
|
import com.volmit.iris.util.scheduling.Ref;
|
||||||
|
import com.volmit.iris.util.scheduling.Task;
|
||||||
|
import com.volmit.iris.util.scheduling.Task.Completable;
|
||||||
|
import com.volmit.iris.util.scheduling.paper.PaperTask;
|
||||||
|
import com.volmit.iris.util.scheduling.split.IRegionScheduler;
|
||||||
|
import io.papermc.paper.threadedregions.scheduler.RegionScheduler;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Range;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class PaperRegionScheduler implements IRegionScheduler {
|
||||||
|
private final Plugin plugin;
|
||||||
|
private final RegionScheduler scheduler;
|
||||||
|
|
||||||
|
public PaperRegionScheduler(Plugin plugin, RegionScheduler scheduler) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.scheduler = scheduler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull <R> Completable<R> runDelayed(@NotNull World world,
|
||||||
|
int chunkX,
|
||||||
|
int chunkZ,
|
||||||
|
@NotNull Function<Completable<R>, R> task, @Range(from = 1, to = Long.MAX_VALUE) long delayTicks) {
|
||||||
|
Ref<Completable<R>> ref = new Ref<>();
|
||||||
|
return ref.value = new PaperTask.Completable<>(scheduler.runDelayed(plugin, world, chunkX, chunkZ, t -> ref.value.complete(task), delayTicks), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Task runAtFixedRate(@NotNull World world,
|
||||||
|
int chunkX,
|
||||||
|
int chunkZ,
|
||||||
|
@NotNull Consumer<Task> task,
|
||||||
|
@Range(from = 1, to = Long.MAX_VALUE) long initialDelayTicks,
|
||||||
|
@Range(from = 1, to = Long.MAX_VALUE) long periodTicks) {
|
||||||
|
Ref<Task> ref = new Ref<>();
|
||||||
|
return ref.value = new PaperTask(scheduler.runAtFixedRate(plugin, world, chunkX, chunkZ, t -> task.accept(ref.value), initialDelayTicks, periodTicks), false);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,105 @@
|
|||||||
|
package com.volmit.iris.util.scheduling.spigot;
|
||||||
|
|
||||||
|
import com.volmit.iris.util.scheduling.Platform;
|
||||||
|
import com.volmit.iris.util.scheduling.spigot.split.SpigotAsyncScheduler;
|
||||||
|
import com.volmit.iris.util.scheduling.spigot.split.SpigotEntityScheduler;
|
||||||
|
import com.volmit.iris.util.scheduling.spigot.split.SpigotGlobalScheduler;
|
||||||
|
import com.volmit.iris.util.scheduling.spigot.split.SpigotRegionScheduler;
|
||||||
|
import com.volmit.iris.util.scheduling.split.IAsyncScheduler;
|
||||||
|
import com.volmit.iris.util.scheduling.split.IEntityScheduler;
|
||||||
|
import com.volmit.iris.util.scheduling.split.IGlobalScheduler;
|
||||||
|
import com.volmit.iris.util.scheduling.split.IRegionScheduler;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Server;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.entity.Projectile;
|
||||||
|
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
public class SpigotPlatform implements Platform {
|
||||||
|
private final Server server;
|
||||||
|
private final IAsyncScheduler async;
|
||||||
|
private final IGlobalScheduler global;
|
||||||
|
private final IRegionScheduler region;
|
||||||
|
|
||||||
|
public SpigotPlatform(@NotNull Plugin plugin) {
|
||||||
|
server = plugin.getServer();
|
||||||
|
var scheduler = server.getScheduler();
|
||||||
|
async = new SpigotAsyncScheduler(plugin, scheduler);
|
||||||
|
global = new SpigotGlobalScheduler(plugin, scheduler);
|
||||||
|
region = new SpigotRegionScheduler(global);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOwnedByCurrentRegion(@NotNull Location location) {
|
||||||
|
return server.isPrimaryThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOwnedByCurrentRegion(@NotNull Location location, int squareRadiusChunks) {
|
||||||
|
return server.isPrimaryThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOwnedByCurrentRegion(@NotNull Block block) {
|
||||||
|
return server.isPrimaryThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOwnedByCurrentRegion(@NotNull World world, int chunkX, int chunkZ) {
|
||||||
|
return server.isPrimaryThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOwnedByCurrentRegion(@NotNull World world, int chunkX, int chunkZ, int squareRadiusChunks) {
|
||||||
|
return server.isPrimaryThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOwnedByCurrentRegion(@NotNull Entity entity) {
|
||||||
|
return server.isPrimaryThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isGlobalTickThread() {
|
||||||
|
return server.isPrimaryThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull IAsyncScheduler async() {
|
||||||
|
return async;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull IEntityScheduler entity(@NotNull Entity entity) {
|
||||||
|
return new SpigotEntityScheduler(global, entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull IGlobalScheduler global() {
|
||||||
|
return global;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull IRegionScheduler region() {
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull CompletableFuture<@NotNull Boolean> teleportAsync(@NotNull Entity entity, @NotNull Location location, PlayerTeleportEvent.@NotNull TeleportCause cause) {
|
||||||
|
return global().<Boolean>run(task -> isValid(entity) && entity.teleport(location)).result().thenApply(b -> b != null ? b : false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isValid(Entity entity) {
|
||||||
|
if (entity.isValid()) {
|
||||||
|
return !(entity instanceof Player) || ((Player) entity).isOnline();
|
||||||
|
}
|
||||||
|
return entity instanceof Projectile && !entity.isDead();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
package com.volmit.iris.util.scheduling.spigot;
|
||||||
|
|
||||||
|
import com.volmit.iris.util.scheduling.Task;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
import org.bukkit.scheduler.BukkitScheduler;
|
||||||
|
import org.bukkit.scheduler.BukkitTask;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
public class SpigotTask implements Task {
|
||||||
|
protected final BukkitTask task;
|
||||||
|
|
||||||
|
public SpigotTask(@NotNull BukkitTask task) {
|
||||||
|
this.task = task;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancel() {
|
||||||
|
task.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean cancelled() {
|
||||||
|
return task.isCancelled();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Plugin owner() {
|
||||||
|
return task.getOwner();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean async() {
|
||||||
|
return !task.isSync();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
public static class Completable<T> extends SpigotTask implements Task.Completable<T> {
|
||||||
|
private final CompletableFuture<T> result = new CompletableFuture<>();
|
||||||
|
private final BukkitScheduler scheduler;
|
||||||
|
|
||||||
|
public Completable(@NotNull BukkitTask task, @NotNull BukkitScheduler scheduler) {
|
||||||
|
super(task);
|
||||||
|
this.scheduler = scheduler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancel() {
|
||||||
|
scheduler.cancelTask(task.getTaskId());
|
||||||
|
if (scheduler.isCurrentlyRunning(task.getTaskId())) return;
|
||||||
|
result.cancel(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull CompletableFuture<T> result() {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
package com.volmit.iris.util.scheduling.spigot.split;
|
||||||
|
|
||||||
|
import com.volmit.iris.util.scheduling.Ref;
|
||||||
|
import com.volmit.iris.util.scheduling.Task;
|
||||||
|
import com.volmit.iris.util.scheduling.Task.Completable;
|
||||||
|
import com.volmit.iris.util.scheduling.spigot.SpigotTask;
|
||||||
|
import com.volmit.iris.util.scheduling.split.IAsyncScheduler;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
import org.bukkit.scheduler.BukkitScheduler;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Range;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
public class SpigotAsyncScheduler implements IAsyncScheduler {
|
||||||
|
private final Plugin plugin;
|
||||||
|
private final BukkitScheduler scheduler;
|
||||||
|
|
||||||
|
public SpigotAsyncScheduler(Plugin plugin, BukkitScheduler scheduler) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.scheduler = scheduler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull <R> Completable<R> run(@NotNull Function<Completable<R>, R> task) {
|
||||||
|
Ref<Completable<R>> ref = new Ref<>();
|
||||||
|
return ref.value = new SpigotTask.Completable<>(scheduler.runTaskAsynchronously(plugin, () -> ref.value.complete(task)), scheduler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull <R> Completable<R> runDelayed(@NotNull Function<Completable<R>, R> task, @Range(from = 0, to = Long.MAX_VALUE) long delay, @NotNull TimeUnit unit) {
|
||||||
|
Ref<Completable<R>> ref = new Ref<>();
|
||||||
|
return ref.value = new SpigotTask.Completable<>(scheduler.runTaskLaterAsynchronously(plugin, () -> ref.value.complete(task), unit.toMillis(delay) / 50), scheduler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Task runAtFixedRate(@NotNull Consumer<Task> task, @Range(from = 0, to = Long.MAX_VALUE) long initialDelay, @Range(from = 0, to = Long.MAX_VALUE) long period, @NotNull TimeUnit unit) {
|
||||||
|
Ref<Task> ref = new Ref<>();
|
||||||
|
return ref.value = new SpigotTask(scheduler.runTaskTimerAsynchronously(plugin, () -> task.accept(ref.value), unit.toMillis(initialDelay) / 50, unit.toMillis(period) / 50));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
package com.volmit.iris.util.scheduling.spigot.split;
|
||||||
|
|
||||||
|
import com.volmit.iris.util.scheduling.Task;
|
||||||
|
import com.volmit.iris.util.scheduling.Task.Completable;
|
||||||
|
import com.volmit.iris.util.scheduling.split.IEntityScheduler;
|
||||||
|
import com.volmit.iris.util.scheduling.split.IGlobalScheduler;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.annotations.Range;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import static com.volmit.iris.util.scheduling.spigot.SpigotPlatform.isValid;
|
||||||
|
|
||||||
|
public class SpigotEntityScheduler implements IEntityScheduler {
|
||||||
|
private final IGlobalScheduler scheduler;
|
||||||
|
private final Entity entity;
|
||||||
|
|
||||||
|
public SpigotEntityScheduler(IGlobalScheduler scheduler, Entity entity) {
|
||||||
|
this.scheduler = scheduler;
|
||||||
|
this.entity = entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable <R> Completable<R> runDelayed(@NotNull Function<Completable<R>, R> task, @Nullable Runnable retired, @Range(from = 1, to = Long.MAX_VALUE) long delayTicks) {
|
||||||
|
if (!isValid(entity)) return null;
|
||||||
|
return scheduler.runDelayed(t -> {
|
||||||
|
if (!isValid(entity)) {
|
||||||
|
t.cancel();
|
||||||
|
if (retired != null)
|
||||||
|
retired.run();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return task.apply(t);
|
||||||
|
}, delayTicks);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable Task runAtFixedRate(@NotNull Consumer<Task> task, @Nullable Runnable retired, @Range(from = 1, to = Long.MAX_VALUE) long initialDelayTicks, @Range(from = 1, to = Long.MAX_VALUE) long periodTicks) {
|
||||||
|
if (!isValid(entity)) return null;
|
||||||
|
return scheduler.runAtFixedRate(t -> {
|
||||||
|
if (!isValid(entity)) {
|
||||||
|
t.cancel();
|
||||||
|
if (retired != null)
|
||||||
|
retired.run();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
task.accept(t);
|
||||||
|
}, initialDelayTicks, periodTicks);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
package com.volmit.iris.util.scheduling.spigot.split;
|
||||||
|
|
||||||
|
import com.volmit.iris.util.scheduling.Ref;
|
||||||
|
import com.volmit.iris.util.scheduling.Task;
|
||||||
|
import com.volmit.iris.util.scheduling.Task.Completable;
|
||||||
|
import com.volmit.iris.util.scheduling.spigot.SpigotTask;
|
||||||
|
import com.volmit.iris.util.scheduling.split.IGlobalScheduler;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
import org.bukkit.scheduler.BukkitScheduler;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Range;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
public class SpigotGlobalScheduler implements IGlobalScheduler {
|
||||||
|
private final Plugin plugin;
|
||||||
|
private final BukkitScheduler scheduler;
|
||||||
|
|
||||||
|
public SpigotGlobalScheduler(Plugin plugin, BukkitScheduler scheduler) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.scheduler = scheduler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull <R> Completable<R> runDelayed(@NotNull Function<Completable<R>, R> task, @Range(from = 1, to = Long.MAX_VALUE) long delayTicks) {
|
||||||
|
Ref<Completable<R>> ref = new Ref<>();
|
||||||
|
return ref.value = new SpigotTask.Completable<>(scheduler.runTaskLater(plugin, () -> ref.value.complete(task), delayTicks), scheduler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Task runAtFixedRate(@NotNull Consumer<Task> task, @Range(from = 1, to = Long.MAX_VALUE) long initialDelayTicks, @Range(from = 1, to = Long.MAX_VALUE) long periodTicks) {
|
||||||
|
Ref<Task> ref = new Ref<>();
|
||||||
|
return ref.value = new SpigotTask(scheduler.runTaskTimer(plugin, () -> task.accept(ref.value), initialDelayTicks, periodTicks));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package com.volmit.iris.util.scheduling.spigot.split;
|
||||||
|
|
||||||
|
import com.volmit.iris.util.scheduling.Task;
|
||||||
|
import com.volmit.iris.util.scheduling.Task.Completable;
|
||||||
|
import com.volmit.iris.util.scheduling.split.IGlobalScheduler;
|
||||||
|
import com.volmit.iris.util.scheduling.split.IRegionScheduler;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Range;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class SpigotRegionScheduler implements IRegionScheduler {
|
||||||
|
private final IGlobalScheduler scheduler;
|
||||||
|
|
||||||
|
public SpigotRegionScheduler(IGlobalScheduler scheduler) {
|
||||||
|
this.scheduler = scheduler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull <R> Completable<R> runDelayed(@NotNull World world, int chunkX, int chunkZ, @NotNull Function<Completable<R>, R> task, @Range(from = 1, to = Long.MAX_VALUE) long delayTicks) {
|
||||||
|
return scheduler.runDelayed(task, delayTicks);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Task runAtFixedRate(@NotNull World world, int chunkX, int chunkZ, @NotNull Consumer<Task> task, @Range(from = 1, to = Long.MAX_VALUE) long initialDelayTicks, @Range(from = 1, to = Long.MAX_VALUE) long periodTicks) {
|
||||||
|
return scheduler.runAtFixedRate(task, initialDelayTicks, periodTicks);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
package com.volmit.iris.util.scheduling.split;
|
||||||
|
|
||||||
|
import com.volmit.iris.util.scheduling.Task;
|
||||||
|
import com.volmit.iris.util.scheduling.Task.Completable;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Range;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scheduler that may be used by plugins to schedule tasks to execute asynchronously from the server tick process.
|
||||||
|
*/
|
||||||
|
public interface IAsyncScheduler {
|
||||||
|
/**
|
||||||
|
* Schedules the specified task to be executed asynchronously immediately.
|
||||||
|
* @param task Specified task.
|
||||||
|
* @return The {@link Task} that represents the scheduled task.
|
||||||
|
*/
|
||||||
|
default @NotNull Task run(@NotNull Consumer<Task> task) {
|
||||||
|
return run(t -> {
|
||||||
|
task.accept(t);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules the specified task to be executed asynchronously immediately.
|
||||||
|
* @param task Specified task.
|
||||||
|
* @return The {@link Completable} that represents the scheduled task.
|
||||||
|
*/
|
||||||
|
@NotNull <R> Completable<R> run(@NotNull Function<Completable<R>, R> task);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules the specified task to be executed asynchronously after the time delay has passed.
|
||||||
|
* @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 Task} that represents the scheduled task.
|
||||||
|
*/
|
||||||
|
default @NotNull Task runDelayed(@NotNull Consumer<Task> task,
|
||||||
|
@Range(from = 0, to = Long.MAX_VALUE) long delay,
|
||||||
|
@NotNull TimeUnit unit) {
|
||||||
|
return runDelayed(t -> {
|
||||||
|
task.accept(t);
|
||||||
|
return null;
|
||||||
|
}, delay, unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules the specified task to be executed asynchronously after the time delay has passed.
|
||||||
|
* @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 Completable} that represents the scheduled task.
|
||||||
|
*/
|
||||||
|
@NotNull <R> Completable<R> runDelayed(@NotNull Function<Completable<R>, R> task,
|
||||||
|
@Range(from = 0, to = Long.MAX_VALUE) long delay,
|
||||||
|
@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 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 Task} that represents the scheduled task.
|
||||||
|
*/
|
||||||
|
@NotNull Task runAtFixedRate(@NotNull Consumer<Task> task,
|
||||||
|
@Range(from = 0, to = Long.MAX_VALUE) long initialDelay,
|
||||||
|
@Range(from = 0, to = Long.MAX_VALUE) long period,
|
||||||
|
@NotNull TimeUnit unit);
|
||||||
|
}
|
@ -0,0 +1,136 @@
|
|||||||
|
package com.volmit.iris.util.scheduling.split;
|
||||||
|
|
||||||
|
import com.volmit.iris.util.scheduling.Task;
|
||||||
|
import com.volmit.iris.util.scheduling.Task.Completable;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.annotations.Range;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 IEntityScheduler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 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 Task} that represents the scheduled task, or {@code null} if the entity has been removed.
|
||||||
|
*/
|
||||||
|
default @Nullable Task run(@NotNull Consumer<Task> task,
|
||||||
|
@Nullable Runnable retired) {
|
||||||
|
return run(t -> {
|
||||||
|
task.accept(t);
|
||||||
|
return null;
|
||||||
|
}, retired);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 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 Completable} that represents the scheduled task, or {@code null} if the entity has been removed.
|
||||||
|
*/
|
||||||
|
default @Nullable <R> Completable<R> run(@NotNull Function<Completable<R>, R> task,
|
||||||
|
@Nullable Runnable retired) {
|
||||||
|
return runDelayed(task, retired, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 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 Task} that represents the scheduled task, or {@code null} if the entity has been removed.
|
||||||
|
*/
|
||||||
|
default @Nullable Task runDelayed(@NotNull Consumer<Task> task,
|
||||||
|
@Nullable Runnable retired,
|
||||||
|
@Range(from = 1, to = Long.MAX_VALUE) long delayTicks) {
|
||||||
|
return runDelayed(t -> {
|
||||||
|
task.accept(t);
|
||||||
|
return null;
|
||||||
|
}, retired, delayTicks);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 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 Completable} that represents the scheduled task, or {@code null} if the entity has been removed.
|
||||||
|
*/
|
||||||
|
@Nullable <R> Completable<R> runDelayed(@NotNull Function<Completable<R>, R> task,
|
||||||
|
@Nullable Runnable retired,
|
||||||
|
@Range(from = 1, to = Long.MAX_VALUE) long delayTicks);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 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 Task} that represents the scheduled task, or {@code null} if the entity has been removed.
|
||||||
|
*/
|
||||||
|
@Nullable Task runAtFixedRate(@NotNull Consumer<Task> task,
|
||||||
|
@Nullable Runnable retired,
|
||||||
|
@Range(from = 1, to = Long.MAX_VALUE) long initialDelayTicks,
|
||||||
|
@Range(from = 1, to = Long.MAX_VALUE) long periodTicks);
|
||||||
|
}
|
@ -0,0 +1,74 @@
|
|||||||
|
package com.volmit.iris.util.scheduling.split;
|
||||||
|
|
||||||
|
import com.volmit.iris.util.scheduling.Task;
|
||||||
|
import com.volmit.iris.util.scheduling.Task.Completable;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Range;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 IGlobalScheduler {
|
||||||
|
/**
|
||||||
|
* Schedules a task to be executed on the global region on the next tick.
|
||||||
|
* @param task The task to execute
|
||||||
|
* @return The {@link Task} that represents the scheduled task.
|
||||||
|
*/
|
||||||
|
default @NotNull Task run(@NotNull Consumer<Task> task) {
|
||||||
|
return run(t -> {
|
||||||
|
task.accept(t);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules a task to be executed on the global region on the next tick.
|
||||||
|
* @param task The task to execute
|
||||||
|
* @return The {@link Completable} that represents the scheduled task.
|
||||||
|
*/
|
||||||
|
default @NotNull <R> Completable<R> run(@NotNull Function<Completable<R>, R> task) {
|
||||||
|
return runDelayed(task, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules a task to be executed on the global region after the specified delay in ticks.
|
||||||
|
* @param task The task to execute
|
||||||
|
* @param delayTicks The delay, in ticks.
|
||||||
|
* @return The {@link Task} that represents the scheduled task.
|
||||||
|
*/
|
||||||
|
default @NotNull Task runDelayed(@NotNull Consumer<Task> task,
|
||||||
|
@Range(from = 1, to = Long.MAX_VALUE) long delayTicks) {
|
||||||
|
return runDelayed(t -> {
|
||||||
|
task.accept(t);
|
||||||
|
return null;
|
||||||
|
}, delayTicks);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules a task to be executed on the global region after the specified delay in ticks.
|
||||||
|
* @param task The task to execute
|
||||||
|
* @param delayTicks The delay, in ticks.
|
||||||
|
* @return The {@link Completable} that represents the scheduled task.
|
||||||
|
*/
|
||||||
|
@NotNull <R> Completable<R> runDelayed(@NotNull Function<Completable<R>, R> task,
|
||||||
|
@Range(from = 1, to = Long.MAX_VALUE) long delayTicks);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules a repeating task to be executed on the global region after the initial delay with the
|
||||||
|
* specified period.
|
||||||
|
* @param task The task to execute
|
||||||
|
* @param initialDelayTicks The initial delay, in ticks.
|
||||||
|
* @param periodTicks The period, in ticks.
|
||||||
|
* @return The {@link Task} that represents the scheduled task.
|
||||||
|
*/
|
||||||
|
@NotNull Task runAtFixedRate(@NotNull Consumer<Task> task,
|
||||||
|
@Range(from = 1, to = Long.MAX_VALUE) long initialDelayTicks,
|
||||||
|
@Range(from = 1, to = Long.MAX_VALUE) long periodTicks);
|
||||||
|
}
|
@ -0,0 +1,182 @@
|
|||||||
|
package com.volmit.iris.util.scheduling.split;
|
||||||
|
|
||||||
|
import com.volmit.iris.util.scheduling.Task;
|
||||||
|
import com.volmit.iris.util.scheduling.Task.Completable;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Range;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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>
|
||||||
|
*/
|
||||||
|
public interface IRegionScheduler {
|
||||||
|
/**
|
||||||
|
* Schedules a task to be executed on the region which owns the location on the next tick.
|
||||||
|
*
|
||||||
|
* @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 Task} that represents the scheduled task.
|
||||||
|
*/
|
||||||
|
default @NotNull Task run(@NotNull World world,
|
||||||
|
int chunkX,
|
||||||
|
int chunkZ,
|
||||||
|
@NotNull Consumer<Task> task) {
|
||||||
|
return run(world, chunkX, chunkZ, t -> {
|
||||||
|
task.accept(t);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules a task to be executed on the region which owns the location on the next tick.
|
||||||
|
*
|
||||||
|
* @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 Completable} that represents the scheduled task.
|
||||||
|
*/
|
||||||
|
default @NotNull <R> Completable<R> run(@NotNull World world,
|
||||||
|
int chunkX,
|
||||||
|
int chunkZ,
|
||||||
|
@NotNull Function<Completable<R>, R> task) {
|
||||||
|
return runDelayed(world, chunkX, chunkZ, task, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules a task to be executed on the region which owns the location on the next tick.
|
||||||
|
*
|
||||||
|
* @param location The location at which the region executing should own
|
||||||
|
* @param task The task to execute
|
||||||
|
* @return The {@link Task} that represents the scheduled task.
|
||||||
|
*/
|
||||||
|
default @NotNull Task run(@NotNull Location location,
|
||||||
|
@NotNull Consumer<Task> task) {
|
||||||
|
return run(location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4, task);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules a task to be executed on the region which owns the location on the next tick.
|
||||||
|
*
|
||||||
|
* @param location The location at which the region executing should own
|
||||||
|
* @param task The task to execute
|
||||||
|
* @return The {@link Completable} that represents the scheduled task.
|
||||||
|
*/
|
||||||
|
default @NotNull <R> Completable<R> run(@NotNull Location location,
|
||||||
|
@NotNull Function<Completable<R>, R> task) {
|
||||||
|
return run(location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4, task);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules a task to be executed on the region which owns the location after the specified delay in ticks.
|
||||||
|
*
|
||||||
|
* @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 Task} that represents the scheduled task.
|
||||||
|
*/
|
||||||
|
default @NotNull Task runDelayed(@NotNull World world,
|
||||||
|
int chunkX,
|
||||||
|
int chunkZ,
|
||||||
|
@NotNull Consumer<Task> task,
|
||||||
|
@Range(from = 1, to = Long.MAX_VALUE) long delayTicks) {
|
||||||
|
return runDelayed(world, chunkX, chunkZ, t -> {
|
||||||
|
task.accept(t);
|
||||||
|
return null;
|
||||||
|
}, delayTicks);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules a task to be executed on the region which owns the location after the specified delay in ticks.
|
||||||
|
*
|
||||||
|
* @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 Completable} that represents the scheduled task.
|
||||||
|
*/
|
||||||
|
@NotNull <R> Completable<R> runDelayed(@NotNull World world,
|
||||||
|
int chunkX,
|
||||||
|
int chunkZ,
|
||||||
|
@NotNull Function<Completable<R>, R> task,
|
||||||
|
@Range(from = 1, to = Long.MAX_VALUE) long delayTicks);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules a task to be executed on the region which owns the location after the specified delay in ticks.
|
||||||
|
*
|
||||||
|
* @param location The location at which the region executing should own
|
||||||
|
* @param task The task to execute
|
||||||
|
* @param delayTicks The delay, in ticks.
|
||||||
|
* @return The {@link Task} that represents the scheduled task.
|
||||||
|
*/
|
||||||
|
default @NotNull Task runDelayed(@NotNull Location location,
|
||||||
|
@NotNull Consumer<Task> task,
|
||||||
|
@Range(from = 1, to = Long.MAX_VALUE) long delayTicks) {
|
||||||
|
return runDelayed(location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4, task, delayTicks);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Schedules a task to be executed on the region which owns the location after the specified delay in ticks.
|
||||||
|
*
|
||||||
|
* @param location The location at which the region executing should own
|
||||||
|
* @param task The task to execute
|
||||||
|
* @param delayTicks The delay, in ticks.
|
||||||
|
* @return The {@link Completable} that represents the scheduled task.
|
||||||
|
*/
|
||||||
|
default @NotNull <R> Completable<R> runDelayed(@NotNull Location location,
|
||||||
|
@NotNull Function<Completable<R>, R> task,
|
||||||
|
@Range(from = 1, to = Long.MAX_VALUE) long delayTicks) {
|
||||||
|
return runDelayed(location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4, task, delayTicks);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules a repeating task to be executed on the region which owns the location after the initial delay with the
|
||||||
|
* specified period.
|
||||||
|
*
|
||||||
|
* @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 initialDelayTicks The initial delay, in ticks.
|
||||||
|
* @param periodTicks The period, in ticks.
|
||||||
|
* @return The {@link Task} that represents the scheduled task.
|
||||||
|
*/
|
||||||
|
@NotNull Task runAtFixedRate(@NotNull World world,
|
||||||
|
int chunkX,
|
||||||
|
int chunkZ,
|
||||||
|
@NotNull Consumer<Task> task,
|
||||||
|
@Range(from = 1, to = Long.MAX_VALUE) long initialDelayTicks,
|
||||||
|
@Range(from = 1, to = Long.MAX_VALUE) long periodTicks);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules a repeating task to be executed on the region which owns the location after the initial delay with the
|
||||||
|
* specified period.
|
||||||
|
*
|
||||||
|
* @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 Task} that represents the scheduled task.
|
||||||
|
*/
|
||||||
|
default @NotNull Task runAtFixedRate(@NotNull Location location,
|
||||||
|
@NotNull Consumer<Task> task,
|
||||||
|
@Range(from = 1, to = Long.MAX_VALUE) long initialDelayTicks,
|
||||||
|
@Range(from = 1, to = Long.MAX_VALUE) long periodTicks) {
|
||||||
|
return runAtFixedRate(location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4, task, initialDelayTicks, periodTicks);
|
||||||
|
}
|
||||||
|
}
|
@ -39,3 +39,4 @@ include(
|
|||||||
":nms:v1_20_R2",
|
":nms:v1_20_R2",
|
||||||
":nms:v1_20_R1",
|
":nms:v1_20_R1",
|
||||||
)
|
)
|
||||||
|
include("scheduler")
|
Loading…
x
Reference in New Issue
Block a user