Adds missing comments, simplifies proxy distinction, moves updating to own class and fixes formatting

This commit is contained in:
Kristian Knarvik 2020-08-11 19:29:28 +02:00
parent 094a1facb2
commit ab6453cdc3
30 changed files with 845 additions and 593 deletions

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

View File

@ -1,33 +1,30 @@
package net.knarcraft.minecraftserverlauncher;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import net.knarcraft.minecraftserverlauncher.profile.Collection;
import net.knarcraft.minecraftserverlauncher.profile.Profile;
import net.knarcraft.minecraftserverlauncher.server.Server;
import net.knarcraft.minecraftserverlauncher.userinterface.GUI;
import net.knarcraft.minecraftserverlauncher.userinterface.ServerConsoles;
import net.knarcraft.minecraftserverlauncher.utility.Updater;
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URISyntaxException;
import java.util.Scanner;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.*;
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.stringBetween;
//Java 8 required.
/**
* A software for managing Minecraft servers.
*
* @author Kristian Knarvik <kristian.knarvik@knett.no>
* @version 1.0.0
* @since 1.0.0
* @author Kristian Knarvik <kristian.knarvik@knett.no>
* @version 1.0.0
* @since 1.0.0
*/
public class Main {
@ -38,10 +35,10 @@ public class Main {
private static GUI gui;
public static void main(String[] args) throws IOException {
checkForUpdate();
Updater.checkForUpdate(updateURL, updateChannel, gui);
try (PrintWriter file = new PrintWriter(Main.getApplicationWorkDirectory() + File.separator + "latestrun.log")) {
file.print("");
} catch (IOException e ) {
} catch (IOException e) {
e.printStackTrace();
}
EventQueue.invokeLater(() -> {
@ -60,7 +57,7 @@ public class Main {
/**
* Retrieves the directory the .jar file is running from
*
* @return A string path
* @return A string path
*/
public static String getApplicationWorkDirectory() {
if (applicationWorkDirectory == null) {
@ -112,7 +109,7 @@ public class Main {
/**
* Goes through all servers and looks for any running servers.
*
* @return Is at least one server running?
* @return Is at least one server running?
*/
private static boolean serversRunning() {
int num = 0;
@ -126,13 +123,13 @@ public class Main {
}
/**
* Looks for strings implying a player has joined or left, and updates the appropriate lists.
* Looks for strings implying a player has joined or left, and updates the appropriate lists
*
* @param text The text to search.
* @param server The server which sent the text.
* @param text <p>The text to search</p>
* @param server <p>The server which sent the text</p>
*/
private static void updatePlayerList(String text, Server server) {
if (!server.getTypeName().equals("Bungee")) {
if (!server.getType().isProxy()) {
String joinedPlayer = getPlayer(text, true);
String leftPlayer = getPlayer(text, false);
if (!joinedPlayer.equals("")) {
@ -148,11 +145,11 @@ public class Main {
}
/**
* Searches a string for players joining or leaving.
* Searches a string for players joining or leaving
*
* @param text The string to search
* @param joined Are we searching for a joining player or not
* @return The name of a player or an empty string
* @param text <p>The text string to search through</p>
* @param joined <p>Whether to search for a joining player</p>
* @return <p>The name of a player, or an empty string</p>
*/
private static String getPlayer(String text, boolean joined) {
String playerName;
@ -169,75 +166,4 @@ public class Main {
}
return playerName;
}
/**
* Checks if a newer version is available
*
* @throws IOException <p>If the update check fails.</p>
*/
private static void checkForUpdate() throws IOException {
Scanner file = getResourceAsScanner("currentversion.csv");
if (!file.hasNextLine()) {
throw new FileNotFoundException("File currentversion.csv is invalid");
}
String oldType = file.nextLine();
if (!file.hasNextLine()) {
throw new FileNotFoundException("File currentversion.csv is invalid");
}
String oldVer = file.nextLine();
file.close();
String data = readFile(updateURL);
JsonObject jsonObject = new JsonParser().parse(data).getAsJsonObject();
String latest = jsonObject.getAsJsonObject("latest").get(updateChannel).getAsString();
if (!oldType.equals(updateChannel) || !oldVer.equals(latest)) {
String dir = getApplicationWorkDirectory() + File.separator;
JsonArray versionList = jsonObject.getAsJsonArray("versions");
String url = "";
for (JsonElement elem : versionList) {
JsonObject obj = elem.getAsJsonObject();
String ver = obj.get("id").getAsString();
String type = obj.get("type").getAsString();
if (ver.equals(latest) && type.equals(updateChannel)) {
url = obj.get("url").getAsString();
}
}
if (downloadFile(url, new File(dir + "update.jar").toPath())) {
doUpdate(dir);
} else {
gui.showError("Update available",
"An update is available, but could not be downloaded.");
}
}
}
private static void doUpdate(String dir) {
int answer = JOptionPane.showConfirmDialog(
null,
"An update is available. Do you want to update?",
"Update available",
JOptionPane.YES_NO_OPTION
);
if (answer == JOptionPane.YES_NO_OPTION) {
if (new File (dir + "Minecraft-Server-Launcher.jar").renameTo(new File(dir +
"Old.jar"))) {
if (new File(dir + "update.jar").renameTo(new File (dir +
"Minecraft-Server-Launcher.jar"))) {
if (new File(dir + "Old.jar").delete()) {
gui.showMessage("Update complete",
"Update finished. Please run the software again.");
System.exit(0);
}
} else {
if (!new File(dir + "Old.jar").renameTo(new File (dir +
"Minecraft-Server-Launcher.jar"))) {
System.out.println("Shit");
}
}
}
gui.showError("Update failed",
"Could not replace the main .jar with the downloaded .jar.");
}
}
}

View File

@ -6,6 +6,7 @@ import net.knarcraft.minecraftserverlauncher.userinterface.ServerConsoles;
import net.knarcraft.minecraftserverlauncher.userinterface.ServerTab;
import javax.naming.ConfigurationException;
import java.io.Serializable;
/**
* Acts as a wrapper for objects necessary for each server.
@ -14,9 +15,9 @@ import javax.naming.ConfigurationException;
* @version 1.0.0
* @since 1.0.0
*/
public class Collection {
public class Collection implements Serializable {
private final Server server;
private final ServerTab serverTab;
private final transient ServerTab serverTab;
private final Console serverConsole;
private final String name;
@ -32,6 +33,20 @@ public class Collection {
this.name = name;
}
/**
* Creates a new collection with the given server
*
* @param server <p>The server used for as part of the collection</p>
* @throws ConfigurationException <p>If unable to configure the collection</p>
*/
Collection(Server server) throws ConfigurationException {
String serverName = server.getName();
this.serverTab = new ServerTab(serverName);
this.server = server;
this.serverConsole = ServerConsoles.addConsoleTab(serverName);
this.name = serverName;
}
/**
* Creates a new collection with the given parameters
*
@ -41,16 +56,11 @@ public class Collection {
* @param typeName <p>The name of the server type the server uses</p>
* @param serverVersion <p>The version of the running server type.</p>
* @param maxRam <p>The maximum amount of RAM the server is allowed to use.</p>
* @param vanillaVersion <p>The currently selected vanilla version</p>
* @param snapshotVersion <p>The currently selected snapshot version</p>
* @param spongeVanillaVersion <p>The currently selected SpongeVanilla version</p>
* @param bungeeVersion <p>The currently selected Bungee version</p>
*/
Collection(String name, String serverPath, boolean enabled, String typeName, String serverVersion, String maxRam,
String vanillaVersion, String snapshotVersion, String spongeVanillaVersion, String bungeeVersion) throws ConfigurationException {
Collection(String name, String serverPath, boolean enabled, String typeName, String serverVersion, String maxRam)
throws ConfigurationException {
this.serverTab = new ServerTab(name);
this.server = new Server(name, serverPath, enabled, typeName, serverVersion, maxRam, vanillaVersion,
snapshotVersion, spongeVanillaVersion, bungeeVersion);
this.server = new Server(name, serverPath, enabled, typeName, serverVersion, maxRam);
this.serverConsole = ServerConsoles.addConsoleTab(name);
this.name = name;
this.serverTab.setData(serverPath, enabled, typeName, serverVersion, maxRam);

View File

@ -1,16 +1,20 @@
package net.knarcraft.minecraftserverlauncher.profile;
import net.knarcraft.minecraftserverlauncher.server.ServerTypeHandler;
import net.knarcraft.minecraftserverlauncher.userinterface.ServerLauncherGUI;
import net.knarcraft.minecraftserverlauncher.userinterface.ServerConsoles;
import net.knarcraft.minecraftserverlauncher.userinterface.ServerTab;
import net.knarcraft.minecraftserverlauncher.server.Server;
import net.knarcraft.minecraftserverlauncher.Main;
import net.knarcraft.minecraftserverlauncher.server.Server;
import net.knarcraft.minecraftserverlauncher.server.ServerTypeHandler;
import net.knarcraft.minecraftserverlauncher.userinterface.ServerConsoles;
import net.knarcraft.minecraftserverlauncher.userinterface.ServerLauncherGUI;
import net.knarcraft.minecraftserverlauncher.userinterface.ServerTab;
import net.knarcraft.minecraftserverlauncher.utility.JarDownloader;
import javax.naming.ConfigurationException;
import javax.swing.*;
import java.io.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.NoSuchElementException;
import java.util.Scanner;
@ -19,26 +23,22 @@ import java.util.concurrent.Executors;
/**
* Contains all user settings, and a list of servers.
*
* @author Kristian Knarvik <kristian.knarvik@knett.no>
* @version 1.0.0
* @since 1.0.0
* @author Kristian Knarvik <kristian.knarvik@knett.no>
* @version 1.0.0
* @since 1.0.0
*/
public class Profile {
public class Profile implements java.io.Serializable {
private static final ArrayList<Profile> profiles = new ArrayList<>();
private static Profile current;
private static ServerLauncherGUI serverLauncherGui;
private static final String profilesDir = Main.getApplicationWorkDirectory() + File.separator + "files";
private static final String profilesFile = Main.getApplicationWorkDirectory() + File.separator + "files" + File.separator + "Profiles.txt";
private static final String profilesDir = Main.getApplicationWorkDirectory() + File.separator + "files";
private static final String profilesFile = Main.getApplicationWorkDirectory() + File.separator + "files" + File.separator + "Profiles.txt";
private static final String jarDirectory = Main.getApplicationWorkDirectory() + File.separator + "files" + File.separator + "Jars" + File.separator;
private static Profile current;
private static transient ServerLauncherGUI serverLauncherGui;
private final ArrayList<Collection> collections;
private final String name;
private boolean runInBackground;
private int delayStartup;
private boolean downloadAllAvailableJARFiles;
private static String vanillaVersion;
private static String snapshotVersion;
private static String bungeeVersion;
private Profile(String name) {
this.collections = new ArrayList<>();
@ -68,43 +68,22 @@ public class Profile {
return serverLauncherGui;
}
public boolean getRunInBackground() {
return this.runInBackground;
}
public int getDelayStartup() {
return this.delayStartup;
}
public boolean getDownloadAllAvailableJARFiles() {
return this.downloadAllAvailableJARFiles;
}
public static Profile getCurrent() {
return current;
}
public ArrayList<Collection> getCollections() {
return this.collections;
}
public String getName() {
return this.name;
}
/**
* Gets a Collection object by name.
* Set the current profile to the profile with a certain name.
*
* @param name The name of the collection.
* @return A collection object.
* @param name The name of the profile
*/
public Collection getCollection(String name) {
for (Collection collection : this.collections) {
if (collection.getName().equals(name)) {
return collection;
public static void setCurrent(String name) {
for (Profile profile : profiles) {
if (profile.name.equals(name)) {
current = profile;
break;
}
}
return null;
}
public static Profile getProfile(String name) {
@ -120,38 +99,144 @@ public class Profile {
return profiles;
}
/**
* Adds a profile if the name is valid and unique.
*
* @param name The name of the new profile.
*/
public static void addProfile(String name) {
if (name == null) { //If a user cancels or crosses out window
return;
}
if (name.equals("") && !name.matches("^[!?;]+$")) {
serverLauncherGui.showError("Profile name can't be blank.");
return;
}
for (Profile profile : profiles) {
if (profile.name.equals(name)) {
serverLauncherGui.showError("There is already a profile with this name.");
return;
}
}
new Profile(name);
}
/**
* 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 rempve</p>
*/
public static void removeProfile(String name) {
if (profiles.size() > 1) {
profiles.removeIf(profile -> profile.name.equals(name));
}
}
/**
* Parses a profile, and creates a profile with the data.
*
* @param profileData <p>The data of the new profile</p>
* @return <p>The new profile</p>
*/
private static Profile parseProfile(String[] profileData) {
return new Profile(
profileData[0],
Boolean.parseBoolean(profileData[1]),
Integer.parseInt(profileData[2]),
Boolean.parseBoolean(profileData[3])
);
}
/**
* Parses a server, and creates a new collection.
*
* @param profile <p>The profile which to add the collection</p>
* @param serverData <p>The data to parse</p>
*/
private static void parseServer(Profile profile, String[] serverData) throws ConfigurationException {
profile.collections.add(new Collection(
serverData[0],
serverData[1],
Boolean.parseBoolean(serverData[2]),
serverData[3],
serverData[4],
serverData[5])
);
}
public boolean getRunInBackground() {
return this.runInBackground;
}
public void setRunInBackground(boolean value) {
this.runInBackground = value;
}
public int getDelayStartup() {
return this.delayStartup;
}
public void setDelayStartup(int value) {
if (value >= 0) {
this.delayStartup = value;
}
}
/**
* Gets the state of the download all jar files setting
*
* @return <p>Whether to download all jars</p>
*/
public boolean getDownloadAllAvailableJARFiles() {
return this.downloadAllAvailableJARFiles;
}
/**
* Sets the state of the download all jar files setting
*
* @param value <p>The new value of the download all jar files setting</p>
*/
public void setDownloadAllAvailableJARFiles(boolean value) {
this.downloadAllAvailableJARFiles = value;
}
/**
* Set the current profile to the profile with a certain name.
* Gets all collections stored as part of this profile
*
* @param name The name of the profile
* @return <p>All collections stored by this profile</p>
*/
public static void setCurrent(String name) {
for (Profile profile : profiles) {
if (profile.name.equals(name)) {
current = profile;
break;
public ArrayList<Collection> getCollections() {
return this.collections;
}
/**
* Gets the name of this profile
*
* @return <p>The name of this profile</p>
*/
public String getName() {
return this.name;
}
/**
* Gets a Collection object by name.
*
* @param name The name of the collection.
* @return A collection object.
*/
public Collection getCollection(String name) {
for (Collection collection : this.collections) {
if (collection.getName().equals(name)) {
return collection;
}
}
return null;
}
/**
* Adds a collection to the profile if the name is valid.
*
* @param name The name of the collection and its elements.
* @param name The name of the collection and its elements.
*/
public void addCollection(String name) throws ConfigurationException {
if (name == null) { //If a user cancels or crosses out window
@ -171,28 +256,6 @@ public class Profile {
}
}
/**
* Adds a profile if the name is valid and unique.
*
* @param name The name of the new profile.
*/
public static void addProfile(String name) {
if (name == null) { //If a user cancels or crosses out window
return;
}
if (name.equals("") && !name.matches("^[!?;]+$")) {
serverLauncherGui.showError("Profile name can't be blank.");
return;
}
for (Profile profile : profiles) {
if (profile.name.equals(name)) {
serverLauncherGui.showError("There is already a profile with this name.");
return;
}
}
new Profile(name);
}
public void removeCollection(String name) {
for (int i = 0; i < collections.size(); i++) {
if (collections.get(i).getName().equals(name)) {
@ -203,16 +266,6 @@ public class Profile {
}
}
/**
* 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 rempve</p>
*/
public static void removeProfile(String name) {
if (profiles.size() > 1) {
profiles.removeIf(profile -> profile.name.equals(name));
}
}
public void updateConsoles() {
JTabbedPane consolesTab = ServerConsoles.getTabbedPane();
consolesTab.removeAll();
@ -224,8 +277,8 @@ public class Profile {
/**
* Sends a command to a server, or all servers
*
* @param serverName The target server
* @param command The command to send.
* @param serverName The target server
* @param command The command to send.
*/
public void sendCommand(String serverName, String command) {
if (serverName.equals("All")) {
@ -256,6 +309,18 @@ public class Profile {
* Saves all profiles and servers to a text file.
*/
public void save() throws FileNotFoundException {
/*try {
FileOutputStream fileOut =
new FileOutputStream(profilesFile);
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(this);
out.close();
fileOut.close();
} catch (IOException i) {
System.out.println("Unable to serialize or write the profile settings file");
i.printStackTrace();
}*/
for (Collection collection : this.collections) {
Server server = collection.getServer();
ServerTab serverTab = collection.getServerTab();
@ -267,7 +332,7 @@ public class Profile {
} catch (IllegalArgumentException e) {
serverLauncherGui.showError("Invalid server version for " + server.getName());
}
server.toggle(serverTab.enabled());
server.setEnabled(serverTab.enabled());
}
if (!new File(profilesDir).exists() && !new File(profilesDir).mkdirs()) {
serverLauncherGui.showError("Unable to create the folder " + profilesDir);
@ -284,11 +349,8 @@ public class Profile {
height = serverLauncherGui.getSize().height;
}
file.println(String.format(
"%s;%s;%s;%s;%d;%d",
"%s;%s;%s",
current.name,
vanillaVersion,
snapshotVersion,
bungeeVersion,
width,
height
));
@ -304,17 +366,13 @@ public class Profile {
for (Collection collection : profile.collections) {
Server server = collection.getServer();
saveString.append(String.format(
"%s;%s;%b;%s;%s;%s;%s;%s;%s;%s!",
"%s;%s;%b;%s;%s;%s!",
server.getName(),
server.getPath(),
server.isEnabled(),
server.getTypeName(),
server.getServerVersion(),
server.getMaxRam(),
server.getVanillaVersion(),
server.getSnapshotVersion(),
server.getSpongeVanillaVersion(),
server.getBungeeVersion()
server.getMaxRam()
)
);
}
@ -344,16 +402,32 @@ public class Profile {
/**
* Reads profiles and servers from a text file.
*/
public static void load() throws ConfigurationException {
public static void load() throws ConfigurationException, IOException {
/*Profile p;
if (!new File(profilesFile).exists()) {
addProfile("Default");
return;
}
try {
FileInputStream fileIn = new FileInputStream(profilesFile);
ObjectInputStream in = new ObjectInputStream(fileIn);
p = (Profile) in.readObject();
in.close();
fileIn.close();
profiles.add(p);
} catch (IOException i) {
i.printStackTrace();
} catch (ClassNotFoundException c) {
System.out.println("Profile class not found");
c.printStackTrace();
}*/
try (Scanner in = new Scanner(new File(profilesFile))) {
try {
String[] staticData = in.nextLine().split(";", -1);
String profileName = staticData[0];
vanillaVersion = staticData[1];
snapshotVersion = staticData[2];
bungeeVersion = staticData[3];
int guiWidth = Integer.parseInt(staticData[4]);
int guiHeight = Integer.parseInt(staticData[5]);
int guiWidth = Integer.parseInt(staticData[1]);
int guiHeight = Integer.parseInt(staticData[2]);
serverLauncherGui = new ServerLauncherGUI(guiWidth, guiHeight);
while (in.hasNextLine()) {
String line = in.nextLine();
@ -379,6 +453,7 @@ public class Profile {
current = getProfile(profileName);
} catch (ArrayIndexOutOfBoundsException | NumberFormatException e) {
e.printStackTrace();
serverLauncherGui = new ServerLauncherGUI();
serverLauncherGui.showError("Invalid Profile.txt file. Profiles could not be loaded. If this error persists, please " +
"manually delete the file.");
System.exit(1);
@ -392,7 +467,6 @@ public class Profile {
serverLauncherGui.showMessage("A profiles file was not found. Default profile was created.");
try {
serverLauncherGui = new ServerLauncherGUI();
} catch (FileNotFoundException ex) {
serverLauncherGui.showMessage("Failed to load ServerLauncherGUI messages. The ServerLauncherGUI can't be shown.");
} catch (IOException ex) {
ex.printStackTrace();
@ -417,38 +491,4 @@ public class Profile {
serverLauncherGui.hide();
}
}
/**
* Parses a profile, and creates a profile with the data.
* @param profileData <p>The data of the new profile</p>
* @return <p>The new profile</p>
*/
private static Profile parseProfile(String[] profileData) {
return new Profile(
profileData[0],
Boolean.parseBoolean(profileData[1]),
Integer.parseInt(profileData[2]),
Boolean.parseBoolean(profileData[3])
);
}
/**
* Parses a server, and creates a new collection.
* @param profile <p>The profile which to add the collection</p>
* @param serverData <p>The data to parse</p>
*/
private static void parseServer(Profile profile, String[] serverData) throws ConfigurationException {
profile.collections.add(new Collection(
serverData[0],
serverData[1],
Boolean.parseBoolean(serverData[2]),
serverData[3],
serverData[4],
serverData[5],
serverData[6],
serverData[7],
serverData[8],
serverData[9])
);
}
}

View File

@ -13,17 +13,18 @@ import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* Contains all necessary information to create, run and manage a Minecraft server.
* Contains all necessary information to create, runServer and manage a Minecraft server.
*
* @author Kristian Knarvik <kristian.knarvik@knett.no>
* @version 1.0.0
* @since 1.0.0
*/
public class Server {
public class Server implements java.io.Serializable {
/**
* Available ram sizes. For ServerLauncherGUI dropdown
*/
@ -33,19 +34,15 @@ public class Server {
private static final String jarDirectory = Main.getApplicationWorkDirectory() + File.separator + "files" + File.separator + "Jars" + File.separator;
private final String name;
private final ArrayList<String> playerList;
private String path;
private boolean enabled;
private final ArrayList<String> playerList;
private ServerType type;
private String serverVersion;
private String maxRam;
private Process process;
private BufferedWriter writer;
private BufferedReader reader;
private final String vanillaVersion;
private final String snapshotVersion;
private final String spongeVanillaVersion;
private final String bungeeVersion;
private boolean started;
/**
@ -64,41 +61,83 @@ public class Server {
this.process = null;
this.writer = null;
this.reader = null;
this.vanillaVersion = "";
this.snapshotVersion = "";
this.spongeVanillaVersion = "";
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>
* @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>
*/
public Server(String name, String path, boolean enabled, String typeName, String serverVersion, String maxRam,
String vanillaVersion, String snapshotVersion, String spongeVanillaVersion, String bungeeVersion) {
public Server(String name, String path, boolean enabled, String typeName, String serverVersion, String maxRam) {
this.name = name;
this.path = path;
this.enabled = enabled;
this.type = ServerTypeHandler.getByName(typeName);
this.serverVersion = serverVersion;
this.maxRam = maxRam;
this.vanillaVersion = vanillaVersion;
this.snapshotVersion = snapshotVersion;
this.spongeVanillaVersion = spongeVanillaVersion;
this.bungeeVersion = bungeeVersion;
this.playerList = new ArrayList<>();
}
public static String[] getRamList() {
return ramList;
}
/**
* Tries to stop all enabled servers.
*
* @throws IOException If a writer's process is already closed but not null.
*/
public static void stop() throws IOException {
for (Collection collection : Profile.getCurrent().getCollections()) {
Server server = collection.getServer();
if (server.writer != null) {
if (server.type.isProxy()) {
server.writer.write("end\n");
} else {
server.writer.write("stop\n");
}
server.writer.flush();
server.writer = null;
server.started = false;
}
}
}
/**
* Runs all enabled servers with their settings
*/
public static void startServers() {
Profile.getGUI().setStatus("Starting servers");
for (Collection collection : Profile.getCurrent().getCollections()) {
if (!collection.getServer().runServer()) {
Profile.getGUI().setStatus("An error occurred. Start aborted");
try {
Server.stop();
} catch (IOException e) {
e.printStackTrace();
}
Profile.getGUI().updateRunning(false);
return;
}
}
}
/**
* Gets a server object from a server save string
*
* @param saveString <p>The string containing necessary data regarding the server</p>
* @return <p>A server in the same state it was saved in</p>
*/
public static Server fromString(String saveString) {
String[] data = saveString.split(";");
return new Server(data[0], data[1], Boolean.parseBoolean(data[2]), data[3], data[4], data[5]);
}
/**
* Gets the name of the server
*
@ -126,6 +165,15 @@ public class Server {
return this.type.getName();
}
/**
* Gets the server type used by this server
*
* @return <p>The server type used by this server</p>
*/
public ServerType getType() {
return this.type;
}
/**
* Gets the version used given server type used
*
@ -135,108 +183,10 @@ public class Server {
return this.serverVersion;
}
public String getPath() {
return this.path;
}
public Process getProcess() {
return this.process;
}
public String getMaxRam() {
return this.maxRam;
}
public static String[] getRamList() {
return ramList;
}
public String getVanillaVersion() {
return this.vanillaVersion;
}
public String getSnapshotVersion() {
return this.snapshotVersion;
}
public String getSpongeVanillaVersion() {
return this.spongeVanillaVersion;
}
public String getBungeeVersion() {
return this.bungeeVersion;
}
public ArrayList<String> getPlayers() {
return this.playerList;
}
public void stopped() {
process = null;
writer = null;
reader = null;
started = false;
}
/**
* @return A representation of the name of a jarfile.
*/
private String getType() {
if (this.type.getName().equals("Custom")) {
return this.serverVersion;
} else {
return "";
}
}
public boolean isEnabled() {
return this.enabled;
}
public void toggle(boolean value) {
this.enabled = value;
}
public boolean hasPlayer(String name) {
for (String player : this.playerList) {
if (player.equals(name)) {
return true;
}
}
return false;
}
public void addPlayer(String name) {
this.playerList.add(name);
Profile.getGUI().addPlayer(name);
}
/**
* Removes a player with the selected name from the playerlist.
* Sets the server's server version to a valid version, or ignores the request
*
* @param name The name of the player to remove
*/
public void removePlayer(String name) {
playerList.removeIf(player -> player.equals(name));
Profile.getGUI().removePlayer(name);
}
public void setPath(String path) {
this.path = path;
}
public void setType(ServerType type) {
this.type = type;
}
public void setMaxRam(String ram) {
this.maxRam = ram;
}
/**
* Sets the server's server version to a valid version, or ignores the request.
*
* @param serverVersion Version number.
* @param serverVersion <p>The new server version</p>
*/
public void setServerVersion(String serverVersion) throws IllegalArgumentException {
if (this.type.getName().equals("Custom")) {
@ -254,43 +204,129 @@ public class Server {
}
/**
* Tries to stop all enabled servers.
* Gets the path for this server's files
*
* @throws IOException If a writer's process is already closed but not null.
* @return <p>The path of this server's files</p>
*/
public static void stop() throws IOException {
for (Collection collection : Profile.getCurrent().getCollections()) {
Server server = collection.getServer();
if (server.writer != null) {
if (server.type.getName().equals("Bungee")) {
server.writer.write("end\n");
} else {
server.writer.write("stop\n");
}
server.writer.flush();
server.writer = null;
server.started = false;
}
}
public String getPath() {
return this.path;
}
/**
* Runs all enabled servers with their settings.
* Sets the path of this server's files
*
* @param path <p>The new path of the server's files</p>
*/
public static void startServers() {
Profile.getGUI().setStatus("Starting servers");
for (Collection collection : Profile.getCurrent().getCollections()) {
if (!collection.getServer().run()) {
Profile.getGUI().setStatus("An error occurred. Start aborted");
try {
Server.stop();
} catch (IOException e) {
e.printStackTrace();
}
Profile.getGUI().updateRunning(false);
return;
public void setPath(String path) {
this.path = path;
}
/**
* Gets the process of the server
*
* @return <p>The server process</p>
*/
public Process getProcess() {
return this.process;
}
/**
* Gets the maximum amount of ram usable by this server
*
* @return <p>The maximum amount of ram this server can use</p>
*/
public String getMaxRam() {
return this.maxRam;
}
/**
* Sets the max ram to be used by the server
*
* @param ram <p>The new maximum ram amount</p>
*/
public void setMaxRam(String ram) {
this.maxRam = ram;
}
/**
* Gets a list of all players connected to this server
*
* @return <p>A list of all players connected to the server</p>
*/
public List<String> getPlayers() {
return this.playerList;
}
/**
* Checks whether this server is fully stopped
*/
public void stopped() {
process = null;
writer = null;
reader = null;
started = false;
}
/**
* Checks whether this server is currently enabled
*
* @return <p>True if the server is currently enabled</p>
*/
public boolean isEnabled() {
return this.enabled;
}
/**
* Sets whether this server is currently enabled
*
* @param value <p>Whether the server is currently enabled</p>
*/
public void setEnabled(boolean value) {
this.enabled = value;
}
/**
* Checks whether this server has a given player
*
* @param name <p>The name of the player to check</p>
* @return <p>True if the player is connected</p>
*/
public boolean hasPlayer(String name) {
for (String player : this.playerList) {
if (player.equals(name)) {
return true;
}
}
return false;
}
/**
* Adds a player to the GUI and this server's player list
*
* @param name <p>The name of the player to add</p>
*/
public void addPlayer(String name) {
this.playerList.add(name);
Profile.getGUI().addPlayer(name);
}
/**
* Removes a player with the selected name from the player list
*
* @param name The name of the player to remove
*/
public void removePlayer(String name) {
playerList.removeIf(player -> player.equals(name));
Profile.getGUI().removePlayer(name);
}
/**
* Sets the server type to be used by the server
*
* @param type <p>The new server type to be used by the server</p>
*/
public void setType(ServerType type) {
this.type = type;
}
/**
@ -298,7 +334,7 @@ public class Server {
*
* @return <p>True if nothing went wrong</p>
*/
private boolean run() {
private boolean runServer() {
if (!this.enabled) {
this.started = false;
return true;
@ -393,7 +429,6 @@ public class Server {
this.downloadJar();
Profile.getGUI().setStatus("File downloaded");
} catch (IOException e) {
System.out.println(e.getMessage());
Profile.getGUI().setStatus("Error: Jar file not found");
e.printStackTrace();
this.started = false;
@ -410,7 +445,10 @@ public class Server {
*/
private void downloadJar() throws IOException {
String path = this.path + File.separator;
File file = new File(path + this.getType());
if (this.type.getName().equals("Custom")) {
path += this.serverVersion;
}
File file = new File(path);
if (!(file.isFile() || type.downloadJar(path, this.serverVersion))) {
throw new FileNotFoundException("Jar file could not be downloaded.");
}
@ -428,4 +466,17 @@ public class Server {
this.writer.flush();
}
}
@Override
public String toString() {
return String.format(
"%s;%s;%b;%s;%s;%s;!",
this.getName(),
this.getPath(),
this.isEnabled(),
this.getTypeName(),
this.getServerVersion(),
this.getMaxRam()
);
}
}

View File

@ -29,7 +29,8 @@ public class ServerTypeHandler {
/**
* Gets a list of all server types' names.
* @return <p>A list of strings</p>
*
* @return <p>A list of strings</p>
*/
public static String[] getTypeNames() throws ConfigurationException {
ArrayList<ServerType> types = getServerTypes();
@ -42,6 +43,7 @@ public class ServerTypeHandler {
/**
* Gets all instantiated server types
*
* @return <p>A list of server types</p>
*/
public static ArrayList<ServerType> getServerTypes() throws ConfigurationException {
@ -53,6 +55,7 @@ public class ServerTypeHandler {
/**
* Gets a server type by the given name
*
* @param name <p>Then name of the server type</p>
* @return <p>A AbstractServerType</p>
*/
@ -67,6 +70,7 @@ public class ServerTypeHandler {
/**
* Reads valid server types and version from a file, and creates their objects.
*
* @throws ConfigurationException <p>If anything goes wrong</p>
*/
private static void loadServerTypes() throws ConfigurationException {
@ -102,41 +106,47 @@ public class ServerTypeHandler {
ServerType newType;
switch (serverTypeInfo[0]) {
case "Craftbukkit":
newType = new CraftBukkit("Bukkit", serverVersions, serverTypeInfo[2], serverTypeInfo[3]);
newType = new CraftBukkit("Bukkit", false, serverVersions, serverTypeInfo[2],
serverTypeInfo[3]);
break;
case "Spigot":
newType = new Spigot("Spigot", serverVersions, serverTypeInfo[2], serverTypeInfo[3]);
newType = new Spigot("Spigot", false, serverVersions, serverTypeInfo[2],
serverTypeInfo[3]);
break;
case "Vanilla":
newType = new Vanilla("Vanilla", serverVersions, serverTypeInfo[2], serverTypeInfo[3]);
newType = new Vanilla("Vanilla", false, serverVersions, serverTypeInfo[2],
serverTypeInfo[3]);
break;
case "Snapshot":
newType = new Snapshot("Snapshot", serverVersions, serverTypeInfo[2], serverTypeInfo[3]);
newType = new Snapshot("Snapshot", false, serverVersions, serverTypeInfo[2],
serverTypeInfo[3]);
break;
case "MCPCplus":
newType = new MCPCPlus("MCPCplus", serverVersions, serverTypeInfo[2], serverTypeInfo[3]);
newType = new MCPCPlus("MCPCplus", false, serverVersions, serverTypeInfo[2],
serverTypeInfo[3]);
break;
case "Paper":
newType = new Paper("Paper", serverVersions, serverTypeInfo[2], serverTypeInfo[3]);
newType = new Paper("Paper", false, serverVersions, serverTypeInfo[2],
serverTypeInfo[3]);
break;
case "Bungee":
newType = new BungeeCord("Bungee", serverVersions, serverTypeInfo[2], serverTypeInfo[3],
serverTypeInfo[4], serverTypeInfo[5]);
newType = new BungeeCord("Bungee", true, serverVersions, serverTypeInfo[2],
serverTypeInfo[3], serverTypeInfo[4], serverTypeInfo[5]);
break;
case "Travertine":
newType = new Travertine("Travertine", serverVersions, serverTypeInfo[2], serverTypeInfo[3],
serverTypeInfo[4], serverTypeInfo[5]);
newType = new Travertine("Travertine", true, serverVersions, serverTypeInfo[2],
serverTypeInfo[3], serverTypeInfo[4], serverTypeInfo[5]);
break;
case "Waterfall":
newType = new Waterfall("Waterfall", serverVersions, serverTypeInfo[2], serverTypeInfo[3],
serverTypeInfo[4], serverTypeInfo[5]);
newType = new Waterfall("Waterfall", true, serverVersions, serverTypeInfo[2],
serverTypeInfo[3], serverTypeInfo[4], serverTypeInfo[5]);
break;
case "SpongeVanilla":
newType = new SpongeVanilla("SpongeVanilla", serverVersions, serverTypeInfo[2], serverTypeInfo[3],
serverTypeInfo[4], serverTypeInfo[5], serverTypeInfo[6]);
newType = new SpongeVanilla("SpongeVanilla", false, serverVersions,
serverTypeInfo[2], serverTypeInfo[3], serverTypeInfo[4], serverTypeInfo[5], serverTypeInfo[6]);
break;
case "Custom":
newType = new Custom("Custom", serverVersions, serverTypeInfo[2]);
newType = new Custom("Custom");
break;
default:
throw new IllegalArgumentException("Unknown server type defined in config file.");

View File

@ -0,0 +1,88 @@
package net.knarcraft.minecraftserverlauncher.server;
import java.util.Map;
public class ServerVersionContainer implements java.io.Serializable {
private String vanillaVersion;
private String snapshotVersion;
private String bungeeVersion;
private String waterfallVersion;
private String travertineVersion;
private Map<String, String> spongeVanillaVersions;
public ServerVersionContainer() {
}
public String getVanillaVersion() {
return this.vanillaVersion;
}
/**
* Sets the vanilla server version
*
* @param newVersion <p>The new vanilla server version</p>
* @return <p>This object</p>
*/
public ServerVersionContainer setVanillaVersion(String newVersion) {
this.vanillaVersion = newVersion;
return this;
}
public String getSnapshotVersion() {
return this.snapshotVersion;
}
public ServerVersionContainer setSnapshotVersion(String newVersion) {
this.snapshotVersion = newVersion;
return this;
}
public String getBungeeVersion() {
return this.bungeeVersion;
}
public ServerVersionContainer setBungeeVersion(String newVersion) {
this.bungeeVersion = newVersion;
return this;
}
public String getWaterfallVersion() {
return this.waterfallVersion;
}
public ServerVersionContainer setWaterfallVersion(String newVersion) {
this.waterfallVersion = newVersion;
return this;
}
public String getTravertineVersion() {
return this.travertineVersion;
}
public ServerVersionContainer setTravertineVersion(String newVersion) {
this.travertineVersion = newVersion;
return this;
}
public Map<String, String> getSpongeVanillaVersions() {
return this.spongeVanillaVersions;
}
public String getSpongeVanillaVersion(String versionKey) {
return spongeVanillaVersions.get(versionKey);
}
public ServerVersionContainer setSpongeVanillaVersion(Map<String, String> newVersions) {
this.spongeVanillaVersions = newVersions;
return this;
}
public ServerVersionContainer setSpongeVanillaVersion(String mapKey, String newValue) {
spongeVanillaVersions.put(mapKey, newValue);
return this;
}
}

View File

@ -3,49 +3,44 @@ package net.knarcraft.minecraftserverlauncher.server.servertypes;
/**
* Contains the bare minimum to be a functional server type.
*
* @author Kristian Knarvik <kristian.knarvik@knett.no>
* @version 1.0.0
* @since 1.0.0
* @author Kristian Knarvik <kristian.knarvik@knett.no>
* @version 1.0.0
* @since 1.0.0
*/
public abstract class AbstractServerType implements ServerType {
private final String typeName;
private final String[] versions;
final String downloadURL;
final String downloadURL;
private final String typeName;
private final boolean isProxy;
private final String[] versions;
/**
* Instantiates a new server type
* @param typeName <p>The typeName of the server type</p>
* @param versions <p>A list of one or more server versions for the type</p>
* @param downloadURL <p>The URL used for downloading .jar files</p>
*/
AbstractServerType(String typeName, String[] versions, String downloadURL) {
this.typeName = typeName;
this.versions = versions;
this.downloadURL = downloadURL;
}
/**
* Instantiates a new server type
*
* @param typeName <p>The typeName of the server type</p>
* @param isProxy <p>Whether this server type is a proxy server</p>
* @param versions <p>A list of one or more server versions for the type</p>
* @param downloadURL <p>The URL used for downloading .jar files</p>
*/
AbstractServerType(String typeName, boolean isProxy, String[] versions, String downloadURL) {
this.typeName = typeName;
this.isProxy = isProxy;
this.versions = versions;
this.downloadURL = downloadURL;
}
/**
* Gets the name of the server type
* @return <p>Server type typeName</p>
*/
public String getName() {
return this.typeName;
}
@Override
public String getName() {
return this.typeName;
}
/**
* Gets a list of versions available for the server type
* @return <p>A list of server versions</p>
*/
public String[] getVersions() {
return this.versions;
}
@Override
public boolean isProxy() {
return this.isProxy;
}
/**
* Gets the url used for downloading JAR files
* @return <p>A download URL</p>
*/
public String getDownloadURL() {
return this.downloadURL;
}
@Override
public String[] getVersions() {
return this.versions;
}
}

View File

@ -18,15 +18,16 @@ public class BungeeCord extends AbstractServerType {
/**
* Instantiates a new BungeeCord server type
*
* @param typeName <p>The name of the server type</p>
* @param versions <p>The available versions for the server type</p>
* @param versionURL <p>The URL used to finding the newest version</p>
* @param srcStart <p>The string after which the version id starts</p>
* @param srcEnd <p>The string marking the end of the version id</p>
* @param typeName <p>The name of the server type</p>
* @param isProxy <p>Whether this server type is a proxy server</p>
* @param versions <p>The available versions for the server type</p>
* @param versionURL <p>The URL used to finding the newest version</p>
* @param srcStart <p>The string after which the version id starts</p>
* @param srcEnd <p>The string marking the end of the version id</p>
* @param downloadURL <p>The URL used for downloading the latest version</p>
*/
public BungeeCord(String typeName, String[] versions, String versionURL, String srcStart, String srcEnd, String downloadURL) {
super(typeName, versions, downloadURL);
public BungeeCord(String typeName, boolean isProxy, String[] versions, String versionURL, String srcStart, String srcEnd, String downloadURL) {
super(typeName, isProxy, versions, downloadURL);
this.versionURL = versionURL;
this.srcStart = srcStart;
this.srcEnd = srcEnd;

View File

@ -12,13 +12,14 @@ public class CraftBukkit extends AbstractServerType {
/**
* Instantiates a new server type
*
* @param typeName <p>The name of the server type</p>
* @param versions <p>A list of one or more server versions for the type</p>
* @param downloadURL <p>The URL used for downloading .jar files</p>
* @param typeName <p>The name of the server type</p>
* @param isProxy <p>Whether this server type is a proxy server</p>
* @param versions <p>A list of one or more server versions for the type</p>
* @param downloadURL <p>The URL used for downloading .jar files</p>
* @param downloadURLPart <p>A string used after the download url as an additional part of the URL</p>
*/
public CraftBukkit(String typeName, String[] versions, String downloadURL, String downloadURLPart) {
super(typeName, versions, downloadURL);
public CraftBukkit(String typeName, boolean isProxy, String[] versions, String downloadURL, String downloadURLPart) {
super(typeName, isProxy, versions, downloadURL);
this.downloadURLPart = downloadURLPart;
}

View File

@ -8,11 +8,9 @@ public class Custom extends AbstractServerType {
* Instantiates a new server type
*
* @param typeName <p>The name of the server type</p>
* @param versions <p>A list of one or more server versions for the type</p>
* @param downloadURL <p>The URL used for downloading .jar files</p>
*/
public Custom(String typeName, String[] versions, String downloadURL) {
super(typeName, versions, downloadURL);
public Custom(String typeName) {
super(typeName, false, new String[]{}, "");
}
@Override

View File

@ -5,13 +5,14 @@ public class MCPCPlus extends CraftBukkit {
/**
* Instantiates a new server type
*
* @param typeName <p>The name of the server type</p>
* @param versions <p>A list of one or more server versions for the type</p>
* @param downloadURL <p>The URL used for downloading .jar files</p>
* @param typeName <p>The name of the server type</p>
* @param isProxy <p>Whether this server type is a proxy server</p>
* @param versions <p>A list of one or more server versions for the type</p>
* @param downloadURL <p>The URL used for downloading .jar files</p>
* @param downloadURLPart <p>A string used after the download url as an additional part of the URL</p>
*/
public MCPCPlus(String typeName, String[] versions, String downloadURL, String downloadURLPart) {
super(typeName, versions, downloadURL, downloadURLPart);
public MCPCPlus(String typeName, boolean isProxy, String[] versions, String downloadURL, String downloadURLPart) {
super(typeName, isProxy, versions, downloadURL, downloadURLPart);
}
}

View File

@ -5,13 +5,14 @@ public class Paper extends Spigot {
/**
* Instantiates a new server type
*
* @param typeName <p>The typeName of the server type</p>
* @param versions <p>A list of one or more server versions for the type</p>
* @param downloadURL <p>The URL used for downloading .jar files</p>
* @param typeName <p>The typeName of the server type</p>
* @param isProxy <p>Whether this server type is a proxy server</p>
* @param versions <p>A list of one or more server versions for the type</p>
* @param downloadURL <p>The URL used for downloading .jar files</p>
* @param downloadURLPart <p>A string used after the download url as an additional part of the URL</p>
*/
public Paper(String typeName, String[] versions, String downloadURL, String downloadURLPart) {
super(typeName, versions, downloadURL, downloadURLPart);
public Paper(String typeName, boolean isProxy, String[] versions, String downloadURL, String downloadURLPart) {
super(typeName, isProxy, versions, downloadURL, downloadURLPart);
}
}

View File

@ -7,14 +7,23 @@ import java.io.IOException;
*/
public interface ServerType {
/**
* Gets whether this server type is a proxy server
*
* @return <p>True if this server type is a proxy server</p>
*/
boolean isProxy();
/**
* Gets the name of the server type
*
* @return <p>Server type name</p>
*/
String getName();
/**
* Gets a list of versions available for the server type
*
* @return <p>A list of server versions</p>
*/
String[] getVersions();
@ -22,7 +31,7 @@ public interface ServerType {
/**
* Downloads a .jar file for this server type
*
* @param folder <p>The folder to save the downloaded file to</p>
* @param folder <p>The folder to save the downloaded file to</p>
* @param version <p>The server type version to use</p>
* @return <p>True if the file exists or was downloaded</p>
*/

View File

@ -5,13 +5,14 @@ public class Snapshot extends Vanilla {
/**
* Instantiates a snapshot server type
*
* @param typeName <p>The name of this server type</p>
* @param versions <p>Available versions for this server type</p>
* @param versionURL <p>The URL used for downloading the version document</p>
* @param downloadURL <p>The URL used for downloading the new file</p>
* @param typeName <p>The name of this server type</p>
* @param isProxy <p>Whether this server type is a proxy server</p>
* @param versions <p>Available versions for this server type</p>
* @param versionURL <p>The URL used for downloading the version document</p>
* @param downloadURL <p>The URL used for downloading the new file</p>
*/
public Snapshot(String typeName, String[] versions, String versionURL, String downloadURL) {
super(typeName, versions, versionURL, downloadURL);
public Snapshot(String typeName, boolean isProxy, String[] versions, String versionURL, String downloadURL) {
super(typeName, isProxy, versions, versionURL, downloadURL);
this.releaseType = "snapshot";
}

View File

@ -5,13 +5,14 @@ public class Spigot extends CraftBukkit {
/**
* Instantiates a new server type
*
* @param typeName <p>The typeName of the server type</p>
* @param versions <p>A list of one or more server versions for the type</p>
* @param downloadURL <p>The URL used for downloading .jar files</p>
* @param typeName <p>The typeName of the server type</p>
* @param isProxy <p>Whether this server type is a proxy server</p>
* @param versions <p>A list of one or more server versions for the type</p>
* @param downloadURL <p>The URL used for downloading .jar files</p>
* @param downloadURLPart <p>A string used after the download url as an additional part of the URL</p>
*/
public Spigot(String typeName, String[] versions, String downloadURL, String downloadURLPart) {
super(typeName, versions, downloadURL, downloadURLPart);
public Spigot(String typeName, boolean isProxy, String[] versions, String downloadURL, String downloadURLPart) {
super(typeName, isProxy, versions, downloadURL, downloadURLPart);
}
}

View File

@ -20,6 +20,7 @@ public class SpongeVanilla extends AbstractServerType {
* Instantiates a new SpongeVanilla server type
*
* @param typeName <p>The name of this server type</p>
* @param isProxy <p>Whether this server type is a proxy server</p>
* @param versions <p>Available versions for this server type</p>
* @param versionURL <p>The URL used for downloading the version document</p>
* @param srcStart <p>The string to search for to determine newest version</p>
@ -27,9 +28,9 @@ public class SpongeVanilla extends AbstractServerType {
* @param downloadURL <p>The URL used for downloading the new file</p>
* @param downloadURLPart <p>A string used after the download url as an additional part of the URL</p>
*/
public SpongeVanilla(String typeName, String[] versions, String versionURL, String srcStart, String srcEnd,
public SpongeVanilla(String typeName, boolean isProxy, String[] versions, String versionURL, String srcStart, String srcEnd,
String downloadURL, String downloadURLPart) {
super(typeName, versions, downloadURL);
super(typeName, isProxy, versions, downloadURL);
this.versionURL = versionURL;
this.srcStart = srcStart;
this.srcEnd = srcEnd;

View File

@ -5,15 +5,16 @@ public class Travertine extends Waterfall {
/**
* Instantiates a new Travertine server type
*
* @param typeName <p>The name of the server type</p>
* @param versions <p>The available versions for the server type</p>
* @param versionURL <p>The URL used to finding the newest version</p>
* @param srcStart <p>The string after which the version id starts</p>
* @param srcEnd <p>The string marking the end of the version id</p>
* @param typeName <p>The name of the server type</p>
* @param isProxy <p>Whether this server type is a proxy server</p>
* @param versions <p>The available versions for the server type</p>
* @param versionURL <p>The URL used to finding the newest version</p>
* @param srcStart <p>The string after which the version id starts</p>
* @param srcEnd <p>The string marking the end of the version id</p>
* @param downloadURL <p>The URL used for downloading the latest version</p>
*/
public Travertine(String typeName, String[] versions, String versionURL, String srcStart, String srcEnd, String downloadURL) {
super(typeName, versions, versionURL, srcStart, srcEnd, downloadURL);
public Travertine(String typeName, boolean isProxy, String[] versions, String versionURL, String srcStart, String srcEnd, String downloadURL) {
super(typeName, isProxy, versions, versionURL, srcStart, srcEnd, downloadURL);
}
}

View File

@ -16,19 +16,20 @@ import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.read
public class Vanilla extends AbstractServerType {
private final String versionURL;
private String lastVersion;
String releaseType;
private String lastVersion;
/**
* Instantiates a vanilla server type
*
* @param typeName <p>The name of this server type to display</p>
* @param versions <p>Available versions for this server type</p>
* @param versionURL <p>The URL used for downloading the version document</p>
* @param downloadURL <p>The URL used for downloading the new file</p>
* @param typeName <p>The name of this server type to display</p>
* @param isProxy <p>Whether this server type is a proxy server</p>
* @param versions <p>Available versions for this server type</p>
* @param versionURL <p>The URL used for downloading the version document</p>
* @param downloadURL <p>The URL used for downloading the new file</p>
*/
public Vanilla(String typeName, String[] versions, String versionURL, String downloadURL) {
super(typeName, versions, downloadURL);
public Vanilla(String typeName, boolean isProxy, String[] versions, String versionURL, String downloadURL) {
super(typeName, isProxy, versions, downloadURL);
this.versionURL = versionURL;
this.releaseType = "release";
}

View File

@ -18,15 +18,17 @@ public class Waterfall extends AbstractServerType {
/**
* Instantiates a new Waterfall server type
*
* @param typeName <p>The name of the server type</p>
* @param versions <p>The available versions for the server type</p>
* @param versionURL <p>The URL used to finding the newest version</p>
* @param srcStart <p>The string after which the version id starts</p>
* @param srcEnd <p>The string marking the end of the version id</p>
* @param typeName <p>The name of the server type</p>
* @param isProxy <p>Whether this server type is a proxy server</p>
* @param versions <p>The available versions for the server type</p>
* @param versionURL <p>The URL used to finding the newest version</p>
* @param srcStart <p>The string after which the version id starts</p>
* @param srcEnd <p>The string marking the end of the version id</p>
* @param downloadURL <p>The URL used for downloading the latest version</p>
*/
public Waterfall(String typeName, String[] versions, String versionURL, String srcStart, String srcEnd, String downloadURL) {
super(typeName, versions, downloadURL);
public Waterfall(String typeName, boolean isProxy, String[] versions, String versionURL, String srcStart,
String srcEnd, String downloadURL) {
super(typeName, isProxy, versions, downloadURL);
this.srcStart = srcStart;
this.srcEnd = srcEnd;
this.versionURL = versionURL;

View File

@ -17,9 +17,9 @@ import static javax.swing.text.DefaultCaret.ALWAYS_UPDATE;
* Acts as a single writable/readable tab
* Has a box for user input, and a textArea for server output.
*
* @author Kristian Knarvik <kristian.knarvik@knett.no>
* @version 1.0.0
* @since 1.0.0
* @author Kristian Knarvik <kristian.knarvik@knett.no>
* @version 1.0.0
* @since 1.0.0
*/
public class Console implements ActionListener, KeyListener {
private final JTextField textInput;
@ -55,7 +55,7 @@ public class Console implements ActionListener, KeyListener {
/**
* Prints a string to the textArea.
*
* @param text The text to print
* @param text The text to print
*/
public void output(String text) {
this.textOutput.setText(this.textOutput.getText() + "\n" + text);

View File

@ -15,7 +15,7 @@ public interface GUI {
/**
* Displays an error to the user as an independent box
*
* @param title <p>The title of the error message</p>
* @param title <p>The title of the error message</p>
* @param message <p>The error message contents</p>
*/
void showError(String title, String message);
@ -30,7 +30,7 @@ public interface GUI {
/**
* Displays a message to the user as an independent box
*
* @param title <p>The title of the message</p>
* @param title <p>The title of the message</p>
* @param message <p>The message contents</p>
*/
void showMessage(String title, String message);

View File

@ -46,8 +46,8 @@ public abstract class MessageHandler implements GUI {
/**
* Shows a JOptionPane
*
* @param title <p>The title of the pane</p>
* @param message <p>The message of the pane</p>
* @param title <p>The title of the pane</p>
* @param message <p>The message of the pane</p>
* @param paneType <p>The type of the pane</p>
*/
private void showJOptionPane(String title, String message, int paneType) {

View File

@ -1,17 +1,16 @@
package net.knarcraft.minecraftserverlauncher.userinterface;
import javax.swing.JFrame;
import javax.swing.JTabbedPane;
import java.awt.BorderLayout;
import javax.swing.*;
import java.awt.*;
/**
* A parent window for server consoles.
* Should be toggled with the "View server consoles" button.
* Keeps track of all consoles.
*
* @author Kristian Knarvik <kristian.knarvik@knett.no>
* @version 1.0.0
* @since 1.0.0
* @author Kristian Knarvik <kristian.knarvik@knett.no>
* @version 1.0.0
* @since 1.0.0
*/
public class ServerConsoles {
private static JFrame frame;
@ -30,6 +29,7 @@ public class ServerConsoles {
/**
* Adds a new console tab
*
* @param name <p>The name of the consoles tab</p>
* @return <p>A new console element with the new tabbed pane</p>
*/
@ -46,6 +46,7 @@ public class ServerConsoles {
/**
* Returns the tabbed pane containing the server consoles
*
* @return <p>A tabbed pane</p>
*/
public static JTabbedPane getTabbedPane() {

View File

@ -1,17 +1,26 @@
package net.knarcraft.minecraftserverlauncher.userinterface;
import net.knarcraft.minecraftserverlauncher.utility.CommonFunctions;
import net.knarcraft.minecraftserverlauncher.profile.Collection;
import net.knarcraft.minecraftserverlauncher.Main;
import net.knarcraft.minecraftserverlauncher.server.Server;
import net.knarcraft.minecraftserverlauncher.profile.Collection;
import net.knarcraft.minecraftserverlauncher.profile.Profile;
import net.knarcraft.minecraftserverlauncher.server.Server;
import net.knarcraft.minecraftserverlauncher.utility.CommonFunctions;
import javax.imageio.ImageIO;
import javax.naming.ConfigurationException;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Objects;
import java.util.Scanner;
@ -25,12 +34,14 @@ import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.getR
/**
* Generates a ServerLauncherGUI.
*
* @author Kristian Knarvik <kristian.knarvik@knett.no>
* @version 1.0.0
* @since 1.0.0
* @author Kristian Knarvik <kristian.knarvik@knett.no>
* @version 1.0.0
* @since 1.0.0
*/
public class ServerLauncherGUI extends MessageHandler implements ActionListener, GUI {
private final JLabel lblStatuslabel = new JLabel("Servers are stopped");
private final ArrayList<String> globalPlayers;
private JFrame frame;
private JTabbedPane tabbedPane;
private JTabbedPane serversPane;
@ -42,7 +53,6 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener,
//Basic controls
private JButton btnStartServer, btnStopServer, addServer, backup, addProfile, delProfile;
private JComboBox<String> profiles;
private final JLabel lblStatuslabel = new JLabel("Servers are stopped");
//Server controls
private JComboBox<String> targetServer;
private JComboBox<String> targetPlayer;
@ -54,8 +64,6 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener,
private String delayStartupText;
private String downloadJarsText;
private String aboutText;
private final ArrayList<String> globalPlayers;
private SystemTray tray;
private TrayIcon trayIcon;
@ -71,7 +79,8 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener,
/**
* Creates the application window with a preferred width and height
* @param width <p>The preferred width</p>
*
* @param width <p>The preferred width</p>
* @param height <p>The preferred height</p>
*/
public ServerLauncherGUI(int width, int height) throws IOException {
@ -84,7 +93,7 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener,
/**
* Gets the pane used for server configurations
*
* @return A JTabbedPane
* @return A JTabbedPane
*/
public JTabbedPane getPane() {
return this.serversPane;
@ -95,7 +104,7 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener,
this.lblStatuslabel.setText(text);
try (PrintWriter file = new PrintWriter(new FileWriter(Main.getApplicationWorkDirectory() + File.separator + "latestrun.log", true))) {
file.println(text);
} catch (IOException e ) {
} catch (IOException e) {
e.printStackTrace();
}
}
@ -103,7 +112,7 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener,
/**
* Adds a player to the global playerlist, and updates the players combo.
*
* @param name The name of the player to add
* @param name The name of the player to add
*/
public void addPlayer(String name) {
this.globalPlayers.add(name);
@ -113,7 +122,7 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener,
/**
* Removes a player from the global list of players.
*
* @param name The name of the player to remove.
* @param name The name of the player to remove.
*/
public void removePlayer(String name) {
globalPlayers.removeIf(playerName -> playerName.equals(name));
@ -133,7 +142,7 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener,
/**
* Gets the size of the main JFrame
*
* @return The Dimension of the frame
* @return The Dimension of the frame
*/
public Dimension getSize() {
return frame.getContentPane().getSize();
@ -439,7 +448,7 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener,
PopupMenu popup = new PopupMenu();
trayIcon = new TrayIcon(trayImage, "Minecraft Server Launcher", popup);
trayIcon.setImageAutoSize(true);
ActionListener exitListener= e -> {
ActionListener exitListener = e -> {
stop();
try {
Profile.getCurrent().save();
@ -491,7 +500,7 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener,
trayIcon.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
if(e.getClickCount() >= 1 && e.getButton() == MouseEvent.BUTTON1){
if (e.getClickCount() >= 1 && e.getButton() == MouseEvent.BUTTON1) {
frame.setExtendedState(NORMAL);
tray.remove(trayIcon);
frame.setVisible(true);
@ -560,12 +569,12 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener,
} else if (e.getSource() == mntmStory) {
CommonFunctions.goToURL("https://archive.knarcraft.net/Scripts/BungeeMinecraftServerLauncherStory/");
} else if (e.getSource() == btnStartServer) {
try {
Profile.getCurrent().save();
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
Executors.newSingleThreadExecutor().execute(Server::startServers);
try {
Profile.getCurrent().save();
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
Executors.newSingleThreadExecutor().execute(Server::startServers);
} else if (e.getSource() == btnStopServer) {
stop();
} else if (e.getSource() == addServer) {
@ -589,11 +598,11 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener,
updateProfiles();
}
} else if (e.getSource() == profiles) {
try {
changeProfile();
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
try {
changeProfile();
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
} else if (e.getSource() == btnKick) {
if (selectedServerValue != null && selectedPlayerValue != null) {
Profile.getCurrent().sendCommand(selectedServerValue, "kick " + selectedPlayerValue);
@ -633,7 +642,7 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener,
/**
* Updates the ServerLauncherGUI components to block a user from doing illegal actions.
*
* @param running Are the servers currently running?
* @param running Are the servers currently running?
*/
public void updateRunning(boolean running) {
boolean stopped = !running; //Most gui is only enabled when the server is stopped rather than running.

View File

@ -2,8 +2,8 @@ package net.knarcraft.minecraftserverlauncher.userinterface;
import net.knarcraft.minecraftserverlauncher.profile.Profile;
import net.knarcraft.minecraftserverlauncher.server.Server;
import net.knarcraft.minecraftserverlauncher.server.servertypes.ServerType;
import net.knarcraft.minecraftserverlauncher.server.ServerTypeHandler;
import net.knarcraft.minecraftserverlauncher.server.servertypes.ServerType;
import javax.naming.ConfigurationException;
import javax.swing.*;
@ -14,9 +14,9 @@ import java.awt.event.ActionListener;
* Contains all buttons for configuring a server.
* Does some visual stuff by itself, but otherwise reads user inputs.
*
* @author Kristian Knarvik <kristian.knarvik@knett.no>
* @version 1.0.0
* @since 1.0.0
* @author Kristian Knarvik <kristian.knarvik@knett.no>
* @version 1.0.0
* @since 1.0.0
*/
public class ServerTab implements ActionListener {
private final JComboBox<String> serverTypes, serverVersions, maxRam;
@ -26,24 +26,6 @@ public class ServerTab implements ActionListener {
private final JPanel panel;
private final String name;
/**
* Updates the server tab components according to the received parameters.
*
* @param path The new path
* @param enabled The enabled status of the server
* @param typeName The name of the selected server type
* @param serverVersion The version of the server
* @param maxRam The max usable ram for the server
*/
public void setData(String path, boolean enabled, String typeName, String serverVersion, String maxRam) throws ConfigurationException {
this.directory.setText(path);
this.chckbxEnabled.setSelected(enabled);
this.serverTypes.setSelectedItem(typeName);
this.serverTypes();
this.serverVersions.setSelectedItem(serverVersion);
this.maxRam.setSelectedItem(maxRam);
}
public ServerTab(String name) throws ConfigurationException {
this.name = name;
panel = new JPanel();
@ -129,6 +111,24 @@ public class ServerTab implements ActionListener {
btnBrowse.addActionListener(this);
}
/**
* Updates the server tab components according to the received parameters.
*
* @param path The new path
* @param enabled The enabled status of the server
* @param typeName The name of the selected server type
* @param serverVersion The version of the server
* @param maxRam The max usable ram for the server
*/
public void setData(String path, boolean enabled, String typeName, String serverVersion, String maxRam) throws ConfigurationException {
this.directory.setText(path);
this.chckbxEnabled.setSelected(enabled);
this.serverTypes.setSelectedItem(typeName);
this.serverTypes();
this.serverVersions.setSelectedItem(serverVersion);
this.maxRam.setSelectedItem(maxRam);
}
public JPanel getPanel() {
return this.panel;
}
@ -158,7 +158,7 @@ public class ServerTab implements ActionListener {
/**
* Gets the selected version from the serverVersion combo
*
* @return The combo value, or defaults to "Latest" on null
* @return The combo value, or defaults to "Latest" on null
*/
public String getVersion() {
Object selected = this.serverVersions.getSelectedItem();
@ -172,7 +172,7 @@ public class ServerTab implements ActionListener {
/**
* Checks if the server is enabled
*
* @return True if the checkbox is checked. False otherwise.
* @return True if the checkbox is checked. False otherwise.
*/
public boolean enabled() {
return this.chckbxEnabled.isSelected();

View File

@ -24,7 +24,7 @@ import java.util.Scanner;
* @version 1.0.0
* @since 1.0.0
*/
public class CommonFunctions {
public final class CommonFunctions {
/**
* Gets a resource as an InputStream

View File

@ -1,7 +1,7 @@
package net.knarcraft.minecraftserverlauncher.utility;
import net.knarcraft.minecraftserverlauncher.server.servertypes.ServerType;
import net.knarcraft.minecraftserverlauncher.server.ServerTypeHandler;
import net.knarcraft.minecraftserverlauncher.server.servertypes.ServerType;
import net.knarcraft.minecraftserverlauncher.userinterface.GUI;
import javax.naming.ConfigurationException;
@ -12,7 +12,7 @@ import java.io.IOException;
/**
* This class handles all downloading of .jar files
*/
public class JarDownloader {
public final class JarDownloader {
private final String jarDirectory;
private GUI gui;

View File

@ -0,0 +1,104 @@
package net.knarcraft.minecraftserverlauncher.utility;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import net.knarcraft.minecraftserverlauncher.userinterface.GUI;
import javax.swing.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Scanner;
import static net.knarcraft.minecraftserverlauncher.Main.getApplicationWorkDirectory;
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.downloadFile;
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.getResourceAsScanner;
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.readFile;
/**
* A utility used for updating the software
*/
public final class Updater {
/**
* Checks if a newer version is available
*
* @param updateURL <p>The URL used for checking for updates</p>
* @param updateChannel <p>The release channel to use</p>
* @param gui <p>The GUI to use for output</p>
* @throws IOException <p>If the update data cannot be read</p>
*/
public static void checkForUpdate(String updateURL, String updateChannel, GUI gui) throws IOException {
Scanner file = getResourceAsScanner("currentversion.csv");
if (!file.hasNextLine()) {
throw new FileNotFoundException("File currentversion.csv is invalid");
}
String oldType = file.nextLine();
if (!file.hasNextLine()) {
throw new FileNotFoundException("File currentversion.csv is invalid");
}
String oldVer = file.nextLine();
file.close();
String data = readFile(updateURL);
JsonObject jsonObject = new JsonParser().parse(data).getAsJsonObject();
String latest = jsonObject.getAsJsonObject("latest").get(updateChannel).getAsString();
if (!oldType.equals(updateChannel) || !oldVer.equals(latest)) {
String dir = getApplicationWorkDirectory() + File.separator;
JsonArray versionList = jsonObject.getAsJsonArray("versions");
String url = "";
for (JsonElement elem : versionList) {
JsonObject obj = elem.getAsJsonObject();
String ver = obj.get("id").getAsString();
String type = obj.get("type").getAsString();
if (ver.equals(latest) && type.equals(updateChannel)) {
url = obj.get("url").getAsString();
}
}
if (downloadFile(url, new File(dir + "update.jar").toPath())) {
doUpdate(dir, gui);
} else {
gui.showError("Update available",
"An update is available, but could not be downloaded.");
}
}
}
/**
* Asks the user whether to update and downloads the new update
*
* @param dir <p>The directory to save the updated file to</p>
* @param gui <p>The GUI to write output to</p>
*/
public static void doUpdate(String dir, GUI gui) {
int answer = JOptionPane.showConfirmDialog(
null,
"An update is available. Do you want to update?",
"Update available",
JOptionPane.YES_NO_OPTION
);
if (answer == JOptionPane.YES_NO_OPTION) {
if (new File(dir + "Minecraft-Server-Launcher.jar").renameTo(new File(dir +
"Old.jar"))) {
if (new File(dir + "update.jar").renameTo(new File(dir +
"Minecraft-Server-Launcher.jar"))) {
if (new File(dir + "Old.jar").delete()) {
gui.showMessage("Update complete",
"Update finished. Please run the software again.");
System.exit(0);
}
} else {
if (!new File(dir + "Old.jar").renameTo(new File(dir +
"Minecraft-Server-Launcher.jar"))) {
System.out.println("Shit");
}
}
}
gui.showError("Update failed",
"Could not replace the main .jar with the downloaded .jar.");
}
}
}

View File

@ -11,7 +11,7 @@ public class DownloadTests {
@Test
public void downloadJarsTest() throws IOException {
String targetDirectory = Main.getApplicationWorkDirectory() + File.separator + "files" + File.separator + "testjars" + File.separator;
String targetDirectory = Main.getApplicationWorkDirectory() + File.separator + "files" + File.separator + "testjars" + File.separator;
JarDownloader downloader = new JarDownloader(new FakeGUI(), targetDirectory);
downloader.downloadJars();
}