forked from BLOCKFANTASY/LOOHP-Limbo
reupload
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
package com.loohp.limbo.scheduler;
|
||||
|
||||
import com.loohp.limbo.Limbo;
|
||||
import com.loohp.limbo.plugins.LimboPlugin;
|
||||
|
||||
public abstract class LimboRunnable implements LimboTask {
|
||||
|
||||
private volatile boolean registered = false;
|
||||
protected volatile int taskId = -1;
|
||||
|
||||
public void cancel() {
|
||||
synchronized (this) {
|
||||
if (registered && taskId >= 0) {
|
||||
Limbo.getInstance().getScheduler().cancelTask(taskId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getTaskId() {
|
||||
if (registered && taskId >= 0) {
|
||||
return taskId;
|
||||
} else {
|
||||
throw new IllegalStateException("LimboRunnable not yet scheduled");
|
||||
}
|
||||
}
|
||||
|
||||
public LimboRunnable runTask(LimboPlugin plugin) {
|
||||
synchronized (this) {
|
||||
if (!registered) {
|
||||
taskId = Limbo.getInstance().getScheduler().runTask(plugin, this);
|
||||
registered = true;
|
||||
return this;
|
||||
} else {
|
||||
throw new IllegalStateException("LimboRunnable already scheduled");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public LimboRunnable runTaskLater(LimboPlugin plugin, long delay) {
|
||||
synchronized (this) {
|
||||
if (!registered) {
|
||||
taskId = Limbo.getInstance().getScheduler().runTaskLater(plugin, this, delay);
|
||||
registered = true;
|
||||
return this;
|
||||
} else {
|
||||
throw new IllegalStateException("LimboRunnable already scheduled");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public LimboRunnable runTaskAsync(LimboPlugin plugin) {
|
||||
synchronized (this) {
|
||||
if (!registered) {
|
||||
taskId = Limbo.getInstance().getScheduler().runTaskAsync(plugin, this);
|
||||
registered = true;
|
||||
return this;
|
||||
} else {
|
||||
throw new IllegalStateException("LimboRunnable already scheduled");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public LimboRunnable runTaskLaterAsync(LimboPlugin plugin, long delay) {
|
||||
synchronized (this) {
|
||||
if (!registered) {
|
||||
taskId = Limbo.getInstance().getScheduler().runTaskLaterAsync(plugin, this, delay);
|
||||
registered = true;
|
||||
return this;
|
||||
} else {
|
||||
throw new IllegalStateException("LimboRunnable already scheduled");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public LimboRunnable runTaskTimer(LimboPlugin plugin, long delay, long period) {
|
||||
synchronized (this) {
|
||||
if (!registered) {
|
||||
taskId = Limbo.getInstance().getScheduler().runTaskTimer(plugin, this, delay, period);
|
||||
registered = true;
|
||||
return this;
|
||||
} else {
|
||||
throw new IllegalStateException("LimboRunnable already scheduled");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public LimboRunnable runTaskTimerAsync(LimboPlugin plugin, long delay, long period) {
|
||||
synchronized (this) {
|
||||
if (!registered) {
|
||||
taskId = Limbo.getInstance().getScheduler().runTaskTimerAsync(plugin, this, delay, period);
|
||||
registered = true;
|
||||
return this;
|
||||
} else {
|
||||
throw new IllegalStateException("LimboRunnable already scheduled");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
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<Long, List<LimboSchedulerTask>> registeredTasks = new HashMap<>();
|
||||
private Map<Integer, LimboSchedulerTask> tasksById = new HashMap<>();
|
||||
private Set<Integer> 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<LimboSchedulerTask> 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<LimboSchedulerTask> 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<LimboSchedulerTask> 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<LimboSchedulerTask> 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<LimboSchedulerTask> tasks = registeredTasks.remove(currentTick);
|
||||
if (tasks == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<LimboSchedulerTask> asyncTasks = new LinkedList<>();
|
||||
List<LimboSchedulerTask> 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<LimboSchedulerTask> asyncTasks;
|
||||
private List<LimboSchedulerTask> syncedTasks;
|
||||
|
||||
public CurrentSchedulerTask(List<LimboSchedulerTask> syncedTasks, List<LimboSchedulerTask> asyncTasks) {
|
||||
this.asyncTasks = asyncTasks;
|
||||
this.syncedTasks = syncedTasks;
|
||||
}
|
||||
|
||||
public List<LimboSchedulerTask> getAsyncTasks() {
|
||||
return asyncTasks;
|
||||
}
|
||||
|
||||
public List<LimboSchedulerTask> 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;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.loohp.limbo.scheduler;
|
||||
|
||||
public interface LimboTask extends Runnable {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
package com.loohp.limbo.scheduler;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import com.loohp.limbo.Limbo;
|
||||
import com.loohp.limbo.scheduler.LimboScheduler.CurrentSchedulerTask;
|
||||
import com.loohp.limbo.scheduler.LimboScheduler.LimboSchedulerTask;
|
||||
|
||||
public class Tick {
|
||||
|
||||
private int tickingInterval;
|
||||
private AtomicLong tick = new AtomicLong(0);
|
||||
|
||||
private List<Thread> threads = new ArrayList<>();
|
||||
private Queue<LimboSchedulerTask> asyncTasksQueue = new ConcurrentLinkedQueue<>();
|
||||
|
||||
public Tick(Limbo instance) {
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
tickingInterval = (int) Math.round(1000.0 / Limbo.getInstance().getServerProperties().getDefinedTicksPerSecond());
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
Thread thread = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
while (instance.isRunning()) {
|
||||
LimboSchedulerTask task = asyncTasksQueue.poll();
|
||||
if (task == null) {
|
||||
try {
|
||||
TimeUnit.NANOSECONDS.sleep(10000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
LimboTask limboTask = task.getTask();
|
||||
try {
|
||||
limboTask.run();
|
||||
} catch (Throwable e) {
|
||||
System.err.println("Task " + task.getTaskId() + " threw an exception: " + e.getLocalizedMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
thread.start();
|
||||
threads.add(thread);
|
||||
}
|
||||
|
||||
while (instance.isRunning()) {
|
||||
long start = System.currentTimeMillis();
|
||||
tick.incrementAndGet();
|
||||
instance.getPlayers().forEach(each -> {
|
||||
if (each.clientConnection.isReady()) {
|
||||
try {
|
||||
each.playerInteractManager.update();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
/*
|
||||
try {
|
||||
each.getDataWatcher().update();
|
||||
} catch (IllegalArgumentException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
*/
|
||||
}
|
||||
});
|
||||
instance.getWorlds().forEach(each -> {
|
||||
try {
|
||||
each.update();
|
||||
} catch (IllegalArgumentException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
|
||||
CurrentSchedulerTask tasks = instance.getScheduler().collectTasks(getCurrentTick());
|
||||
if (tasks != null) {
|
||||
asyncTasksQueue.addAll(tasks.getAsyncTasks());
|
||||
|
||||
tasks.getSyncedTasks().forEach(task -> {
|
||||
LimboTask limboTask = task.getTask();
|
||||
try {
|
||||
limboTask.run();
|
||||
} catch (Throwable e) {
|
||||
System.err.println("Task " + task.getTaskId() + " threw an exception: " + e.getLocalizedMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
long end = System.currentTimeMillis();
|
||||
try {
|
||||
TimeUnit.MILLISECONDS.sleep(tickingInterval - (end - start));
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
public long getCurrentTick() {
|
||||
return tick.get();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public void waitAndKillThreads(long waitTime) {
|
||||
long end = System.currentTimeMillis() + waitTime;
|
||||
for (Thread thread : threads) {
|
||||
try {
|
||||
thread.join(Math.max(end - System.currentTimeMillis(), 1));
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (thread.isAlive()) {
|
||||
thread.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user