From 5d471881fbf62308c16bca3e7bb2b7c5070b8b97 Mon Sep 17 00:00:00 2001 From: Kristian Knarvik Date: Tue, 13 Feb 2018 12:21:39 +0100 Subject: [PATCH] Optimization for jar compiling Some things won't work without compiling anymore (like creating a profiles file). Downloading jars is finished. --- config/servertypes.csv | 2 +- src/net/knarcraft/serverlauncher/Main.java | 28 +- .../serverlauncher/profile/Profile.java | 254 +++++++++++++++++- .../server/AdvancedServerType.java | 2 +- .../serverlauncher/server/Server.java | 92 +++---- .../serverlauncher/userinterface/GUI.java | 9 +- .../userinterface/ServerConsoles.java | 8 +- .../userinterface/ServerTab.java | 2 +- 8 files changed, 326 insertions(+), 71 deletions(-) diff --git a/config/servertypes.csv b/config/servertypes.csv index e19eda3..be97e14 100644 --- a/config/servertypes.csv +++ b/config/servertypes.csv @@ -2,7 +2,7 @@ Vanilla;Latest,1.12.2,1.11.2,1.10.2,1.9.4,1.8.9,1.7.10,1.6.4,1.5.2,1.4.7,1.3.2,1 Snapshot;Latest;https://launchermeta.mojang.com/mc/game/version_manifest.json;"snapshot":";";https://s3.amazonaws.com/Minecraft.Download/versions/;/minecraft_server. SpongeVanilla;1.12.2,1.11.2,1.10.2,1.8.9;https://dl-api.spongepowered.org/v1/org.spongepowered/spongevanilla/downloads?type=stable&minecraft=;"version":";",;https://repo.spongepowered.org/maven/org/spongepowered/spongevanilla/;/spongevanilla- Bungee;Latest;https://ci.md-5.net/job/BungeeCord/lastSuccessfulBuild/artifact/bootstrap/target/;Artifacts of BungeeCord #; ;http://ci.md-5.net/job/BungeeCord/lastSuccessfulBuild/artifact/bootstrap/target/BungeeCord.jar; -Spigot;1.12.2,1.11.2,1.10.2,1.9.4,1.9,1.8.8,1.7.10,1.6.4,1.5.2,1.4.7;https://knarcraft.net/Api/Download/bungeeminecraftserverlauncher/jars/Spigot/ +Spigot;1.12.2,1.11.2,1.10.2,1.9.4,1.9.4,1.8.8,1.7.10,1.6.4,1.5.2,1.4.7;https://knarcraft.net/Api/Download/bungeeminecraftserverlauncher/jars/Spigot/ MCPCplus;1.6.4,1.6.2,1.5.2,1.4.7;https://knarcraft.net/Api/Download/bungeeminecraftserverlauncher/jars/MCPC+/ Craftbukkit;1.12.2,1.11.2,1.10.2,1.9.4,1.8.8,1.7.10,1.6.4,1.5.2,1.4.6,1.3.2,1.2.5,1.1,1.0;https://knarcraft.net/Api/Download/bungeeminecraftserverlauncher/jars/Bukkit/ Custom;; \ No newline at end of file diff --git a/src/net/knarcraft/serverlauncher/Main.java b/src/net/knarcraft/serverlauncher/Main.java index 0669cef..e9195cf 100644 --- a/src/net/knarcraft/serverlauncher/Main.java +++ b/src/net/knarcraft/serverlauncher/Main.java @@ -9,7 +9,9 @@ import net.knarcraft.serverlauncher.userinterface.ServerConsoles; import javax.naming.ConfigurationException; import java.awt.*; +import java.io.File; import java.io.IOException; +import java.net.URISyntaxException; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -25,8 +27,18 @@ import java.util.concurrent.TimeUnit; public class Main { private static GUI gui; + @SuppressWarnings("CanBeFinal") + public static String jarDir; - public static void main(String[] args) { + static { + try { + jarDir = String.valueOf(new File(Main.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getParentFile()); + } catch (URISyntaxException e) { + e.printStackTrace(); + } + } + + public static void main(String[] args) { EventQueue.invokeLater(() -> { try { setup(); @@ -35,7 +47,7 @@ public class Main { Profile.load(); ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor(); - exec.scheduleAtFixedRate(Main::updateConsoles, 10, 250, TimeUnit.MILLISECONDS); + exec.scheduleAtFixedRate(Main::updateConsoles, 10, 500, TimeUnit.MILLISECONDS); } catch (Exception e) { e.printStackTrace(); } @@ -59,14 +71,15 @@ public class Main { * Reads from server processes, and writes the output to our custom consoles. */ private static void updateConsoles() { + Server server; for (Collection collection : Profile.getCurrent().getCollections()) { - Server server = collection.getServer(); + server = collection.getServer(); if (server.isEnabled() && server.getProcess() != null) { try { String readText = server.read(); if (!readText.equals("")) { collection.getServerConsole().output(readText); - updatePlayerList(readText, collection); + updatePlayerList(readText, server); } } catch (IOException e) { e.printStackTrace(); @@ -79,10 +92,9 @@ public class Main { * Looks for strings implying a player has joined or left, and updates the appropriate lists. * * @param text The text to search. - * @param collection The server which sent the text. + * @param server The server which sent the text. */ - private static void updatePlayerList(String text, Collection collection) { - Server server = collection.getServer(); + private static void updatePlayerList(String text, Server server) { if (!server.getTypeName().equals("Bungee")) { String joinedPlayer = stringBetween(text, "[Server thread/INFO]: ", " joined the game"); if (!joinedPlayer.equals("")) { @@ -123,7 +135,7 @@ public class Main { * @param end The substring after the wanted substring * @return The wanted substring. */ - private static String stringBetween(String string, String start, String end) { + public static String stringBetween(String string, String start, String end) { int startPos = string.indexOf(start) + start.length(); if (!string.contains(start) || string.indexOf(end, startPos) < startPos) { return ""; diff --git a/src/net/knarcraft/serverlauncher/profile/Profile.java b/src/net/knarcraft/serverlauncher/profile/Profile.java index f29d9c6..4f9f94e 100644 --- a/src/net/knarcraft/serverlauncher/profile/Profile.java +++ b/src/net/knarcraft/serverlauncher/profile/Profile.java @@ -1,13 +1,21 @@ package net.knarcraft.serverlauncher.profile; +import net.knarcraft.serverlauncher.server.AdvancedServerType; import net.knarcraft.serverlauncher.server.Server; import net.knarcraft.serverlauncher.server.ServerType; +import net.knarcraft.serverlauncher.userinterface.ServerConsoles; import net.knarcraft.serverlauncher.userinterface.ServerTab; import net.knarcraft.serverlauncher.Main; import javax.swing.*; import java.io.*; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; import java.util.ArrayList; +import java.util.Objects; import java.util.Scanner; import java.util.concurrent.Executors; @@ -21,12 +29,18 @@ import java.util.concurrent.Executors; public class Profile { private static final ArrayList profiles = new ArrayList<>(); private static Profile current; + private static final String profilesDir = Main.jarDir + File.separator + "files"; + private static final String profilesFile = Main.jarDir + File.separator + "files" + File.separator + "Profiles.txt"; + private static final String jarDir = Main.jarDir + File.separator + "files" + File.separator + "Jars" + File.separator; private final ArrayList collections; private final String name; private boolean runInBackground; private int delayStartup; private boolean downloadJars; + private static String vanillaVersion; + private static String snapshotVersion; + private static String bungeeVersion; private Profile(String name) { this.collections = new ArrayList<>(); @@ -201,6 +215,14 @@ public class Profile { } } + public void updateConsoles() { + JTabbedPane consolesTab = ServerConsoles.getTab(); + consolesTab.removeAll(); + for (Collection collection : collections) { + consolesTab.add(collection.getName(), collection.getServerConsole().getPanel()); + } + } + /** * Sends a command to a server, or all servers * @@ -268,8 +290,19 @@ public class Profile { } server.toggle(serverTab.enabled()); } - try (PrintWriter file = new PrintWriter("files/Profiles.txt")) { - file.println(current.name); + if (!new File(profilesFile).exists()) { + if (!new File(profilesDir).mkdirs()) { + JOptionPane.showMessageDialog( + null, + "Unable to create the file " + profilesFile, + "Error", + JOptionPane.ERROR_MESSAGE + ); + return; + } + } + try (PrintWriter file = new PrintWriter(profilesFile)) { + file.println(String.format("%s;%s;%s;%s", current.name, vanillaVersion, snapshotVersion, bungeeVersion)); file.close(); for (Profile profile : profiles) { StringBuilder saveString = new StringBuilder(String.format( @@ -297,7 +330,7 @@ public class Profile { } saveString = new StringBuilder(saveString.substring(0, saveString.length() - 1)); try (PrintWriter fileAppend = new PrintWriter(new FileWriter( - "files/Profiles.txt", + profilesFile, true ))) { fileAppend.println(saveString); @@ -324,9 +357,13 @@ public class Profile { * Reads profiles and servers from a text file. */ public static void load() { - try (Scanner in = new Scanner(new File("files/Profiles.txt"))) { - String profileName = in.nextLine(); + try (Scanner in = new Scanner(new File(profilesFile))) { try { + String[] staticData = in.nextLine().split(";", -1); + String profileName = staticData[0]; + vanillaVersion = staticData[1]; + snapshotVersion = staticData[2]; + bungeeVersion = staticData[3]; while (in.hasNextLine()) { String line = in.nextLine(); if (line.contains("?")) { @@ -374,10 +411,14 @@ public class Profile { addProfile("Default"); } Main.gui().update(); - if (current.getRunInBackground()) { + current.updateConsoles(); + if (current.runInBackground) { Main.gui().hide(); Executors.newSingleThreadExecutor().execute(Server::startServers); } + if (current.downloadJars) { + Executors.newSingleThreadExecutor().execute(Profile::downloadJars); + } } private static Profile parseProfile(String[] profileData) { @@ -403,4 +444,205 @@ public class Profile { serverData[9]) ); } + + private static void downloadJars() { + if (!new File(jarDir).exists() && !new File(jarDir).mkdirs()) { + JOptionPane.showMessageDialog( + null, + "Could not create the Jars folder. Please run the program with admin permissions, or move it to a writable directory.", + "Error", + JOptionPane.ERROR_MESSAGE + ); + } + downloadSimple("Spigot"); + downloadSimple("Craftbukkit"); + downloadSimple("MCPCplus"); + downloadMixed("Vanilla"); + downloadMixed("Snapshot"); + downloadSponge(); + downloadBungee(); + Main.gui().setStatus("Finished downloading jars"); + } + + private static void downloadSimple(String typeName) { + ServerType type = ServerType.getByName(typeName); + String url = Objects.requireNonNull(type).getDownloadURL(); + String name = type.getName(); + Boolean success; + + for (String version : type.getVersions()) { + File file = new File(jarDir + type.getName() + version + ".jar"); + if (!file.isFile()) { + Path filePath = Paths.get(jarDir + type.getName() + version + ".jar"); + Main.gui().setStatus("Downloading: " + name + version + ".jar"); + success = downloadFile(url + name + version + ".jar", filePath); + if (!success) { + Main.gui().setStatus("Error downloading: " + name + version + ".jar"); + } + } + } + } + + private static void downloadMixed(String typeName) { + AdvancedServerType type = (AdvancedServerType) ServerType.getByName(typeName); + String url = Objects.requireNonNull(type).getDownloadURL(); + String name = type.getName(); + String versionText = ""; + String newestVersion; + Boolean success; + for (String version : type.getVersions()) { + File file = new File(jarDir + type.getName() + version + ".jar"); + Path filePath = Paths.get(jarDir + type.getName() + version + ".jar"); + Main.gui().setStatus("Downloading: " + name + version + ".jar"); + if (version.equals("Latest")) { + try { + versionText = readFile(type.getVersionURL()); + } catch (IOException e) { + System.out.println("Error reading: " + type.getVersionURL()); + } + newestVersion = Main.stringBetween(versionText, type.getSrcStart(), type.getSrcEnd()); + if (!file.isFile() || !newestVersion.equals(getVersion(name))) { + success = downloadFile( + url + newestVersion + type.getDownloadURLPart() + newestVersion + ".jar", + filePath + ); + setVersion(name, newestVersion); + if (!success) { + System.out.println("Error downloading: " + name + version + ".jar"); + } + } + } else { + if (!file.isFile()) { + success = downloadFile(url + version + type.getDownloadURLPart() + version + ".jar", filePath); + if (!success) { + System.out.println("Error downloading: " + name + version + ".jar"); + } + } + } + } + } + + private static void downloadSponge() { + AdvancedServerType type = (AdvancedServerType) ServerType.getByName("SpongeVanilla"); + String url = Objects.requireNonNull(type).getDownloadURL(); + String name = type.getName(); + String versionText = ""; + String newestVersion; + Boolean success; + for (String version : type.getVersions()) { + File file = new File(jarDir + type.getName() + version + ".jar"); + Path filePath = Paths.get(jarDir + type.getName() + version + ".jar"); + Main.gui().setStatus("Downloading: " + name + version + ".jar"); + try { + versionText = readFile(type.getVersionURL() + version); + } catch (IOException e) { + System.out.println("Error reading: " + type.getVersionURL()); + } + newestVersion = Main.stringBetween(versionText, type.getSrcStart(), type.getSrcEnd()); + if (!file.isFile()) { + success = downloadFile( + url + newestVersion + type.getDownloadURLPart() + newestVersion + ".jar", + filePath + ); + if (!success) { + System.out.println("Error downloading: " + name + version + ".jar"); + } + } + } + } + + private static void downloadBungee() { + AdvancedServerType type = (AdvancedServerType) ServerType.getByName("Bungee"); + String url = Objects.requireNonNull(type).getDownloadURL(); + String name = type.getName(); + String versionText = ""; + String newestVersion; + Boolean success; + File file = new File(jarDir + type.getName() + ".jar"); + Path filePath = Paths.get(jarDir + type.getName() + ".jar"); + Main.gui().setStatus("Downloading: " + name + ".jar"); + try { + versionText = readFile(type.getVersionURL()); + } catch (IOException e) { + System.out.println("Error reading: " + type.getVersionURL()); + } + newestVersion = Main.stringBetween(versionText, type.getSrcStart(), type.getSrcEnd()); + if (!file.isFile() || !newestVersion.equals(getVersion(name))) { + success = downloadFile(url, filePath); + setVersion(name, newestVersion); + if (!success) { + System.out.println("Error downloading: " + name + ".jar"); + } + } + } + + /** + * Downloads a file from a website. + * + * @param path The full url of the file to download. + * @param outfile The file to save to + * @return True if successful. False otherwise + */ + private static boolean downloadFile(String path, Path outfile) { + try { + URL url = new URL(path); + InputStream in = url.openStream(); + Files.copy(in, outfile, StandardCopyOption.REPLACE_EXISTING); + return true; + } catch (IOException e) { + return false; + } + } + + /** + * Reads a file from a website. + * This is used to find the newest version of the software. + * + * @param path The full url of the file to read + * @return True if successful. False otherwise + */ + private static String readFile(String path) throws IOException { + URL url = new URL(path); + return new Scanner(url.openStream()).useDelimiter("\\Z").next(); + } + + /** + * Returns the current version of a type + * + * @param type The version type + * @return The version string + */ + private static String getVersion(String type) { + switch (type) { + case "Vanilla": + return vanillaVersion; + case "Snapshot": + return snapshotVersion; + case "Bungee": + return bungeeVersion; + default: + return ""; + } + } + + /** + * Sets a server type's last downloaded version. + * + * @param type The version type + * @param version The version string + */ + private static void setVersion(String type, String version) { + if (!type.equals("")) { + switch (type) { + case "Vanilla": + vanillaVersion = version; + break; + case "Snapshot": + snapshotVersion = version; + break; + case "Bungee": + bungeeVersion = version; + } + } + } } diff --git a/src/net/knarcraft/serverlauncher/server/AdvancedServerType.java b/src/net/knarcraft/serverlauncher/server/AdvancedServerType.java index 300c9d9..246aa76 100644 --- a/src/net/knarcraft/serverlauncher/server/AdvancedServerType.java +++ b/src/net/knarcraft/serverlauncher/server/AdvancedServerType.java @@ -7,7 +7,7 @@ package net.knarcraft.serverlauncher.server; * @version 0.0.0.1 * @since 0.0.0.1 */ -class AdvancedServerType extends ServerType { +public class AdvancedServerType extends ServerType { private final String versionURL; private final String downloadURLPart; private final String srcStart; diff --git a/src/net/knarcraft/serverlauncher/server/Server.java b/src/net/knarcraft/serverlauncher/server/Server.java index dadec2c..ab2065f 100644 --- a/src/net/knarcraft/serverlauncher/server/Server.java +++ b/src/net/knarcraft/serverlauncher/server/Server.java @@ -22,6 +22,7 @@ public class Server { private static final String[] ramList = { "512M", "1G", "2G", "3G", "4G", "5G", "6G", "7G", "8G", "9G", "10G","11G", "12G", "13G", "14G", "15G", "16G" }; + private static final String jarDir = Main.jarDir + File.separator + "files" + File.separator + "Jars" + File.separator; private final String name; private String path; @@ -209,14 +210,15 @@ public class Server { */ public static void stop() throws IOException { for (Collection collection : Profile.getCurrent().getCollections()) { - if (collection.getServer().writer != null) { - if (collection.getServer().type.getName().equals("Bungee")) { - collection.getServer().writer.write("end\n"); + Server server = collection.getServer(); + if (server.writer != null) { + if (server.type.getName().equals("Bungee")) { + server.writer.write("end\n"); } else { - collection.getServer().writer.write("stop\n"); + server.writer.write("stop\n"); } - collection.getServer().writer.flush(); - collection.getServer().writer = null; + server.writer.flush(); + server.writer = null; } } } @@ -238,25 +240,41 @@ public class Server { */ private boolean run() { if (this.enabled) { - try { - Main.gui().setStatus("Downloading jar..."); - this.downloadJar(); - Main.gui().setStatus("File downloaded"); - } catch (FileNotFoundException e) { - Main.gui().setStatus("Error: Jar file not found"); - return false; + if (!Profile.getCurrent().getDownloadJars()) { + try { + Main.gui().setStatus("Downloading jar..."); + this.downloadJar(); + Main.gui().setStatus("File downloaded"); + } catch (FileNotFoundException e) { + Main.gui().setStatus("Error: Jar file not found"); + return false; + } } try { - ProcessBuilder builder = new ProcessBuilder( - "java", - "-Xmx" + this.maxRam, - "-Xms512M", - "-Djline.terminal=jline.UnsupportedTerminal", - "-Dcom.mojang.eula.agree=true", - "-jar", - "\"" + this.path + "\\" + this.getType() + "\"", - "nogui" - ); + ProcessBuilder builder; + if (Profile.getCurrent().getDownloadJars() && !type.getName().equals("Custom")) { + builder = new ProcessBuilder( + "java", + "-Xmx" + this.maxRam, + "-Xms512M", + "-Djline.terminal=jline.UnsupportedTerminal", + "-Dcom.mojang.eula.agree=true", + "-jar", + "\"" + jarDir + this.getType() + "\"", + "nogui" + ); + } else { + builder = new ProcessBuilder( + "java", + "-Xmx" + this.maxRam, + "-Xms512M", + "-Djline.terminal=jline.UnsupportedTerminal", + "-Dcom.mojang.eula.agree=true", + "-jar", + "\"" + this.path + File.separator + this.getType() + "\"", + "nogui" + ); + } builder.directory(new File(this.path)); builder.redirectErrorStream(true); this.process = builder.start(); @@ -292,8 +310,8 @@ public class Server { */ private void downloadJar() throws FileNotFoundException { AdvancedServerType type; - File file = new File(this.path + "\\" + this.getType()); - Path filePath = Paths.get(this.path + "\\" + this.getType()); + File file = new File(this.path + File.separator + this.getType()); + Path filePath = Paths.get(this.path + File.separator + this.getType()); String versionText; String newestVersion; String url = this.type.getDownloadURL(); @@ -325,13 +343,13 @@ public class Server { } catch (IOException e) { throw new FileNotFoundException("Version file could not be downloaded."); } - newestVersion = stringBetween(versionText, type.getSrcStart(), type.getSrcEnd()); + newestVersion = Main.stringBetween(versionText, type.getSrcStart(), type.getSrcEnd()); if (!file.isFile() || !newestVersion.equals(this.getVersion(name))) { success = downloadFile( url + newestVersion + type.getDownloadURLPart() + newestVersion + ".jar", filePath ); - this.setVersion(this.type.getName(), newestVersion); + this.setVersion(name, newestVersion); if (!success) { throw new FileNotFoundException("Jar file could not be downloaded."); } @@ -352,7 +370,7 @@ public class Server { } catch (IOException e) { throw new FileNotFoundException("Version file could not be downloaded."); } - newestVersion = stringBetween(versionText, type.getSrcStart(), type.getSrcEnd()); + newestVersion = Main.stringBetween(versionText, type.getSrcStart(), type.getSrcEnd()); if (!file.isFile() || !newestVersion.equals(this.getVersion(name))) { success = downloadFile( url + newestVersion + type.getDownloadURLPart() + newestVersion + ".jar", @@ -371,7 +389,7 @@ public class Server { } catch (IOException e) { throw new FileNotFoundException("Version file could not be downloaded."); } - newestVersion = stringBetween(versionText, type.getSrcStart(), type.getSrcEnd()); + newestVersion = Main.stringBetween(versionText, type.getSrcStart(), type.getSrcEnd()); if (!file.isFile() || !newestVersion.equals(this.getVersion(name))) { success = downloadFile(url, filePath); this.setVersion(name, newestVersion); @@ -457,22 +475,6 @@ public class Server { } } - /** - * Finds a substring between two substrings in a string. - * - * @param string The string containing the substrings - * @param start The substring before the wanted substring - * @param end The substring after the wanted substring - * @return The wanted substring. - */ - private static String stringBetween(String string, String start, String end) { - int startPos = string.indexOf(start) + start.length(); - if (!string.contains(start) || string.indexOf(end, startPos) < startPos) { - return ""; - } - return string.substring(startPos, string.indexOf(end, startPos)); - } - /** * Sends a command to this server through its writer. * diff --git a/src/net/knarcraft/serverlauncher/userinterface/GUI.java b/src/net/knarcraft/serverlauncher/userinterface/GUI.java index ff219a6..0052951 100644 --- a/src/net/knarcraft/serverlauncher/userinterface/GUI.java +++ b/src/net/knarcraft/serverlauncher/userinterface/GUI.java @@ -540,7 +540,7 @@ public class GUI implements ActionListener { String serverName = JOptionPane.showInputDialog("Name of server: "); Profile.getCurrent().addCollection(serverName); this.update(); - ServerConsoles.update(); + Profile.getCurrent().updateConsoles(); } else if (e.getSource() == backup) { backup(); } else if (e.getSource() == addProfile) { @@ -591,12 +591,12 @@ public class GUI implements ActionListener { */ private void changeProfile() { Profile.getCurrent().save(); - Object current = profiles.getSelectedItem(); + Object current = this.profiles.getSelectedItem(); if (current != null) { Profile.setCurrent(current.toString()); } - update(); - ServerConsoles.update(); + this.update(); + Profile.getCurrent().updateConsoles(); } /** @@ -614,6 +614,7 @@ public class GUI implements ActionListener { "Error", JOptionPane.ERROR_MESSAGE ); + e1.printStackTrace(); } } diff --git a/src/net/knarcraft/serverlauncher/userinterface/ServerConsoles.java b/src/net/knarcraft/serverlauncher/userinterface/ServerConsoles.java index ef3cef9..6b95fac 100644 --- a/src/net/knarcraft/serverlauncher/userinterface/ServerConsoles.java +++ b/src/net/knarcraft/serverlauncher/userinterface/ServerConsoles.java @@ -36,10 +36,8 @@ public class ServerConsoles { public static void show() { frame.setVisible(true); } - public static void update() { - consolesTab.removeAll(); - for (Collection collection : Profile.getCurrent().getCollections()) { - consolesTab.add(collection.getName(), collection.getServerConsole().getPanel()); - } + + public static JTabbedPane getTab() { + return consolesTab; } } \ No newline at end of file diff --git a/src/net/knarcraft/serverlauncher/userinterface/ServerTab.java b/src/net/knarcraft/serverlauncher/userinterface/ServerTab.java index 5f12a12..540c014 100644 --- a/src/net/knarcraft/serverlauncher/userinterface/ServerTab.java +++ b/src/net/knarcraft/serverlauncher/userinterface/ServerTab.java @@ -172,7 +172,7 @@ public class ServerTab implements ActionListener { private void remove() { Profile.getCurrent().removeCollection(name); Main.gui().update(); - ServerConsoles.update(); + Profile.getCurrent().updateConsoles(); } private void browse() {