Version: 1.0.3
Package: fr.hytale.loader.scheduler
The Scheduler API provides task scheduling and execution capabilities for HytaleLoader plugins.
The Scheduler allows you to:
- Execute tasks immediately or after a delay
- Run repeating tasks at fixed intervals
- Execute tasks asynchronously (non-blocking)
- Cancel scheduled tasks
- Monitor task status
Main scheduler class for executing tasks.
public class MyPlugin extends SimplePlugin {
@Override
public void onEnable() {
Scheduler scheduler = getScheduler();
}
}Executes a task immediately on the next available thread.
getScheduler().runTask(() -> {
// Task code here
player.sendMessage("Hello!");
});Returns: ScheduledTask
Executes a task after a specified delay.
getScheduler().runTaskLater(() -> {
player.sendMessage("5 seconds have passed!");
}, 5000); // 5 secondsParameters:
task- The task to executedelayMillis- Delay in milliseconds
Returns: ScheduledTask
Executes a task repeatedly with a fixed delay between executions.
ScheduledTask task = getScheduler().runTaskTimer(() -> {
player.sendMessage("Tick!");
}, 0, 1000); // Every second, starting immediatelyParameters:
task- The task to executeinitialDelayMillis- Delay before first executionperiodMillis- Period between successive executions
Returns: ScheduledTask
Executes a task asynchronously on a separate thread pool.
getScheduler().runTaskAsync(() -> {
// Long-running task
String data = fetchFromDatabase();
// Switch back to sync for game modifications
getScheduler().runTask(() -> {
player.sendMessage("Data: " + data);
});
});Returns: CompletableFuture<Void>
Executes a task asynchronously and returns a result.
CompletableFuture<Integer> future = getScheduler().runTaskAsync(() -> {
// Compute something
return calculateScore(player);
});
future.thenAccept(score -> {
getScheduler().runTask(() -> {
player.sendMessage("Your score: " + score);
});
});Returns: CompletableFuture<T>
Wrapper for scheduled tasks with control methods.
Cancels the task. Returns true if successfully cancelled.
ScheduledTask task = getScheduler().runTaskTimer(() -> {
// Repeating task
}, 0, 1000);
// Cancel after 10 seconds
getScheduler().runTaskLater(task::cancel, 10000);Cancels the task and attempts to interrupt if running.
Checks if the task was cancelled.
Checks if the task has completed.
Checks if the task is still running or scheduled.
public class CountdownCommand extends SimpleCommand {
@Command(name = "countdown")
public void onCountdown(CommandContext ctx) {
Player player = CommandUtils.requirePlayer(ctx);
AtomicInteger counter = new AtomicInteger(5);
ScheduledTask task = getScheduler().runTaskTimer(() -> {
int count = counter.getAndDecrement();
if (count <= 0) {
player.sendMessage("§aGo!");
task.cancel();
} else {
player.sendMessage("§e" + count + "...");
}
}, 0, 1000); // Every second
}
}@EventHandler
public void onJoin(PlayerJoinEvent event) {
Player player = event.getPlayer();
// Async database query (non-blocking)
getScheduler().runTaskAsync(() -> {
PlayerData data = database.loadPlayer(player.getUUID());
// Switch back to sync thread for game modifications
getScheduler().runTask(() -> {
player.sendMessage("Welcome back! Level: " + data.getLevel());
// Apply permissions from database
data.getPermissions().forEach(player::addPermission);
});
});
}public void teleportWithDelay(Player player, Location target) {
player.sendMessage("§eTeleporting in 3 seconds...");
player.sendMessage("§cDon't move!");
Location startLoc = player.getLocation();
getScheduler().runTaskLater(() -> {
// Check if player moved
if (player.getLocation().equals(startLoc)) {
player.teleport(target);
player.sendMessage("§aTeleported!");
} else {
player.sendMessage("§cTeleport cancelled - you moved!");
}
}, 3000); // 3 seconds
}public void startParticleEffect(Player player, int durationSeconds) {
AtomicInteger timeLeft = new AtomicInteger(durationSeconds);
ScheduledTask task = getScheduler().runTaskTimer(() -> {
if (timeLeft.getAndDecrement() <= 0) {
task.cancel();
return;
}
// Spawn particles around player
spawnParticles(player.getLocation());
}, 0, 50); // Every 50ms (20 times per second)
}- Use async for I/O operations (file, network, database)
- Cancel repeating tasks when no longer needed
- Use
runTask()to switch back from async to sync - Keep task code short and focused
- Don't modify game state directly from async tasks
- Don't create infinite loops in repeating tasks
- Don't forget to cancel tasks on plugin disable (handled automatically)
- Don't use Thread.sleep() - use delay instead
- Scheduler operations are thread-safe
- Async tasks run on separate thread pool
- Always use
runTask()to modify game state from async context - Scheduler automatically shuts down when plugin is disabled
- Default thread pools: 4 scheduled threads, 8 async threads
- Daemon threads auto-cleanup on JVM shutdown
ScheduledExecutorServicefor precise timing- Thread-safe task management