public final class Scheduler
{
private static Scheduler server;
private static Scheduler client;
/**
* <p>Return a Scheduler that executes tasks on the main server thread.</p>
* @return a Scheduler
*/
public static Scheduler server(){
return server;
}
/**
* <p>The Scheduler that executes tasks on the main client thread. On a dedicated server this method will return null.</p>
* @return a Scheduler or null
*/
public static Scheduler client(){
return client;
}
/**
* <p>Return {@link #client()} if {@code side} is {@code Side.CLIENT}, {@link #server()} otherwise.</p>
* @param side the side
* @return a Scheduler for the side
*/
public static Scheduler forSide(Side side){
return side.isClient() ? client : server;
}
public void execute(Runnable task){
schedule(task, 0);
}
/**
* <p>Execute the given task after {@code tickDelay} ticks have passed.</p>
* @param task the task
* @param tickDelay the delay, in ticks
*/
public void schedule(Runnable task, long tickDelay){
checkArgument(tickDelay >= 0);
synchronized(ticker.queue)
{
ticker.queue.add(new Task(task, tickDelay + 1));
}
}
static{
if(FMLCommonHandler.instance().getSide().isClient()){
client = new Scheduler(Side.CLIENT);
TickRegistry.registerTickHandler(client.ticker, Side.CLIENT);
//MinecraftForge.EVENT_BUS.register(client.ticker);
}else{
client = null;
}
server = new Scheduler(Side.SERVER);
TickRegistry.registerTickHandler(server.ticker, Side.SERVER);
//MinecraftForge.EVENT_BUS.register(server.ticker);
}
private final Ticker ticker;
private Scheduler(Side side){
ticker = new Ticker(side);
}
private static class Task{
public final Runnable runnable;
public long ticks;
public Task(Runnable taskRunnable, long taskTicks){
runnable = taskRunnable;
ticks = taskTicks;
}
}
private static class Ticker implements ITickHandler
{
private final List<Task> queue = new ArrayList<Task>();
private final List<Task> scheduledNow = new ArrayList<Task>();
private final EnumSet<TickType> tickTypes;
public Ticker(Side side) {
tickTypes = EnumSet.of(side.isClient() ? TickType.CLIENT : TickType.SERVER);
}
@Override
public void tickStart(EnumSet<TickType> type, Object... tickData)
{
synchronized (queue) {
int idx = queue.size();
while (--idx >= 0) {
Task task = queue.get(idx);
if (--task.ticks == 0) {
queue.remove(idx);
scheduledNow.add(task);
}
}
}
int idx = scheduledNow.size();
while (--idx >= 0) {
scheduledNow.remove(idx).runnable.run();
}
}
@Override
public void tickEnd(EnumSet<TickType> type, Object... tickData) { }
@Override
public EnumSet<TickType> ticks() {
return tickTypes;
}
@Override
public String getLabel() {
return "SC|Scheduler";
}
}
}