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.File; import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Scanner; import java.util.concurrent.Executors; /** * This class handles profiles, GUI creation and session restoration */ public class ServerLauncherController { 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 ServerLauncherController controller; private String javaCommand = "java"; private String oldJavaCommand = "java"; /** * Instantiates a new controller */ private ServerLauncherController() { this.profileList = new ArrayList<>(); } /** * Gets an instance of the controller * * @return

An instance of the controller

*/ public static ServerLauncherController getInstance() { if (controller == null) { controller = new ServerLauncherController(); } 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(); } /** * Gets the command for running java * * @return

The command for running Java

*/ public String getJavaCommand() { return javaCommand; } /** * Gets the command for running older versions of Java * *

The command used to run older minecraft server versions. JRE 8 should probably work. * Can be just "java" or a file path.

* * @return

The command for running older versions of Java

*/ public String getOldJavaCommand() { return oldJavaCommand; } /** * Sets the command for running Java * *

To play on the newest version of Minecraft, this needs to be JDK 16. Can be just "java" or a file path.

* * @param javaCommand

The command used for running Java

*/ public void setJavaCommand(String javaCommand) { this.javaCommand = javaCommand; } /** * Sets the command for running older versions of java * * @param oldJavaCommand

The command used for running older versions of Java

*/ public void setOldJavaCommand(String oldJavaCommand) { this.oldJavaCommand = oldJavaCommand; } @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("selectedProfile;%s\nguiWidth;%d\nguiHeight;%d\ndownloadAllJars;%b\njavaCommand;%s\noldJavaCommand;%s", currentProfile.getName(), guiWidth, guiHeight, downloadAllJars, javaCommand, oldJavaCommand); } /** * 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 remove

*/ 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; } /** * 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); } /** * Gets the directory containing .jar files * * @return

The directory containing .jar files

*/ public String getJarDirectory() { return this.jarDirectory; } /** * Saves the state of the entire application to disk */ public void saveState() { saveGUIStateToServer(); try { CommonFunctions.createAllFolders(); CommonFunctions.writeFile(mainFile, this.toString()); StringBuilder builder = new StringBuilder(); for (Profile profile : profileList) { builder.append(profile.toString()).append("\n"); } CommonFunctions.writeFile(profilesFile, builder.toString()); } catch (IOException e) { serverLauncherGUI.showError("Unable to save data."); e.printStackTrace(); } } /** * Reads profiles and servers from a text file */ public void loadState() throws ConfigurationException, IOException { loadState(false); } /** * Reads profiles and servers from a text file * * @param silent

If silent, no GUI will be created

*/ public void loadState(boolean silent) throws ConfigurationException, IOException { //Loads data regarding this controller String currentProfile = null; if (new File(mainFile).exists()) { currentProfile = this.fromString(silent); } else if (!silent) { this.serverLauncherGUI = new ServerLauncherGUI(); } if (silent) { return; } //Loads all saved profiles loadProfiles(currentProfile); //Makes the GUI show the loaded data executeGUILoadingTasks(); } /** * Loads data about the controller from a save string * * @param silent

If silent, no GUI will be created

* @return

The currently selected profile

*/ private String fromString(boolean silent) { Map loadedData = new HashMap<>(); try { String currentData = CommonFunctions.readFile(mainFile); for (String line : currentData.split("\n")) { parseSaveLine(loadedData, line); } this.downloadAllJars = Boolean.parseBoolean(loadedData.get("downloadAllJars")); if (!silent) { if (loadedData.get("guiWidth") != null && loadedData.get("guiHeight") != null) { this.serverLauncherGUI = new ServerLauncherGUI(Integer.parseInt(loadedData.get("guiWidth")), Integer.parseInt(loadedData.get("guiHeight"))); } else { this.serverLauncherGUI = new ServerLauncherGUI(); } } else { this.serverLauncherGUI = new ServerLauncherGUI(true); } if (loadedData.get("javaCommand") != null) { this.javaCommand = loadedData.get("javaCommand"); } if (loadedData.get("oldJavaCommand") != null) { this.oldJavaCommand = loadedData.get("oldJavaCommand"); } return loadedData.get("selectedProfile"); } catch (IOException e) { e.printStackTrace(); return null; } } /** * Saves one config line to the provided map * * @param loadedData

The map to save the loaded configuration to

* @param line

The line to read

*/ private void parseSaveLine(Map loadedData, String line) { String[] lineData = line.split(";"); if (lineData.length != 2) { return; } loadedData.put(lineData[0], lineData[1]); } /** * Loads all saved profiles * * @param currentProfile

The profile saved as the current profile

* @throws ConfigurationException

If unable to load a profile

*/ private void loadProfiles(String currentProfile) throws ConfigurationException { try (Scanner in = new Scanner(new File(profilesFile))) { while (in.hasNextLine()) { String profileData = in.nextLine(); Profile loadedProfile = Profile.fromString(profileData); if (loadedProfile == null) { continue; } profileList.add(loadedProfile); } } catch (FileNotFoundException e) { addProfile("Default"); } this.currentProfile = getProfileByName(currentProfile); if (this.currentProfile == null) { this.currentProfile = this.profileList.get(0); } } /** * Updates the GUI as necessary to display loaded data */ private void executeGUILoadingTasks() { this.serverLauncherGUI.updateProfiles(); this.serverLauncherGUI.updateWithSavedProfileData(); 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.hideToTray(); } } /** * 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.isEnabled()); } } }