refactor: get mappings from jar rather than file

This commit is contained in:
Sculas 2024-03-20 18:19:45 +01:00
parent 6e12d17cd4
commit f48c48e6e5
No known key found for this signature in database
GPG Key ID: 1530BFF96D1EEB89
1 changed files with 89 additions and 93 deletions

View File

@ -102,7 +102,7 @@ public final class Limbo {
private static Limbo instance; private static Limbo instance;
public static boolean noGui = false; public static boolean noGui = false;
public static void main(String args[]) throws IOException, ParseException, NumberFormatException, ClassNotFoundException, InterruptedException { public static void main(String args[]) throws IOException, ParseException, NumberFormatException, ClassNotFoundException, InterruptedException {
for (String flag : args) { for (String flag : args) {
if (flag.equals("--nogui") || flag.equals("nogui")) { if (flag.equals("--nogui") || flag.equals("nogui")) {
@ -129,57 +129,57 @@ public final class Limbo {
}); });
t1.start(); t1.start();
} }
new Limbo(); new Limbo();
} }
public static Limbo getInstance() { public static Limbo getInstance() {
return instance; return instance;
} }
//=========================== //===========================
public final String SERVER_IMPLEMENTATION_VERSION = "1.20.4"; public final String SERVER_IMPLEMENTATION_VERSION = "1.20.4";
public final int SERVER_IMPLEMENTATION_PROTOCOL = 765; public final int SERVER_IMPLEMENTATION_PROTOCOL = 765;
public final String LIMBO_IMPLEMENTATION_VERSION; public final String LIMBO_IMPLEMENTATION_VERSION;
private final AtomicBoolean isRunning; private final AtomicBoolean isRunning;
private final ServerConnection server; private final ServerConnection server;
private final Console console; private final Console console;
private final List<World> worlds = new CopyOnWriteArrayList<>(); private final List<World> worlds = new CopyOnWriteArrayList<>();
final Map<String, Player> playersByName = new ConcurrentHashMap<>(); final Map<String, Player> playersByName = new ConcurrentHashMap<>();
final Map<UUID, Player> playersByUUID = new ConcurrentHashMap<>(); final Map<UUID, Player> playersByUUID = new ConcurrentHashMap<>();
private final Map<Key, KeyedBossBar> bossBars = new ConcurrentHashMap<>(); private final Map<Key, KeyedBossBar> bossBars = new ConcurrentHashMap<>();
private final ServerProperties properties; private final ServerProperties properties;
private final PluginManager pluginManager; private final PluginManager pluginManager;
private final EventsManager eventsManager; private final EventsManager eventsManager;
private final PermissionsManager permissionManager; private final PermissionsManager permissionManager;
private final File pluginFolder; private final File pluginFolder;
private final File internalDataFolder; private final File internalDataFolder;
private final DimensionRegistry dimensionRegistry; private final DimensionRegistry dimensionRegistry;
private final Tick tick; private final Tick tick;
private final LimboScheduler scheduler; private final LimboScheduler scheduler;
private final Metrics metrics; private final Metrics metrics;
public final AtomicInteger entityIdCount = new AtomicInteger(); public final AtomicInteger entityIdCount = new AtomicInteger();
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
private Unsafe unsafe; private Unsafe unsafe;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public Limbo() throws IOException, ParseException, NumberFormatException, ClassNotFoundException, InterruptedException { public Limbo() throws IOException, ParseException, NumberFormatException, ClassNotFoundException, InterruptedException {
instance = this; instance = this;
unsafe = new Unsafe(this); unsafe = new Unsafe(this);
isRunning = new AtomicBoolean(true); isRunning = new AtomicBoolean(true);
if (!noGui) { if (!noGui) {
while (!GUI.loadFinish) { while (!GUI.loadFinish) {
TimeUnit.MILLISECONDS.sleep(500); TimeUnit.MILLISECONDS.sleep(500);
@ -188,10 +188,10 @@ public final class Limbo {
} else { } else {
console = new Console(System.in, System.out, System.err); console = new Console(System.in, System.out, System.err);
} }
LIMBO_IMPLEMENTATION_VERSION = getLimboVersion(); LIMBO_IMPLEMENTATION_VERSION = getLimboVersion();
console.sendMessage("Loading Limbo Version " + LIMBO_IMPLEMENTATION_VERSION + " on Minecraft " + SERVER_IMPLEMENTATION_VERSION); console.sendMessage("Loading Limbo Version " + LIMBO_IMPLEMENTATION_VERSION + " on Minecraft " + SERVER_IMPLEMENTATION_VERSION);
String spName = "server.properties"; String spName = "server.properties";
File sp = new File(spName); File sp = new File(spName);
if (!sp.exists()) { if (!sp.exists()) {
@ -202,37 +202,33 @@ public final class Limbo {
} }
} }
properties = new ServerProperties(sp); properties = new ServerProperties(sp);
if (!properties.isBungeecord()) { if (!properties.isBungeecord()) {
console.sendMessage("If you are using bungeecord, consider turning that on in the settings!"); console.sendMessage("If you are using bungeecord, consider turning that on in the settings!");
} else { } else {
console.sendMessage("Starting Limbo server in bungeecord mode!"); console.sendMessage("Starting Limbo server in bungeecord mode!");
} }
internalDataFolder = new File("internal_data"); internalDataFolder = new File("internal_data");
if (!internalDataFolder.exists()) { if (!internalDataFolder.exists()) {
internalDataFolder.mkdirs(); internalDataFolder.mkdirs();
} }
String mappingName = "mapping.json";
File mappingFile = new File(internalDataFolder, mappingName);
if (!mappingFile.exists()) {
try (InputStream in = getClass().getClassLoader().getResourceAsStream(mappingName)) {
Files.copy(in, mappingFile.toPath());
} catch (IOException e) {
e.printStackTrace();
}
}
console.sendMessage("Loading packet id mappings from mapping.json ..."); console.sendMessage("Loading packet id mappings from mapping.json ...");
InputStreamReader reader = new InputStreamReader(Files.newInputStream(mappingFile.toPath()), StandardCharsets.UTF_8); InputStream mappingStream = getClass().getClassLoader().getResourceAsStream("mapping.json");
if (mappingStream == null) {
console.sendMessage("Failed to load mapping.json from jar!");
System.exit(1);
}
InputStreamReader reader = new InputStreamReader(mappingStream, StandardCharsets.UTF_8);
JSONObject json = (JSONObject) new JSONParser().parse(reader); JSONObject json = (JSONObject) new JSONParser().parse(reader);
reader.close(); reader.close();
String classPrefix = Packet.class.getName().substring(0, Packet.class.getName().lastIndexOf(".") + 1); String classPrefix = Packet.class.getName().substring(0, Packet.class.getName().lastIndexOf(".") + 1);
int mappingsCount = 0; int mappingsCount = 0;
Map<Integer, Class<? extends PacketIn>> HandshakeIn = new HashMap<>(); Map<Integer, Class<? extends PacketIn>> HandshakeIn = new HashMap<>();
for (Object key : ((JSONObject) json.get("HandshakeIn")).keySet()) { for (Object key : ((JSONObject) json.get("HandshakeIn")).keySet()) {
int packetId = Integer.decode((String) key); int packetId = Integer.decode((String) key);
@ -240,7 +236,7 @@ public final class Limbo {
} }
Packet.setHandshakeIn(HandshakeIn); Packet.setHandshakeIn(HandshakeIn);
mappingsCount += HandshakeIn.size(); mappingsCount += HandshakeIn.size();
Map<Integer, Class<? extends PacketIn>> StatusIn = new HashMap<>(); Map<Integer, Class<? extends PacketIn>> StatusIn = new HashMap<>();
for (Object key : ((JSONObject) json.get("StatusIn")).keySet()) { for (Object key : ((JSONObject) json.get("StatusIn")).keySet()) {
int packetId = Integer.decode((String) key); int packetId = Integer.decode((String) key);
@ -248,7 +244,7 @@ public final class Limbo {
} }
Packet.setStatusIn(StatusIn); Packet.setStatusIn(StatusIn);
mappingsCount += StatusIn.size(); mappingsCount += StatusIn.size();
Map<Class<? extends PacketOut>, Integer> StatusOut = new HashMap<>(); Map<Class<? extends PacketOut>, Integer> StatusOut = new HashMap<>();
for (Object key : ((JSONObject) json.get("StatusOut")).keySet()) { for (Object key : ((JSONObject) json.get("StatusOut")).keySet()) {
Class<? extends PacketOut> packetClass = (Class<? extends PacketOut>) Class.forName(classPrefix + key); Class<? extends PacketOut> packetClass = (Class<? extends PacketOut>) Class.forName(classPrefix + key);
@ -256,7 +252,7 @@ public final class Limbo {
} }
Packet.setStatusOut(StatusOut); Packet.setStatusOut(StatusOut);
mappingsCount += StatusOut.size(); mappingsCount += StatusOut.size();
Map<Integer, Class<? extends PacketIn>> LoginIn = new HashMap<>(); Map<Integer, Class<? extends PacketIn>> LoginIn = new HashMap<>();
for (Object key : ((JSONObject) json.get("LoginIn")).keySet()) { for (Object key : ((JSONObject) json.get("LoginIn")).keySet()) {
int packetId = Integer.decode((String) key); int packetId = Integer.decode((String) key);
@ -264,7 +260,7 @@ public final class Limbo {
} }
Packet.setLoginIn(LoginIn); Packet.setLoginIn(LoginIn);
mappingsCount += LoginIn.size(); mappingsCount += LoginIn.size();
Map<Class<? extends PacketOut>, Integer> LoginOut = new HashMap<>(); Map<Class<? extends PacketOut>, Integer> LoginOut = new HashMap<>();
for (Object key : ((JSONObject) json.get("LoginOut")).keySet()) { for (Object key : ((JSONObject) json.get("LoginOut")).keySet()) {
Class<? extends PacketOut> packetClass = (Class<? extends PacketOut>) Class.forName(classPrefix + key); Class<? extends PacketOut> packetClass = (Class<? extends PacketOut>) Class.forName(classPrefix + key);
@ -288,7 +284,7 @@ public final class Limbo {
} }
Packet.setConfigurationOut(ConfigurationOut); Packet.setConfigurationOut(ConfigurationOut);
mappingsCount += ConfigurationOut.size(); mappingsCount += ConfigurationOut.size();
Map<Integer, Class<? extends PacketIn>> PlayIn = new HashMap<>(); Map<Integer, Class<? extends PacketIn>> PlayIn = new HashMap<>();
for (Object key : ((JSONObject) json.get("PlayIn")).keySet()) { for (Object key : ((JSONObject) json.get("PlayIn")).keySet()) {
int packetId = Integer.decode((String) key); int packetId = Integer.decode((String) key);
@ -296,7 +292,7 @@ public final class Limbo {
} }
Packet.setPlayIn(PlayIn); Packet.setPlayIn(PlayIn);
mappingsCount += PlayIn.size(); mappingsCount += PlayIn.size();
Map<Class<? extends PacketOut>, Integer> PlayOut = new HashMap<>(); Map<Class<? extends PacketOut>, Integer> PlayOut = new HashMap<>();
for (Object key : ((JSONObject) json.get("PlayOut")).keySet()) { for (Object key : ((JSONObject) json.get("PlayOut")).keySet()) {
Class<? extends PacketOut> packetClass = (Class<? extends PacketOut>) Class.forName(classPrefix + key); Class<? extends PacketOut> packetClass = (Class<? extends PacketOut>) Class.forName(classPrefix + key);
@ -304,15 +300,15 @@ public final class Limbo {
} }
Packet.setPlayOut(PlayOut); Packet.setPlayOut(PlayOut);
mappingsCount += PlayOut.size(); mappingsCount += PlayOut.size();
console.sendMessage("Loaded all " + mappingsCount + " packet id mappings!"); console.sendMessage("Loaded all " + mappingsCount + " packet id mappings!");
dimensionRegistry = new DimensionRegistry(); dimensionRegistry = new DimensionRegistry();
worlds.add(loadDefaultWorld()); worlds.add(loadDefaultWorld());
Location spawn = properties.getWorldSpawn(); Location spawn = properties.getWorldSpawn();
properties.setWorldSpawn(new Location(getWorld(properties.getLevelName().value()), spawn.getX(), spawn.getY(), spawn.getZ(), spawn.getYaw(), spawn.getPitch())); properties.setWorldSpawn(new Location(getWorld(properties.getLevelName().value()), spawn.getX(), spawn.getY(), spawn.getZ(), spawn.getYaw(), spawn.getPitch()));
if (!NetworkUtils.available(properties.getServerPort())) { if (!NetworkUtils.available(properties.getServerPort())) {
console.sendMessage(""); console.sendMessage("");
console.sendMessage("*****FAILED TO BIND PORT [" + properties.getServerPort() + "]*****"); console.sendMessage("*****FAILED TO BIND PORT [" + properties.getServerPort() + "]*****");
@ -321,7 +317,7 @@ public final class Limbo {
console.sendMessage(""); console.sendMessage("");
System.exit(2); System.exit(2);
} }
String permissionName = "permission.yml"; String permissionName = "permission.yml";
File permissionFile = new File(permissionName); File permissionFile = new File(permissionName);
if (!permissionFile.exists()) { if (!permissionFile.exists()) {
@ -334,15 +330,15 @@ public final class Limbo {
scheduler = new LimboScheduler(); scheduler = new LimboScheduler();
tick = new Tick(this); tick = new Tick(this);
permissionManager = new PermissionsManager(); permissionManager = new PermissionsManager();
permissionManager.loadDefaultPermissionFile(permissionFile); permissionManager.loadDefaultPermissionFile(permissionFile);
eventsManager = new EventsManager(); eventsManager = new EventsManager();
pluginFolder = new File("plugins"); pluginFolder = new File("plugins");
pluginFolder.mkdirs(); pluginFolder.mkdirs();
pluginManager = new PluginManager(new DefaultCommands(), pluginFolder); pluginManager = new PluginManager(new DefaultCommands(), pluginFolder);
try { try {
Method loadPluginsMethod = PluginManager.class.getDeclaredMethod("loadPlugins"); Method loadPluginsMethod = PluginManager.class.getDeclaredMethod("loadPlugins");
@ -352,7 +348,7 @@ public final class Limbo {
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace(); e.printStackTrace();
} }
for (LimboPlugin plugin : Limbo.getInstance().getPluginManager().getPlugins()) { for (LimboPlugin plugin : Limbo.getInstance().getPluginManager().getPlugins()) {
try { try {
console.sendMessage("Enabling plugin " + plugin.getName() + " " + plugin.getInfo().getVersion()); console.sendMessage("Enabling plugin " + plugin.getName() + " " + plugin.getInfo().getVersion());
@ -361,11 +357,11 @@ public final class Limbo {
new RuntimeException("Error while enabling " + plugin.getName() + " " + plugin.getInfo().getVersion(), e).printStackTrace(); new RuntimeException("Error while enabling " + plugin.getName() + " " + plugin.getInfo().getVersion(), e).printStackTrace();
} }
} }
server = new ServerConnection(properties.getServerIp(), properties.getServerPort()); server = new ServerConnection(properties.getServerIp(), properties.getServerPort());
metrics = new Metrics(); metrics = new Metrics();
Runtime.getRuntime().addShutdownHook(new Thread(() -> { Runtime.getRuntime().addShutdownHook(new Thread(() -> {
Limbo.getInstance().terminate(); Limbo.getInstance().terminate();
})); }));
@ -377,11 +373,11 @@ public final class Limbo {
public Unsafe getUnsafe() { public Unsafe getUnsafe() {
return unsafe; return unsafe;
} }
public Tick getHeartBeat() { public Tick getHeartBeat() {
return tick; return tick;
} }
public LimboScheduler getScheduler() { public LimboScheduler getScheduler() {
return scheduler; return scheduler;
} }
@ -401,20 +397,20 @@ public final class Limbo {
public EventsManager getEventsManager() { public EventsManager getEventsManager() {
return eventsManager; return eventsManager;
} }
public File getPluginFolder() { public File getPluginFolder() {
return pluginFolder; return pluginFolder;
} }
public PluginManager getPluginManager() { public PluginManager getPluginManager() {
return pluginManager; return pluginManager;
} }
private World loadDefaultWorld() throws IOException { private World loadDefaultWorld() throws IOException {
console.sendMessage("Loading world " + properties.getLevelName() + " with the schematic file " + properties.getSchemFileName() + " ..."); console.sendMessage("Loading world " + properties.getLevelName() + " with the schematic file " + properties.getSchemFileName() + " ...");
File schem = new File(properties.getSchemFileName()); File schem = new File(properties.getSchemFileName());
if (!schem.exists()) { if (!schem.exists()) {
console.sendMessage("Schemetic file " + properties.getSchemFileName() + " for world " + properties.getLevelName() + " not found!"); console.sendMessage("Schemetic file " + properties.getSchemFileName() + " for world " + properties.getLevelName() + " not found!");
console.sendMessage("Creating default world..."); console.sendMessage("Creating default world...");
@ -424,10 +420,10 @@ public final class Limbo {
e.printStackTrace(); e.printStackTrace();
} }
} }
try { try {
World world = Schematic.toWorld(properties.getLevelName().value(), Environment.fromKey(properties.getLevelDimension()), (CompoundTag) NBTUtil.read(schem).getTag()); World world = Schematic.toWorld(properties.getLevelName().value(), Environment.fromKey(properties.getLevelDimension()), (CompoundTag) NBTUtil.read(schem).getTag());
console.sendMessage("Loaded world " + properties.getLevelName() + "!"); console.sendMessage("Loaded world " + properties.getLevelName() + "!");
return world; return world;
} catch (Throwable e) { } catch (Throwable e) {
console.sendMessage("Unable to load world " + properties.getSchemFileName() + "!"); console.sendMessage("Unable to load world " + properties.getSchemFileName() + "!");
@ -437,7 +433,7 @@ public final class Limbo {
return null; return null;
} }
} }
public void registerWorld(World world) { public void registerWorld(World world) {
if (!worlds.contains(world)) { if (!worlds.contains(world)) {
worlds.add(world); worlds.add(world);
@ -445,7 +441,7 @@ public final class Limbo {
throw new RuntimeException("World already registered"); throw new RuntimeException("World already registered");
} }
} }
public void unregisterWorld(World world) { public void unregisterWorld(World world) {
if (worlds.indexOf(world) == 0) { if (worlds.indexOf(world) == 0) {
throw new RuntimeException("World already registered"); throw new RuntimeException("World already registered");
@ -486,7 +482,7 @@ public final class Limbo {
public ServerProperties getServerProperties() { public ServerProperties getServerProperties() {
return properties; return properties;
} }
public ServerConnection getServerConnection() { public ServerConnection getServerConnection() {
return server; return server;
} }
@ -494,7 +490,7 @@ public final class Limbo {
public Console getConsole() { public Console getConsole() {
return console; return console;
} }
public Metrics getMetrics() { public Metrics getMetrics() {
return metrics; return metrics;
} }
@ -502,19 +498,19 @@ public final class Limbo {
public Set<Player> getPlayers() { public Set<Player> getPlayers() {
return new HashSet<>(playersByUUID.values()); return new HashSet<>(playersByUUID.values());
} }
public Player getPlayer(String name) { public Player getPlayer(String name) {
return playersByName.get(name); return playersByName.get(name);
} }
public Player getPlayer(UUID uuid) { public Player getPlayer(UUID uuid) {
return playersByUUID.get(uuid); return playersByUUID.get(uuid);
} }
public List<World> getWorlds() { public List<World> getWorlds() {
return new ArrayList<>(worlds); return new ArrayList<>(worlds);
} }
public World getWorld(String name) { public World getWorld(String name) {
for (World world : worlds) { for (World world : worlds) {
if (world.getName().equalsIgnoreCase(name)) { if (world.getName().equalsIgnoreCase(name)) {
@ -523,7 +519,7 @@ public final class Limbo {
} }
return null; return null;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public String buildServerListResponseJson(String version, int protocol, Component motd, int maxPlayers, int playersOnline, BufferedImage favicon) throws IOException { public String buildServerListResponseJson(String version, int protocol, Component motd, int maxPlayers, int playersOnline, BufferedImage favicon) throws IOException {
JSONObject json = new JSONObject(); JSONObject json = new JSONObject();
@ -532,14 +528,14 @@ public final class Limbo {
versionJson.put("name", version); versionJson.put("name", version);
versionJson.put("protocol", protocol); versionJson.put("protocol", protocol);
json.put("version", versionJson); json.put("version", versionJson);
JSONObject playersJson = new JSONObject(); JSONObject playersJson = new JSONObject();
playersJson.put("max", maxPlayers); playersJson.put("max", maxPlayers);
playersJson.put("online", playersOnline); playersJson.put("online", playersOnline);
json.put("players", playersJson); json.put("players", playersJson);
json.put("description", "%MOTD%"); json.put("description", "%MOTD%");
if (favicon != null) { if (favicon != null) {
if (favicon.getWidth() == 64 && favicon.getHeight() == 64) { if (favicon.getWidth() == 64 && favicon.getHeight() == 64) {
String base64 = "data:image/png;base64," + ImageUtils.imgToBase64String(favicon, "png"); String base64 = "data:image/png;base64," + ImageUtils.imgToBase64String(favicon, "png");
@ -548,30 +544,30 @@ public final class Limbo {
console.sendMessage("Server List Favicon must be 64 x 64 in size!"); console.sendMessage("Server List Favicon must be 64 x 64 in size!");
} }
} }
JSONObject modInfoJson = new JSONObject(); JSONObject modInfoJson = new JSONObject();
modInfoJson.put("type", "FML"); modInfoJson.put("type", "FML");
modInfoJson.put("modList", new JSONArray()); modInfoJson.put("modList", new JSONArray());
json.put("modinfo", modInfoJson); json.put("modinfo", modInfoJson);
TreeMap<String, Object> treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); TreeMap<String, Object> treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
treeMap.putAll(json); treeMap.putAll(json);
Gson g = new GsonBuilder().create(); Gson g = new GsonBuilder().create();
return g.toJson(treeMap).replace("\"%MOTD%\"", GsonComponentSerializer.gson().serialize(motd)); return g.toJson(treeMap).replace("\"%MOTD%\"", GsonComponentSerializer.gson().serialize(motd));
} }
public String buildLegacyPingResponse(String version, Component motd, int maxPlayers, int playersOnline) { public String buildLegacyPingResponse(String version, Component motd, int maxPlayers, int playersOnline) {
String begin = "<EFBFBD>1"; String begin = "<EFBFBD>1";
return String.join("\00", begin, "127", version, String.join("", Arrays.asList(motd).stream().map(each -> LegacyComponentSerializer.legacySection().serialize(each)).collect(Collectors.toList())), String.valueOf(playersOnline), String.valueOf(maxPlayers)); return String.join("\00", begin, "127", version, String.join("", Arrays.asList(motd).stream().map(each -> LegacyComponentSerializer.legacySection().serialize(each)).collect(Collectors.toList())), String.valueOf(playersOnline), String.valueOf(maxPlayers));
} }
protected void terminate() { protected void terminate() {
isRunning.set(false); isRunning.set(false);
console.sendMessage("Stopping Server..."); console.sendMessage("Stopping Server...");
for (LimboPlugin plugin : Limbo.getInstance().getPluginManager().getPlugins()) { for (LimboPlugin plugin : Limbo.getInstance().getPluginManager().getPlugins()) {
try { try {
console.sendMessage("Disabling plugin " + plugin.getName() + " " + plugin.getInfo().getVersion()); console.sendMessage("Disabling plugin " + plugin.getName() + " " + plugin.getInfo().getVersion());
@ -580,9 +576,9 @@ public final class Limbo {
new RuntimeException("Error while disabling " + plugin.getName() + " " + plugin.getInfo().getVersion(), e).printStackTrace(); new RuntimeException("Error while disabling " + plugin.getName() + " " + plugin.getInfo().getVersion(), e).printStackTrace();
} }
} }
tick.waitAndKillThreads(5000); tick.waitAndKillThreads(5000);
for (Player player : getPlayers()) { for (Player player : getPlayers()) {
player.disconnect("Server closed"); player.disconnect("Server closed");
} }
@ -593,23 +589,23 @@ public final class Limbo {
e.printStackTrace(); e.printStackTrace();
} }
} }
console.sendMessage("Server closed"); console.sendMessage("Server closed");
console.logs.close(); console.logs.close();
} }
public void stopServer() { public void stopServer() {
System.exit(0); System.exit(0);
} }
public boolean isRunning() { public boolean isRunning() {
return isRunning.get(); return isRunning.get();
} }
public int getNextEntityId() { public int getNextEntityId() {
return entityIdCount.getAndUpdate(i -> i == Integer.MAX_VALUE ? 0 : ++i); return entityIdCount.getAndUpdate(i -> i == Integer.MAX_VALUE ? 0 : ++i);
} }
public void dispatchCommand(CommandSender sender, String str) { public void dispatchCommand(CommandSender sender, String str) {
String[] command; String[] command;
if (str.startsWith("/")) { if (str.startsWith("/")) {
@ -619,7 +615,7 @@ public final class Limbo {
} }
dispatchCommand(sender, command); dispatchCommand(sender, command);
} }
public void dispatchCommand(CommandSender sender, String... args) { public void dispatchCommand(CommandSender sender, String... args) {
try { try {
Limbo.getInstance().getPluginManager().fireExecutors(sender, args); Limbo.getInstance().getPluginManager().fireExecutors(sender, args);
@ -627,7 +623,7 @@ public final class Limbo {
e.printStackTrace(); e.printStackTrace();
} }
} }
private String getLimboVersion() throws IOException { private String getLimboVersion() throws IOException {
Enumeration<URL> manifests = getClass().getClassLoader().getResources("META-INF/MANIFEST.MF"); Enumeration<URL> manifests = getClass().getClassLoader().getResources("META-INF/MANIFEST.MF");
while (manifests.hasMoreElements()) { while (manifests.hasMoreElements()) {