From a3de8a9f6c3937128b4be67b353858247c62eac2 Mon Sep 17 00:00:00 2001 From: Kristian Knarvik Date: Mon, 17 Aug 2020 21:41:38 +0200 Subject: [PATCH] Changes a lot of things to make everything cleaner. Closes #3 Drops the idea of using serializable Adds a new controller object which takes care of profiles and saving Moves profile independent settings to its own file Makes saving and loading from file a lot cleaner Fixes the bug preventing lastly used profile from loading Makes the profile object only do profile things Moves gui initialization to the controller object Updates vanilla version from 1.16.1 to 1.16.2 Moves backup to common functions --- .../minecraftserverlauncher/Main.java | 30 +- .../profile/Collection.java | 26 +- .../profile/Controller.java | 293 +++++++++++++ .../profile/Profile.java | 406 ++++-------------- .../server/Server.java | 53 ++- .../server/ServerVersionContainer.java | 23 +- .../server/servertypes/BungeeCord.java | 6 +- .../server/servertypes/CraftBukkit.java | 2 +- .../server/servertypes/Custom.java | 3 +- .../server/servertypes/SpongeVanilla.java | 8 +- .../server/servertypes/Travertine.java | 2 +- .../server/servertypes/Waterfall.java | 11 +- .../userinterface/Console.java | 4 +- .../userinterface/GUI.java | 10 + .../userinterface/MessageHandler.java | 3 + .../userinterface/ServerLauncherGUI.java | 155 +++---- .../userinterface/ServerTab.java | 10 +- .../utility/CommonFunctions.java | 49 ++- .../utility/JarDownloader.java | 2 +- src/main/resources/servertypes.csv | 2 +- .../server/ServerTest.java | 23 + .../server/ServerVersionContainerTest.java | 2 +- .../userinterface/FakeGUI.java | 7 + .../utility/CommonFunctionsTest.java | 10 +- 24 files changed, 603 insertions(+), 537 deletions(-) create mode 100644 src/main/java/net/knarcraft/minecraftserverlauncher/profile/Controller.java create mode 100644 src/test/java/net/knarcraft/minecraftserverlauncher/server/ServerTest.java diff --git a/src/main/java/net/knarcraft/minecraftserverlauncher/Main.java b/src/main/java/net/knarcraft/minecraftserverlauncher/Main.java index 8b77908..fd8a6d3 100644 --- a/src/main/java/net/knarcraft/minecraftserverlauncher/Main.java +++ b/src/main/java/net/knarcraft/minecraftserverlauncher/Main.java @@ -1,10 +1,10 @@ package net.knarcraft.minecraftserverlauncher; import net.knarcraft.minecraftserverlauncher.profile.Collection; -import net.knarcraft.minecraftserverlauncher.profile.Profile; +import net.knarcraft.minecraftserverlauncher.profile.Controller; import net.knarcraft.minecraftserverlauncher.server.Server; -import net.knarcraft.minecraftserverlauncher.userinterface.GUI; import net.knarcraft.minecraftserverlauncher.userinterface.ServerConsoles; +import net.knarcraft.minecraftserverlauncher.userinterface.ServerLauncherGUI; import net.knarcraft.minecraftserverlauncher.utility.CommonFunctions; import net.knarcraft.minecraftserverlauncher.utility.Updater; @@ -33,7 +33,8 @@ public class Main { private static boolean serversAreRunning = false; private static final String updateChannel = "alpha"; private static final String updateURL = "https://api.knarcraft.net/minecraftserverlauncher"; - private static GUI gui; + private static ServerLauncherGUI gui; + private static final Controller controller = Controller.getInstance(); public static void main(String[] args) throws IOException { Updater.checkForUpdate(updateURL, updateChannel, gui); @@ -45,8 +46,8 @@ public class Main { EventQueue.invokeLater(() -> { try { new ServerConsoles(); - Profile.load(); - gui = Profile.getGUI(); + controller.loadState(); + gui = controller.getGUI(); ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor(); exec.scheduleAtFixedRate(Main::updateConsoles, 10, 500, TimeUnit.MILLISECONDS); } catch (Exception e) { @@ -55,6 +56,15 @@ public class Main { }); } + /** + * Gets the controller used by the software + * + * @return

The controller used by the software

+ */ + public static Controller getController() { + return controller; + } + /** * Retrieves the directory the .jar file is running from * @@ -77,7 +87,7 @@ public class Main { */ private static void updateConsoles() { try { - for (Collection collection : Profile.getCurrent().getCollections()) { + for (Collection collection : controller.getCurrentProfile().getCollections()) { Server server = collection.getServer(); if (server.isEnabled() && server.getProcess() != null) { try { @@ -96,10 +106,10 @@ public class Main { } boolean runningNew = serversRunning(); if (!runningNew && serversAreRunning) { - Profile.getGUI().updateRunning(false); - Profile.getGUI().setStatus("Servers are stopped"); + gui.updateRunning(false); + gui.setStatus("Servers are stopped"); } else if (runningNew && !serversAreRunning) { - Profile.getGUI().updateRunning(true); + gui.updateRunning(true); } serversAreRunning = runningNew; } catch (Exception e) { @@ -114,7 +124,7 @@ public class Main { */ private static boolean serversRunning() { int num = 0; - for (Collection collection : Profile.getCurrent().getCollections()) { + for (Collection collection : controller.getCurrentProfile().getCollections()) { if (collection.getServer().isStarted() || (collection.getServer().getProcess() != null && collection.getServer().getProcess().isAlive())) { num++; diff --git a/src/main/java/net/knarcraft/minecraftserverlauncher/profile/Collection.java b/src/main/java/net/knarcraft/minecraftserverlauncher/profile/Collection.java index 42b3334..0dd037e 100644 --- a/src/main/java/net/knarcraft/minecraftserverlauncher/profile/Collection.java +++ b/src/main/java/net/knarcraft/minecraftserverlauncher/profile/Collection.java @@ -6,7 +6,6 @@ import net.knarcraft.minecraftserverlauncher.userinterface.ServerConsoles; import net.knarcraft.minecraftserverlauncher.userinterface.ServerTab; import javax.naming.ConfigurationException; -import java.io.Serializable; /** * Acts as a wrapper for objects necessary for each server. @@ -15,9 +14,9 @@ import java.io.Serializable; * @version 1.0.0 * @since 1.0.0 */ -public class Collection implements Serializable { +public class Collection { private final Server server; - private final transient ServerTab serverTab; + private final ServerTab serverTab; private final Console serverConsole; private final String name; @@ -45,25 +44,8 @@ public class Collection implements Serializable { this.server = server; this.serverConsole = ServerConsoles.addConsoleTab(serverName); this.name = serverName; - } - - /** - * Creates a new collection with the given parameters - * - * @param name

The name identifying the server, server tab, collection and server console

- * @param serverPath

The path of the server folder

- * @param enabled

Whether the server should be run when starting servers

- * @param typeName

The name of the server type the server uses

- * @param serverVersion

The version of the running server type.

- * @param maxRam

The maximum amount of RAM the server is allowed to use.

- */ - Collection(String name, String serverPath, boolean enabled, String typeName, String serverVersion, String maxRam) - throws ConfigurationException { - this.serverTab = new ServerTab(name); - this.server = new Server(name, serverPath, enabled, typeName, serverVersion, maxRam); - this.serverConsole = ServerConsoles.addConsoleTab(name); - this.name = name; - this.serverTab.setData(serverPath, enabled, typeName, serverVersion, maxRam); + this.serverTab.setData(server.getPath(), server.isEnabled(), server.getTypeName(), server.getServerVersion(), + server.getMaxRam()); } /** diff --git a/src/main/java/net/knarcraft/minecraftserverlauncher/profile/Controller.java b/src/main/java/net/knarcraft/minecraftserverlauncher/profile/Controller.java new file mode 100644 index 0000000..49b86b6 --- /dev/null +++ b/src/main/java/net/knarcraft/minecraftserverlauncher/profile/Controller.java @@ -0,0 +1,293 @@ +package net.knarcraft.minecraftserverlauncher.profile; + +import net.knarcraft.minecraftserverlauncher.Main; +import net.knarcraft.minecraftserverlauncher.server.Server; +import net.knarcraft.minecraftserverlauncher.server.ServerTypeHandler; +import net.knarcraft.minecraftserverlauncher.userinterface.ServerLauncherGUI; +import net.knarcraft.minecraftserverlauncher.userinterface.ServerTab; +import net.knarcraft.minecraftserverlauncher.utility.CommonFunctions; +import net.knarcraft.minecraftserverlauncher.utility.JarDownloader; + +import javax.naming.ConfigurationException; +import java.io.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; +import java.util.concurrent.Executors; + +/** + * This class controls + */ +public class Controller { + + private final String workingDirectory = Main.getApplicationWorkDirectory() + File.separator + "files"; + private final String profilesFile = workingDirectory + File.separator + "Profiles.txt"; + private final String mainFile = workingDirectory + File.separator + "Config.txt"; + private final String jarDirectory = workingDirectory + File.separator + "Jars" + File.separator; + private final List profileList; + private ServerLauncherGUI serverLauncherGUI; + private Profile currentProfile; + private boolean downloadAllJars; + private static Controller controller; + + private Controller() { + this.profileList = new ArrayList<>(); + } + + /** + * Gets an instance of the controller + * + * @return

An instance of the controller

+ */ + public static Controller getInstance() { + if (controller == null) { + controller = new Controller(); + } + return controller; + } + + /** + * Returns the GUI used by the software + * + * @return

The GUI used by the software

+ */ + public ServerLauncherGUI getGUI() { + return this.serverLauncherGUI; + } + + /** + * Gets whether to download all jar files + * + * @return

Whether to download all .jar files

+ */ + public boolean getDownloadAllJars() { + return downloadAllJars; + } + + /** + * Gets whether to run in background after closing + * + * @return

Whether to run in background after closing

+ */ + public boolean getRunInBackground() { + return currentProfile.getRunInBackground(); + } + + /** + * Gets whether to delay server startup + * + * @return

Whether to delay server startup

+ */ + public int getDelayStartup() { + return currentProfile.getDelayStartup(); + } + + @Override + public String toString() { + int guiWidth; + int guiHeight; + if (serverLauncherGUI == null) { + guiWidth = 440; + guiHeight = 170; + } else { + guiWidth = serverLauncherGUI.getSize().width; + guiHeight = serverLauncherGUI.getSize().height; + } + return String.format("%s;%d;%d;%b", currentProfile.getName(), guiWidth, guiHeight, downloadAllJars); + } + + /** + * Gets a profile by its name + * + * @param name

The name of the profile to get

+ * @return

The profile with the given name or null if not found

+ */ + public Profile getProfileByName(String name) { + for (Profile profile : profileList) { + if (profile.getName().equals(name)) { + return profile; + } + } + return null; + } + + /** + * Gets the names of all available profiles + * + * @return

A list of all available profiles

+ */ + public List getProfileNames() { + List profileNames = new ArrayList<>(); + profileList.forEach((profile) -> profileNames.add(profile.getName())); + return profileNames; + } + + /** + * Adds a profile if the name is valid and unique. + * + * @param name The name of the new profile. + */ + public void addProfile(String name) { + if (!CommonFunctions.nameIsValid(name)) { + serverLauncherGUI.showError("Profile name cannot be blank and cannot contain special characters."); + return; + } + for (Profile profile : profileList) { + if (profile.getName().equals(name)) { + serverLauncherGUI.showError("There is already a profile with this name."); + return; + } + } + Profile newProfile = new Profile(name); + profileList.add(newProfile); + if (currentProfile == null) { + currentProfile = newProfile; + } + } + + /** + * Removes a profile with the given name from the list of profiles, if such a profile exists + * + * @param name

The name of the profile to rempve

+ */ + public void removeProfile(String name) { + if (profileList.size() > 1) { + profileList.removeIf(profile -> profile.getName().equals(name)); + } else { + serverLauncherGUI.showError("This software requires the existence of at least one profile."); + } + } + + /** + * Gets the currently selected profile + * + * @return

The currently selected profile

+ */ + public Profile getCurrentProfile() { + return this.currentProfile; + } + + /** + * Loads data about the controller from a save string + * + * @param data

The save string to load

+ * @return

The currently selected profile

+ * @throws IOException

If unable to create the GUI

+ */ + private String fromString(String data) throws IOException { + String[] dataList = data.split(";"); + this.downloadAllJars = Boolean.parseBoolean(dataList[3]); + this.serverLauncherGUI = new ServerLauncherGUI(Integer.parseInt(dataList[1]), Integer.parseInt(dataList[2])); + return dataList[0]; + } + + /** + * Reads profiles and servers from a text file. + */ + public void loadState() throws ConfigurationException, IOException { + //Loads data regarding this controller + String currentProfile = null; + if (new File(mainFile).exists()) { + String controllerData = CommonFunctions.readBufferedReader(new BufferedReader(new InputStreamReader(new FileInputStream(mainFile)))); + currentProfile = this.fromString(controllerData); + } else { + this.serverLauncherGUI = new ServerLauncherGUI(); + } + + try (Scanner in = new Scanner(new File(profilesFile))) { + while (in.hasNextLine()) { + String profileData = in.nextLine(); + Profile loadedProfile = Profile.fromString(profileData); + profileList.add(loadedProfile); + } + } catch (FileNotFoundException e) { + addProfile("Default"); + } + + this.currentProfile = getProfileByName(currentProfile); + if (this.currentProfile == null) { + this.currentProfile = this.profileList.get(0); + } + + this.serverLauncherGUI.updateProfiles(); + this.serverLauncherGUI.update(); + this.currentProfile.updateConsoles(); + if (this.downloadAllJars) { + Executors.newSingleThreadExecutor().execute(() -> { + JarDownloader downloader = new JarDownloader(serverLauncherGUI, jarDirectory); + try { + downloader.downloadJars(); + } catch (IOException e) { + e.printStackTrace(); + } + }); + } + if (this.currentProfile.getRunInBackground()) { + Executors.newSingleThreadExecutor().execute(Server::startServers); + this.serverLauncherGUI.hide(); + } + } + + /** + * Sets the download all jars option + * + * @param downloadAllJars

Whether to download all jars

+ */ + public void setDownloadAllJars(boolean downloadAllJars) { + this.downloadAllJars = downloadAllJars; + } + + /** + * Sets the currently selected profile + * + * @param profileName

The name of the currently selected profile

+ */ + public void setCurrentProfile(String profileName) { + this.currentProfile = getProfileByName(profileName); + } + + /** + * Saves the state of the entire application to disk + */ + public void saveState() { + saveGUIStateToServer(); + try { + CommonFunctions.createAllFolders(); + PrintWriter mFile = new PrintWriter(mainFile); + mFile.println(this.toString()); + mFile.close(); + PrintWriter pFile = new PrintWriter(profilesFile); + for (Profile profile : profileList) { + pFile.println(profile.toString()); + } + pFile.close(); + } catch (FileNotFoundException e) { + serverLauncherGUI.showError("Unable to save data."); + e.printStackTrace(); + } + } + + /** + * Updates the server object with the current state of the GUI server tab + */ + private void saveGUIStateToServer() { + for (Collection collection : this.currentProfile.getCollections()) { + Server server = collection.getServer(); + ServerTab serverTab = collection.getServerTab(); + server.setPath(serverTab.getPath()); + server.setMaxRam(serverTab.getMaxRam()); + try { + server.setType(ServerTypeHandler.getByName(serverTab.getType())); + } catch (ConfigurationException e) { + e.printStackTrace(); + } + try { + server.setServerVersion(serverTab.getVersion()); + } catch (IllegalArgumentException e) { + serverLauncherGUI.showError("Invalid server version for " + server.getName()); + } + server.setEnabled(serverTab.enabled()); + } + } + +} diff --git a/src/main/java/net/knarcraft/minecraftserverlauncher/profile/Profile.java b/src/main/java/net/knarcraft/minecraftserverlauncher/profile/Profile.java index c1b51a5..d23fb0a 100644 --- a/src/main/java/net/knarcraft/minecraftserverlauncher/profile/Profile.java +++ b/src/main/java/net/knarcraft/minecraftserverlauncher/profile/Profile.java @@ -2,23 +2,14 @@ package net.knarcraft.minecraftserverlauncher.profile; import net.knarcraft.minecraftserverlauncher.Main; import net.knarcraft.minecraftserverlauncher.server.Server; -import net.knarcraft.minecraftserverlauncher.server.ServerTypeHandler; import net.knarcraft.minecraftserverlauncher.userinterface.ServerConsoles; import net.knarcraft.minecraftserverlauncher.userinterface.ServerLauncherGUI; -import net.knarcraft.minecraftserverlauncher.userinterface.ServerTab; -import net.knarcraft.minecraftserverlauncher.utility.JarDownloader; +import net.knarcraft.minecraftserverlauncher.utility.CommonFunctions; import javax.naming.ConfigurationException; import javax.swing.*; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileWriter; -import java.io.IOException; -import java.io.PrintWriter; +import java.io.*; import java.util.ArrayList; -import java.util.NoSuchElementException; -import java.util.Scanner; -import java.util.concurrent.Executors; /** * Contains all user settings, and a list of servers. @@ -27,110 +18,38 @@ import java.util.concurrent.Executors; * @version 1.0.0 * @since 1.0.0 */ -public class Profile implements java.io.Serializable { - private static final ArrayList profiles = new ArrayList<>(); - private static final String workingDirectory = Main.getApplicationWorkDirectory() + File.separator + "files"; - private static final String profilesDir = workingDirectory; - private static final String profilesFile = workingDirectory + File.separator + "Profiles.txt"; - private static final String jarDirectory = workingDirectory + File.separator + "Jars" + File.separator; - private static Profile current; - private static transient ServerLauncherGUI serverLauncherGui; +public class Profile { + + private static final ServerLauncherGUI serverLauncherGui = Main.getController().getGUI(); private final ArrayList collections; private final String name; private boolean runInBackground; private int delayStartup; - private boolean downloadAllAvailableJARFiles; - private Profile(String name) { + /** + * Instantiates a new default profile + * + * @param name

The name of the profile

+ */ + public Profile(String name) { this.collections = new ArrayList<>(); this.name = name; this.runInBackground = false; this.delayStartup = 0; - this.downloadAllAvailableJARFiles = false; - profiles.add(this); - if (current == null) { - current = this; - } } - private Profile(String name, boolean runInBackground, int delayStartup, boolean downloadAllAvailableJARFiles) { + /** + * Instantiates a new profile + * + * @param name

The name of the profile

+ * @param runInBackground

Whether to run the software in the background the next time it starts

+ * @param delayStartup

Whether to delay the startup of servers

+ */ + private Profile(String name, boolean runInBackground, int delayStartup) { this.collections = new ArrayList<>(); this.name = name; this.runInBackground = runInBackground; this.delayStartup = delayStartup; - this.downloadAllAvailableJARFiles = downloadAllAvailableJARFiles; - profiles.add(this); - if (current == null) { - current = this; - } - } - - public static ServerLauncherGUI getGUI() { - return serverLauncherGui; - } - - public static Profile getCurrent() { - return current; - } - - /** - * Set the current profile to the profile with a certain name. - * - * @param name The name of the profile - */ - public static void setCurrent(String name) { - for (Profile profile : profiles) { - if (profile.name.equals(name)) { - current = profile; - break; - } - } - } - - public static Profile getProfile(String name) { - for (Profile profile : profiles) { - if (profile.name.equals(name)) { - return profile; - } - } - return null; - } - - public static ArrayList getProfiles() { - return profiles; - } - - /** - * Adds a profile if the name is valid and unique. - * - * @param name The name of the new profile. - */ - public static void addProfile(String name) { - if (name == null) { //If a user cancels or crosses out window - return; - } - if (name.equals("") && !name.matches("^[!?;]+$")) { - serverLauncherGui.showError("Profile name can't be blank."); - return; - } - for (Profile profile : profiles) { - if (profile.name.equals(name)) { - serverLauncherGui.showError("There is already a profile with this name."); - return; - } - } - new Profile(name); - } - - /** - * Removes a profile with the given name from the list of profiles, if such a profile exists - * - * @param name

The name of the profile to rempve

- */ - public static void removeProfile(String name) { - if (profiles.size() > 1) { - profiles.removeIf(profile -> profile.name.equals(name)); - } } /** @@ -140,67 +59,47 @@ public class Profile implements java.io.Serializable { * @return

The new profile

*/ private static Profile parseProfile(String[] profileData) { - return new Profile( - profileData[0], - Boolean.parseBoolean(profileData[1]), - Integer.parseInt(profileData[2]), - Boolean.parseBoolean(profileData[3]) - ); + return new Profile(profileData[0], Boolean.parseBoolean(profileData[1]), Integer.parseInt(profileData[2])); } /** - * Parses a server, and creates a new collection. + * Gets whether the software should keep running in the background * - * @param profile

The profile which to add the collection

- * @param serverData

The data to parse

+ * @return

Whether the software should keep running in the backgound

*/ - private static void parseServer(Profile profile, String[] serverData) throws ConfigurationException { - profile.collections.add(new Collection( - serverData[0], - serverData[1], - Boolean.parseBoolean(serverData[2]), - serverData[3], - serverData[4], - serverData[5]) - ); - } - public boolean getRunInBackground() { return this.runInBackground; } + /** + * Sets whether the software should keep running in the background + * + * @param value

Whether the software should keep running in the background

+ */ public void setRunInBackground(boolean value) { this.runInBackground = value; } + /** + * Gets the number of seconds to delay startup + * + * @return

The number of seconds to delay starup

+ */ public int getDelayStartup() { return this.delayStartup; } + /** + * Sets the amount of time to delay startup + * + * @param value

The number of seconds to delay startup

+ */ public void setDelayStartup(int value) { if (value >= 0) { this.delayStartup = value; } } - /** - * Gets the state of the download all jar files setting - * - * @return

Whether to download all jars

- */ - public boolean getDownloadAllAvailableJARFiles() { - return this.downloadAllAvailableJARFiles; - } - - /** - * Sets the state of the download all jar files setting - * - * @param value

The new value of the download all jar files setting

- */ - public void setDownloadAllAvailableJARFiles(boolean value) { - this.downloadAllAvailableJARFiles = value; - } - /** * Gets all collections stored as part of this profile * @@ -243,13 +142,7 @@ public class Profile implements java.io.Serializable { if (name == null) { //If a user cancels or crosses out window return; } - if (getCollection(name) == null && - !name.equals("") && - !name.equals("All") && - !name.contains("!") && - !name.contains("?") && - !name.contains(";") - ) { + if (getCollection(name) == null && !name.equals("All") && CommonFunctions.nameIsValid(name)) { collections.add(new Collection(name)); } else { serverLauncherGui.showError("A server name must my unique and not empty or \"All\"." + @@ -257,6 +150,11 @@ public class Profile implements java.io.Serializable { } } + /** + * Removes the collection with the given name + * + * @param name

The name of the collection to remove

+ */ public void removeCollection(String name) { for (int i = 0; i < collections.size(); i++) { if (collections.get(i).getName().equals(name)) { @@ -267,6 +165,9 @@ public class Profile implements java.io.Serializable { } } + /** + * Updates console tabs with the current servers + */ public void updateConsoles() { JTabbedPane consolesTab = ServerConsoles.getTabbedPane(); consolesTab.removeAll(); @@ -278,8 +179,8 @@ public class Profile implements java.io.Serializable { /** * Sends a command to a server, or all servers * - * @param serverName The target server - * @param command The command to send. + * @param serverName

The target server

+ * @param command

The command to send

*/ public void sendCommand(String serverName, String command) { if (serverName.equals("All")) { @@ -305,194 +206,45 @@ public class Profile implements java.io.Serializable { } } - /** - * Reads all server tabs, and saves it to the variables of the corresponding servers. - * Saves all profiles and servers to a text file. - */ - public void save() throws FileNotFoundException { - /*try { - FileOutputStream fileOut = - new FileOutputStream(profilesFile); - ObjectOutputStream out = new ObjectOutputStream(fileOut); - out.writeObject(this); - out.close(); - fileOut.close(); - } catch (IOException i) { - System.out.println("Unable to serialize or write the profile settings file"); - i.printStackTrace(); - }*/ - + @Override + public String toString() { + StringBuilder saveString = new StringBuilder(String.format( + "%s;%b;%d?", + this.name, + this.runInBackground, + this.delayStartup) + ); for (Collection collection : this.collections) { - Server server = collection.getServer(); - ServerTab serverTab = collection.getServerTab(); - server.setPath(serverTab.getPath()); - server.setMaxRam(serverTab.getMaxRam()); - try { - server.setType(ServerTypeHandler.getByName(serverTab.getType())); - } catch (ConfigurationException e) { - e.printStackTrace(); - } - try { - server.setServerVersion(serverTab.getVersion()); - } catch (IllegalArgumentException e) { - serverLauncherGui.showError("Invalid server version for " + server.getName()); - } - server.setEnabled(serverTab.enabled()); - } - if (!new File(profilesDir).exists() && !new File(profilesDir).mkdirs()) { - serverLauncherGui.showError("Unable to create the folder " + profilesDir); - throw new FileNotFoundException("Unable to create the profiles folder: " + profilesDir); - } - try (PrintWriter file = new PrintWriter(profilesFile)) { - int width; - int height; - if (serverLauncherGui == null) { - width = 440; - height = 170; - } else { - width = serverLauncherGui.getSize().width; - height = serverLauncherGui.getSize().height; - } - file.println(String.format( - "%s;%s;%s", - current.name, - width, - height - )); - file.close(); - for (Profile profile : profiles) { - StringBuilder saveString = new StringBuilder(String.format( - "%s;%b;%d;%b?", - profile.name, - profile.runInBackground, - profile.delayStartup, - profile.downloadAllAvailableJARFiles) - ); - for (Collection collection : profile.collections) { - Server server = collection.getServer(); - saveString.append(String.format( - "%s;%s;%b;%s;%s;%s!", - server.getName(), - server.getPath(), - server.isEnabled(), - server.getTypeName(), - server.getServerVersion(), - server.getMaxRam() - ) - ); - } - saveString = new StringBuilder(saveString.substring(0, saveString.length() - 1)); - try (PrintWriter fileAppend = new PrintWriter(new FileWriter( - profilesFile, - true - ))) { - fileAppend.println(saveString); - } catch (IOException e) { - if (serverLauncherGui != null) { - serverLauncherGui.showError("Unable to save to file. Try running the software as an administrator."); - } else { - System.out.println("Unable to save to file. Try running the software as an administrator."); - } - throw new FileNotFoundException("Unable to save to the profiles file."); - } - } - } catch (IOException e) { - if (serverLauncherGui != null) { - serverLauncherGui.showError("Unable to save to file. Try running the software as an administrator."); - } - throw new FileNotFoundException("Unable to create the profiles file"); + saveString.append(collection.getServer().toString()); } + saveString = new StringBuilder(saveString.substring(0, saveString.length() - 1)); + return saveString.toString(); } /** - * Reads profiles and servers from a text file. + * Gets a profile given a saved string + * + * @param profileString

The string containing all profile data

+ * @return

A profile with the given data

+ * @throws ConfigurationException

If unable to load one of the profile's servers

*/ - public static void load() throws ConfigurationException, IOException { - /*Profile p; - if (!new File(profilesFile).exists()) { - addProfile("Default"); - return; - } - try { - FileInputStream fileIn = new FileInputStream(profilesFile); - ObjectInputStream in = new ObjectInputStream(fileIn); - p = (Profile) in.readObject(); - in.close(); - fileIn.close(); - profiles.add(p); - } catch (IOException i) { - i.printStackTrace(); - } catch (ClassNotFoundException c) { - System.out.println("Profile class not found"); - c.printStackTrace(); - }*/ - - try (Scanner in = new Scanner(new File(profilesFile))) { - try { - String[] staticData = in.nextLine().split(";", -1); - String profileName = staticData[0]; - int guiWidth = Integer.parseInt(staticData[1]); - int guiHeight = Integer.parseInt(staticData[2]); - serverLauncherGui = new ServerLauncherGUI(guiWidth, guiHeight); - while (in.hasNextLine()) { - String line = in.nextLine(); - if (line.contains("?")) { - String[] data = line.split("\\?"); - String[] profileData = data[0].split(";", -1); - Profile profile = parseProfile(profileData); - if (data[1].contains("!")) { - String[] servers = data[1].split("!", -1); - for (String server : servers) { - String[] serverData = server.split(";", -1); - parseServer(profile, serverData); - } - } else { - String[] serverData = data[1].split(";", -1); - parseServer(profile, serverData); - } - } else { - String[] profileData = line.split(";", -1); - parseProfile(profileData); - } + public static Profile fromString(String profileString) throws ConfigurationException { + Profile profile; + if (profileString.contains("?")) { + String[] data = profileString.split("\\?"); + String[] profileData = data[0].split(";", -1); + profile = parseProfile(profileData); + if (data[1].contains("!")) { + String[] servers = data[1].split("!", -1); + for (String server : servers) { + profile.collections.add(new Collection(Server.fromString(server))); } - current = getProfile(profileName); - } catch (ArrayIndexOutOfBoundsException | NumberFormatException e) { - e.printStackTrace(); - serverLauncherGui = new ServerLauncherGUI(); - serverLauncherGui.showError("Invalid Profile.txt file. Profiles could not be loaded. If this error persists, please " + - "manually delete the file."); - System.exit(1); - } catch (IOException e) { - e.printStackTrace(); + } else { + profile.collections.add(new Collection(Server.fromString(data[1]))); } - if (profiles.size() == 0) { - addProfile("Default"); - } - } catch (FileNotFoundException | NoSuchElementException e) { - try { - serverLauncherGui = new ServerLauncherGUI(); - serverLauncherGui.showMessage("A profiles file was not found. Default profile was created."); - } catch (IOException ex) { - ex.printStackTrace(); - } - addProfile("Default"); - } - serverLauncherGui.update(); - serverLauncherGui.updateProfiles(); - current.updateConsoles(); - if (current.downloadAllAvailableJARFiles) { - Executors.newSingleThreadExecutor().execute(() -> { - JarDownloader downloader = new JarDownloader(serverLauncherGui, jarDirectory); - try { - downloader.downloadJars(); - } catch (IOException e) { - e.printStackTrace(); - } - }); - } - if (current.runInBackground) { - Executors.newSingleThreadExecutor().execute(Server::startServers); - serverLauncherGui.hide(); + } else { + profile = parseProfile(profileString.split(";", -1)); } + return profile; } } diff --git a/src/main/java/net/knarcraft/minecraftserverlauncher/server/Server.java b/src/main/java/net/knarcraft/minecraftserverlauncher/server/Server.java index 2a237d5..40dc806 100644 --- a/src/main/java/net/knarcraft/minecraftserverlauncher/server/Server.java +++ b/src/main/java/net/knarcraft/minecraftserverlauncher/server/Server.java @@ -2,7 +2,7 @@ package net.knarcraft.minecraftserverlauncher.server; import net.knarcraft.minecraftserverlauncher.Main; import net.knarcraft.minecraftserverlauncher.profile.Collection; -import net.knarcraft.minecraftserverlauncher.profile.Profile; +import net.knarcraft.minecraftserverlauncher.profile.Controller; import net.knarcraft.minecraftserverlauncher.server.servertypes.ServerType; import javax.naming.ConfigurationException; @@ -25,7 +25,7 @@ import java.util.concurrent.TimeUnit; * @version 1.0.0 * @since 1.0.0 */ -public class Server implements java.io.Serializable { +public class Server { /** * Available ram sizes. For ServerLauncherGUI dropdown */ @@ -108,7 +108,7 @@ public class Server implements java.io.Serializable { * @throws IOException If a writer's process is already closed but not null. */ public static void stop() throws IOException { - for (Collection collection : Profile.getCurrent().getCollections()) { + for (Collection collection : Main.getController().getCurrentProfile().getCollections()) { Server server = collection.getServer(); if (server.writer != null) { if (server.type.isProxy()) { @@ -127,16 +127,17 @@ public class Server implements java.io.Serializable { * Runs all enabled servers with their settings */ public static void startServers() { - Profile.getGUI().setStatus("Starting servers"); - for (Collection collection : Profile.getCurrent().getCollections()) { + Controller controller = Main.getController(); + controller.getGUI().setStatus("Starting servers"); + for (Collection collection : controller.getCurrentProfile().getCollections()) { if (!collection.getServer().runServer()) { - Profile.getGUI().setStatus("An error occurred. Start aborted"); + controller.getGUI().setStatus("An error occurred. Start aborted"); try { Server.stop(); } catch (IOException e) { e.printStackTrace(); } - Profile.getGUI().updateRunning(false); + controller.getGUI().updateRunning(false); return; } } @@ -322,7 +323,7 @@ public class Server implements java.io.Serializable { */ public void addPlayer(String name) { this.playerList.add(name); - Profile.getGUI().addPlayer(name); + Main.getController().getGUI().addPlayer(name); } /** @@ -332,7 +333,7 @@ public class Server implements java.io.Serializable { */ public void removePlayer(String name) { playerList.removeIf(player -> player.equals(name)); - Profile.getGUI().removePlayer(name); + Main.getController().getGUI().removePlayer(name); } /** @@ -350,22 +351,24 @@ public class Server implements java.io.Serializable { * @return

True if nothing went wrong

*/ private boolean runServer() { + //Ignore a disabled server if (!this.enabled) { this.started = false; return true; } - this.started = true; + //Tries to do necessary pre-start work if (!initializeJarDownload() || !delayStartup()) { + this.started = false; return false; } - + //Starts the server if possible try { startServerProcess(); - Profile.getGUI().setStatus("Servers are running"); + Main.getController().getGUI().setStatus("Servers are running"); this.started = true; return true; } catch (IOException e) { - Profile.getGUI().setStatus("Could not start server"); + Main.getController().getGUI().setStatus("Could not start server"); this.started = false; return false; } @@ -379,16 +382,11 @@ public class Server implements java.io.Serializable { private void startServerProcess() throws IOException { ProcessBuilder builder; String serverPath; - String serverFile; + //Decide the path of the .jar file to be executed if (type.getName().equals("Custom")) { - serverFile = serverVersion; + serverPath = this.path + File.separator + serverVersion; } else { - serverFile = this.type.getName() + serverVersion + ".jar"; - } - if (!type.getName().equals("Custom")) { - serverPath = jarDirectory + serverFile; - } else { - serverPath = this.path + File.separator + serverFile; + serverPath = jarDirectory + this.type.getName() + serverVersion + ".jar"; } builder = new ProcessBuilder("java", "-Xmx" + this.maxRam, "-Xms512M", "-Djline.terminal=jline.UnsupportedTerminal", "-Dcom.mojang.eula.agree=true", "-jar", serverPath, @@ -407,8 +405,8 @@ public class Server implements java.io.Serializable { */ private boolean delayStartup() { try { - Profile.getGUI().setStatus("Delaying startup"); - TimeUnit.SECONDS.sleep(Profile.getCurrent().getDelayStartup()); + Main.getController().getGUI().setStatus("Delaying startup"); + TimeUnit.SECONDS.sleep(Main.getController().getCurrentProfile().getDelayStartup()); return true; } catch (InterruptedException e) { e.printStackTrace(); @@ -423,13 +421,14 @@ public class Server implements java.io.Serializable { * @return

True if nothing went wrong

*/ private boolean initializeJarDownload() { - if (!Profile.getCurrent().getDownloadAllAvailableJARFiles()) { + Controller controller = Main.getController(); + if (!controller.getDownloadAllJars()) { try { - Profile.getGUI().setStatus("Downloading jar..."); + controller.getGUI().setStatus("Downloading jar..."); this.downloadJar(); - Profile.getGUI().setStatus("File downloaded"); + controller.getGUI().setStatus("File downloaded"); } catch (IOException e) { - Profile.getGUI().setStatus("Error: Jar file not found"); + controller.getGUI().setStatus("Error: Jar file not found"); e.printStackTrace(); this.started = false; return false; diff --git a/src/main/java/net/knarcraft/minecraftserverlauncher/server/ServerVersionContainer.java b/src/main/java/net/knarcraft/minecraftserverlauncher/server/ServerVersionContainer.java index a95680a..dc43ec2 100644 --- a/src/main/java/net/knarcraft/minecraftserverlauncher/server/ServerVersionContainer.java +++ b/src/main/java/net/knarcraft/minecraftserverlauncher/server/ServerVersionContainer.java @@ -10,10 +10,10 @@ import java.util.Map; /** * This class acts as a container for all "latest" server versions */ -public class ServerVersionContainer implements java.io.Serializable { +public class ServerVersionContainer { private static ServerVersionContainer serverVersionContainer; - private String versionFile = Main.getApplicationWorkDirectory() + File.separator + "files" + File.separator + "versions.csv"; + private final String versionFile = Main.getApplicationWorkDirectory() + File.separator + "files" + File.separator + "versions.csv"; private String vanillaVersion; private String snapshotVersion; private String bungeeVersion; @@ -273,15 +273,6 @@ public class ServerVersionContainer implements java.io.Serializable { saveState(); } - /** - * Gets the entire sponge vanilla version map - * - * @return

The entire sponge vanilla version map

- */ - public Map getSpongeVanillaVersions() { - return this.spongeVanillaVersions; - } - /** * Gets a specific sponge vanilla version * @@ -292,16 +283,6 @@ public class ServerVersionContainer implements java.io.Serializable { return spongeVanillaVersions.get(versionKey); } - /** - * Replaces the entire sponge vanilla version map - * - * @param newVersions

The new version map to use

- */ - public void setSpongeVanillaVersion(Map newVersions) { - this.spongeVanillaVersions = newVersions; - saveState(); - } - /** * Sets the current version for a given sponge vanilla version * diff --git a/src/main/java/net/knarcraft/minecraftserverlauncher/server/servertypes/BungeeCord.java b/src/main/java/net/knarcraft/minecraftserverlauncher/server/servertypes/BungeeCord.java index 0f2e93e..a0b946b 100644 --- a/src/main/java/net/knarcraft/minecraftserverlauncher/server/servertypes/BungeeCord.java +++ b/src/main/java/net/knarcraft/minecraftserverlauncher/server/servertypes/BungeeCord.java @@ -12,9 +12,9 @@ import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.stri public class BungeeCord extends AbstractServerType { - private String versionURL; - private String srcStart; - private String srcEnd; + private final String versionURL; + private final String srcStart; + private final String srcEnd; /** * Instantiates a new BungeeCord server type diff --git a/src/main/java/net/knarcraft/minecraftserverlauncher/server/servertypes/CraftBukkit.java b/src/main/java/net/knarcraft/minecraftserverlauncher/server/servertypes/CraftBukkit.java index a56e389..235d2ef 100644 --- a/src/main/java/net/knarcraft/minecraftserverlauncher/server/servertypes/CraftBukkit.java +++ b/src/main/java/net/knarcraft/minecraftserverlauncher/server/servertypes/CraftBukkit.java @@ -10,7 +10,7 @@ import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.down */ public class CraftBukkit extends AbstractServerType { - private String downloadURLPart; + private final String downloadURLPart; /** * Instantiates a new server type diff --git a/src/main/java/net/knarcraft/minecraftserverlauncher/server/servertypes/Custom.java b/src/main/java/net/knarcraft/minecraftserverlauncher/server/servertypes/Custom.java index 224408c..814b7a9 100644 --- a/src/main/java/net/knarcraft/minecraftserverlauncher/server/servertypes/Custom.java +++ b/src/main/java/net/knarcraft/minecraftserverlauncher/server/servertypes/Custom.java @@ -1,7 +1,6 @@ package net.knarcraft.minecraftserverlauncher.server.servertypes; import java.io.File; -import java.io.IOException; public class Custom extends AbstractServerType { /** @@ -14,7 +13,7 @@ public class Custom extends AbstractServerType { } @Override - public boolean downloadJar(String folder, String version) throws IOException { + public boolean downloadJar(String folder, String version) { File filePath = new File(folder + version); return filePath.isFile(); } diff --git a/src/main/java/net/knarcraft/minecraftserverlauncher/server/servertypes/SpongeVanilla.java b/src/main/java/net/knarcraft/minecraftserverlauncher/server/servertypes/SpongeVanilla.java index 3fa326f..ed18c15 100644 --- a/src/main/java/net/knarcraft/minecraftserverlauncher/server/servertypes/SpongeVanilla.java +++ b/src/main/java/net/knarcraft/minecraftserverlauncher/server/servertypes/SpongeVanilla.java @@ -11,10 +11,10 @@ import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.down public class SpongeVanilla extends AbstractServerType { - private String versionURL; - private String srcStart; - private String srcEnd; - private String downloadURLPart; + private final String versionURL; + private final String srcStart; + private final String srcEnd; + private final String downloadURLPart; /** * Instantiates a new SpongeVanilla server type diff --git a/src/main/java/net/knarcraft/minecraftserverlauncher/server/servertypes/Travertine.java b/src/main/java/net/knarcraft/minecraftserverlauncher/server/servertypes/Travertine.java index 8286d6f..bebad43 100644 --- a/src/main/java/net/knarcraft/minecraftserverlauncher/server/servertypes/Travertine.java +++ b/src/main/java/net/knarcraft/minecraftserverlauncher/server/servertypes/Travertine.java @@ -19,7 +19,7 @@ public class Travertine extends Waterfall { String srcEnd, String downloadURL) { super(typeName, isProxy, versions, versionURL, srcStart, srcEnd, downloadURL); this.oldVersion = ServerVersionContainer.getInstance().getTravertineVersion(); - this.versionUpdateFunction = (newVersion) -> serverVersionContainer.setTravertineVersion(newVersion); + this.versionUpdateFunction = serverVersionContainer::setTravertineVersion; } } diff --git a/src/main/java/net/knarcraft/minecraftserverlauncher/server/servertypes/Waterfall.java b/src/main/java/net/knarcraft/minecraftserverlauncher/server/servertypes/Waterfall.java index cea6ce0..3b8d247 100644 --- a/src/main/java/net/knarcraft/minecraftserverlauncher/server/servertypes/Waterfall.java +++ b/src/main/java/net/knarcraft/minecraftserverlauncher/server/servertypes/Waterfall.java @@ -6,7 +6,6 @@ import java.io.File; import java.io.IOException; import java.nio.file.Paths; import java.util.function.Consumer; -import java.util.function.Function; import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.downloadFile; import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.readFile; @@ -14,12 +13,12 @@ import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.stri public class Waterfall extends AbstractServerType { - private String srcStart; - private String srcEnd; - private String versionURL; + private final String srcStart; + private final String srcEnd; + private final String versionURL; String oldVersion; Consumer versionUpdateFunction; - ServerVersionContainer serverVersionContainer; + final ServerVersionContainer serverVersionContainer; /** * Instantiates a new Waterfall server type @@ -40,7 +39,7 @@ public class Waterfall extends AbstractServerType { this.srcEnd = srcEnd; this.versionURL = versionURL; this.oldVersion = serverVersionContainer.getWaterfallVersion(); - this.versionUpdateFunction = (newVersion) -> serverVersionContainer.setWaterfallVersion(newVersion); + this.versionUpdateFunction = serverVersionContainer::setWaterfallVersion; } @Override diff --git a/src/main/java/net/knarcraft/minecraftserverlauncher/userinterface/Console.java b/src/main/java/net/knarcraft/minecraftserverlauncher/userinterface/Console.java index 2601f4f..a420e03 100644 --- a/src/main/java/net/knarcraft/minecraftserverlauncher/userinterface/Console.java +++ b/src/main/java/net/knarcraft/minecraftserverlauncher/userinterface/Console.java @@ -1,6 +1,6 @@ package net.knarcraft.minecraftserverlauncher.userinterface; -import net.knarcraft.minecraftserverlauncher.profile.Profile; +import net.knarcraft.minecraftserverlauncher.Main; import javax.swing.*; import javax.swing.text.DefaultCaret; @@ -66,7 +66,7 @@ public class Console implements ActionListener, KeyListener { //Sends the command from the input to the server with the same name. if (e.getSource() == textInput) { java.lang.String text = textInput.getText(); - Profile.getCurrent().sendCommand(this.name, text); + Main.getController().getCurrentProfile().sendCommand(this.name, text); commands.add(text); if (commands.size() > 25) { commands.remove(0); diff --git a/src/main/java/net/knarcraft/minecraftserverlauncher/userinterface/GUI.java b/src/main/java/net/knarcraft/minecraftserverlauncher/userinterface/GUI.java index 098c872..c56b869 100644 --- a/src/main/java/net/knarcraft/minecraftserverlauncher/userinterface/GUI.java +++ b/src/main/java/net/knarcraft/minecraftserverlauncher/userinterface/GUI.java @@ -1,5 +1,7 @@ package net.knarcraft.minecraftserverlauncher.userinterface; +import java.io.File; + /** * Describes a generic GUI */ @@ -42,4 +44,12 @@ public interface GUI { */ void showMessage(String message); + /** + * Asks the user for a directory as a file object + * + * @param prompt

The prompt to show the user

+ * @return

The directory given by the user

+ */ + File askForDirectory(String prompt); + } diff --git a/src/main/java/net/knarcraft/minecraftserverlauncher/userinterface/MessageHandler.java b/src/main/java/net/knarcraft/minecraftserverlauncher/userinterface/MessageHandler.java index 6c09f5a..7366b15 100644 --- a/src/main/java/net/knarcraft/minecraftserverlauncher/userinterface/MessageHandler.java +++ b/src/main/java/net/knarcraft/minecraftserverlauncher/userinterface/MessageHandler.java @@ -2,6 +2,9 @@ package net.knarcraft.minecraftserverlauncher.userinterface; import javax.swing.*; +/** + * This class handles displaying messages to the user + */ public abstract class MessageHandler implements GUI { private final boolean silent; diff --git a/src/main/java/net/knarcraft/minecraftserverlauncher/userinterface/ServerLauncherGUI.java b/src/main/java/net/knarcraft/minecraftserverlauncher/userinterface/ServerLauncherGUI.java index 77eb499..69f8849 100644 --- a/src/main/java/net/knarcraft/minecraftserverlauncher/userinterface/ServerLauncherGUI.java +++ b/src/main/java/net/knarcraft/minecraftserverlauncher/userinterface/ServerLauncherGUI.java @@ -2,6 +2,7 @@ package net.knarcraft.minecraftserverlauncher.userinterface; import net.knarcraft.minecraftserverlauncher.Main; import net.knarcraft.minecraftserverlauncher.profile.Collection; +import net.knarcraft.minecraftserverlauncher.profile.Controller; import net.knarcraft.minecraftserverlauncher.profile.Profile; import net.knarcraft.minecraftserverlauncher.server.Server; import net.knarcraft.minecraftserverlauncher.utility.CommonFunctions; @@ -62,6 +63,7 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener, private String aboutText; private SystemTray tray; private TrayIcon trayIcon; + private Controller controller; /** * Creates the application window @@ -70,6 +72,7 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener, super(false); initialize(440, 170); loadMessages(); + this.controller = Main.getController(); this.globalPlayers = new ArrayList<>(); } @@ -83,6 +86,7 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener, super(false); initialize(width, height); loadMessages(); + this.controller = Main.getController(); this.globalPlayers = new ArrayList<>(); } @@ -105,6 +109,21 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener, } } + @Override + public File askForDirectory(String prompt) { + JFileChooser chooser = new JFileChooser(); + chooser.setCurrentDirectory(new java.io.File(".")); + chooser.setDialogTitle(prompt); + chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + chooser.setAcceptAllFileFilterUsed(false); + + if (chooser.showOpenDialog(null) != JFileChooser.APPROVE_OPTION) { + setStatus("Choice aborted by user"); + return null; + } + return chooser.getSelectedFile(); + } + /** * Adds a player to the global playerlist, and updates the players combo. * @@ -129,10 +148,12 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener, * Updates the profiles combo. */ public void updateProfiles() { + String selectedProfile = Main.getController().getCurrentProfile().getName(); this.profiles.removeAllItems(); - for (Profile profile : Profile.getProfiles()) { - this.profiles.addItem(profile.getName()); + for (String profile : Main.getController().getProfileNames()) { + this.profiles.addItem(profile); } + this.profiles.setSelectedItem(selectedProfile); } /** @@ -148,16 +169,15 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener, * Updates ServerLauncherGUI according to current profile settings. */ public void update() { + Controller controller = Main.getController(); serversPane.removeAll(); - for (Collection collection : Profile.getCurrent().getCollections()) { - serversPane.addTab(collection.getName(), collection.getServerTab().getPanel()); - } - chckbxmntmRunInBackground.setState(Profile.getCurrent().getRunInBackground()); - chckbxmntmDelayStartup.setState(Profile.getCurrent().getDelayStartup() > 0); - chckbxmntmDownloadJars.setState(Profile.getCurrent().getDownloadAllAvailableJARFiles()); + chckbxmntmRunInBackground.setState(controller.getRunInBackground()); + chckbxmntmDelayStartup.setState(controller.getDelayStartup() > 0); + chckbxmntmDownloadJars.setState(controller.getDownloadAllJars()); this.targetServer.removeAllItems(); this.targetServer.addItem("All"); - for (Collection collection : Profile.getCurrent().getCollections()) { + for (Collection collection : controller.getCurrentProfile().getCollections()) { + serversPane.addTab(collection.getName(), collection.getServerTab().getPanel()); this.targetServer.addItem(collection.getName()); } } @@ -453,11 +473,7 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener, trayIcon.setImageAutoSize(true); ActionListener exitListener = e -> { stop(); - try { - Profile.getCurrent().save(); - } catch (FileNotFoundException e1) { - e1.printStackTrace(); - } + controller.saveState(); System.exit(0); }; @@ -481,7 +497,7 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener, frame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { - if (Profile.getCurrent().getRunInBackground() && SystemTray.isSupported()) { + if (controller.getRunInBackground() && SystemTray.isSupported()) { try { tray.add(trayIcon); frame.setVisible(false); @@ -490,11 +506,7 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener, } } else { stop(); - try { - Profile.getCurrent().save(); - } catch (FileNotFoundException e1) { - e1.printStackTrace(); - } + controller.saveState(); System.exit(0); } } @@ -514,11 +526,7 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener, frame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { - try { - Profile.getCurrent().save(); - } catch (FileNotFoundException e1) { - e1.printStackTrace(); - } + controller.saveState(); stop(); System.exit(0); } @@ -572,68 +580,60 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener, } else if (e.getSource() == mntmStory) { CommonFunctions.goToURL("https://archive.knarcraft.net/Scripts/BungeeMinecraftServerLauncherStory/"); } else if (e.getSource() == btnStartServer) { - try { - Profile.getCurrent().save(); - } catch (FileNotFoundException e1) { - e1.printStackTrace(); - } + controller.saveState(); Executors.newSingleThreadExecutor().execute(Server::startServers); } else if (e.getSource() == btnStopServer) { stop(); } else if (e.getSource() == addServer) { String serverName = JOptionPane.showInputDialog("Name of server: "); try { - Profile.getCurrent().addCollection(serverName); + controller.getCurrentProfile().addCollection(serverName); } catch (ConfigurationException e1) { e1.printStackTrace(); } this.update(); - Profile.getCurrent().updateConsoles(); + controller.getCurrentProfile().updateConsoles(); } else if (e.getSource() == backup) { - backup(); + CommonFunctions.backup(this); } else if (e.getSource() == addProfile) { - Profile.addProfile(JOptionPane.showInputDialog("Profile name: ")); + controller.addProfile(JOptionPane.showInputDialog("Profile name: ")); updateProfiles(); } else if (e.getSource() == delProfile) { Object selected = profiles.getSelectedItem(); if (selected != null) { - Profile.removeProfile(selected.toString()); + controller.removeProfile(selected.toString()); updateProfiles(); } } else if (e.getSource() == profiles) { - try { - changeProfile(); - } catch (FileNotFoundException e1) { - e1.printStackTrace(); - } + changeProfile(); } else if (e.getSource() == btnKick) { if (selectedServerValue != null && selectedPlayerValue != null) { - Profile.getCurrent().sendCommand(selectedServerValue, "kick " + selectedPlayerValue); + controller.getCurrentProfile().sendCommand(selectedServerValue, "kick " + selectedPlayerValue); } } else if (e.getSource() == btnBan) { if (selectedServerValue != null && selectedPlayerValue != null) { - Profile.getCurrent().sendCommand(selectedServerValue, "ban " + selectedPlayerValue); + controller.getCurrentProfile().sendCommand(selectedServerValue, "ban " + selectedPlayerValue); } } else if (e.getSource() == btnOp) { if (selectedServerValue != null && selectedPlayerValue != null) { - Profile.getCurrent().sendCommand(selectedServerValue, "op " + selectedPlayerValue); + controller.getCurrentProfile().sendCommand(selectedServerValue, "op " + selectedPlayerValue); } } else if (e.getSource() == btnDeop) { if (selectedServerValue != null && selectedPlayerValue != null) { - Profile.getCurrent().sendCommand(selectedServerValue, "deop " + selectedPlayerValue); + controller.getCurrentProfile().sendCommand(selectedServerValue, "deop " + selectedPlayerValue); } } else if (e.getSource() == btnCustomCommand) { if (selectedServerValue != null) { - Profile.getCurrent().sendCommand(selectedServerValue, customCommand.getText()); + controller.getCurrentProfile().sendCommand(selectedServerValue, customCommand.getText()); customCommand.setText(""); } } else if (e.getSource() == btnSaveserver) { if (selectedServerValue != null) { - Profile.getCurrent().sendCommand(selectedServerValue, "save-all"); + controller.getCurrentProfile().sendCommand(selectedServerValue, "save-all"); } } else if (e.getSource() == btnReload) { if (selectedServerValue != null) { - Profile.getCurrent().sendCommand(selectedServerValue, "reload"); + controller.getCurrentProfile().sendCommand(selectedServerValue, "reload"); } } else if (e.getSource() == btnServerConsoles) { ServerConsoles.setAsVisible(); @@ -661,14 +661,14 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener, /** * Saves the previous profile and loads data from the new profile. */ - private void changeProfile() throws FileNotFoundException { - Profile.getCurrent().save(); + private void changeProfile() { + controller.saveState(); Object current = this.profiles.getSelectedItem(); if (current != null) { - Profile.setCurrent(current.toString()); + controller.setCurrentProfile(current.toString()); } this.update(); - Profile.getCurrent().updateConsoles(); + controller.getCurrentProfile().updateConsoles(); } /** @@ -690,11 +690,15 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener, private void delay() { Object selected = profiles.getSelectedItem(); if (selected != null) { - Profile profile = Profile.getProfile(selected.toString()); + Profile profile = controller.getProfileByName(selected.toString()); if (chckbxmntmDelayStartup.isSelected()) { - Objects.requireNonNull(profile).setDelayStartup( - Integer.parseInt(JOptionPane.showInputDialog("Seconds to delay: ")) - ); + String response = JOptionPane.showInputDialog("Seconds to delay: "); + if (response == null) { + chckbxmntmDelayStartup.setState(false); + return; + } + int parsed = Integer.parseInt(response); + Objects.requireNonNull(profile).setDelayStartup(parsed); } else { Objects.requireNonNull(profile).setDelayStartup(0); } @@ -709,7 +713,7 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener, private void background() { Object selected = profiles.getSelectedItem(); if (selected != null) { - Profile profile = Profile.getProfile(selected.toString()); + Profile profile = controller.getProfileByName(selected.toString()); Objects.requireNonNull(profile).setRunInBackground(chckbxmntmRunInBackground.isSelected()); } else { showError("No profile selected"); @@ -722,47 +726,12 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener, private void downloadJars() { Object selected = profiles.getSelectedItem(); if (selected != null) { - Profile profile = Profile.getProfile(selected.toString()); - Objects.requireNonNull(profile).setDownloadAllAvailableJARFiles(chckbxmntmDownloadJars.isSelected()); + controller.setDownloadAllJars(chckbxmntmDownloadJars.isSelected()); } else { showError("No profile selected"); } } - /** - * Copies all server directories to a folder specified by the user. - */ - private void backup() { - JFileChooser chooser = new JFileChooser(); - chooser.setCurrentDirectory(new java.io.File(".")); - chooser.setDialogTitle("Backup folder"); - chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - chooser.setAcceptAllFileFilterUsed(false); - if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) { - File path = chooser.getSelectedFile(); - for (Collection collection : Profile.getCurrent().getCollections()) { - if (!collection.getServer().getPath().equals("") && collection.getServer().isEnabled()) { - String name = collection.getServer().getName(); - File srcFolder = new File(collection.getServer().getPath()); - File destFolder = new File(path, name); - if (!destFolder.exists()) { - if (destFolder.mkdirs()) { - try { - CommonFunctions.copyFolder(this, srcFolder, destFolder); - } catch (IOException e) { - e.printStackTrace(); - return; - } - } else { - return; - } - } - } - } - } - this.setStatus("Backup finished"); - } - /** * Updates the list of players currently online on the selected server, */ @@ -777,7 +746,7 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener, targetPlayer.addItem(player); } } else { - for (String player : Profile.getCurrent().getCollection(selectedServerValue).getServer().getPlayers()) { + for (String player : controller.getCurrentProfile().getCollection(selectedServerValue).getServer().getPlayers()) { targetPlayer.addItem(player); } } diff --git a/src/main/java/net/knarcraft/minecraftserverlauncher/userinterface/ServerTab.java b/src/main/java/net/knarcraft/minecraftserverlauncher/userinterface/ServerTab.java index 3bfa868..30d4054 100644 --- a/src/main/java/net/knarcraft/minecraftserverlauncher/userinterface/ServerTab.java +++ b/src/main/java/net/knarcraft/minecraftserverlauncher/userinterface/ServerTab.java @@ -1,6 +1,6 @@ package net.knarcraft.minecraftserverlauncher.userinterface; -import net.knarcraft.minecraftserverlauncher.profile.Profile; +import net.knarcraft.minecraftserverlauncher.Main; import net.knarcraft.minecraftserverlauncher.server.Server; import net.knarcraft.minecraftserverlauncher.server.ServerTypeHandler; import net.knarcraft.minecraftserverlauncher.server.servertypes.ServerType; @@ -29,7 +29,7 @@ public class ServerTab implements ActionListener { public ServerTab(String name) throws ConfigurationException { this.name = name; panel = new JPanel(); - Profile.getGUI().getPane().addTab(name, null, panel, null); + Main.getController().getGUI().getPane().addTab(name, null, panel, null); SpringLayout sl_panel_3 = new SpringLayout(); panel.setLayout(sl_panel_3); @@ -197,9 +197,9 @@ public class ServerTab implements ActionListener { * Removes the collection containing this ServerTab, and updates everything necessary. */ private void remove() { - Profile.getCurrent().removeCollection(this.name); - Profile.getGUI().update(); - Profile.getCurrent().updateConsoles(); + Main.getController().getCurrentProfile().removeCollection(this.name); + Main.getController().getGUI().update(); + Main.getController().getCurrentProfile().updateConsoles(); } /** diff --git a/src/main/java/net/knarcraft/minecraftserverlauncher/utility/CommonFunctions.java b/src/main/java/net/knarcraft/minecraftserverlauncher/utility/CommonFunctions.java index ff8dc93..824efd3 100644 --- a/src/main/java/net/knarcraft/minecraftserverlauncher/utility/CommonFunctions.java +++ b/src/main/java/net/knarcraft/minecraftserverlauncher/utility/CommonFunctions.java @@ -1,7 +1,9 @@ package net.knarcraft.minecraftserverlauncher.utility; import net.knarcraft.minecraftserverlauncher.Main; -import net.knarcraft.minecraftserverlauncher.userinterface.ServerLauncherGUI; +import net.knarcraft.minecraftserverlauncher.profile.Collection; +import net.knarcraft.minecraftserverlauncher.server.Server; +import net.knarcraft.minecraftserverlauncher.userinterface.GUI; import java.io.*; import java.net.URI; @@ -21,7 +23,7 @@ import java.util.Scanner; */ public final class CommonFunctions { - private static String filesDirectory = Main.getApplicationWorkDirectory() + File.separator + "files"; + private static final String filesDirectory = Main.getApplicationWorkDirectory() + File.separator + "files"; /** * Creates all folders necessary for tests and normal operation @@ -128,7 +130,7 @@ public final class CommonFunctions { * @param destination

Target destination

* @throws IOException

If we can't start a file stream

*/ - public static void copyFolder(ServerLauncherGUI serverLauncherGui, File source, File destination) throws IOException { + public static void copyFolder(GUI serverLauncherGui, File source, File destination) throws IOException { if (!source.isDirectory()) { copyFile(serverLauncherGui, source, destination); } else { @@ -156,7 +158,7 @@ public final class CommonFunctions { * @param destination

The location of the copied file

* @throws IOException

If reading or writing fails

*/ - private static void copyFile(ServerLauncherGUI serverLauncherGui, File source, File destination) throws IOException { + private static void copyFile(GUI serverLauncherGui, File source, File destination) throws IOException { serverLauncherGui.setStatus("Copying file " + source + "..."); InputStream in = new FileInputStream(source); OutputStream out = new FileOutputStream(destination); @@ -199,4 +201,43 @@ public final class CommonFunctions { } return text.toString().trim(); } + + /** + * Copies all server directories to a folder specified by the user. + */ + public static void backup(GUI gui) { + File path = gui.askForDirectory("Backup folder"); + for (Collection collection : Main.getController().getCurrentProfile().getCollections()) { + //Ignore disabled and invalid servers + if (collection.getServer().getPath().equals("") || !collection.getServer().isEnabled()) { + continue; + } + //Decide sub-folders + Server targetServer = collection.getServer(); + String name = targetServer.getName(); + File srcFolder = new File(targetServer.getPath()); + File destinationFolder = new File(path, name); + //Create child folders + if (!destinationFolder.exists() && !destinationFolder.mkdirs()) { + throw new IllegalArgumentException("Unable to create necessary sub-folder in the backup folder"); + } + //Backup + try { + CommonFunctions.copyFolder(gui, srcFolder, destinationFolder); + } catch (IOException e) { + e.printStackTrace(); + } + } + gui.setStatus("Backup finished"); + } + + /** + * Validates that a name is not empty and does not contain invalid characters + * + * @param name

The name to check

+ * @return

True if the name is valid

+ */ + public static boolean nameIsValid(String name) { + return !name.equals("") && name.matches("[^!?;,]+"); + } } diff --git a/src/main/java/net/knarcraft/minecraftserverlauncher/utility/JarDownloader.java b/src/main/java/net/knarcraft/minecraftserverlauncher/utility/JarDownloader.java index f9785ed..48f2313 100644 --- a/src/main/java/net/knarcraft/minecraftserverlauncher/utility/JarDownloader.java +++ b/src/main/java/net/knarcraft/minecraftserverlauncher/utility/JarDownloader.java @@ -15,7 +15,7 @@ import java.io.IOException; public final class JarDownloader { private final String jarDirectory; - private GUI gui; + private final GUI gui; /** * Initializes a jar downloader diff --git a/src/main/resources/servertypes.csv b/src/main/resources/servertypes.csv index 0e6ac59..b114d17 100644 --- a/src/main/resources/servertypes.csv +++ b/src/main/resources/servertypes.csv @@ -6,5 +6,5 @@ Paper;1.16.1,1.15.2,1.14.4,1.13.2,1.12.2,1.11.2,1.10.2,1.9.4,1.8.8;https://stati 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 Waterfall;Latest;https://papermc.io/api/v1/waterfall/1.16;"latest":";";https://papermc.io/api/v1/waterfall/1.16/ Travertine;Latest;https://papermc.io/api/v1/travertine/1.16;"latest":";";https://papermc.io/api/v1/travertine/1.16/ -Vanilla;Latest,Snapshot,1.16.1,1.15.2,1.14.4,1.13.2,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.2.5;https://launchermeta.mojang.com/mc/game/version_manifest.json;"release":";";https://s3.amazonaws.com/Minecraft.Download/versions/ +Vanilla;Latest,Snapshot,1.16.2,1.15.2,1.14.4,1.13.2,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.2.5;https://launchermeta.mojang.com/mc/game/version_manifest.json;"release":";";https://s3.amazonaws.com/Minecraft.Download/versions/ Custom;; \ No newline at end of file diff --git a/src/test/java/net/knarcraft/minecraftserverlauncher/server/ServerTest.java b/src/test/java/net/knarcraft/minecraftserverlauncher/server/ServerTest.java new file mode 100644 index 0000000..119a1ee --- /dev/null +++ b/src/test/java/net/knarcraft/minecraftserverlauncher/server/ServerTest.java @@ -0,0 +1,23 @@ +package net.knarcraft.minecraftserverlauncher.server; + +import org.junit.Test; + +import javax.naming.ConfigurationException; + +import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.assertFalse; + +public class ServerTest { + + @Test + public void fromStringTest() throws ConfigurationException { + Server server = Server.fromString("asd;/home/;false;Bukkit;1.10.2;4G;"); + assertEquals("asd", server.getName()); + assertEquals("/home/", server.getPath()); + assertFalse(server.isEnabled()); + assertEquals("Bukkit", server.getTypeName()); + assertEquals("1.10.2", server.getServerVersion()); + assertEquals("4G", server.getMaxRam()); + } + +} diff --git a/src/test/java/net/knarcraft/minecraftserverlauncher/server/ServerVersionContainerTest.java b/src/test/java/net/knarcraft/minecraftserverlauncher/server/ServerVersionContainerTest.java index 9756246..c60ece9 100644 --- a/src/test/java/net/knarcraft/minecraftserverlauncher/server/ServerVersionContainerTest.java +++ b/src/test/java/net/knarcraft/minecraftserverlauncher/server/ServerVersionContainerTest.java @@ -13,7 +13,7 @@ import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.crea public class ServerVersionContainerTest { private final String filesDirectory = Main.getApplicationWorkDirectory() + File.separator + "files"; - private String versionFile = filesDirectory + File.separator + "versions.csv"; + private final String versionFile = filesDirectory + File.separator + "versions.csv"; private ServerVersionContainer serverVersionContainer; @Before diff --git a/src/test/java/net/knarcraft/minecraftserverlauncher/userinterface/FakeGUI.java b/src/test/java/net/knarcraft/minecraftserverlauncher/userinterface/FakeGUI.java index 024699c..b77787e 100644 --- a/src/test/java/net/knarcraft/minecraftserverlauncher/userinterface/FakeGUI.java +++ b/src/test/java/net/knarcraft/minecraftserverlauncher/userinterface/FakeGUI.java @@ -1,5 +1,7 @@ package net.knarcraft.minecraftserverlauncher.userinterface; +import java.io.File; + public class FakeGUI extends MessageHandler implements GUI { /*** @@ -13,4 +15,9 @@ public class FakeGUI extends MessageHandler implements GUI { public void setStatus(String message) { System.out.println(message); } + + @Override + public File askForDirectory(String prompt) { + return null; + } } diff --git a/src/test/java/net/knarcraft/minecraftserverlauncher/utility/CommonFunctionsTest.java b/src/test/java/net/knarcraft/minecraftserverlauncher/utility/CommonFunctionsTest.java index 6a74f0f..1e90b9f 100644 --- a/src/test/java/net/knarcraft/minecraftserverlauncher/utility/CommonFunctionsTest.java +++ b/src/test/java/net/knarcraft/minecraftserverlauncher/utility/CommonFunctionsTest.java @@ -1,19 +1,17 @@ package net.knarcraft.minecraftserverlauncher.utility; -import net.knarcraft.minecraftserverlauncher.profile.Profile; +import net.knarcraft.minecraftserverlauncher.Main; import org.junit.Test; -import java.io.FileNotFoundException; - import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.stringBetween; import static org.junit.Assert.assertEquals; public class CommonFunctionsTest { @Test - public void saveProfileTest() throws FileNotFoundException { - Profile.addProfile("Test"); - Profile.getCurrent().save(); + public void saveProfileTest() { + Main.getController().addProfile("Test"); + Main.getController().saveState(); } @Test