mirror of https://github.com/LOOHP/Limbo.git
Limbo Schedulers
This commit is contained in:
parent
2a0839963a
commit
25afa65ad9
|
|
@ -11,7 +11,6 @@ import java.io.InputStreamReader;
|
||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStreamWriter;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.io.StringWriter;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,9 @@ public class GUI extends JFrame {
|
||||||
addWindowListener(new WindowAdapter() {
|
addWindowListener(new WindowAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void windowClosing(WindowEvent e) {
|
public void windowClosing(WindowEvent e) {
|
||||||
Limbo.getInstance().stopServer();
|
if (Limbo.getInstance().isRunning()) {
|
||||||
|
Limbo.getInstance().stopServer();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
setBounds(100, 100, 1198, 686);
|
setBounds(100, 100, 1198, 686);
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,8 @@ import com.loohp.limbo.Permissions.PermissionsManager;
|
||||||
import com.loohp.limbo.Player.Player;
|
import com.loohp.limbo.Player.Player;
|
||||||
import com.loohp.limbo.Plugins.LimboPlugin;
|
import com.loohp.limbo.Plugins.LimboPlugin;
|
||||||
import com.loohp.limbo.Plugins.PluginManager;
|
import com.loohp.limbo.Plugins.PluginManager;
|
||||||
|
import com.loohp.limbo.Scheduler.LimboScheduler;
|
||||||
|
import com.loohp.limbo.Scheduler.Tick;
|
||||||
import com.loohp.limbo.Server.ServerConnection;
|
import com.loohp.limbo.Server.ServerConnection;
|
||||||
import com.loohp.limbo.Server.Packets.Packet;
|
import com.loohp.limbo.Server.Packets.Packet;
|
||||||
import com.loohp.limbo.Server.Packets.PacketIn;
|
import com.loohp.limbo.Server.Packets.PacketIn;
|
||||||
|
|
@ -130,8 +132,8 @@ public class Limbo {
|
||||||
|
|
||||||
private DimensionRegistry dimensionRegistry;
|
private DimensionRegistry dimensionRegistry;
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
private Tick tick;
|
private Tick tick;
|
||||||
|
private LimboScheduler scheduler;
|
||||||
|
|
||||||
private Metrics metrics;
|
private Metrics metrics;
|
||||||
|
|
||||||
|
|
@ -281,6 +283,9 @@ public class Limbo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scheduler = new LimboScheduler();
|
||||||
|
tick = new Tick(this);
|
||||||
|
|
||||||
permissionManager = new PermissionsManager();
|
permissionManager = new PermissionsManager();
|
||||||
permissionManager.loadDefaultPermissionFile(permissionFile);
|
permissionManager.loadDefaultPermissionFile(permissionFile);
|
||||||
|
|
||||||
|
|
@ -314,8 +319,6 @@ public class Limbo {
|
||||||
|
|
||||||
server = new ServerConnection(properties.getServerIp(), properties.getServerPort());
|
server = new ServerConnection(properties.getServerIp(), properties.getServerPort());
|
||||||
|
|
||||||
tick = new Tick(this);
|
|
||||||
|
|
||||||
metrics = new Metrics();
|
metrics = new Metrics();
|
||||||
|
|
||||||
console.run();
|
console.run();
|
||||||
|
|
@ -325,6 +328,14 @@ public class Limbo {
|
||||||
public Unsafe getUnsafe() {
|
public Unsafe getUnsafe() {
|
||||||
return unsafe;
|
return unsafe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Tick getHeartBeat() {
|
||||||
|
return tick;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LimboScheduler getScheduler() {
|
||||||
|
return scheduler;
|
||||||
|
}
|
||||||
|
|
||||||
public DimensionRegistry getDimensionRegistry() {
|
public DimensionRegistry getDimensionRegistry() {
|
||||||
return dimensionRegistry;
|
return dimensionRegistry;
|
||||||
|
|
@ -494,6 +505,8 @@ public class Limbo {
|
||||||
plugin.onDisable();
|
plugin.onDisable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tick.waitAndKillThreads(5000);
|
||||||
|
|
||||||
for (Player player : getPlayers()) {
|
for (Player player : getPlayers()) {
|
||||||
player.disconnect("Server closed");
|
player.disconnect("Server closed");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,17 @@ public class LimboPlugin {
|
||||||
private String name;
|
private String name;
|
||||||
private File dataFolder;
|
private File dataFolder;
|
||||||
private PluginInfo info;
|
private PluginInfo info;
|
||||||
|
private File pluginJar;
|
||||||
|
|
||||||
protected final void setInfo(FileConfiguration file) {
|
protected final void setInfo(FileConfiguration file, File pluginJar) {
|
||||||
info = new PluginInfo(file);
|
this.info = new PluginInfo(file);
|
||||||
name = info.getName();
|
this.name = info.getName();
|
||||||
dataFolder = new File(Limbo.getInstance().getPluginFolder(), name);
|
this.dataFolder = new File(Limbo.getInstance().getPluginFolder(), name);
|
||||||
|
this.pluginJar = pluginJar;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final File getPluginJar() {
|
||||||
|
return pluginJar;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onLoad() {
|
public void onLoad() {
|
||||||
|
|
|
||||||
|
|
@ -52,15 +52,13 @@ public class PluginManager {
|
||||||
System.err.println("Ambiguous plugin name in " + file.getName() + " with the plugin \"" + plugins.get(pluginName).getClass().getName() + "\"");
|
System.err.println("Ambiguous plugin name in " + file.getName() + " with the plugin \"" + plugins.get(pluginName).getClass().getName() + "\"");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
URLClassLoader child = new URLClassLoader(new URL[] {file.toURI().toURL()}, Limbo.getInstance().getClass().getClassLoader());
|
||||||
URLClassLoader url = new URLClassLoader(new URL[] {file.toURI().toURL()});
|
Class<?> clazz = Class.forName(main, true, child);
|
||||||
Class<?> clazz = url.loadClass(main);
|
|
||||||
LimboPlugin plugin = (LimboPlugin) clazz.getDeclaredConstructor().newInstance();
|
LimboPlugin plugin = (LimboPlugin) clazz.getDeclaredConstructor().newInstance();
|
||||||
plugin.setInfo(pluginYaml);
|
plugin.setInfo(pluginYaml, file);
|
||||||
plugins.put(plugin.getName(), plugin);
|
plugins.put(plugin.getName(), plugin);
|
||||||
plugin.onLoad();
|
plugin.onLoad();
|
||||||
Limbo.getInstance().getConsole().sendMessage("Loading plugin " + file.getName() + " " + plugin.getInfo().getVersion() + " by " + plugin.getInfo().getAuthor());
|
Limbo.getInstance().getConsole().sendMessage("Loading plugin " + file.getName() + " " + plugin.getInfo().getVersion() + " by " + plugin.getInfo().getAuthor());
|
||||||
url.close();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -357,8 +357,7 @@ public class ClientConnection extends Thread {
|
||||||
int packetId = DataTypeIO.readVarInt(input);
|
int packetId = DataTypeIO.readVarInt(input);
|
||||||
Class<? extends Packet> packetType = Packet.getPlayIn().get(packetId);
|
Class<? extends Packet> packetType = Packet.getPlayIn().get(packetId);
|
||||||
//Limbo.getInstance().getConsole().sendMessage(packetId + " -> " + packetType);
|
//Limbo.getInstance().getConsole().sendMessage(packetId + " -> " + packetType);
|
||||||
CheckedConsumer<PlayerMoveEvent, IOException> processMoveEvent = event ->
|
CheckedConsumer<PlayerMoveEvent, IOException> processMoveEvent = event -> {
|
||||||
{
|
|
||||||
Location originalTo = event.getTo().clone();
|
Location originalTo = event.getTo().clone();
|
||||||
if (event.isCancelled()) {
|
if (event.isCancelled()) {
|
||||||
Location returnTo = event.getFrom();
|
Location returnTo = event.getFrom();
|
||||||
|
|
@ -368,8 +367,7 @@ public class ClientConnection extends Thread {
|
||||||
Location to = event.getTo();
|
Location to = event.getTo();
|
||||||
Limbo.getInstance().getUnsafe().setPlayerLocationSilently(player, to);
|
Limbo.getInstance().getUnsafe().setPlayerLocationSilently(player, to);
|
||||||
// If an event handler used setTo, let's make sure we tell the player about it.
|
// If an event handler used setTo, let's make sure we tell the player about it.
|
||||||
if(!originalTo.equals(to))
|
if (!originalTo.equals(to)) {
|
||||||
{
|
|
||||||
PacketPlayOutPositionAndLook pos = new PacketPlayOutPositionAndLook(to.getX(), to.getY(), to.getZ(), to.getYaw(), to.getPitch(), 1);
|
PacketPlayOutPositionAndLook pos = new PacketPlayOutPositionAndLook(to.getX(), to.getY(), to.getZ(), to.getYaw(), to.getPitch(), 1);
|
||||||
sendPacket(pos);
|
sendPacket(pos);
|
||||||
}
|
}
|
||||||
|
|
@ -426,13 +424,13 @@ public class ClientConnection extends Thread {
|
||||||
} else {
|
} else {
|
||||||
player.chat(chat.getMessage());
|
player.chat(chat.getMessage());
|
||||||
}
|
}
|
||||||
} else if(packetType.equals(PacketPlayInHeldItemChange.class)) {
|
} else if (packetType.equals(PacketPlayInHeldItemChange.class)) {
|
||||||
PacketPlayInHeldItemChange change = new PacketPlayInHeldItemChange(input);
|
PacketPlayInHeldItemChange change = new PacketPlayInHeldItemChange(input);
|
||||||
PlayerSelectedSlotChangeEvent event = Limbo.getInstance().getEventsManager().callEvent(new PlayerSelectedSlotChangeEvent(player, (byte)change.getSlot()));
|
PlayerSelectedSlotChangeEvent event = Limbo.getInstance().getEventsManager().callEvent(new PlayerSelectedSlotChangeEvent(player, (byte) change.getSlot()));
|
||||||
if(event.isCancelled()) {
|
if (event.isCancelled()) {
|
||||||
PacketPlayOutHeldItemChange cancelPacket = new PacketPlayOutHeldItemChange(player.getSelectedSlot());
|
PacketPlayOutHeldItemChange cancelPacket = new PacketPlayOutHeldItemChange(player.getSelectedSlot());
|
||||||
sendPacket(cancelPacket);
|
sendPacket(cancelPacket);
|
||||||
} else if(change.getSlot() != event.getSlot()) {
|
} else if (change.getSlot() != event.getSlot()) {
|
||||||
PacketPlayOutHeldItemChange changePacket = new PacketPlayOutHeldItemChange(event.getSlot());
|
PacketPlayOutHeldItemChange changePacket = new PacketPlayOutHeldItemChange(event.getSlot());
|
||||||
sendPacket(changePacket);
|
sendPacket(changePacket);
|
||||||
Limbo.getInstance().getUnsafe().setSelectedSlotSilently(player, event.getSlot());
|
Limbo.getInstance().getUnsafe().setSelectedSlotSilently(player, event.getSlot());
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import java.io.IOException;
|
||||||
|
|
||||||
public class PacketPlayInHeldItemChange extends PacketIn {
|
public class PacketPlayInHeldItemChange extends PacketIn {
|
||||||
|
|
||||||
private final short slot;
|
private short slot;
|
||||||
|
|
||||||
public PacketPlayInHeldItemChange(short slot) {
|
public PacketPlayInHeldItemChange(short slot) {
|
||||||
this.slot = slot;
|
this.slot = slot;
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import java.io.IOException;
|
||||||
|
|
||||||
public class PacketPlayInKeepAlive extends PacketIn {
|
public class PacketPlayInKeepAlive extends PacketIn {
|
||||||
|
|
||||||
long payload;
|
private long payload;
|
||||||
|
|
||||||
public PacketPlayInKeepAlive(long payload) {
|
public PacketPlayInKeepAlive(long payload) {
|
||||||
this.payload = payload;
|
this.payload = payload;
|
||||||
|
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
package com.loohp.limbo;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Timer;
|
|
||||||
import java.util.TimerTask;
|
|
||||||
|
|
||||||
public class Tick {
|
|
||||||
|
|
||||||
private TimerTask timerTask;
|
|
||||||
|
|
||||||
public Tick(Limbo instance) {
|
|
||||||
this.timerTask = new TimerTask () {
|
|
||||||
@Override
|
|
||||||
public void run () {
|
|
||||||
if (instance.isRunning()) {
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.cancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
new Timer().schedule(timerTask, 0, Math.round(1000 / instance.getServerProperties().getDefinedTicksPerSecond()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void cancel() {
|
|
||||||
timerTask.cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue