package net.knarcraft.serverlauncher.server; import java.io.*; import java.net.URL; import java.util.Scanner; import java.nio.file.StandardCopyOption; import java.nio.file.*; import java.util.ArrayList; /* Contains all necessary information to create, run and manage a Minecraft server. */ public class Server { /** * Available ram sizes. For GUI dropdown */ private static final String[] ramList = {"512M", "1G", "2G", "3G", "4G", "5G", "6G", "7G", "8G", "9G", "10G", "11G", "12G", "13G", "14G", "15G", "16G"}; private String name; private String path; private boolean enabled; private ArrayList playerList; private AdvancedServerType type; private String serverVersion; private String maxRam; private long pid; public Server(String name) { this.name = name; this.path = ""; this.enabled = false; this.playerList = new ArrayList<>(); this.type = null; this.serverVersion = null; this.maxRam = ramList[0]; this.pid = -1; } public void addPlayer(String name) { this.playerList.add(name); } public void removePlayer(String name) { for (int i = 0; i < playerList.size(); i++) { if (name.equals(playerList.get(i))) { playerList.remove(i); return; } } } public String getPath() { return this.path; } public String getType() { return this.type.getName() + this.serverVersion + ".jar"; } public boolean isEnabled() { return this.enabled; } public String maxRam() { return this.maxRam; } public void toggle() { this.enabled = !this.enabled; } public void setPath(String path) { this.path = path; } public void setType(AdvancedServerType type) { this.type = type; } /** * Sets the server's server version to a valid version, or ignores the request. * * @param serverVersion New version number. */ public void setServerVersion(String serverVersion) { String[] versions = this.type.getVersions(); for (String version : versions) { if (version.equals(serverVersion)) { this.serverVersion = serverVersion; } } } public void setMaxRam(String ram) { this.maxRam = ram; } public void updatePid(long pid) { this.pid = pid; } /** * Runs the Minecraft server. */ public void run() { if (this.isEnabled()) { try { this.downloadJar(); System.out.println("File downloaded."); } catch (FileNotFoundException e) { System.out.println("File was not found."); return; } Runtime rt = Runtime.getRuntime(); try { Process pr = rt.exec("\"java\" -Xmx" + this.maxRam + " -Xms512M -jar " + "\"" + this.path + "\\" + this.type + "\" nogui", null, new File(this.path)); this.pid = pr.pid(); System.out.println("Success"); } catch (IOException e) { System.out.println("Error"); } } } /** * 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. */ public void downloadJar() throws FileNotFoundException { File file = new File(this.path + "\\" + this.getType()); Path filePath = Paths.get(this.path + "\\" + this.getType()); String versionText; String newestVersion; boolean success; switch (this.type.getName()) { case "Custom": if (!file.isFile()) { throw new FileNotFoundException("Specified custom jar was not found."); } break; case "Spigot": case "Craftbukkit": case "MCPCplus": if (!file.isFile()) { success = downloadFile(type.getDownloadURL() + type.getName() + this.serverVersion + ".jar", filePath); if (!success) { throw new FileNotFoundException("Jar file could not be downloaded."); } } break; case "Vanilla": case "Snapshot": if (this.serverVersion.equals("Latest")) { try { versionText = readFile(this.type.getVersionURL()); } catch (IOException e) { throw new FileNotFoundException("Version file could not be downloaded."); } newestVersion = stringBetween(versionText, type.getSrcStart(), type.getSrcEnd()); success = downloadFile(type.getDownloadURL() + newestVersion + type.getDownloadURLPart() + newestVersion + ".jar", filePath); //TODO: Register the new version number, and only download if version mismatch or missing file. if (!success) { throw new FileNotFoundException("Jar file could not be downloaded."); } } else { if (!file.isFile()) { success = downloadFile(type.getDownloadURL() + this.serverVersion + type.getDownloadURLPart() + this.serverVersion + ".jar", filePath); if (!success) { throw new FileNotFoundException("Jar file could not be downloaded."); } } } break; case "SpongeVanilla": try { versionText = readFile(this.type.getVersionURL() + this.serverVersion); } catch (IOException e) { throw new FileNotFoundException("Version file could not be downloaded."); } newestVersion = stringBetween(versionText, type.getSrcStart(), type.getSrcEnd()); success = downloadFile(type.getDownloadURL() + newestVersion + type.getDownloadURLPart() + newestVersion + ".jar", filePath); //TODO: Register the new version number, and only download if version mismatch or missing file. if (!success) { throw new FileNotFoundException("Jar file could not be downloaded."); } break; case "Bungee": /*try { versionText = readFile(this.type.getVersionURL()); } catch (IOException e) { throw new FileNotFoundException("Version file could not be downloaded."); } newestVersion = stringBetween(versionText, type.getSrcStart(), type.getSrcEnd());*/ success = downloadFile(type.getDownloadURL(), filePath); //TODO: Register the new version number, and only download if version mismatch or missing file. if (!success) { throw new FileNotFoundException("Jar file could not be downloaded."); } } } /** * Reads a file from a website. * This is used to find the newest version of the software. * * @param path The full url of the file to read. * @return True if successfull. False otherwise. */ private static String readFile(String path) throws IOException { URL url = new URL(path); return new Scanner(url.openStream()).useDelimiter("\\Z").next(); } /** * Downloads a file from a website. * * @param path The full url of the file to download. * @param outfile The file to save to. * @return True if successful. False otherwise. */ private static boolean downloadFile(String path, Path outfile) { try { URL url = new URL(path); InputStream in = url.openStream(); Files.copy(in, outfile, StandardCopyOption.REPLACE_EXISTING); return true; } catch (IOException e) { return false; } } /** * Finds a substring between two substrings in a string. * * @param string The string containing the substrings. * @param start The substring before the wanted substring. * @param end The substring after the wanted substring. * @return The wanted substring. */ private String stringBetween(String string, String start, String end) { int startPos = string.indexOf(start) + start.length(); return string.substring(startPos, string.indexOf(end, startPos)); } }