Skip to main content

Scheduler

Package: dev.anchorlight.stonelib.scheduler

SchedulerService wraps the Bukkit scheduler with two additions: it remembers every task it creates, so cancelAll() in onDisable stops them all, and supplyAsync runs slow work off the main thread and hands the result back on it.

API

MethodRuns onMeaning
new SchedulerService(Plugin)
runSync(Runnable)mainNext tick.
runSyncLater(Runnable, long delayTicks)mainAfter a delay.
runTimer(Runnable, long delayTicks, long periodTicks)mainRepeating.
runAsync(Runnable)asyncAs soon as possible.
runAsyncLater(Runnable, long delayTicks)asyncAfter a delay.
runAsyncTimer(Runnable, long delayTicks, long periodTicks)asyncRepeating.
supplyAsync(Supplier<T>, Consumer<T>)async, then mainComputes a value off-thread, then passes it to the callback on the main thread.
track(BukkitTask)Adds a task created elsewhere, so cancelAll covers it. Returns the same task.
trackedCount()How many tasks are tracked.
cancelAll()Cancels every tracked task and forgets them. Safe to call more than once.

Every run method returns the BukkitTask, so you can still cancel a single task yourself. There are 20 ticks in a second; Durations.toTicks converts a Duration.

Example

@Override
public void onEnable() {
scheduler = new SchedulerService(this);

scheduler.runTimer(this::tickArenas, 20L, 20L); // every second
scheduler.runAsyncTimer(repository::save, 6000L, 6000L); // autosave every five minutes

getServer().getPluginManager().registerEvents(new Listener() {
@EventHandler
public void onJoin(PlayerJoinEvent event) {
Player player = event.getPlayer();
scheduler.supplyAsync(
() -> repository.reload(player.getUniqueId()),
profile -> {
if (player.isOnline() && profile != null) {
player.setLevel(profile.level());
}
});
}
}, this);
}

@Override
public void onDisable() {
scheduler.cancelAll();
}

Check player.isOnline() in a callback, as above. The player can leave while the async part is running.

Behaviour to know about

  • supplyAsync has no error path. If the supplier throws, the callback never runs, and Paper logs the exception as a failed task. Catch exceptions inside the supplier and return something the callback can act on, such as null or an Optional.
  • Tasks are only forgotten by cancelAll. A one-shot task that has finished, or a task you cancelled yourself, stays in the tracked set until then. That is harmless, but it means trackedCount counts every task created since the last cancelAll, not only the live ones.
  • A plugin's tasks are cancelled on disable anyway. Paper cancels them when a plugin disables. cancelAll still matters for reload commands that restart timers, and for stopping repeating tasks before you flush data in onDisable, so a timer cannot fire half-way through shutdown.
  • No Folia support. This wraps the classic Bukkit scheduler, which Folia does not provide.