EpicKnarvik97 f8ba6e7ad1
All checks were successful
KnarCraft/Minecraft-Server-Launcher/pipeline/head This commit looks good
Fixes the software crashing if an old configuration is used
2021-08-03 14:00:02 +02:00

424 lines
14 KiB
Java

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<Profile> 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 <p>An instance of the controller</p>
*/
public static ServerLauncherController getInstance() {
if (controller == null) {
controller = new ServerLauncherController();
}
return controller;
}
/**
* Returns the GUI used by the software
*
* @return <p>The GUI used by the software</p>
*/
public ServerLauncherGUI getGUI() {
return this.serverLauncherGUI;
}
/**
* Gets whether to download all jar files
*
* @return <p>Whether to download all .jar files</p>
*/
public boolean getDownloadAllJars() {
return downloadAllJars;
}
/**
* Gets whether to run in background after closing
*
* @return <p>Whether to run in background after closing</p>
*/
public boolean getRunInBackground() {
return currentProfile.getRunInBackground();
}
/**
* Gets whether to delay server startup
*
* @return <p>Whether to delay server startup</p>
*/
public int getDelayStartup() {
return currentProfile.getDelayStartup();
}
/**
* Gets the command for running java
*
* @return <p>The command for running Java</p>
*/
public String getJavaCommand() {
return javaCommand;
}
/**
* Gets the command for running older versions of Java
*
* <p>The command used to run older minecraft server versions. JRE 8 should probably work.
* Can be just "java" or a file path.</p>
*
* @return <p>The command for running older versions of Java</p>
*/
public String getOldJavaCommand() {
return oldJavaCommand;
}
/**
* Sets the command for running Java
*
* <p>To play on the newest version of Minecraft, this needs to be JDK 16. Can be just "java" or a file path.</p>
*
* @param javaCommand <p>The command used for running Java</p>
*/
public void setJavaCommand(String javaCommand) {
this.javaCommand = javaCommand;
}
/**
* Sets the command for running older versions of java
*
* @param oldJavaCommand <p>The command used for running older versions of Java</p>
*/
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 <p>The name of the profile to get</p>
* @return <p>The profile with the given name or null if not found</p>
*/
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 <p>A list of all available profiles</p>
*/
public List<String> getProfileNames() {
List<String> profileNames = new ArrayList<>();
profileList.forEach((profile) -> profileNames.add(profile.getName()));
return profileNames;
}
/**
* Adds a profile if the name is valid and unique
*
* @param name <p>The name of the new profile</p>
*/
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 <p>The name of the profile to remove</p>
*/
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 <p>The currently selected profile</p>
*/
public Profile getCurrentProfile() {
return this.currentProfile;
}
/**
* Sets the download all jars option
*
* @param downloadAllJars <p>Whether to download all jars</p>
*/
public void setDownloadAllJars(boolean downloadAllJars) {
this.downloadAllJars = downloadAllJars;
}
/**
* Sets the currently selected profile
*
* @param profileName <p>The name of the currently selected profile</p>
*/
public void setCurrentProfile(String profileName) {
this.currentProfile = getProfileByName(profileName);
}
/**
* Gets the directory containing .jar files
*
* @return <p>The directory containing .jar files</p>
*/
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 <p>If silent, no GUI will be created</p>
*/
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 <p>If silent, no GUI will be created</p>
* @return <p>The currently selected profile</p>
*/
private String fromString(boolean silent) {
Map<String, String> 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 <p>The map to save the loaded configuration to</p>
* @param line <p>The line to read</p>
*/
private void parseSaveLine(Map<String, String> loadedData, String line) {
String[] lineData = line.split(";");
if (lineData.length != 2) {
return;
}
loadedData.put(lineData[0], lineData[1]);
}
/**
* Loads all saved profiles
*
* @param currentProfile <p>The profile saved as the current profile</p>
* @throws ConfigurationException <p>If unable to load a profile</p>
*/
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());
}
}
}