Fixes some bugs preventing servers from starting
All checks were successful
KnarCraft/Minecraft-Server-Launcher/pipeline/head This commit looks good

This commit is contained in:
Kristian Knarvik 2020-08-07 04:08:05 +02:00
parent b144bbb903
commit a2d4d491ba
4 changed files with 158 additions and 81 deletions

View File

@ -83,7 +83,7 @@ public class Main {
Server server = collection.getServer(); Server server = collection.getServer();
if (server.isEnabled() && server.getProcess() != null) { if (server.isEnabled() && server.getProcess() != null) {
try { try {
String readText = server.read(); String readText = server.readFromServer();
if (!readText.equals("")) { if (!readText.equals("")) {
collection.getServerConsole().output(readText); collection.getServerConsole().output(readText);
updatePlayerList(readText, server); updatePlayerList(readText, server);
@ -117,7 +117,8 @@ public class Main {
private static boolean serversRunning() { private static boolean serversRunning() {
int num = 0; int num = 0;
for (Collection collection : Profile.getCurrent().getCollections()) { for (Collection collection : Profile.getCurrent().getCollections()) {
if (collection.getServer().isStarted() || (collection.getServer().getProcess() != null && collection.getServer().getProcess().isAlive())) { if (collection.getServer().isStarted() ||
(collection.getServer().getProcess() != null && collection.getServer().getProcess().isAlive())) {
num++; num++;
} }
} }

View File

@ -48,6 +48,11 @@ public class Server {
private final String bungeeVersion; private final String bungeeVersion;
private boolean started; private boolean started;
/**
* Initializes a new server with default values
*
* @param name <p>The name of the server</p>
*/
public Server(String name) { public Server(String name) {
this.name = name; this.name = name;
this.path = ""; this.path = "";
@ -65,6 +70,20 @@ public class Server {
this.bungeeVersion = ""; this.bungeeVersion = "";
} }
/**
* Initializes a server with the given values
*
* @param name <p>The name of the server</p>
* @param path <p>The file path of the folder containing the server files</p>
* @param enabled <p>Whether the server is enabled to start the next time servers are started</p>
* @param typeName <p>The name of the server type currently in use on the server</p>
* @param serverVersion <p>The currently selected server version for the given server type</p>
* @param maxRam <p>The maximum amount of ram the server is allowed to use</p>
* @param vanillaVersion <p>The version of the "latest" downloaded vanilla version</p>
* @param snapshotVersion <p>The version of the "latest" downloaded snapshot version</p>
* @param spongeVanillaVersion <p>The version of the "latest" SpongeVanilla jar downloaded</p>
* @param bungeeVersion <p>The version of the "latest" bungee jar downloaded</p>
*/
public Server(String name, String path, boolean enabled, String typeName, String serverVersion, String maxRam, public Server(String name, String path, boolean enabled, String typeName, String serverVersion, String maxRam,
String vanillaVersion, String snapshotVersion, String spongeVanillaVersion, String bungeeVersion) { String vanillaVersion, String snapshotVersion, String spongeVanillaVersion, String bungeeVersion) {
this.name = name; this.name = name;
@ -80,18 +99,38 @@ public class Server {
this.playerList = new ArrayList<>(); this.playerList = new ArrayList<>();
} }
/**
* Gets the name of the server
*
* @return <p>The name of the server</p>
*/
public String getName() { public String getName() {
return this.name; return this.name;
} }
/**
* Whether the server has been started
*
* @return <p>True if the server has been started. False otherwise</p>
*/
public boolean isStarted() { public boolean isStarted() {
return started; return started;
} }
/**
* Gets the name of the server type used by this server
*
* @return <p>The name of the server type used by this server</p>
*/
public String getTypeName() { public String getTypeName() {
return this.type.getName(); return this.type.getName();
} }
/**
* Gets the version used given server type used
*
* @return <p>The server version given server type</p>
*/
public String getServerVersion() { public String getServerVersion() {
return this.serverVersion; return this.serverVersion;
} }
@ -255,11 +294,99 @@ public class Server {
} }
/** /**
* Runs the Minecraft server. * Runs a Minecraft server
*
* @return <p>True if nothing went wrong</p>
*/ */
private boolean run() { private boolean run() {
if (this.enabled) { if (!this.enabled) {
this.started = false;
return true;
}
this.started = true; this.started = true;
if (!initializeJarDownload() || !delayStartup()) {
return false;
}
try {
startServerProcess();
Profile.getGUI().setStatus("Servers are running");
this.started = true;
return true;
} catch (IOException e) {
Profile.getGUI().setStatus("Could not start server");
this.started = false;
return false;
}
}
/**
* Reads all available output from the server process
*
* @return <p>The server output</p>
* @throws IOException <p>If reading from the reader fails</p>
*/
public String readFromServer() throws IOException {
String line;
StringBuilder text = new StringBuilder();
while (reader.ready() && (line = reader.readLine()) != null) {
text.append(line).append("\n");
}
return text.toString().trim();
}
/**
* Starts the process running this server
*
* @throws IOException <p>If the process cannot be started</p>
*/
private void startServerProcess() throws IOException {
ProcessBuilder builder;
String serverPath;
String serverFile;
if (type.getName().equals("Custom")) {
serverFile = serverVersion;
} else {
serverFile = this.type.getName() + serverVersion + ".jar";
}
if (Profile.getCurrent().getDownloadAllAvailableJARFiles() && !type.getName().equals("Custom")) {
serverPath = jarDirectory + serverFile;
} else {
serverPath = this.path + File.separator + serverFile;
}
builder = new ProcessBuilder("java", "-Xmx" + this.maxRam, "-Xms512M",
"-Djline.terminal=jline.UnsupportedTerminal", "-Dcom.mojang.eula.agree=true", "-jar", serverPath,
"nogui");
builder.directory(new File(this.path));
builder.redirectErrorStream(true);
this.process = builder.start();
this.writer = new BufferedWriter(new OutputStreamWriter(this.process.getOutputStream()));
this.reader = new BufferedReader(new InputStreamReader(this.process.getInputStream()));
}
/**
* Delays the server's startup for the given amount of time
*
* @return <p>True if the delay was successful</p>
*/
private boolean delayStartup() {
try {
Profile.getGUI().setStatus("Delaying startup");
TimeUnit.SECONDS.sleep(Profile.getCurrent().getDelayStartup());
return true;
} catch (InterruptedException e) {
e.printStackTrace();
this.started = false;
return false;
}
}
/**
* Starts downloading the necessary .jar file
*
* @return <p>True if nothing went wrong</p>
*/
private boolean initializeJarDownload() {
if (!Profile.getCurrent().getDownloadAllAvailableJARFiles()) { if (!Profile.getCurrent().getDownloadAllAvailableJARFiles()) {
try { try {
Profile.getGUI().setStatus("Downloading jar..."); Profile.getGUI().setStatus("Downloading jar...");
@ -273,71 +400,13 @@ public class Server {
return false; return false;
} }
} }
try {
Profile.getGUI().setStatus("Delaying startup");
TimeUnit.SECONDS.sleep(Profile.getCurrent().getDelayStartup());
} catch (InterruptedException e) {
e.printStackTrace();
this.started = false;
return false;
}
try {
ProcessBuilder builder;
String serverPath;
if (Profile.getCurrent().getDownloadAllAvailableJARFiles() && !type.getName().equals("Custom")) {
serverPath = jarDirectory + this.getType();
} else {
serverPath = this.path + File.separator + this.getType();
}
builder = new ProcessBuilder(
"java",
"-Xmx" + this.maxRam,
"-Xms512M",
"-Djline.terminal=jline.UnsupportedTerminal",
"-Dcom.mojang.eula.agree=true",
"-jar",
serverPath,
"nogui"
);
builder.directory(new File(this.path));
builder.redirectErrorStream(true);
this.process = builder.start();
this.writer = new BufferedWriter(new OutputStreamWriter(this.process.getOutputStream()));
this.reader = new BufferedReader(new InputStreamReader(this.process.getInputStream()));
Profile.getGUI().setStatus("Servers are running");
this.started = true;
return true; return true;
} catch (IOException e) {
Profile.getGUI().setStatus("Could not start server");
this.started = false;
return false;
}
} else {
this.started = false;
return true;
}
}
/**
* Reads all available output from the server process.
*
* @return The server output
* @throws IOException If reading from the reader fails
*/
public String read() throws IOException {
String line;
StringBuilder text = new StringBuilder();
while (reader.ready() && (line = reader.readLine()) != null) {
text.append(line).append("\n");
}
return text.toString().trim();
} }
/** /**
* Downloads necessary .jar file for the server. * Downloads necessary .jar file for the server.
* This is unfortunately hardcoded since there is no golden standard, and we only host some jars ourselves.
* *
* @throws FileNotFoundException if the file was not found and could not be acquired. * @throws FileNotFoundException <p>If the file was not found and could not be acquired</p>
*/ */
private void downloadJar() throws IOException { private void downloadJar() throws IOException {
String path = this.path + File.separator; String path = this.path + File.separator;

View File

@ -54,7 +54,7 @@ public class Vanilla extends AbstractServerType {
* Gets the URL to the .jar file for the newest version * Gets the URL to the .jar file for the newest version
* *
* @return <p>An array containing the latest version and a link to its file</p> * @return <p>An array containing the latest version and a link to its file</p>
* @throws IOException <p>If the remote resource cannot be read</p> * @throws IOException <p>If the remote resource cannot be readFromServer</p>
*/ */
private String[] getLatestFile() throws IOException { private String[] getLatestFile() throws IOException {
String versionText = readFile(versionURL); String versionText = readFile(versionURL);
@ -70,7 +70,7 @@ public class Vanilla extends AbstractServerType {
* *
* @param versionURL <p>The URL to the version document describing the .jar file</p> * @param versionURL <p>The URL to the version document describing the .jar file</p>
* @return <p>The URL necessary do download the .jar file</p> * @return <p>The URL necessary do download the .jar file</p>
* @throws IOException <p>If the remote resource cannot be read</p> * @throws IOException <p>If the remote resource cannot be readFromServer</p>
*/ */
private String getVanillaDownloadURL(String versionURL) throws IOException { private String getVanillaDownloadURL(String versionURL) throws IOException {
String versionText = readFile(versionURL); String versionText = readFile(versionURL);

View File

@ -2,7 +2,13 @@ package net.knarcraft.minecraftserverlauncher.utility;
import net.knarcraft.minecraftserverlauncher.userinterface.ServerLauncherGUI; import net.knarcraft.minecraftserverlauncher.userinterface.ServerLauncherGUI;
import java.io.*; import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.net.URL; import java.net.URL;
@ -23,7 +29,7 @@ public class CommonFunctions {
/** /**
* Gets a resource as an InputStream * Gets a resource as an InputStream
* *
* @param resourceName <p>The name of the resource you want to read</p> * @param resourceName <p>The name of the resource you want to readFromServer</p>
* @return <p>An input stream which can be used to access the resource</p> * @return <p>An input stream which can be used to access the resource</p>
*/ */
public static InputStream getResourceAsStream(String resourceName) { public static InputStream getResourceAsStream(String resourceName) {
@ -34,8 +40,8 @@ public class CommonFunctions {
/** /**
* Gets a resource as a Scanner * Gets a resource as a Scanner
* *
* @param resourceName <p>The name of the resource you want to read</p> * @param resourceName <p>The name of the resource you want to readFromServer</p>
* @return <p>A scanner which can be used to read contents of the resource</p> * @return <p>A scanner which can be used to readFromServer contents of the resource</p>
* @throws FileNotFoundException <p>If the resource is not found</p> * @throws FileNotFoundException <p>If the resource is not found</p>
*/ */
public static Scanner getResourceAsScanner(String resourceName) throws FileNotFoundException { public static Scanner getResourceAsScanner(String resourceName) throws FileNotFoundException {
@ -67,7 +73,7 @@ public class CommonFunctions {
* *
* <p>This is used to find the newest version of jars and the software.</p> * <p>This is used to find the newest version of jars and the software.</p>
* *
* @param path <p>The full url of the file to read</p> * @param path <p>The full url of the file to readFromServer</p>
* @return <p>True if successful. False otherwise</p> * @return <p>True if successful. False otherwise</p>
*/ */
public static String readFile(String path) throws IOException { public static String readFile(String path) throws IOException {
@ -144,6 +150,7 @@ public class CommonFunctions {
/** /**
* Opens an url in the user's default application. * Opens an url in the user's default application.
*
* @param url <p>The URL to open</p> * @param url <p>The URL to open</p>
*/ */
public static void goToURL(String url) { public static void goToURL(String url) {