All checks were successful
KnarCraft/Minecraft-Server-Launcher/pipeline/head This commit looks good
424 lines
14 KiB
Java
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());
|
|
}
|
|
}
|
|
|
|
}
|