Scheduler
SwiftlyS2 provides a scheduler service for main-thread dispatching and timer-based execution.
Accessing Scheduler Service
Scheduler APIs are available through Core.Scheduler.
public override void Load(bool hotReload)
{
var scheduler = Core.Scheduler;
}Scheduling on the Main Loop
Next Tick
Use NextTick(Action) to run a callback on the next server tick.
Core.Scheduler.NextTick(() =>
{
Console.WriteLine("Runs on next tick.");
});Next World Update
Use NextWorldUpdate(Action) to run a callback on the next world update phase.
Core.Scheduler.NextWorldUpdate(() =>
{
Console.WriteLine("Runs on next world update.");
});Awaitable Variants
You can await scheduler execution using the non-async callback overloads:
await Core.Scheduler.NextTickAsync(() =>
{
Console.WriteLine("Executed in next tick, awaited.");
});
int computedValue = await Core.Scheduler.NextWorldUpdateAsync(() =>
{
return 42;
});Do not pass async callbacks (Func<Task...>) to NextTick or NextWorldUpdate families. Those overloads are obsolete and documented as unsafe.
Timer APIs
Tick-Based Timers
Tick-based APIs use game ticks as units.
var delayCts = Core.Scheduler.Delay(128, () =>
{
Console.WriteLine("Executed once after 128 ticks.");
});
var repeatCts = Core.Scheduler.Repeat(64, () =>
{
Console.WriteLine("Runs immediately, then every 64 ticks.");
});
var delayRepeatCts = Core.Scheduler.DelayAndRepeat(32, 64, () =>
{
Console.WriteLine("Starts after 32 ticks, then repeats every 64 ticks.");
});Second-Based Timers
Use second-based APIs for easier human-readable intervals.
Core.Scheduler.DelayBySeconds(2.0f, () =>
{
Console.WriteLine("Executed after 2 seconds.");
});
Core.Scheduler.RepeatBySeconds(1.0f, () =>
{
Console.WriteLine("Runs immediately, then every 1 second.");
});
Core.Scheduler.DelayAndRepeatBySeconds(3.0f, 1.5f, () =>
{
Console.WriteLine("Starts after 3 seconds, then repeats every 1.5 seconds.");
});Second-based timers are still driven by game ticks, so very small intervals approach tick precision limits (about 15 ms).
Canceling Timers
All timer creation methods return CancellationTokenSource.
var token = Core.Scheduler.Repeat(64, () => Console.WriteLine("Tick"));
// Manual cancel
token.Cancel();
// Auto-cancel on map change
Core.Scheduler.StopOnMapChange(token);Advanced Timers with AddTimer
Use AddTimer(Func<ITimerContext, TimerStep>) when you need dynamic behavior per execution.
var cts = Core.Scheduler.AddTimer(ctx =>
{
Console.WriteLine($"Run #{ctx.ExecutionCount}");
if (ctx.ExecutionCount >= 4)
{
return TimerStep.Stop();
}
return TimerStep.WaitForSeconds(1.0f);
});ITimerContext.ExecutionCount starts at 0 for the first run.
Common TimerStep helpers:
TimerStep.Spin()to run again on next tickTimerStep.WaitForTicks(long ticks)TimerStep.WaitForMilliseconds(long milliseconds)TimerStep.WaitForSeconds(float seconds)TimerStep.Stop()
Reference
See ISchedulerService for scheduler methods.
See ITimerContext and TimerStep for advanced timer flow.