package com.loohp.limbo.Scheduler; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import com.loohp.limbo.Limbo; import com.loohp.limbo.Plugins.LimboPlugin; public class LimboScheduler { private AtomicInteger idProvider = new AtomicInteger(0); private Map> registeredTasks = new HashMap<>(); private Map tasksById = new HashMap<>(); private Set cancelledTasks = new HashSet<>(); public LimboScheduler() { } protected int nextId() { return idProvider.getAndUpdate(id -> id >= Integer.MAX_VALUE ? 0 : id + 1); } public void cancelTask(int taskId) { if (tasksById.containsKey(taskId)) { cancelledTasks.add(taskId); } } public void cancelTask(LimboPlugin plugin) { for (LimboSchedulerTask task : tasksById.values()) { if (task.getPlugin().getName().equals(plugin.getName())) { cancelledTasks.add(task.getTaskId()); } } } protected int runTask(int taskId, LimboPlugin plugin, LimboTask task) { return runTaskLater(taskId, plugin, task, 0); } public int runTask(LimboPlugin plugin, LimboTask task) { return runTaskLater(plugin, task, 0); } protected int runTaskLater(int taskId, LimboPlugin plugin, LimboTask task, long delay) { LimboSchedulerTask st = new LimboSchedulerTask(plugin, task, taskId, LimboSchedulerTaskType.SYNC, 0); if (delay <= 0) { delay = 1; } long tick = Limbo.getInstance().getHeartBeat().getCurrentTick() + delay; tasksById.put(taskId, st); List list = registeredTasks.get(tick); if (list == null) { list = new ArrayList<>(); registeredTasks.put(tick, list); } list.add(st); return taskId; } public int runTaskLater(LimboPlugin plugin, LimboTask task, long delay) { return runTaskLater(nextId(), plugin, task, delay); } protected int runTaskAsync(int taskId, LimboPlugin plugin, LimboTask task) { return runTaskLaterAsync(taskId, plugin, task, 0); } public int runTaskAsync(LimboPlugin plugin, LimboTask task) { return runTaskLaterAsync(plugin, task, 0); } protected int runTaskLaterAsync(int taskId, LimboPlugin plugin, LimboTask task, long delay) { LimboSchedulerTask st = new LimboSchedulerTask(plugin, task, taskId, LimboSchedulerTaskType.ASYNC, 0); if (delay <= 0) { delay = 1; } long tick = Limbo.getInstance().getHeartBeat().getCurrentTick() + delay; tasksById.put(taskId, st); List list = registeredTasks.get(tick); if (list == null) { list = new ArrayList<>(); registeredTasks.put(tick, list); } list.add(st); return taskId; } public int runTaskLaterAsync(LimboPlugin plugin, LimboTask task, long delay) { return runTaskLaterAsync(nextId(), plugin, task, delay); } protected int runTaskTimer(int taskId, LimboPlugin plugin, LimboTask task, long delay, long period) { LimboSchedulerTask st = new LimboSchedulerTask(plugin, task, taskId, LimboSchedulerTaskType.TIMER_SYNC, period); if (delay <= 0) { delay = 1; } if (period <= 0) { period = 1; } long tick = Limbo.getInstance().getHeartBeat().getCurrentTick() + delay; tasksById.put(taskId, st); List list = registeredTasks.get(tick); if (list == null) { list = new ArrayList<>(); registeredTasks.put(tick, list); } list.add(st); return taskId; } public int runTaskTimer(LimboPlugin plugin, LimboTask task, long delay, long period) { return runTaskTimer(nextId(), plugin, task, delay, period); } protected int runTaskTimerAsync(int taskId, LimboPlugin plugin, LimboTask task, long delay, long period) { LimboSchedulerTask st = new LimboSchedulerTask(plugin, task, taskId, LimboSchedulerTaskType.TIMER_ASYNC, period); if (delay <= 0) { delay = 1; } if (period <= 0) { period = 1; } long tick = Limbo.getInstance().getHeartBeat().getCurrentTick() + delay; tasksById.put(taskId, st); List list = registeredTasks.get(tick); if (list == null) { list = new ArrayList<>(); registeredTasks.put(tick, list); } list.add(st); return taskId; } public int runTaskTimerAsync(LimboPlugin plugin, LimboTask task, long delay, long period) { return runTaskTimerAsync(nextId(), plugin, task, delay, period); } protected CurrentSchedulerTask collectTasks(long currentTick) { List tasks = registeredTasks.remove(currentTick); if (tasks == null) { return null; } List asyncTasks = new LinkedList<>(); List syncedTasks = new LinkedList<>(); for (LimboSchedulerTask task : tasks) { int taskId = task.getTaskId(); if (cancelledTasks.contains(taskId)) { cancelledTasks.remove(taskId); continue; } switch (task.getType()) { case ASYNC: asyncTasks.add(task); break; case SYNC: syncedTasks.add(task); break; case TIMER_ASYNC: asyncTasks.add(task); runTaskTimerAsync(task.getTaskId(), task.getPlugin(), task.getTask(), task.getPeriod(), task.getPeriod()); break; case TIMER_SYNC: syncedTasks.add(task); runTaskTimer(task.getTaskId(), task.getPlugin(), task.getTask(), task.getPeriod(), task.getPeriod()); break; } } return new CurrentSchedulerTask(syncedTasks, asyncTasks); } public static class CurrentSchedulerTask { private List asyncTasks; private List syncedTasks; public CurrentSchedulerTask(List syncedTasks, List asyncTasks) { this.asyncTasks = asyncTasks; this.syncedTasks = syncedTasks; } public List getAsyncTasks() { return asyncTasks; } public List getSyncedTasks() { return syncedTasks; } } public static class LimboSchedulerTask { private int taskId; private LimboPlugin plugin; private LimboTask task; private LimboSchedulerTaskType type; private long period; private LimboSchedulerTask(LimboPlugin plugin, LimboTask task, int taskId, LimboSchedulerTaskType type, long period) { this.plugin = plugin; this.task = task; this.taskId = taskId; this.type = type; this.period = period; } public LimboPlugin getPlugin() { return plugin; } public LimboTask getTask() { return task; } public int getTaskId() { return taskId; } public LimboSchedulerTaskType getType() { return type; } public long getPeriod() { return period; } } public static enum LimboSchedulerTaskType { SYNC, ASYNC, TIMER_SYNC, TIMER_ASYNC; } }