Compare commits
69 Commits
v1.2.3-bet
...
Improved-S
Author | SHA1 | Date | |
---|---|---|---|
b808d48bd3 | |||
c3ea85c20b | |||
c83b5a2edd | |||
ee99312a12 | |||
545e7bacc6 | |||
b142b6d05e | |||
166d63f1b2 | |||
8f25fa2796 | |||
3467c900f0 | |||
9f092a73fe | |||
50b9188229 | |||
b021de5594 | |||
a1ae162b07 | |||
b2ee22eb7b | |||
65ede11ab5 | |||
c26a3bc3b5 | |||
71e47acbb0 | |||
60fdcf5ddc | |||
bf77c13072 | |||
849655bfc6 | |||
e8ecee1cd0 | |||
5e24d5daa8 | |||
9532683301 | |||
365d08f2e2 | |||
9d8531535d | |||
30de4b2139 | |||
133e335905 | |||
44d8d6ee6b | |||
cd396eee6b | |||
c67f3bdd2c | |||
8476c78589 | |||
a79300732d | |||
b6baa9ad6f | |||
c2f12a1a49 | |||
5030b4932b | |||
e47b34a472 | |||
28291cf4c3 | |||
f8ba6e7ad1 | |||
c9c2a1b43b | |||
0425617f4c | |||
12189c12d7 | |||
00cfe78491 | |||
dc362eb2c8 | |||
73faa4408e | |||
85febdf41b | |||
6ca49d2ccd | |||
429b1fcec0 | |||
33795a90a9 | |||
e4be75b770 | |||
0018816d90 | |||
f1eead3807 | |||
6ec44f1f92 | |||
d61239c417 | |||
32c17c6005 | |||
52eacb9980 | |||
043f2045e6 | |||
51ceac69da | |||
123a8eddda | |||
8cdb1f143c | |||
3254481326 | |||
fb705f4e13 | |||
15dd8db31b | |||
fa6a0df4c7 | |||
8b0423e231 | |||
b1454b1156 | |||
a4d7b1041c | |||
a705fc8b3e | |||
5fe4384b59 | |||
2f31a6c248 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -28,4 +28,5 @@ hs_err_pid*
|
|||||||
|
|
||||||
bin/
|
bin/
|
||||||
out/
|
out/
|
||||||
|
.idea
|
||||||
*.txt
|
*.txt
|
16
README.md
16
README.md
@ -1,6 +1,14 @@
|
|||||||
# Minecraft-Server-Launcher
|
# Minecraft-Server-Launcher
|
||||||
I originally created this software in 2013 using AutoIt. Since I am now learning Java, I have recreated it in Java.
|
|
||||||
The original version can be found at: https://archive.knarcraft.net/Scripts/BungeeMinecraftServerLauncher/
|
|
||||||
Its goal is to do everything the original does, just better. The original is 1595 lines of code repetition and dirty code. I had no prior programming experience when I first started working on the original, which is why it became such a mess.
|
|
||||||
|
|
||||||
The code is now in a fully working state. It is still missing an auto update feature, but it can be used, and is fully functional.
|
I originally created this software in 2013 using AutoIt. After learning Java, I recreated it in Java. The original
|
||||||
|
version can be found at: https://archive.knarcraft.net/Scripts/BungeeMinecraftServerLauncher/
|
||||||
|
This version's goal is to do everything the original does, just better. The original is 1595 lines of code repetition
|
||||||
|
and dirty code. I had no prior programming experience when I first started working on the original, which is why it
|
||||||
|
became such a mess.
|
||||||
|
|
||||||
|
The software is in a fully working stage with a functional updater. The software is still in beta because there are
|
||||||
|
still a lot of things I want to change and small annoyances. The software is fully portable. Make sure to put it in its
|
||||||
|
own folder as it will create lots of files.
|
||||||
|
|
||||||
|
The updater will move the new version to minecraft-server-launcher.jar, so you should rename the downloaded file to this
|
||||||
|
if it's named something else to avoid confusion.
|
@ -1,3 +1,3 @@
|
|||||||
As this is a personal one-man project, I prefer to stay in charge of the code.
|
As this is a personal one-man project, I prefer to stay in charge of the code. I appreciate code fixing mistakes, or
|
||||||
I appreciate code fixing mistakes, or code improvements, but the software's functionality or purpose, should not be changed.
|
code improvements, but the software's functionality or purpose, should not be changed. I might change anything at any
|
||||||
I might change anything at any time, so you might want to keep that in mind before doing big changes yourself.
|
time, so you might want to keep that in mind before doing big changes yourself.
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
Fixes # .
|
Fixes # .
|
||||||
|
|
||||||
Proposed changes:
|
Proposed changes:
|
||||||
|
|
||||||
-
|
-
|
||||||
-
|
-
|
||||||
-
|
-
|
||||||
|
6
pom.xml
6
pom.xml
@ -126,9 +126,9 @@
|
|||||||
<version>2.8.5</version>
|
<version>2.8.5</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>org.junit.jupiter</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit-jupiter-api</artifactId>
|
||||||
<version>4.11</version>
|
<version>5.7.2</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
package net.knarcraft.minecraftserverlauncher;
|
package net.knarcraft.minecraftserverlauncher;
|
||||||
|
|
||||||
import net.knarcraft.minecraftserverlauncher.profile.Collection;
|
import net.knarcraft.minecraftserverlauncher.profile.Collection;
|
||||||
import net.knarcraft.minecraftserverlauncher.profile.Controller;
|
import net.knarcraft.minecraftserverlauncher.profile.ServerLauncherController;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.server.ServerHandler;
|
||||||
import net.knarcraft.minecraftserverlauncher.userinterface.ServerConsoles;
|
import net.knarcraft.minecraftserverlauncher.userinterface.ServerConsoles;
|
||||||
import net.knarcraft.minecraftserverlauncher.userinterface.ServerLauncherGUI;
|
import net.knarcraft.minecraftserverlauncher.userinterface.ServerLauncherGUI;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.utility.CommonFunctions;
|
||||||
import net.knarcraft.minecraftserverlauncher.utility.Updater;
|
import net.knarcraft.minecraftserverlauncher.utility.Updater;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
@ -20,28 +21,30 @@ import java.util.concurrent.TimeUnit;
|
|||||||
* A software for managing Minecraft servers.
|
* A software for managing Minecraft servers.
|
||||||
*
|
*
|
||||||
* @author Kristian Knarvik <kristian.knarvik@knett.no>
|
* @author Kristian Knarvik <kristian.knarvik@knett.no>
|
||||||
* @version 1.0.0
|
* @version b1.3.4
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class Main {
|
public class Main {
|
||||||
private static final String updateChannel = "beta";
|
private static final String updateChannel = "beta";
|
||||||
private static final String updateURL = "https://api.knarcraft.net/minecraftserverlauncher";
|
private static final String updateURL = "https://api.knarcraft.net/minecraftserverlauncher";
|
||||||
private static final Controller controller = Controller.getInstance();
|
private static final ServerLauncherController controller = ServerLauncherController.getInstance();
|
||||||
private static String applicationWorkDirectory;
|
private static String applicationWorkDirectory;
|
||||||
private static boolean serversAreRunning = false;
|
private static boolean serversAreRunning = false;
|
||||||
private static ServerLauncherGUI gui;
|
private static ServerLauncherGUI gui;
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException {
|
public static void main(String[] args) throws IOException {
|
||||||
Updater.checkForUpdate(updateURL, updateChannel);
|
String logFile = Main.getApplicationWorkDirectory() + File.separator + "latestrun.log";
|
||||||
try (PrintWriter file = new PrintWriter(Main.getApplicationWorkDirectory() + File.separator + "latestrun.log")) {
|
CommonFunctions.writeFile(logFile, "[Info]: Starting Minecraft Server Launcher v." +
|
||||||
file.print("");
|
Updater.getCurrentVersion()[1]);
|
||||||
|
try {
|
||||||
|
Updater.checkForUpdate(updateURL, updateChannel);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
CommonFunctions.appendFile(logFile, "[Warning]: Unable to complete update procedure: " + e.getMessage());
|
||||||
}
|
}
|
||||||
EventQueue.invokeLater(() -> {
|
EventQueue.invokeLater(() -> {
|
||||||
try {
|
try {
|
||||||
new ServerConsoles();
|
ServerConsoles.instantiate();
|
||||||
controller.loadState();
|
controller.loadState();
|
||||||
gui = controller.getGUI();
|
gui = controller.getGUI();
|
||||||
ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();
|
ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();
|
||||||
@ -57,7 +60,7 @@ public class Main {
|
|||||||
*
|
*
|
||||||
* @return <p>The controller used by the software</p>
|
* @return <p>The controller used by the software</p>
|
||||||
*/
|
*/
|
||||||
public static Controller getController() {
|
public static ServerLauncherController getController() {
|
||||||
return controller;
|
return controller;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,6 +88,7 @@ public class Main {
|
|||||||
boolean runningNew = serversRunning();
|
boolean runningNew = serversRunning();
|
||||||
if (serversAreRunning && !runningNew) {
|
if (serversAreRunning && !runningNew) {
|
||||||
//Servers stopped running
|
//Servers stopped running
|
||||||
|
ServerHandler.serversStopped();
|
||||||
gui.updateGUIElementsWhenServersStartOrStop(false);
|
gui.updateGUIElementsWhenServersStartOrStop(false);
|
||||||
gui.setStatus("Servers are stopped");
|
gui.setStatus("Servers are stopped");
|
||||||
} else if (!serversAreRunning && runningNew) {
|
} else if (!serversAreRunning && runningNew) {
|
||||||
|
@ -2,14 +2,16 @@ package net.knarcraft.minecraftserverlauncher.profile;
|
|||||||
|
|
||||||
import net.knarcraft.minecraftserverlauncher.Main;
|
import net.knarcraft.minecraftserverlauncher.Main;
|
||||||
import net.knarcraft.minecraftserverlauncher.server.Server;
|
import net.knarcraft.minecraftserverlauncher.server.Server;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.server.ServerHandler;
|
||||||
import net.knarcraft.minecraftserverlauncher.userinterface.ServerConsoles;
|
import net.knarcraft.minecraftserverlauncher.userinterface.ServerConsoles;
|
||||||
import net.knarcraft.minecraftserverlauncher.userinterface.ServerLauncherGUI;
|
import net.knarcraft.minecraftserverlauncher.userinterface.ServerLauncherGUI;
|
||||||
import net.knarcraft.minecraftserverlauncher.utility.CommonFunctions;
|
import net.knarcraft.minecraftserverlauncher.utility.CommonFunctions;
|
||||||
|
|
||||||
import javax.naming.ConfigurationException;
|
import javax.naming.ConfigurationException;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.io.*;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Keeps track of a set of servers and some user settings
|
* Keeps track of a set of servers and some user settings
|
||||||
@ -21,7 +23,7 @@ import java.util.ArrayList;
|
|||||||
public class Profile {
|
public class Profile {
|
||||||
|
|
||||||
private static final ServerLauncherGUI serverLauncherGui = Main.getController().getGUI();
|
private static final ServerLauncherGUI serverLauncherGui = Main.getController().getGUI();
|
||||||
private final ArrayList<Collection> collections;
|
private final List<Collection> collections;
|
||||||
private final String name;
|
private final String name;
|
||||||
private boolean runInBackground;
|
private boolean runInBackground;
|
||||||
private int delayStartup;
|
private int delayStartup;
|
||||||
@ -105,7 +107,7 @@ public class Profile {
|
|||||||
*
|
*
|
||||||
* @return <p>All collections stored by this profile</p>
|
* @return <p>All collections stored by this profile</p>
|
||||||
*/
|
*/
|
||||||
public ArrayList<Collection> getCollections() {
|
public List<Collection> getCollections() {
|
||||||
return this.collections;
|
return this.collections;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,14 +141,16 @@ public class Profile {
|
|||||||
* @param name <p>The name of the collection and its elements</p>
|
* @param name <p>The name of the collection and its elements</p>
|
||||||
*/
|
*/
|
||||||
public void addCollection(String name) throws ConfigurationException {
|
public void addCollection(String name) throws ConfigurationException {
|
||||||
if (name == null) { //If a user cancels or crosses out window
|
//Skip if no name was given
|
||||||
|
if (name == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (getCollection(name) == null && !name.equals("All") && CommonFunctions.nameIsValid(name)) {
|
if (getCollection(name) == null && !name.equals("All") && CommonFunctions.nameIsValid(name)) {
|
||||||
collections.add(new Collection(name));
|
collections.add(new Collection(name));
|
||||||
} else {
|
} else {
|
||||||
serverLauncherGui.showError("A server name must my unique and not empty or \"All\"." +
|
serverLauncherGui.showError("A server name must be unique and not empty. " +
|
||||||
"It can't contain any of the characters \"!\", \"?\" or \";\".");
|
"In addition, a server cannot be named: \"All\". " +
|
||||||
|
"It cannot contain any of the characters \"!\", \"?\" or \";\".");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,17 +234,19 @@ public class Profile {
|
|||||||
*/
|
*/
|
||||||
public static Profile fromString(String profileString) throws ConfigurationException {
|
public static Profile fromString(String profileString) throws ConfigurationException {
|
||||||
Profile profile;
|
Profile profile;
|
||||||
if (profileString.contains("?")) {
|
if (profileString.equals("")) {
|
||||||
|
return null;
|
||||||
|
} else if (profileString.contains("?")) {
|
||||||
String[] data = profileString.split("\\?");
|
String[] data = profileString.split("\\?");
|
||||||
String[] profileData = data[0].split(";", -1);
|
String[] profileData = data[0].split(";", -1);
|
||||||
profile = parseProfile(profileData);
|
profile = parseProfile(profileData);
|
||||||
if (data[1].contains("!")) {
|
if (data[1].contains("!")) {
|
||||||
String[] servers = data[1].split("!", -1);
|
String[] servers = data[1].split("!", -1);
|
||||||
for (String server : servers) {
|
for (String server : servers) {
|
||||||
profile.collections.add(new Collection(Server.fromString(server)));
|
profile.collections.add(new Collection(ServerHandler.fromString(server)));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
profile.collections.add(new Collection(Server.fromString(data[1])));
|
profile.collections.add(new Collection(ServerHandler.fromString(data[1])));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
profile = parseProfile(profileString.split(";", -1));
|
profile = parseProfile(profileString.split(";", -1));
|
||||||
|
@ -2,6 +2,7 @@ package net.knarcraft.minecraftserverlauncher.profile;
|
|||||||
|
|
||||||
import net.knarcraft.minecraftserverlauncher.Main;
|
import net.knarcraft.minecraftserverlauncher.Main;
|
||||||
import net.knarcraft.minecraftserverlauncher.server.Server;
|
import net.knarcraft.minecraftserverlauncher.server.Server;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.server.ServerHandler;
|
||||||
import net.knarcraft.minecraftserverlauncher.server.ServerTypeHandler;
|
import net.knarcraft.minecraftserverlauncher.server.ServerTypeHandler;
|
||||||
import net.knarcraft.minecraftserverlauncher.userinterface.ServerLauncherGUI;
|
import net.knarcraft.minecraftserverlauncher.userinterface.ServerLauncherGUI;
|
||||||
import net.knarcraft.minecraftserverlauncher.userinterface.ServerTab;
|
import net.knarcraft.minecraftserverlauncher.userinterface.ServerTab;
|
||||||
@ -9,16 +10,20 @@ import net.knarcraft.minecraftserverlauncher.utility.CommonFunctions;
|
|||||||
import net.knarcraft.minecraftserverlauncher.utility.JarDownloader;
|
import net.knarcraft.minecraftserverlauncher.utility.JarDownloader;
|
||||||
|
|
||||||
import javax.naming.ConfigurationException;
|
import javax.naming.ConfigurationException;
|
||||||
import java.io.*;
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class handles profiles, GUI creation and session restoration
|
* This class handles profiles, GUI creation and session restoration
|
||||||
*/
|
*/
|
||||||
public class Controller {
|
public class ServerLauncherController {
|
||||||
|
|
||||||
private final String workingDirectory = Main.getApplicationWorkDirectory() + File.separator + "files";
|
private final String workingDirectory = Main.getApplicationWorkDirectory() + File.separator + "files";
|
||||||
private final String profilesFile = workingDirectory + File.separator + "Profiles.txt";
|
private final String profilesFile = workingDirectory + File.separator + "Profiles.txt";
|
||||||
@ -28,12 +33,14 @@ public class Controller {
|
|||||||
private ServerLauncherGUI serverLauncherGUI;
|
private ServerLauncherGUI serverLauncherGUI;
|
||||||
private Profile currentProfile;
|
private Profile currentProfile;
|
||||||
private boolean downloadAllJars;
|
private boolean downloadAllJars;
|
||||||
private static Controller controller;
|
private static ServerLauncherController controller;
|
||||||
|
private String javaCommand = "java";
|
||||||
|
private String oldJavaCommand = "java";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new controller
|
* Instantiates a new controller
|
||||||
*/
|
*/
|
||||||
private Controller() {
|
private ServerLauncherController() {
|
||||||
this.profileList = new ArrayList<>();
|
this.profileList = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,9 +49,9 @@ public class Controller {
|
|||||||
*
|
*
|
||||||
* @return <p>An instance of the controller</p>
|
* @return <p>An instance of the controller</p>
|
||||||
*/
|
*/
|
||||||
public static Controller getInstance() {
|
public static ServerLauncherController getInstance() {
|
||||||
if (controller == null) {
|
if (controller == null) {
|
||||||
controller = new Controller();
|
controller = new ServerLauncherController();
|
||||||
}
|
}
|
||||||
return controller;
|
return controller;
|
||||||
}
|
}
|
||||||
@ -85,6 +92,47 @@ public class Controller {
|
|||||||
return currentProfile.getDelayStartup();
|
return currentProfile.getDelayStartup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the command for running java
|
||||||
|
*
|
||||||
|
* @return <p>The command for running Java</p>
|
||||||
|
*/
|
||||||
|
public String getJavaCommand() {
|
||||||
|
return javaCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the command for running older versions of Java
|
||||||
|
*
|
||||||
|
* <p>The command used to run older minecraft server versions. JRE 8 should probably work.
|
||||||
|
* Can be just "java" or a file path.</p>
|
||||||
|
*
|
||||||
|
* @return <p>The command for running older versions of Java</p>
|
||||||
|
*/
|
||||||
|
public String getOldJavaCommand() {
|
||||||
|
return oldJavaCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the command for running Java
|
||||||
|
*
|
||||||
|
* <p>To play on the newest version of Minecraft, this needs to be JDK 16. Can be just "java" or a file path.</p>
|
||||||
|
*
|
||||||
|
* @param javaCommand <p>The command used for running Java</p>
|
||||||
|
*/
|
||||||
|
public void setJavaCommand(String javaCommand) {
|
||||||
|
this.javaCommand = javaCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the command for running older versions of java
|
||||||
|
*
|
||||||
|
* @param oldJavaCommand <p>The command used for running older versions of Java</p>
|
||||||
|
*/
|
||||||
|
public void setOldJavaCommand(String oldJavaCommand) {
|
||||||
|
this.oldJavaCommand = oldJavaCommand;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
int guiWidth;
|
int guiWidth;
|
||||||
@ -96,7 +144,8 @@ public class Controller {
|
|||||||
guiWidth = serverLauncherGUI.getSize().width;
|
guiWidth = serverLauncherGUI.getSize().width;
|
||||||
guiHeight = serverLauncherGUI.getSize().height;
|
guiHeight = serverLauncherGUI.getSize().height;
|
||||||
}
|
}
|
||||||
return String.format("%s;%d;%d;%b", currentProfile.getName(), guiWidth, guiHeight, downloadAllJars);
|
return String.format("selectedProfile;%s\nguiWidth;%d\nguiHeight;%d\ndownloadAllJars;%b\njavaCommand;%s\noldJavaCommand;%s",
|
||||||
|
currentProfile.getName(), guiWidth, guiHeight, downloadAllJars, javaCommand, oldJavaCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -170,84 +219,6 @@ public class Controller {
|
|||||||
return this.currentProfile;
|
return this.currentProfile;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads data about the controller from a save string
|
|
||||||
*
|
|
||||||
* @param data <p>The save string to load</p>
|
|
||||||
* @return <p>The currently selected profile</p>
|
|
||||||
* @throws IOException <p>If unable to create the GUI</p>
|
|
||||||
*/
|
|
||||||
private String fromString(String data) throws IOException {
|
|
||||||
String[] dataList = data.split(";");
|
|
||||||
this.downloadAllJars = Boolean.parseBoolean(dataList[3]);
|
|
||||||
this.serverLauncherGUI = new ServerLauncherGUI(Integer.parseInt(dataList[1]), Integer.parseInt(dataList[2]));
|
|
||||||
return dataList[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads profiles and servers from a text file
|
|
||||||
*/
|
|
||||||
public void loadState() throws ConfigurationException, IOException {
|
|
||||||
//Loads data regarding this controller
|
|
||||||
String currentProfile = null;
|
|
||||||
if (new File(mainFile).exists()) {
|
|
||||||
String controllerData = CommonFunctions.readBufferedReader(new BufferedReader(new InputStreamReader(new FileInputStream(mainFile))));
|
|
||||||
currentProfile = this.fromString(controllerData);
|
|
||||||
} else {
|
|
||||||
this.serverLauncherGUI = new ServerLauncherGUI();
|
|
||||||
}
|
|
||||||
//Loads all saved profiles
|
|
||||||
loadProfiles(currentProfile);
|
|
||||||
//Makes the GUI show the loaded data
|
|
||||||
executeGUILoadingTasks();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads all saved profiles
|
|
||||||
*
|
|
||||||
* @param currentProfile <p>The profile saved as the current profile</p>
|
|
||||||
* @throws ConfigurationException <p>If unable to load a profile</p>
|
|
||||||
*/
|
|
||||||
private void loadProfiles(String currentProfile) throws ConfigurationException {
|
|
||||||
try (Scanner in = new Scanner(new File(profilesFile))) {
|
|
||||||
while (in.hasNextLine()) {
|
|
||||||
String profileData = in.nextLine();
|
|
||||||
Profile loadedProfile = Profile.fromString(profileData);
|
|
||||||
profileList.add(loadedProfile);
|
|
||||||
}
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
addProfile("Default");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.currentProfile = getProfileByName(currentProfile);
|
|
||||||
if (this.currentProfile == null) {
|
|
||||||
this.currentProfile = this.profileList.get(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the GUI as necessary to display loaded data
|
|
||||||
*/
|
|
||||||
private void executeGUILoadingTasks() {
|
|
||||||
this.serverLauncherGUI.updateProfiles();
|
|
||||||
this.serverLauncherGUI.updateWithSavedProfileData();
|
|
||||||
this.currentProfile.updateConsoles();
|
|
||||||
if (this.downloadAllJars) {
|
|
||||||
Executors.newSingleThreadExecutor().execute(() -> {
|
|
||||||
JarDownloader downloader = new JarDownloader(serverLauncherGUI, jarDirectory);
|
|
||||||
try {
|
|
||||||
downloader.downloadJars();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (this.currentProfile.getRunInBackground()) {
|
|
||||||
Executors.newSingleThreadExecutor().execute(Server::startServers);
|
|
||||||
this.serverLauncherGUI.hideToTray();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the download all jars option
|
* Sets the download all jars option
|
||||||
*
|
*
|
||||||
@ -266,6 +237,15 @@ public class Controller {
|
|||||||
this.currentProfile = getProfileByName(profileName);
|
this.currentProfile = getProfileByName(profileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the directory containing .jar files
|
||||||
|
*
|
||||||
|
* @return <p>The directory containing .jar files</p>
|
||||||
|
*/
|
||||||
|
public String getJarDirectory() {
|
||||||
|
return this.jarDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves the state of the entire application to disk
|
* Saves the state of the entire application to disk
|
||||||
*/
|
*/
|
||||||
@ -273,20 +253,151 @@ public class Controller {
|
|||||||
saveGUIStateToServer();
|
saveGUIStateToServer();
|
||||||
try {
|
try {
|
||||||
CommonFunctions.createAllFolders();
|
CommonFunctions.createAllFolders();
|
||||||
PrintWriter mFile = new PrintWriter(mainFile);
|
CommonFunctions.writeFile(mainFile, this.toString());
|
||||||
mFile.println(this.toString());
|
StringBuilder builder = new StringBuilder();
|
||||||
mFile.close();
|
|
||||||
PrintWriter pFile = new PrintWriter(profilesFile);
|
|
||||||
for (Profile profile : profileList) {
|
for (Profile profile : profileList) {
|
||||||
pFile.println(profile.toString());
|
builder.append(profile.toString()).append("\n");
|
||||||
}
|
}
|
||||||
pFile.close();
|
CommonFunctions.writeFile(profilesFile, builder.toString());
|
||||||
} catch (FileNotFoundException e) {
|
} catch (IOException e) {
|
||||||
serverLauncherGUI.showError("Unable to save data.");
|
serverLauncherGUI.showError("Unable to save data.");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads profiles and servers from a text file
|
||||||
|
*/
|
||||||
|
public void loadState() throws ConfigurationException, IOException {
|
||||||
|
loadState(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads profiles and servers from a text file
|
||||||
|
*
|
||||||
|
* @param silent <p>If silent, no GUI will be created</p>
|
||||||
|
*/
|
||||||
|
public void loadState(boolean silent) throws ConfigurationException, IOException {
|
||||||
|
//Loads data regarding this controller
|
||||||
|
String currentProfile = null;
|
||||||
|
if (new File(mainFile).exists()) {
|
||||||
|
currentProfile = this.fromString(silent);
|
||||||
|
} else if (!silent) {
|
||||||
|
this.serverLauncherGUI = new ServerLauncherGUI();
|
||||||
|
}
|
||||||
|
if (silent) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//Loads all saved profiles
|
||||||
|
loadProfiles(currentProfile);
|
||||||
|
//Makes the GUI show the loaded data
|
||||||
|
executeGUILoadingTasks();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads data about the controller from a save string
|
||||||
|
*
|
||||||
|
* @param silent <p>If silent, no GUI will be created</p>
|
||||||
|
* @return <p>The currently selected profile</p>
|
||||||
|
*/
|
||||||
|
private String fromString(boolean silent) {
|
||||||
|
Map<String, String> loadedData = new HashMap<>();
|
||||||
|
|
||||||
|
try {
|
||||||
|
String currentData = CommonFunctions.readFile(mainFile);
|
||||||
|
for (String line : currentData.split("\n")) {
|
||||||
|
parseSaveLine(loadedData, line);
|
||||||
|
}
|
||||||
|
this.downloadAllJars = Boolean.parseBoolean(loadedData.get("downloadAllJars"));
|
||||||
|
|
||||||
|
if (!silent) {
|
||||||
|
if (loadedData.get("guiWidth") != null && loadedData.get("guiHeight") != null) {
|
||||||
|
this.serverLauncherGUI = new ServerLauncherGUI(Integer.parseInt(loadedData.get("guiWidth")),
|
||||||
|
Integer.parseInt(loadedData.get("guiHeight")));
|
||||||
|
} else {
|
||||||
|
this.serverLauncherGUI = new ServerLauncherGUI();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.serverLauncherGUI = new ServerLauncherGUI(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loadedData.get("javaCommand") != null) {
|
||||||
|
this.javaCommand = loadedData.get("javaCommand");
|
||||||
|
}
|
||||||
|
if (loadedData.get("oldJavaCommand") != null) {
|
||||||
|
this.oldJavaCommand = loadedData.get("oldJavaCommand");
|
||||||
|
}
|
||||||
|
return loadedData.get("selectedProfile");
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves one config line to the provided map
|
||||||
|
*
|
||||||
|
* @param loadedData <p>The map to save the loaded configuration to</p>
|
||||||
|
* @param line <p>The line to read</p>
|
||||||
|
*/
|
||||||
|
private void parseSaveLine(Map<String, String> loadedData, String line) {
|
||||||
|
String[] lineData = line.split(";");
|
||||||
|
if (lineData.length != 2) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
loadedData.put(lineData[0], lineData[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads all saved profiles
|
||||||
|
*
|
||||||
|
* @param currentProfile <p>The profile saved as the current profile</p>
|
||||||
|
* @throws ConfigurationException <p>If unable to load a profile</p>
|
||||||
|
*/
|
||||||
|
private void loadProfiles(String currentProfile) throws ConfigurationException {
|
||||||
|
try (Scanner in = new Scanner(new File(profilesFile))) {
|
||||||
|
while (in.hasNextLine()) {
|
||||||
|
String profileData = in.nextLine();
|
||||||
|
Profile loadedProfile = Profile.fromString(profileData);
|
||||||
|
if (loadedProfile == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
profileList.add(loadedProfile);
|
||||||
|
}
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
addProfile("Default");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.currentProfile = getProfileByName(currentProfile);
|
||||||
|
if (this.currentProfile == null) {
|
||||||
|
this.currentProfile = this.profileList.get(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the GUI as necessary to display loaded data
|
||||||
|
*/
|
||||||
|
private void executeGUILoadingTasks() {
|
||||||
|
this.serverLauncherGUI.getControlPanelTab().updateProfiles();
|
||||||
|
this.serverLauncherGUI.updateWithSavedProfileData();
|
||||||
|
this.currentProfile.updateConsoles();
|
||||||
|
if (this.downloadAllJars) {
|
||||||
|
Executors.newSingleThreadExecutor().execute(() -> {
|
||||||
|
JarDownloader downloader = new JarDownloader(serverLauncherGUI, jarDirectory);
|
||||||
|
try {
|
||||||
|
downloader.downloadJars();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (this.currentProfile.getRunInBackground()) {
|
||||||
|
Executors.newSingleThreadExecutor().execute(ServerHandler::startServers);
|
||||||
|
this.serverLauncherGUI.hideToTray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the server object with the current state of the GUI server tab
|
* Updates the server object with the current state of the GUI server tab
|
||||||
*/
|
*/
|
@ -0,0 +1,179 @@
|
|||||||
|
package net.knarcraft.minecraftserverlauncher.server;
|
||||||
|
|
||||||
|
import net.knarcraft.minecraftserverlauncher.Main;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.profile.ServerLauncherController;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.userinterface.GUI;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.userinterface.ServerLauncherGUI;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.utility.CommonFunctions;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The jar builder is responsible for building the newest Spigot and CraftBukkit .jar files using BuildTools
|
||||||
|
*/
|
||||||
|
public class JarBuilder {
|
||||||
|
|
||||||
|
private final String buildDirectory;
|
||||||
|
private final String jarDirectory;
|
||||||
|
private final ServerVersionContainer versionContainer;
|
||||||
|
private final GUI gui;
|
||||||
|
private final String javaCommand;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new jar builder
|
||||||
|
*
|
||||||
|
* @param buildDirectory <p>The directory containing BuildTool files</p>
|
||||||
|
* @param jarDirectory <p>The directory containing downloaded .jar files</p>
|
||||||
|
* @param gui <p>The GUI to write messages to</p>
|
||||||
|
*/
|
||||||
|
public JarBuilder(String buildDirectory, String jarDirectory, GUI gui) {
|
||||||
|
this.buildDirectory = buildDirectory;
|
||||||
|
this.jarDirectory = jarDirectory;
|
||||||
|
this.gui = gui;
|
||||||
|
this.versionContainer = ServerVersionContainer.getInstance();
|
||||||
|
this.javaCommand = ServerLauncherController.getInstance().getJavaCommand();
|
||||||
|
try {
|
||||||
|
CommonFunctions.createFolder(new File(buildDirectory));
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the latest version of the spigot .jar file
|
||||||
|
*/
|
||||||
|
public boolean buildSpigotJar() {
|
||||||
|
gui.setStatus("Building Spigot jar ...");
|
||||||
|
downloadBuildTools();
|
||||||
|
ProcessBuilder processBuilder = new ProcessBuilder(javaCommand, "-jar", "BuildTools.jar", "--rev",
|
||||||
|
"latest", "--output-dir", jarDirectory);
|
||||||
|
if (executeBuildProcess(processBuilder) && moveBuiltJar("spigot-", "SpigotLatest.jar")) {
|
||||||
|
gui.setStatus("Finished moving spigot.jar");
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the latest version of the craftbukkit .jar file
|
||||||
|
*/
|
||||||
|
public boolean buildBukkitJar() {
|
||||||
|
gui.setStatus("Building Bukkit jar ...");
|
||||||
|
downloadBuildTools();
|
||||||
|
ProcessBuilder processBuilder = new ProcessBuilder(javaCommand, "-jar", "BuildTools.jar", "--compile",
|
||||||
|
"craftbukkit", "--rev", "latest", "--output-dir", jarDirectory);
|
||||||
|
if (executeBuildProcess(processBuilder) && moveBuiltJar("craftbukkit-", "BukkitLatest.jar")) {
|
||||||
|
gui.setStatus("Finished moving craftbukkit.jar");
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Downloads the latest BuildTools version
|
||||||
|
*/
|
||||||
|
public void downloadBuildTools() {
|
||||||
|
ServerLauncherGUI gui = Main.getController().getGUI();
|
||||||
|
try {
|
||||||
|
String latestVersion = getLatestBuildToolsVersion();
|
||||||
|
boolean exists = new File(buildDirectory + "BuildTools.jar").exists();
|
||||||
|
boolean isUpdated = latestVersion.equals(versionContainer.getDownloadedBuildToolsVersion());
|
||||||
|
|
||||||
|
if (!exists || !isUpdated) {
|
||||||
|
String buildToolsURL = "https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar";
|
||||||
|
boolean success = CommonFunctions.downloadFile(buildToolsURL, Paths.get(buildDirectory + "BuildTools.jar"));
|
||||||
|
if (!success) {
|
||||||
|
gui.setStatus("Unable to download the latest BuildTools");
|
||||||
|
gui.logError("Target: " + buildDirectory + "BuildTools.jar");
|
||||||
|
gui.logError("URL: " + buildToolsURL);
|
||||||
|
} else {
|
||||||
|
versionContainer.setDownloadedBuildToolsVersion(latestVersion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
gui.setStatus("Unable to download the latest BuildTools");
|
||||||
|
gui.logMessage(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves a built .jar file to its target file
|
||||||
|
*
|
||||||
|
* @param searchString <p>The start of the name of the built file used to find it</p>
|
||||||
|
* @param newName <p>The new name of the built file</p>
|
||||||
|
* @return <p>True if the .jar file was moved successfully</p>
|
||||||
|
*/
|
||||||
|
private boolean moveBuiltJar(String searchString, String newName) {
|
||||||
|
File[] foundFiles = new File(jarDirectory).listFiles((file) -> file.isFile() && file.getName().startsWith(searchString));
|
||||||
|
if (foundFiles != null && foundFiles.length == 1) {
|
||||||
|
File newFileLocation = new File(jarDirectory + File.separator + newName);
|
||||||
|
if (newFileLocation.exists()) {
|
||||||
|
if (!newFileLocation.delete()) {
|
||||||
|
gui.showError("Unable to delete previously built .jar");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!foundFiles[0].renameTo(newFileLocation)) {
|
||||||
|
gui.showError("Unable to move built .jar");
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts the build process and initializes
|
||||||
|
*
|
||||||
|
* @param processBuilder <p>The process builder to execute</p>
|
||||||
|
* @return <p>True if the process exited successfully</p>
|
||||||
|
*/
|
||||||
|
private boolean executeBuildProcess(ProcessBuilder processBuilder) {
|
||||||
|
processBuilder.directory(new File(buildDirectory));
|
||||||
|
processBuilder.redirectErrorStream(true);
|
||||||
|
try {
|
||||||
|
Process process = processBuilder.start();
|
||||||
|
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||||
|
|
||||||
|
do {
|
||||||
|
writer.write(CommonFunctions.readBufferedReader(reader));
|
||||||
|
} while (process.isAlive());
|
||||||
|
|
||||||
|
writer.newLine();
|
||||||
|
writer.flush();
|
||||||
|
|
||||||
|
if (process.exitValue() == 0) {
|
||||||
|
gui.setStatus("Jar building process finished successfully.");
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
gui.showError("Jar building process failed with exit code " + process.exitValue() +
|
||||||
|
". Please check the BuildTools log for errors.");
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the latest build tools version available
|
||||||
|
*
|
||||||
|
* @return <p>The latest build tools version available</p>
|
||||||
|
* @throws IOException <p>If unable to read the version file</p>
|
||||||
|
*/
|
||||||
|
String getLatestBuildToolsVersion() throws IOException {
|
||||||
|
String versionDocument;
|
||||||
|
versionDocument = CommonFunctions.readRemoteFile("https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/");
|
||||||
|
return CommonFunctions.stringBetween(versionDocument, "BuildTools #", " [");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,9 +1,9 @@
|
|||||||
package net.knarcraft.minecraftserverlauncher.server;
|
package net.knarcraft.minecraftserverlauncher.server;
|
||||||
|
|
||||||
import net.knarcraft.minecraftserverlauncher.Main;
|
import net.knarcraft.minecraftserverlauncher.Main;
|
||||||
import net.knarcraft.minecraftserverlauncher.profile.Collection;
|
import net.knarcraft.minecraftserverlauncher.profile.ServerLauncherController;
|
||||||
import net.knarcraft.minecraftserverlauncher.profile.Controller;
|
|
||||||
import net.knarcraft.minecraftserverlauncher.server.servertypes.ServerType;
|
import net.knarcraft.minecraftserverlauncher.server.servertypes.ServerType;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.userinterface.ServerLauncherGUI;
|
||||||
import net.knarcraft.minecraftserverlauncher.utility.CommonFunctions;
|
import net.knarcraft.minecraftserverlauncher.utility.CommonFunctions;
|
||||||
|
|
||||||
import javax.naming.ConfigurationException;
|
import javax.naming.ConfigurationException;
|
||||||
@ -19,8 +19,8 @@ import java.util.List;
|
|||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.stringBetween;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -31,14 +31,9 @@ import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.stri
|
|||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public class Server {
|
public class Server {
|
||||||
/**
|
|
||||||
* Available ram sizes. For ServerLauncherGUI combo
|
|
||||||
*/
|
|
||||||
private static final String[] ramList = {"512M", "1G", "2G", "3G", "4G", "5G", "6G", "7G", "8G", "9G", "10G",
|
|
||||||
"11G", "12G", "13G", "14G", "15G", "16G"};
|
|
||||||
private static final String jarDirectory = Main.getApplicationWorkDirectory() + File.separator + "files" +
|
private static final String jarDirectory = Main.getApplicationWorkDirectory() + File.separator + "files" +
|
||||||
File.separator + "Jars" + File.separator;
|
File.separator + "Jars" + File.separator;
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
private final ArrayList<String> playerList;
|
private final ArrayList<String> playerList;
|
||||||
private String path;
|
private String path;
|
||||||
@ -51,6 +46,7 @@ public class Server {
|
|||||||
private BufferedReader reader;
|
private BufferedReader reader;
|
||||||
private boolean started;
|
private boolean started;
|
||||||
private ScheduledExecutorService consoleOutputExecutor;
|
private ScheduledExecutorService consoleOutputExecutor;
|
||||||
|
private final ServerLauncherGUI gui = Main.getController().getGUI();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes a new server with default values
|
* Initializes a new server with default values
|
||||||
@ -64,7 +60,7 @@ public class Server {
|
|||||||
this.playerList = new ArrayList<>();
|
this.playerList = new ArrayList<>();
|
||||||
this.type = null;
|
this.type = null;
|
||||||
this.serverVersion = "";
|
this.serverVersion = "";
|
||||||
this.maxRam = ramList[0];
|
this.maxRam = ServerHandler.getRamList()[0];
|
||||||
this.process = null;
|
this.process = null;
|
||||||
this.writer = null;
|
this.writer = null;
|
||||||
this.reader = null;
|
this.reader = null;
|
||||||
@ -90,15 +86,6 @@ public class Server {
|
|||||||
this.playerList = new ArrayList<>();
|
this.playerList = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the list of available RAM choices allowed
|
|
||||||
*
|
|
||||||
* @return <p>All available RAM choices</p>
|
|
||||||
*/
|
|
||||||
public static String[] getRamList() {
|
|
||||||
return ramList;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the buffered reader used to read from this server
|
* Gets the buffered reader used to read from this server
|
||||||
*
|
*
|
||||||
@ -108,58 +95,6 @@ public class Server {
|
|||||||
return this.reader;
|
return this.reader;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Tries to stop all enabled servers
|
|
||||||
*
|
|
||||||
* @throws IOException <p>If a writer's process is already closed but not null</p>
|
|
||||||
*/
|
|
||||||
public static void stop() throws IOException {
|
|
||||||
for (Collection collection : Main.getController().getCurrentProfile().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() {
|
|
||||||
Controller controller = Main.getController();
|
|
||||||
controller.getGUI().setStatus("Starting servers");
|
|
||||||
for (Collection collection : controller.getCurrentProfile().getCollections()) {
|
|
||||||
if (!collection.getServer().runServer()) {
|
|
||||||
controller.getGUI().setStatus("An error occurred. Start aborted");
|
|
||||||
try {
|
|
||||||
Server.stop();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
controller.getGUI().updateGUIElementsWhenServersStartOrStop(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) throws ConfigurationException {
|
|
||||||
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
|
* Gets the name of the server
|
||||||
*
|
*
|
||||||
@ -225,6 +160,42 @@ public class Server {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets whether this server is a proxy server
|
||||||
|
*
|
||||||
|
* <p>A proxy server is a server running BungeeCord, Waterfall or Travertine.</p>
|
||||||
|
*
|
||||||
|
* @return <p>True if this server is a proxy server</p>
|
||||||
|
*/
|
||||||
|
public boolean isProxy() {
|
||||||
|
return this.type.isProxy();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks this server as stopped
|
||||||
|
*/
|
||||||
|
public void setStopped() {
|
||||||
|
this.started = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the writer used to write to this server
|
||||||
|
*
|
||||||
|
* @return <p>The writer used.</p>
|
||||||
|
*/
|
||||||
|
public BufferedWriter getWriter() {
|
||||||
|
return this.writer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the writer used to write to this server
|
||||||
|
*
|
||||||
|
* @param writer <p>The new writer to use.</p>
|
||||||
|
*/
|
||||||
|
public void setWriter(BufferedWriter writer) {
|
||||||
|
this.writer = writer;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the path for this server's files
|
* Gets the path for this server's files
|
||||||
*
|
*
|
||||||
@ -280,9 +251,9 @@ public class Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether this server is fully stopped
|
* Removes all information about the server's process, writer and reader
|
||||||
*/
|
*/
|
||||||
private void stopped() {
|
private void cleanStoppedServerValues() {
|
||||||
consoleOutputExecutor.shutdown();
|
consoleOutputExecutor.shutdown();
|
||||||
process = null;
|
process = null;
|
||||||
writer = null;
|
writer = null;
|
||||||
@ -330,7 +301,7 @@ public class Server {
|
|||||||
*/
|
*/
|
||||||
private void addPlayer(String name) {
|
private void addPlayer(String name) {
|
||||||
this.playerList.add(name);
|
this.playerList.add(name);
|
||||||
Main.getController().getGUI().getServerControlTab().addPlayer(name);
|
gui.getServerControlTab().addPlayer(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -340,7 +311,7 @@ public class Server {
|
|||||||
*/
|
*/
|
||||||
private void removePlayer(String name) {
|
private void removePlayer(String name) {
|
||||||
playerList.removeIf(player -> player.equals(name));
|
playerList.removeIf(player -> player.equals(name));
|
||||||
Main.getController().getGUI().getServerControlTab().removePlayer(name);
|
gui.getServerControlTab().removePlayer(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -355,49 +326,85 @@ public class Server {
|
|||||||
/**
|
/**
|
||||||
* Runs a Minecraft server
|
* Runs a Minecraft server
|
||||||
*
|
*
|
||||||
|
* @param skipDelay <p>Whether to skip the startup delay for this server</p>
|
||||||
* @return <p>True if nothing went wrong</p>
|
* @return <p>True if nothing went wrong</p>
|
||||||
*/
|
*/
|
||||||
private boolean runServer() {
|
public boolean runServer(boolean skipDelay) {
|
||||||
|
if (ServerHandler.stoppingServers()) {
|
||||||
|
gui.logMessage("Stopping servers. Cannot start yet.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
//Ignore a disabled server
|
//Ignore a disabled server
|
||||||
if (!this.enabled) {
|
if (!this.enabled) {
|
||||||
this.started = false;
|
this.started = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//Tries to do necessary pre-start work
|
//Tries to do necessary pre-start work
|
||||||
if (!initializeJarDownload() || !delayStartup()) {
|
if (!initializeJarDownload() || (!skipDelay && !delayStartup())) {
|
||||||
|
gui.logError("Failed to perform startup tasks.");
|
||||||
this.started = false;
|
this.started = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (ServerHandler.stoppingServers()) {
|
||||||
|
gui.logMessage("Stopping servers. Cannot start yet.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
//Starts the server if possible
|
//Starts the server if possible
|
||||||
try {
|
try {
|
||||||
startServerProcess();
|
startServerProcess();
|
||||||
Main.getController().getGUI().setStatus("Servers are running");
|
gui.setStatus("Servers are running");
|
||||||
this.started = true;
|
this.started = true;
|
||||||
return true;
|
return true;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Main.getController().getGUI().setStatus("Could not start server");
|
gui.setStatus("Could not start server");
|
||||||
this.started = false;
|
this.started = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the correct java command to use for the selected server version
|
||||||
|
*
|
||||||
|
* @return <p>The java version to run</p>
|
||||||
|
*/
|
||||||
|
private String getJavaCommand() {
|
||||||
|
ServerLauncherController controller = ServerLauncherController.getInstance();
|
||||||
|
|
||||||
|
if (versionAtLeast("1.17")) {
|
||||||
|
return controller.getJavaCommand();
|
||||||
|
} else {
|
||||||
|
return controller.getOldJavaCommand();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the current server version is at least the given version
|
||||||
|
*
|
||||||
|
* @param version <p>The version to require</p>
|
||||||
|
* @return <p>True if the server version is at least the given version</p>
|
||||||
|
*/
|
||||||
|
private boolean versionAtLeast(String version) {
|
||||||
|
if (serverVersion.toLowerCase().contains("latest")) {
|
||||||
|
return true;
|
||||||
|
} else if (serverVersion.contains(".") && serverVersion.split("\\.").length >= 2) {
|
||||||
|
try {
|
||||||
|
return Integer.parseInt(serverVersion.split("\\.")[0]) >=
|
||||||
|
Integer.parseInt(version.split("\\.")[0]) &&
|
||||||
|
Integer.parseInt(serverVersion.split("\\.")[1]) >=
|
||||||
|
Integer.parseInt(version.split("\\.")[1]);
|
||||||
|
} catch (NumberFormatException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts the process running this server
|
* Starts the process running this server
|
||||||
*
|
*
|
||||||
* @throws IOException <p>If the process cannot be started</p>
|
* @throws IOException <p>If the process cannot be started</p>
|
||||||
*/
|
*/
|
||||||
private void startServerProcess() throws IOException {
|
private void startServerProcess() throws IOException {
|
||||||
ProcessBuilder builder;
|
ProcessBuilder builder = new ProcessBuilder(generateServerProcessArguments());
|
||||||
String serverPath;
|
|
||||||
//Decide the path of the .jar file to be executed
|
|
||||||
if (type.getName().equals("Custom")) {
|
|
||||||
serverPath = this.path + File.separator + serverVersion;
|
|
||||||
} else {
|
|
||||||
serverPath = jarDirectory + this.type.getName() + serverVersion + ".jar";
|
|
||||||
}
|
|
||||||
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.directory(new File(this.path));
|
||||||
builder.redirectErrorStream(true);
|
builder.redirectErrorStream(true);
|
||||||
this.process = builder.start();
|
this.process = builder.start();
|
||||||
@ -415,6 +422,64 @@ public class Server {
|
|||||||
}, 10, 500, TimeUnit.MILLISECONDS);
|
}, 10, 500, TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the process arguments required for starting this Minecraft server
|
||||||
|
*
|
||||||
|
* @return <p>The process arguments required for starting this Minecraft server</p>
|
||||||
|
*/
|
||||||
|
private List<String> generateServerProcessArguments() {
|
||||||
|
//Decide the path of the .jar file to be executed
|
||||||
|
String serverPath;
|
||||||
|
if (type.getName().equalsIgnoreCase("Custom")) {
|
||||||
|
serverPath = this.path + File.separator + serverVersion;
|
||||||
|
} else {
|
||||||
|
serverPath = jarDirectory + this.type.getName() + serverVersion + ".jar";
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> processArguments = new ArrayList<>(20);
|
||||||
|
processArguments.add(getJavaCommand());
|
||||||
|
processArguments.add("-Xmx" + this.maxRam);
|
||||||
|
processArguments.add("-Xms512M");
|
||||||
|
if (versionAtLeast("1.8") && !getType().isProxy()) {
|
||||||
|
addGarbageCollectorFlags(processArguments);
|
||||||
|
}
|
||||||
|
processArguments.add("-Djline.terminal=jline.UnsupportedTerminal");
|
||||||
|
processArguments.add("-Dcom.mojang.eula.agree=true");
|
||||||
|
processArguments.add("-jar");
|
||||||
|
processArguments.add(serverPath);
|
||||||
|
processArguments.add("nogui");
|
||||||
|
return processArguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds garbage collector flags to the server process arguments to improve performance
|
||||||
|
*
|
||||||
|
* @param processArguments <p>The process arguments to add the flags to</p>
|
||||||
|
*/
|
||||||
|
private void addGarbageCollectorFlags(List<String> processArguments) {
|
||||||
|
processArguments.add("-XX:+UseG1GC");
|
||||||
|
processArguments.add("-XX:+ParallelRefProcEnabled");
|
||||||
|
processArguments.add("-XX:MaxGCPauseMillis=200");
|
||||||
|
processArguments.add("-XX:+UnlockExperimentalVMOptions");
|
||||||
|
processArguments.add("-XX:+DisableExplicitGC");
|
||||||
|
processArguments.add("-XX:+AlwaysPreTouch");
|
||||||
|
boolean excessiveRam = Integer.parseInt(this.maxRam.substring(0, this.maxRam.length() - 1)) > 11;
|
||||||
|
processArguments.add("-XX:G1NewSizePercent=" + (excessiveRam ? 40 : 30));
|
||||||
|
processArguments.add("-XX:G1MaxNewSizePercent=" + (excessiveRam ? 50 : 40));
|
||||||
|
processArguments.add("-XX:G1HeapRegionSize=" + (excessiveRam ? "16M" : "8M"));
|
||||||
|
processArguments.add("-XX:G1ReservePercent=" + (excessiveRam ? 15 : 20));
|
||||||
|
processArguments.add("-XX:G1HeapWastePercent=5");
|
||||||
|
processArguments.add("-XX:G1MixedGCCountTarget=4");
|
||||||
|
processArguments.add("-XX:InitiatingHeapOccupancyPercent=" + (excessiveRam ? 20 : 15));
|
||||||
|
processArguments.add("-XX:G1MixedGCLiveThresholdPercent=90");
|
||||||
|
processArguments.add("-XX:G1RSetUpdatingPauseTimePercent=5");
|
||||||
|
processArguments.add("-XX:SurvivorRatio=32");
|
||||||
|
processArguments.add("-XX:+PerfDisableSharedMem");
|
||||||
|
processArguments.add("-XX:MaxTenuringThreshold=1");
|
||||||
|
processArguments.add("-Dusing.aikars.flags=https://mcflags.emc.gs");
|
||||||
|
processArguments.add("-Daikars.new.flags=true");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates a single console with process output
|
* Updates a single console with process output
|
||||||
*
|
*
|
||||||
@ -427,14 +492,14 @@ public class Server {
|
|||||||
updatePlayerList(readText);
|
updatePlayerList(readText);
|
||||||
}
|
}
|
||||||
if (!getProcess().isAlive()) {
|
if (!getProcess().isAlive()) {
|
||||||
stopped();
|
cleanStoppedServerValues();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 <p>The text to search</p>
|
* @param text <p>The text to search</p>
|
||||||
*/
|
*/
|
||||||
private void updatePlayerList(String text) {
|
private void updatePlayerList(String text) {
|
||||||
if (!getType().isProxy()) {
|
if (!getType().isProxy()) {
|
||||||
@ -461,23 +526,44 @@ public class Server {
|
|||||||
*/
|
*/
|
||||||
private String getPlayer(String text, boolean joined) {
|
private String getPlayer(String text, boolean joined) {
|
||||||
String playerName;
|
String playerName;
|
||||||
|
|
||||||
|
String loginPattern1 = " ([A-Z0-9a-z_]+)\\[/[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+:[0-9]+] logged in";
|
||||||
|
String loginPattern2 = "UUID of player ([A-Z0-9a-z_]+) is";
|
||||||
|
|
||||||
|
String logoutPattern1 = "INFO]: ([A-Z0-9a-z_]+) lost connection";
|
||||||
|
String logoutPattern2 = " ([A-Z0-9a-z_]+) left the game";
|
||||||
|
|
||||||
if (joined) {
|
if (joined) {
|
||||||
playerName = stringBetween(text, "[Server thread/INFO]: ", " joined the game");
|
playerName = getFirstRegexCaptureGroup(loginPattern1, text);
|
||||||
if (playerName.equals("")) {
|
if (playerName.equals("")) {
|
||||||
playerName = stringBetween(text, "UUID of player ", " is ");
|
playerName = getFirstRegexCaptureGroup(loginPattern2, text);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
playerName = stringBetween(text, "INFO]: ", " lost connection");
|
playerName = getFirstRegexCaptureGroup(logoutPattern1, text);
|
||||||
if (playerName.equals("")) {
|
if (playerName.equals("")) {
|
||||||
playerName = stringBetween(text, "[Server thread/INFO]: ", " left the game");
|
playerName = getFirstRegexCaptureGroup(logoutPattern2, text);
|
||||||
}
|
|
||||||
if (playerName.equals("")) {
|
|
||||||
playerName = stringBetween(text, "INFO]: ", " left the game");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return playerName;
|
return playerName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the first regex capture group found in a pattern
|
||||||
|
*
|
||||||
|
* @param pattern <p>The regex pattern to use</p>
|
||||||
|
* @param text <p>The string to execute the pattern on</p>
|
||||||
|
* @return <p>The first capture group if a match is found. An empty string otherwise</p>
|
||||||
|
*/
|
||||||
|
private String getFirstRegexCaptureGroup(String pattern, String text) {
|
||||||
|
Pattern compiledPattern = Pattern.compile(pattern);
|
||||||
|
Matcher patternMatcher = compiledPattern.matcher(text);
|
||||||
|
if (patternMatcher.find()) {
|
||||||
|
return patternMatcher.group(1);
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delays the server's startup for the given amount of time
|
* Delays the server's startup for the given amount of time
|
||||||
*
|
*
|
||||||
@ -485,7 +571,7 @@ public class Server {
|
|||||||
*/
|
*/
|
||||||
private boolean delayStartup() {
|
private boolean delayStartup() {
|
||||||
try {
|
try {
|
||||||
Main.getController().getGUI().setStatus("Delaying startup");
|
gui.setStatus("Delaying startup");
|
||||||
TimeUnit.SECONDS.sleep(Main.getController().getCurrentProfile().getDelayStartup());
|
TimeUnit.SECONDS.sleep(Main.getController().getCurrentProfile().getDelayStartup());
|
||||||
return true;
|
return true;
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
@ -501,18 +587,15 @@ public class Server {
|
|||||||
* @return <p>True if nothing went wrong</p>
|
* @return <p>True if nothing went wrong</p>
|
||||||
*/
|
*/
|
||||||
private boolean initializeJarDownload() {
|
private boolean initializeJarDownload() {
|
||||||
Controller controller = Main.getController();
|
try {
|
||||||
if (!controller.getDownloadAllJars()) {
|
gui.setStatus("Downloading jar...");
|
||||||
try {
|
this.downloadJar();
|
||||||
controller.getGUI().setStatus("Downloading jar...");
|
gui.setStatus("File downloaded");
|
||||||
this.downloadJar();
|
} catch (IOException e) {
|
||||||
controller.getGUI().setStatus("File downloaded");
|
gui.setStatus("Error: Jar file could not be found, downloaded or built.");
|
||||||
} catch (IOException e) {
|
gui.logError("Unable to get required .jar file: " + e.getMessage());
|
||||||
controller.getGUI().setStatus("Error: Jar file not found");
|
this.started = false;
|
||||||
e.printStackTrace();
|
return false;
|
||||||
this.started = false;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -560,4 +643,5 @@ public class Server {
|
|||||||
this.getMaxRam()
|
this.getMaxRam()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,151 @@
|
|||||||
|
package net.knarcraft.minecraftserverlauncher.server;
|
||||||
|
|
||||||
|
import net.knarcraft.minecraftserverlauncher.Main;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.profile.Collection;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.profile.ServerLauncherController;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.userinterface.ServerLauncherGUI;
|
||||||
|
|
||||||
|
import javax.naming.ConfigurationException;
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public class ServerHandler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Available ram sizes. For ServerLauncherGUI combo
|
||||||
|
*/
|
||||||
|
private static final String[] ramList = {"512M", "1G", "2G", "3G", "4G", "5G", "6G", "7G", "8G", "9G", "10G",
|
||||||
|
"11G", "12G", "13G", "14G", "15G", "16G", "17G", "18G", "19G", "20G", "21G", "22G", "23G", "24G"};
|
||||||
|
|
||||||
|
private static boolean stoppingServers = false;
|
||||||
|
private static final ServerLauncherGUI gui = Main.getController().getGUI();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the list of available RAM choices allowed
|
||||||
|
*
|
||||||
|
* @return <p>All available RAM choices</p>
|
||||||
|
*/
|
||||||
|
public static String[] getRamList() {
|
||||||
|
return ramList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets whether the servers are currently in the process of stopping
|
||||||
|
*
|
||||||
|
* @return <p>True if the servers are in the process of stopping.</p>
|
||||||
|
*/
|
||||||
|
public static boolean stoppingServers() {
|
||||||
|
return stoppingServers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks the servers as finished stopping when a stop is confirmed
|
||||||
|
*/
|
||||||
|
public static void serversStopped() {
|
||||||
|
if (stoppingServers) {
|
||||||
|
stoppingServers = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to stop all enabled servers
|
||||||
|
*
|
||||||
|
* @throws IOException <p>If a writer's process is already closed but not null</p>
|
||||||
|
*/
|
||||||
|
public static void stop() throws IOException, InterruptedException {
|
||||||
|
if (stoppingServers) {
|
||||||
|
killServers();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
stoppingServers = true;
|
||||||
|
int serversRunning = 0;
|
||||||
|
|
||||||
|
for (Collection collection : Main.getController().getCurrentProfile().getCollections()) {
|
||||||
|
Server server = collection.getServer();
|
||||||
|
BufferedWriter writer = server.getWriter();
|
||||||
|
if (writer != null) {
|
||||||
|
serversRunning++;
|
||||||
|
if (server.isProxy()) {
|
||||||
|
writer.write("end\n");
|
||||||
|
} else {
|
||||||
|
writer.write("stop\n");
|
||||||
|
}
|
||||||
|
writer.flush();
|
||||||
|
server.setWriter(null);
|
||||||
|
server.setStopped();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (serversRunning == 0) {
|
||||||
|
stoppingServers = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kills all server processes
|
||||||
|
*
|
||||||
|
* @throws InterruptedException <p>If interrupted waiting for any of the servers to stop</p>
|
||||||
|
*/
|
||||||
|
private static void killServers() throws InterruptedException {
|
||||||
|
for (Collection collection : Main.getController().getCurrentProfile().getCollections()) {
|
||||||
|
Server server = collection.getServer();
|
||||||
|
killServer(server);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kills the given server after waiting 30 seconds for it to terminate normally
|
||||||
|
*
|
||||||
|
* @param server <p>The server to kill</p>
|
||||||
|
* @throws InterruptedException <p>If interrupted waiting for the server to stop</p>
|
||||||
|
*/
|
||||||
|
private static void killServer(Server server) throws InterruptedException {
|
||||||
|
Process serverProcess = server.getProcess();
|
||||||
|
if (serverProcess != null) {
|
||||||
|
if (!serverProcess.waitFor(30, TimeUnit.SECONDS)) {
|
||||||
|
serverProcess.destroyForcibly();
|
||||||
|
serverProcess.waitFor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs all enabled servers with their settings
|
||||||
|
*/
|
||||||
|
public static void startServers() {
|
||||||
|
ServerLauncherController controller = Main.getController();
|
||||||
|
gui.setStatus("Starting servers");
|
||||||
|
Server previouslyStartedServer = null;
|
||||||
|
|
||||||
|
for (Collection collection : controller.getCurrentProfile().getCollections()) {
|
||||||
|
Server server = collection.getServer();
|
||||||
|
if (!server.runServer(previouslyStartedServer == null || previouslyStartedServer.isProxy())) {
|
||||||
|
gui.showError("An error occurred. Start aborted. Please check relevant log files.");
|
||||||
|
try {
|
||||||
|
stop();
|
||||||
|
} catch (IOException | InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
gui.updateGUIElementsWhenServersStartOrStop(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (server.isEnabled()) {
|
||||||
|
previouslyStartedServer = server;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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) throws ConfigurationException {
|
||||||
|
String[] data = saveString.split(";");
|
||||||
|
return new Server(data[0], data[1], Boolean.parseBoolean(data[2]), data[3], data[4], data[5]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,6 +1,17 @@
|
|||||||
package net.knarcraft.minecraftserverlauncher.server;
|
package net.knarcraft.minecraftserverlauncher.server;
|
||||||
|
|
||||||
import net.knarcraft.minecraftserverlauncher.server.servertypes.*;
|
import net.knarcraft.minecraftserverlauncher.server.servertypes.BungeeCord;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.server.servertypes.CraftBukkit;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.server.servertypes.Custom;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.server.servertypes.MCPCPlus;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.server.servertypes.Paper;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.server.servertypes.ServerType;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.server.servertypes.Spigot;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.server.servertypes.SpongeForge;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.server.servertypes.SpongeVanilla;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.server.servertypes.Travertine;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.server.servertypes.Vanilla;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.server.servertypes.Waterfall;
|
||||||
|
|
||||||
import javax.naming.ConfigurationException;
|
import javax.naming.ConfigurationException;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
@ -76,8 +87,13 @@ public class ServerTypeHandler {
|
|||||||
throw new ConfigurationException("Server type configuration file is missing.");
|
throw new ConfigurationException("Server type configuration file is missing.");
|
||||||
}
|
}
|
||||||
while (file.hasNextLine()) {
|
while (file.hasNextLine()) {
|
||||||
|
String nextLine = file.nextLine();
|
||||||
|
if (nextLine.startsWith("#")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
//Splits the next file line into arguments
|
//Splits the next file line into arguments
|
||||||
String[] serverTypeInfo = file.nextLine().split(";", -1);
|
String[] serverTypeInfo = nextLine.split(";", -1);
|
||||||
|
|
||||||
//Gets list of server versions from file line
|
//Gets list of server versions from file line
|
||||||
String[] serverVersions;
|
String[] serverVersions;
|
||||||
@ -118,7 +134,7 @@ public class ServerTypeHandler {
|
|||||||
break;
|
break;
|
||||||
case "Paper":
|
case "Paper":
|
||||||
newType = new Paper("Paper", false, serverVersions, serverTypeInfo[2],
|
newType = new Paper("Paper", false, serverVersions, serverTypeInfo[2],
|
||||||
serverTypeInfo[3]);
|
serverTypeInfo[3], serverTypeInfo[4], serverTypeInfo[5]);
|
||||||
break;
|
break;
|
||||||
case "Bungee":
|
case "Bungee":
|
||||||
newType = new BungeeCord("Bungee", true, serverVersions, serverTypeInfo[2],
|
newType = new BungeeCord("Bungee", true, serverVersions, serverTypeInfo[2],
|
||||||
|
@ -3,7 +3,10 @@ package net.knarcraft.minecraftserverlauncher.server;
|
|||||||
import net.knarcraft.minecraftserverlauncher.Main;
|
import net.knarcraft.minecraftserverlauncher.Main;
|
||||||
import net.knarcraft.minecraftserverlauncher.utility.CommonFunctions;
|
import net.knarcraft.minecraftserverlauncher.utility.CommonFunctions;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -19,8 +22,10 @@ public class ServerVersionContainer {
|
|||||||
private String bungeeVersion;
|
private String bungeeVersion;
|
||||||
private Map<String, String> waterfallVersions;
|
private Map<String, String> waterfallVersions;
|
||||||
private Map<String, String> travertineVersions;
|
private Map<String, String> travertineVersions;
|
||||||
|
private Map<String, String> paperVersions;
|
||||||
private Map<String, String> spongeVanillaVersions;
|
private Map<String, String> spongeVanillaVersions;
|
||||||
private Map<String, String> spongeForgeVersions;
|
private Map<String, String> spongeForgeVersions;
|
||||||
|
private String downloadedBuildToolsVersion;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes a new server version container
|
* Initializes a new server version container
|
||||||
@ -28,6 +33,7 @@ public class ServerVersionContainer {
|
|||||||
private ServerVersionContainer() {
|
private ServerVersionContainer() {
|
||||||
this.waterfallVersions = new HashMap<>();
|
this.waterfallVersions = new HashMap<>();
|
||||||
this.travertineVersions = new HashMap<>();
|
this.travertineVersions = new HashMap<>();
|
||||||
|
this.paperVersions = new HashMap<>();
|
||||||
this.spongeVanillaVersions = new HashMap<>();
|
this.spongeVanillaVersions = new HashMap<>();
|
||||||
this.spongeForgeVersions = new HashMap<>();
|
this.spongeForgeVersions = new HashMap<>();
|
||||||
loadState();
|
loadState();
|
||||||
@ -54,8 +60,10 @@ public class ServerVersionContainer {
|
|||||||
this.bungeeVersion = null;
|
this.bungeeVersion = null;
|
||||||
this.waterfallVersions = new HashMap<>();
|
this.waterfallVersions = new HashMap<>();
|
||||||
this.travertineVersions = new HashMap<>();
|
this.travertineVersions = new HashMap<>();
|
||||||
|
this.paperVersions = new HashMap<>();
|
||||||
this.spongeVanillaVersions = new HashMap<>();
|
this.spongeVanillaVersions = new HashMap<>();
|
||||||
this.spongeForgeVersions = new HashMap<>();
|
this.spongeForgeVersions = new HashMap<>();
|
||||||
|
this.downloadedBuildToolsVersion = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -65,8 +73,10 @@ public class ServerVersionContainer {
|
|||||||
"bungeeVersion;" + bungeeVersion + "\n" +
|
"bungeeVersion;" + bungeeVersion + "\n" +
|
||||||
"waterfallVersions;" + mapToString(waterfallVersions) + "\n" +
|
"waterfallVersions;" + mapToString(waterfallVersions) + "\n" +
|
||||||
"travertineVersions;" + mapToString(travertineVersions) + "\n" +
|
"travertineVersions;" + mapToString(travertineVersions) + "\n" +
|
||||||
|
"paperVersions;" + mapToString(paperVersions) + "\n" +
|
||||||
"spongeVanillaVersions;" + mapToString(spongeVanillaVersions) + "\n" +
|
"spongeVanillaVersions;" + mapToString(spongeVanillaVersions) + "\n" +
|
||||||
"spongeForgeVersions;" + mapToString(spongeForgeVersions);
|
"spongeForgeVersions;" + mapToString(spongeForgeVersions) + "\n" +
|
||||||
|
"downloadedBuildToolsVersion;" + downloadedBuildToolsVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -105,7 +115,7 @@ public class ServerVersionContainer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
file = new PrintWriter(versionFile);
|
file = new PrintWriter(versionFile);
|
||||||
file.println(this.toString());
|
file.println(this);
|
||||||
file.close();
|
file.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@ -119,8 +129,8 @@ public class ServerVersionContainer {
|
|||||||
if (!new File(versionFile).exists()) {
|
if (!new File(versionFile).exists()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(versionFile)))) {
|
try {
|
||||||
String currentData = CommonFunctions.readBufferedReader(reader);
|
String currentData = CommonFunctions.readFile(versionFile);
|
||||||
for (String line : currentData.split("\n")) {
|
for (String line : currentData.split("\n")) {
|
||||||
parseSaveLine(line);
|
parseSaveLine(line);
|
||||||
}
|
}
|
||||||
@ -157,12 +167,18 @@ public class ServerVersionContainer {
|
|||||||
case "travertineVersions":
|
case "travertineVersions":
|
||||||
parseVersionsToMap(travertineVersions, variableValue);
|
parseVersionsToMap(travertineVersions, variableValue);
|
||||||
break;
|
break;
|
||||||
|
case "paperVersions":
|
||||||
|
parseVersionsToMap(paperVersions, variableValue);
|
||||||
|
break;
|
||||||
case "spongeVanillaVersions":
|
case "spongeVanillaVersions":
|
||||||
parseVersionsToMap(spongeVanillaVersions, variableValue);
|
parseVersionsToMap(spongeVanillaVersions, variableValue);
|
||||||
break;
|
break;
|
||||||
case "spongeForgeVersions":
|
case "spongeForgeVersions":
|
||||||
parseVersionsToMap(spongeForgeVersions, variableValue);
|
parseVersionsToMap(spongeForgeVersions, variableValue);
|
||||||
break;
|
break;
|
||||||
|
case "downloadedBuildToolsVersion":
|
||||||
|
downloadedBuildToolsVersion = variableValue;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("Invalid key encountered in the server version file.");
|
throw new IllegalArgumentException("Invalid key encountered in the server version file.");
|
||||||
}
|
}
|
||||||
@ -172,9 +188,9 @@ public class ServerVersionContainer {
|
|||||||
* Reads versions from a text string and updates the version map
|
* Reads versions from a text string and updates the version map
|
||||||
*
|
*
|
||||||
* @param targetMap <p>The map to update</p>
|
* @param targetMap <p>The map to update</p>
|
||||||
* @param data <p>The data string to parse</p>
|
* @param data <p>The data string to parse</p>
|
||||||
*/
|
*/
|
||||||
private void parseVersionsToMap(Map<String,String> targetMap, String data) {
|
private void parseVersionsToMap(Map<String, String> targetMap, String data) {
|
||||||
String[] versions = data.split(",");
|
String[] versions = data.split(",");
|
||||||
for (String version : versions) {
|
for (String version : versions) {
|
||||||
String[] versionData = version.split("!");
|
String[] versionData = version.split("!");
|
||||||
@ -282,6 +298,27 @@ public class ServerVersionContainer {
|
|||||||
saveState();
|
saveState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a specific paper version
|
||||||
|
*
|
||||||
|
* @param versionKey <p>The version to check the current version of</p>
|
||||||
|
* @return <p>The current paper version</p>
|
||||||
|
*/
|
||||||
|
public String getPaperVersion(String versionKey) {
|
||||||
|
return this.paperVersions.get(versionKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the current version for a given paper version
|
||||||
|
*
|
||||||
|
* @param mapKey <p>The version key to set version for</p>
|
||||||
|
* @param newValue <p>The new current version</p>
|
||||||
|
*/
|
||||||
|
public void setPaperVersion(String mapKey, String newValue) {
|
||||||
|
this.paperVersions.put(mapKey, newValue);
|
||||||
|
saveState();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a specific sponge vanilla version
|
* Gets a specific sponge vanilla version
|
||||||
*
|
*
|
||||||
@ -323,5 +360,25 @@ public class ServerVersionContainer {
|
|||||||
spongeForgeVersions.put(mapKey, newValue);
|
spongeForgeVersions.put(mapKey, newValue);
|
||||||
saveState();
|
saveState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the version of the downloaded BuildTools file
|
||||||
|
*
|
||||||
|
* @return <p>The version of the downloaded BuildTools file</p>
|
||||||
|
*/
|
||||||
|
public String getDownloadedBuildToolsVersion() {
|
||||||
|
return this.downloadedBuildToolsVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the version of the downloaded BuildTools file
|
||||||
|
*
|
||||||
|
* @param newValue <p>The new version</p></p>
|
||||||
|
*/
|
||||||
|
public void setDownloadedBuildToolsVersion(String newValue) {
|
||||||
|
this.downloadedBuildToolsVersion = newValue;
|
||||||
|
saveState();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ import java.io.IOException;
|
|||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.downloadFile;
|
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.downloadFile;
|
||||||
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.readFile;
|
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.readRemoteFile;
|
||||||
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.stringBetween;
|
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.stringBetween;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -65,7 +65,7 @@ public class BungeeCord extends AbstractServerType {
|
|||||||
private boolean downloadLatestJar(File filePath) throws IOException {
|
private boolean downloadLatestJar(File filePath) throws IOException {
|
||||||
ServerVersionContainer versionContainer = ServerVersionContainer.getInstance();
|
ServerVersionContainer versionContainer = ServerVersionContainer.getInstance();
|
||||||
|
|
||||||
String newestVersion = stringBetween(readFile(versionURL), srcStart, srcEnd);
|
String newestVersion = stringBetween(readRemoteFile(versionURL), srcStart, srcEnd);
|
||||||
String oldVersion = versionContainer.getBungeeVersion();
|
String oldVersion = versionContainer.getBungeeVersion();
|
||||||
//The file is already the newest version
|
//The file is already the newest version
|
||||||
if (filePath.isFile() && newestVersion.equals(oldVersion)) {
|
if (filePath.isFile() && newestVersion.equals(oldVersion)) {
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
package net.knarcraft.minecraftserverlauncher.server.servertypes;
|
package net.knarcraft.minecraftserverlauncher.server.servertypes;
|
||||||
|
|
||||||
|
import net.knarcraft.minecraftserverlauncher.Main;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.profile.ServerLauncherController;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.server.JarBuilder;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.userinterface.GUI;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
@ -31,7 +36,31 @@ public class CraftBukkit extends AbstractServerType {
|
|||||||
String targetFile = this.getName() + version + ".jar";
|
String targetFile = this.getName() + version + ".jar";
|
||||||
String file = downloadURLPart + version + ".jar";
|
String file = downloadURLPart + version + ".jar";
|
||||||
File filePath = new File(folder + targetFile);
|
File filePath = new File(folder + targetFile);
|
||||||
return filePath.isFile() || downloadFile(downloadURL + file, Paths.get(filePath.toURI()));
|
|
||||||
|
if (version.equals("Latest")) {
|
||||||
|
return filePath.isFile() || buildJar(folder);
|
||||||
|
} else {
|
||||||
|
return filePath.isFile() || downloadFile(downloadURL + file, Paths.get(filePath.toURI()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the necessary .jar file
|
||||||
|
*
|
||||||
|
* @param folder <p>The folder the build file should be moved to</p>
|
||||||
|
* @return <p>True if the build was successful</p>
|
||||||
|
*/
|
||||||
|
private boolean buildJar(String folder) {
|
||||||
|
String buildToolsDirectory = Main.getApplicationWorkDirectory() + File.separator + "files" + File.separator +
|
||||||
|
"BuildTools" + File.separator;
|
||||||
|
|
||||||
|
GUI gui = ServerLauncherController.getInstance().getGUI();
|
||||||
|
JarBuilder jarBuilder = new JarBuilder(buildToolsDirectory, folder, gui);
|
||||||
|
if (this instanceof Spigot) {
|
||||||
|
return jarBuilder.buildSpigotJar();
|
||||||
|
} else {
|
||||||
|
return jarBuilder.buildBukkitJar();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,19 +3,25 @@ package net.knarcraft.minecraftserverlauncher.server.servertypes;
|
|||||||
/**
|
/**
|
||||||
* This class represents the Paper Minecraft server type
|
* This class represents the Paper Minecraft server type
|
||||||
*/
|
*/
|
||||||
public class Paper extends Spigot {
|
public class Paper extends Waterfall {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new Paper server type
|
* Instantiates a new Paper server type
|
||||||
*
|
*
|
||||||
* @param typeName <p>The name of the server type</p>
|
* @param typeName <p>The name of the server type</p>
|
||||||
* @param isProxy <p>Whether this server type is a proxy server</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 versions <p>The available versions for the server type</p>
|
||||||
* @param downloadURL <p>The URL used for downloading .jar files</p>
|
* @param versionURL <p>The URL used to finding the newest version</p>
|
||||||
* @param downloadURLPart <p>A string used after the download url as an additional part of the URL</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 Paper(String typeName, boolean isProxy, String[] versions, String downloadURL, String downloadURLPart) {
|
public Paper(String typeName, boolean isProxy, String[] versions, String versionURL, String srcStart,
|
||||||
super(typeName, isProxy, versions, downloadURL, downloadURLPart);
|
String srcEnd, String downloadURL) {
|
||||||
|
super(typeName, isProxy, versions, versionURL, srcStart, srcEnd, downloadURL);
|
||||||
|
|
||||||
|
this.oldVersionFunction = serverVersionContainer::getPaperVersion;
|
||||||
|
this.versionUpdateFunction = serverVersionContainer::setPaperVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,8 +20,8 @@ public class SpongeVanilla extends AbstractServerType {
|
|||||||
private final String srcStart;
|
private final String srcStart;
|
||||||
private final String srcEnd;
|
private final String srcEnd;
|
||||||
private final String downloadURLPart;
|
private final String downloadURLPart;
|
||||||
Function<String,String> oldVersionFunction;
|
Function<String, String> oldVersionFunction;
|
||||||
BiConsumer<String,String> versionUpdateFunction;
|
BiConsumer<String, String> versionUpdateFunction;
|
||||||
final ServerVersionContainer serverVersionContainer;
|
final ServerVersionContainer serverVersionContainer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -53,7 +53,7 @@ public class SpongeVanilla extends AbstractServerType {
|
|||||||
String file = this.getName() + version + ".jar";
|
String file = this.getName() + version + ".jar";
|
||||||
File filePath = new File(folder + file);
|
File filePath = new File(folder + file);
|
||||||
|
|
||||||
String versionText = CommonFunctions.readFile(versionURL + version);
|
String versionText = CommonFunctions.readRemoteFile(versionURL + version);
|
||||||
String newestVersion = CommonFunctions.stringBetween(versionText, srcStart, srcEnd);
|
String newestVersion = CommonFunctions.stringBetween(versionText, srcStart, srcEnd);
|
||||||
|
|
||||||
String jarURL = downloadURL + newestVersion + downloadURLPart + newestVersion + ".jar";
|
String jarURL = downloadURL + newestVersion + downloadURLPart + newestVersion + ".jar";
|
||||||
|
@ -12,7 +12,7 @@ import java.io.IOException;
|
|||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.downloadFile;
|
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.downloadFile;
|
||||||
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.readFile;
|
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.readRemoteFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class represents the regular vanilla Minecraft server type
|
* This class represents the regular vanilla Minecraft server type
|
||||||
@ -54,9 +54,9 @@ public class Vanilla extends AbstractServerType {
|
|||||||
/**
|
/**
|
||||||
* Downloads the latest .jar file found if necessary
|
* Downloads the latest .jar file found if necessary
|
||||||
*
|
*
|
||||||
* @param filePath <p>The path of the jar file to download</p>
|
* @param filePath <p>The path of the jar file to download</p>
|
||||||
* @param releaseType <p>The release type used for downloading</p>
|
* @param releaseType <p>The release type used for downloading</p>
|
||||||
* @param lastVersion <p>The last server version found</p>
|
* @param lastVersion <p>The last server version found</p>
|
||||||
* @param versionContainer <p>The version container to use</p>
|
* @param versionContainer <p>The version container to use</p>
|
||||||
* @return <p>True if the jar exists and is the latest version or was downloaded</p>
|
* @return <p>True if the jar exists and is the latest version or was downloaded</p>
|
||||||
* @throws IOException <p>If the .jar cannot be downloaded</p>
|
* @throws IOException <p>If the .jar cannot be downloaded</p>
|
||||||
@ -90,7 +90,7 @@ public class Vanilla extends AbstractServerType {
|
|||||||
* @throws IOException <p>If the remote resource cannot be readFromServer</p>
|
* @throws IOException <p>If the remote resource cannot be readFromServer</p>
|
||||||
*/
|
*/
|
||||||
private String[] getLatestFile(String releaseType) throws IOException {
|
private String[] getLatestFile(String releaseType) throws IOException {
|
||||||
String versionText = readFile(versionURL);
|
String versionText = readRemoteFile(versionURL);
|
||||||
JsonObject jsonObject = new JsonParser().parse(versionText).getAsJsonObject();
|
JsonObject jsonObject = new JsonParser().parse(versionText).getAsJsonObject();
|
||||||
String latest = jsonObject.getAsJsonObject("latest").get(releaseType).getAsString();
|
String latest = jsonObject.getAsJsonObject("latest").get(releaseType).getAsString();
|
||||||
String versionURL = getServerFileVersionURL(latest);
|
String versionURL = getServerFileVersionURL(latest);
|
||||||
@ -106,7 +106,7 @@ public class Vanilla extends AbstractServerType {
|
|||||||
* @throws IOException <p>If the remote resource cannot be readFromServer</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 = readRemoteFile(versionURL);
|
||||||
JsonObject jsonObject = new JsonParser().parse(versionText).getAsJsonObject();
|
JsonObject jsonObject = new JsonParser().parse(versionText).getAsJsonObject();
|
||||||
return jsonObject.getAsJsonObject("downloads").getAsJsonObject("server").get("url").getAsString();
|
return jsonObject.getAsJsonObject("downloads").getAsJsonObject("server").get("url").getAsString();
|
||||||
}
|
}
|
||||||
@ -119,7 +119,7 @@ public class Vanilla extends AbstractServerType {
|
|||||||
* @throws IOException <p>If the file cannot be downloaded</p>
|
* @throws IOException <p>If the file cannot be downloaded</p>
|
||||||
*/
|
*/
|
||||||
private String getServerFileVersionURL(String targetVersion) throws IOException {
|
private String getServerFileVersionURL(String targetVersion) throws IOException {
|
||||||
String versionText = readFile(versionURL);
|
String versionText = readRemoteFile(versionURL);
|
||||||
JsonObject jsonObject = new JsonParser().parse(versionText).getAsJsonObject();
|
JsonObject jsonObject = new JsonParser().parse(versionText).getAsJsonObject();
|
||||||
JsonArray availableVersions = jsonObject.getAsJsonArray("versions");
|
JsonArray availableVersions = jsonObject.getAsJsonArray("versions");
|
||||||
for (JsonElement availableVersion : availableVersions) {
|
for (JsonElement availableVersion : availableVersions) {
|
||||||
|
@ -9,7 +9,7 @@ import java.util.function.BiConsumer;
|
|||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.downloadFile;
|
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.downloadFile;
|
||||||
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.readFile;
|
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.readRemoteFile;
|
||||||
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.stringBetween;
|
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.stringBetween;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,13 +50,21 @@ public class Waterfall extends AbstractServerType {
|
|||||||
public boolean downloadJar(String folder, String version) throws IOException {
|
public boolean downloadJar(String folder, String version) throws IOException {
|
||||||
String file = this.getName() + version + ".jar";
|
String file = this.getName() + version + ".jar";
|
||||||
File filePath = new File(folder + file);
|
File filePath = new File(folder + file);
|
||||||
String newestVersion = stringBetween(readFile(versionURL + version), srcStart, srcEnd);
|
String versionFileContents = readRemoteFile(versionURL + version);
|
||||||
String fullURL = downloadURL + version + "/" + newestVersion + "/download";
|
String[] versions = stringBetween(versionFileContents, srcStart, srcEnd).split(",");
|
||||||
|
String newestVersion = versions[versions.length - 1];
|
||||||
String oldVersion = oldVersionFunction.apply(version);
|
String oldVersion = oldVersionFunction.apply(version);
|
||||||
|
|
||||||
//The file is already the newest version
|
//The file is already the newest version
|
||||||
if (filePath.isFile() && newestVersion.equals(oldVersion)) {
|
if (filePath.isFile() && newestVersion.equals(oldVersion)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Get necessary information for downloading the latest version
|
||||||
|
String newestVersionInfoURL = versionURL + version + "/builds/" + newestVersion;
|
||||||
|
String fileName = stringBetween(readRemoteFile(newestVersionInfoURL), "\"name\":\"", "\"");
|
||||||
|
String fullURL = downloadURL + version + "/builds/" + newestVersion + "/downloads/" + fileName;
|
||||||
|
|
||||||
//The new jar file could not be downloaded
|
//The new jar file could not be downloaded
|
||||||
if (!downloadFile(fullURL, Paths.get(filePath.toURI()))) {
|
if (!downloadFile(fullURL, Paths.get(filePath.toURI()))) {
|
||||||
return false;
|
return false;
|
||||||
@ -64,4 +72,5 @@ public class Waterfall extends AbstractServerType {
|
|||||||
versionUpdateFunction.accept(version, newestVersion);
|
versionUpdateFunction.accept(version, newestVersion);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,106 @@
|
|||||||
|
package net.knarcraft.minecraftserverlauncher.userinterface;
|
||||||
|
|
||||||
|
import net.knarcraft.minecraftserverlauncher.utility.BackupUtil;
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.getResourceAsStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Backup GUI is used to display backup progress
|
||||||
|
*/
|
||||||
|
public class BackupGUI implements ActionListener {
|
||||||
|
private static JFrame frame;
|
||||||
|
private static JTextArea progressTextArea;
|
||||||
|
private static JProgressBar progressBar;
|
||||||
|
private static JButton cancelButton;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new GUI
|
||||||
|
*/
|
||||||
|
public BackupGUI() {
|
||||||
|
instantiate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the server consoles frame
|
||||||
|
*/
|
||||||
|
public void instantiate() {
|
||||||
|
if (frame != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
frame = new JFrame("Running backup...");
|
||||||
|
frame.setBounds(100, 100, 500, 140);
|
||||||
|
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
|
||||||
|
ImageIcon img;
|
||||||
|
try {
|
||||||
|
img = new ImageIcon(ImageIO.read(getResourceAsStream("GUIIcon.png")));
|
||||||
|
frame.setIconImage(img.getImage());
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
|
progressTextArea = new JTextArea();
|
||||||
|
progressTextArea.setEditable(false);
|
||||||
|
progressBar = new JProgressBar();
|
||||||
|
cancelButton = new JButton("Cancel");
|
||||||
|
JPanel panel = new JPanel();
|
||||||
|
panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
|
||||||
|
panel.add(progressTextArea);
|
||||||
|
panel.add(Box.createRigidArea(new Dimension(0, 5)));
|
||||||
|
panel.add(progressBar);
|
||||||
|
|
||||||
|
JPanel buttonPane = new JPanel();
|
||||||
|
buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS));
|
||||||
|
buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
|
||||||
|
buttonPane.add(Box.createHorizontalGlue());
|
||||||
|
buttonPane.add(cancelButton);
|
||||||
|
cancelButton.addActionListener(BackupGUI.this);
|
||||||
|
|
||||||
|
panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
|
||||||
|
Container contentPane = frame.getContentPane();
|
||||||
|
contentPane.add(panel, BorderLayout.CENTER);
|
||||||
|
contentPane.add(buttonPane, BorderLayout.PAGE_END);
|
||||||
|
frame.setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates information about the backup progress
|
||||||
|
*
|
||||||
|
* @param infoText <p>The text to display</p>
|
||||||
|
* @param progressPercent <p>The new percent of the progress bar</p>
|
||||||
|
*/
|
||||||
|
public static void updateProgress(String infoText, int progressPercent) {
|
||||||
|
if (progressTextArea != null) {
|
||||||
|
progressTextArea.setText(infoText);
|
||||||
|
}
|
||||||
|
if (progressBar != null) {
|
||||||
|
progressBar.setValue(progressPercent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroys the backup GUI
|
||||||
|
*/
|
||||||
|
public static void destroy() {
|
||||||
|
if (frame != null) {
|
||||||
|
frame.dispose();
|
||||||
|
frame = null;
|
||||||
|
progressBar = null;
|
||||||
|
progressTextArea = null;
|
||||||
|
cancelButton = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
|
if (actionEvent.getSource() == cancelButton) {
|
||||||
|
BackupUtil.abortBackup();
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
package net.knarcraft.minecraftserverlauncher.userinterface;
|
||||||
|
|
||||||
|
import net.knarcraft.minecraftserverlauncher.Main;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.profile.ServerLauncherController;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listener for clicking the close button of a server tab
|
||||||
|
*/
|
||||||
|
public class CloseTabActionListener implements ActionListener {
|
||||||
|
|
||||||
|
private final String tabName;
|
||||||
|
private final JTabbedPane tabPane;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new close tab action listener
|
||||||
|
*
|
||||||
|
* @param tabPane <p>The tab pane containing all tabs</p>
|
||||||
|
* @param tabName <p>The name of the tab connected to this action listener</p>
|
||||||
|
*/
|
||||||
|
public CloseTabActionListener(JTabbedPane tabPane, String tabName) {
|
||||||
|
this.tabName = tabName;
|
||||||
|
this.tabPane = tabPane;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent evt) {
|
||||||
|
int index = tabPane.indexOfTab(tabName);
|
||||||
|
if (index >= 0) {
|
||||||
|
//Abort if the user just mis-clicked
|
||||||
|
int answer = JOptionPane.showConfirmDialog(null,
|
||||||
|
String.format("Do you really want to remove the server %s?", tabName), "Remove server",
|
||||||
|
JOptionPane.YES_NO_OPTION
|
||||||
|
);
|
||||||
|
if (answer == JOptionPane.YES_NO_OPTION) {
|
||||||
|
//Remove the server
|
||||||
|
ServerLauncherController controller = Main.getController();
|
||||||
|
controller.getCurrentProfile().removeCollection(tabName);
|
||||||
|
controller.getGUI().updateWithSavedProfileData();
|
||||||
|
controller.getCurrentProfile().updateConsoles();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -5,7 +5,11 @@ import net.knarcraft.minecraftserverlauncher.Main;
|
|||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.text.DefaultCaret;
|
import javax.swing.text.DefaultCaret;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.*;
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.awt.event.KeyAdapter;
|
||||||
|
import java.awt.event.KeyEvent;
|
||||||
|
import java.awt.event.KeyListener;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import static javax.swing.text.DefaultCaret.ALWAYS_UPDATE;
|
import static javax.swing.text.DefaultCaret.ALWAYS_UPDATE;
|
||||||
@ -26,11 +30,12 @@ public class Console extends KeyAdapter implements ActionListener, KeyListener {
|
|||||||
private final JPanel panel;
|
private final JPanel panel;
|
||||||
private final ArrayList<String> commands = new ArrayList<>();
|
private final ArrayList<String> commands = new ArrayList<>();
|
||||||
private int commandIndex;
|
private int commandIndex;
|
||||||
|
private final int maxConsoleLines = 1000;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new console
|
* Instantiates a new console
|
||||||
*
|
*
|
||||||
* @param tab <p>The tabbed pane used for displaying the console</p>
|
* @param tab <p>The tabbed pane used for displaying the console</p>
|
||||||
* @param name <p>The name of the console tab</p>
|
* @param name <p>The name of the console tab</p>
|
||||||
*/
|
*/
|
||||||
Console(JTabbedPane tab, String name) {
|
Console(JTabbedPane tab, String name) {
|
||||||
@ -67,9 +72,33 @@ public class Console extends KeyAdapter implements ActionListener, KeyListener {
|
|||||||
* @param text <p>The string to print</p>
|
* @param text <p>The string to print</p>
|
||||||
*/
|
*/
|
||||||
public void output(String text) {
|
public void output(String text) {
|
||||||
|
int outputLines = this.textOutput.getLineCount();
|
||||||
|
if (outputLines > maxConsoleLines) {
|
||||||
|
truncateConsole(outputLines);
|
||||||
|
}
|
||||||
this.textOutput.setText(this.textOutput.getText() + "\n" + text);
|
this.textOutput.setText(this.textOutput.getText() + "\n" + text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Truncates the first 50 lines if the console output has reached the max limit
|
||||||
|
*
|
||||||
|
* @param outputLines <p>The currently readable lines in the console output field</p>
|
||||||
|
*/
|
||||||
|
private void truncateConsole(int outputLines) {
|
||||||
|
String oldText = this.textOutput.getText();
|
||||||
|
String[] oldTextList = oldText.split("\n");
|
||||||
|
for (int i = 0; i < outputLines - maxConsoleLines + 50; i++) {
|
||||||
|
oldTextList[i] = "";
|
||||||
|
}
|
||||||
|
StringBuilder newTextBuilder = new StringBuilder();
|
||||||
|
for (String line : oldTextList) {
|
||||||
|
if (!line.equals("")) {
|
||||||
|
newTextBuilder.append(line).append("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.textOutput.setText(newTextBuilder.toString());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
//Sends the command from the input to the server with the same name.
|
//Sends the command from the input to the server with the same name.
|
||||||
@ -99,7 +128,7 @@ public class Console extends KeyAdapter implements ActionListener, KeyListener {
|
|||||||
* Shows the previously executed command in the input field
|
* Shows the previously executed command in the input field
|
||||||
*
|
*
|
||||||
* <p>Shows the previously executed command if a command was just executed.
|
* <p>Shows the previously executed command if a command was just executed.
|
||||||
* Shows the command executed earlier if already showing a previously executed command.</p>
|
* Shows the command executed earlier if already showing a previously executed command</p>
|
||||||
*/
|
*/
|
||||||
private void showPreviousCommand() {
|
private void showPreviousCommand() {
|
||||||
if (commands.size() > 0 && commandIndex > 0) {
|
if (commands.size() > 0 && commandIndex > 0) {
|
||||||
@ -111,7 +140,7 @@ public class Console extends KeyAdapter implements ActionListener, KeyListener {
|
|||||||
* Shows the next previously executed command or clears the input field
|
* Shows the next previously executed command or clears the input field
|
||||||
*
|
*
|
||||||
* <p>Shows the next previously executed command if such a command exists.
|
* <p>Shows the next previously executed command if such a command exists.
|
||||||
* Clears the input field if no next used command exists.</p>
|
* Clears the input field if no next used command exists</p>
|
||||||
*/
|
*/
|
||||||
private void showNextCommand() {
|
private void showNextCommand() {
|
||||||
if (commands.size() > 0) {
|
if (commands.size() > 0) {
|
||||||
|
@ -0,0 +1,218 @@
|
|||||||
|
package net.knarcraft.minecraftserverlauncher.userinterface;
|
||||||
|
|
||||||
|
import net.knarcraft.minecraftserverlauncher.Main;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.profile.ServerLauncherController;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.server.ServerHandler;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.utility.BackupUtil;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
public class ControlPanelTab implements ActionListener {
|
||||||
|
|
||||||
|
private JButton startServerButton;
|
||||||
|
private JButton stopServerButton;
|
||||||
|
private JButton backupButton;
|
||||||
|
private JButton addProfileButton;
|
||||||
|
private JButton showConsolesButton;
|
||||||
|
private JButton deleteProfileButton;
|
||||||
|
private JComboBox<String> profiles;
|
||||||
|
private final JPanel controlPanelPanel;
|
||||||
|
private final ServerLauncherController controller;
|
||||||
|
private final JLabel statusLabel = new JLabel("Servers are stopped");
|
||||||
|
|
||||||
|
public ControlPanelTab(JPanel controlPanelPanel) {
|
||||||
|
this.controlPanelPanel = controlPanelPanel;
|
||||||
|
this.controller = Main.getController();
|
||||||
|
initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the text of the status label
|
||||||
|
*
|
||||||
|
* @param text <p>The new text of the status label</p>
|
||||||
|
*/
|
||||||
|
public void setStatusText(String text) {
|
||||||
|
this.statusLabel.setText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the ServerLauncherGUI components to block a user from doing illegal actions
|
||||||
|
*
|
||||||
|
* @param running <p>Whether the servers are currently running</p>
|
||||||
|
*/
|
||||||
|
public void updateGUIElementsWhenServersStartOrStop(boolean running) {
|
||||||
|
boolean stopped = !running; //Most gui is only enabled when the server is stopped rather than running.
|
||||||
|
profiles.setEnabled(stopped);
|
||||||
|
addProfileButton.setEnabled(stopped);
|
||||||
|
deleteProfileButton.setEnabled(stopped);
|
||||||
|
startServerButton.setEnabled(stopped);
|
||||||
|
stopServerButton.setEnabled(running);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops all servers
|
||||||
|
*/
|
||||||
|
public void stopServers() {
|
||||||
|
GUI gui = Main.getController().getGUI();
|
||||||
|
try {
|
||||||
|
gui.setStatus("Servers are stopping...");
|
||||||
|
ServerHandler.stop();
|
||||||
|
} catch (IOException e1) {
|
||||||
|
gui.showError("Could not stop server.");
|
||||||
|
e1.printStackTrace();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
gui.showError("Could not kill server.");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the currently selected profile
|
||||||
|
*
|
||||||
|
* @return <p>The currently selected profile or null</p>
|
||||||
|
*/
|
||||||
|
public String getSelectedProfile() {
|
||||||
|
Object selectedProfile = profiles.getSelectedItem();
|
||||||
|
if (selectedProfile != null) {
|
||||||
|
return selectedProfile.toString();
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the profiles combo
|
||||||
|
*/
|
||||||
|
public void updateProfiles() {
|
||||||
|
String selectedProfile = Main.getController().getCurrentProfile().getName();
|
||||||
|
this.profiles.removeAllItems();
|
||||||
|
for (String profile : Main.getController().getProfileNames()) {
|
||||||
|
this.profiles.addItem(profile);
|
||||||
|
}
|
||||||
|
this.profiles.setSelectedItem(selectedProfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes the selected profile
|
||||||
|
*/
|
||||||
|
private void deleteProfile() {
|
||||||
|
Object selected = profiles.getSelectedItem();
|
||||||
|
int answer = JOptionPane.showConfirmDialog(null,
|
||||||
|
String.format("Do you really want to remove the profile %s?", selected), "Remove profile",
|
||||||
|
JOptionPane.YES_NO_OPTION
|
||||||
|
);
|
||||||
|
if (answer == JOptionPane.YES_NO_OPTION) {
|
||||||
|
if (selected != null) {
|
||||||
|
controller.removeProfile(selected.toString());
|
||||||
|
updateProfiles();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves the previous profile and loads data from the new profile
|
||||||
|
*/
|
||||||
|
private void changeProfile() {
|
||||||
|
controller.saveState();
|
||||||
|
Object current = this.profiles.getSelectedItem();
|
||||||
|
if (current != null) {
|
||||||
|
controller.setCurrentProfile(current.toString());
|
||||||
|
}
|
||||||
|
controller.getGUI().updateWithSavedProfileData();
|
||||||
|
controller.getCurrentProfile().updateConsoles();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initialize() {
|
||||||
|
SpringLayout springLayout = new SpringLayout();
|
||||||
|
controlPanelPanel.setLayout(springLayout);
|
||||||
|
|
||||||
|
JLabel lblBasicControls = new JLabel("Basic controls");
|
||||||
|
springLayout.putConstraint(SpringLayout.NORTH, lblBasicControls, 10, SpringLayout.NORTH, controlPanelPanel);
|
||||||
|
controlPanelPanel.add(lblBasicControls);
|
||||||
|
|
||||||
|
startServerButton = new JButton("Start servers");
|
||||||
|
springLayout.putConstraint(SpringLayout.WEST, lblBasicControls, 0, SpringLayout.WEST, startServerButton);
|
||||||
|
springLayout.putConstraint(SpringLayout.NORTH, startServerButton, 6, SpringLayout.SOUTH, lblBasicControls);
|
||||||
|
springLayout.putConstraint(SpringLayout.WEST, startServerButton, 10, SpringLayout.WEST, controlPanelPanel);
|
||||||
|
controlPanelPanel.add(startServerButton);
|
||||||
|
startServerButton.addActionListener(this);
|
||||||
|
|
||||||
|
stopServerButton = new JButton("Stop servers");
|
||||||
|
springLayout.putConstraint(SpringLayout.NORTH, stopServerButton, 0, SpringLayout.NORTH, startServerButton);
|
||||||
|
springLayout.putConstraint(SpringLayout.WEST, stopServerButton, 6, SpringLayout.EAST, startServerButton);
|
||||||
|
controlPanelPanel.add(stopServerButton);
|
||||||
|
stopServerButton.addActionListener(this);
|
||||||
|
|
||||||
|
showConsolesButton = new JButton("View server consoles");
|
||||||
|
springLayout.putConstraint(SpringLayout.NORTH, showConsolesButton, 0, SpringLayout.NORTH, stopServerButton);
|
||||||
|
springLayout.putConstraint(SpringLayout.WEST, showConsolesButton, 6, SpringLayout.EAST, stopServerButton);
|
||||||
|
controlPanelPanel.add(showConsolesButton);
|
||||||
|
showConsolesButton.addActionListener(this);
|
||||||
|
|
||||||
|
backupButton = new JButton("Backup");
|
||||||
|
springLayout.putConstraint(SpringLayout.NORTH, backupButton, 0, SpringLayout.NORTH, showConsolesButton);
|
||||||
|
springLayout.putConstraint(SpringLayout.WEST, backupButton, 6, SpringLayout.EAST, showConsolesButton);
|
||||||
|
controlPanelPanel.add(backupButton);
|
||||||
|
backupButton.addActionListener(this);
|
||||||
|
|
||||||
|
JLabel profileLabel = new JLabel("Profile");
|
||||||
|
springLayout.putConstraint(SpringLayout.NORTH, profileLabel, 6, SpringLayout.SOUTH, startServerButton);
|
||||||
|
springLayout.putConstraint(SpringLayout.WEST, profileLabel, 10, SpringLayout.WEST, controlPanelPanel);
|
||||||
|
controlPanelPanel.add(profileLabel);
|
||||||
|
|
||||||
|
addProfileButton = new JButton("+");
|
||||||
|
springLayout.putConstraint(SpringLayout.NORTH, addProfileButton, 6, SpringLayout.SOUTH, profileLabel);
|
||||||
|
springLayout.putConstraint(SpringLayout.WEST, addProfileButton, 10, SpringLayout.WEST, controlPanelPanel);
|
||||||
|
controlPanelPanel.add(addProfileButton);
|
||||||
|
addProfileButton.addActionListener(this);
|
||||||
|
|
||||||
|
deleteProfileButton = new JButton("-");
|
||||||
|
springLayout.putConstraint(SpringLayout.NORTH, deleteProfileButton, 0, SpringLayout.NORTH, addProfileButton);
|
||||||
|
springLayout.putConstraint(SpringLayout.WEST, deleteProfileButton, 6, SpringLayout.EAST, addProfileButton);
|
||||||
|
controlPanelPanel.add(deleteProfileButton);
|
||||||
|
deleteProfileButton.addActionListener(this);
|
||||||
|
|
||||||
|
profiles = new JComboBox<>();
|
||||||
|
springLayout.putConstraint(SpringLayout.NORTH, profiles, 0, SpringLayout.NORTH, addProfileButton);
|
||||||
|
springLayout.putConstraint(SpringLayout.WEST, profiles, 6, SpringLayout.EAST, deleteProfileButton);
|
||||||
|
springLayout.putConstraint(SpringLayout.EAST, profiles, 124, SpringLayout.EAST, deleteProfileButton);
|
||||||
|
controlPanelPanel.add(profiles);
|
||||||
|
profiles.addActionListener(this);
|
||||||
|
|
||||||
|
springLayout.putConstraint(SpringLayout.NORTH, statusLabel, 6, SpringLayout.SOUTH, addProfileButton);
|
||||||
|
springLayout.putConstraint(SpringLayout.SOUTH, statusLabel, -10, SpringLayout.SOUTH, controlPanelPanel);
|
||||||
|
springLayout.putConstraint(SpringLayout.WEST, statusLabel, 10, SpringLayout.WEST, controlPanelPanel);
|
||||||
|
springLayout.putConstraint(SpringLayout.EAST, statusLabel, -10, SpringLayout.EAST, controlPanelPanel);
|
||||||
|
statusLabel.setFont(new Font("", Font.BOLD, 12));
|
||||||
|
controlPanelPanel.add(statusLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
|
Object actionSource = actionEvent.getSource();
|
||||||
|
if (actionSource == startServerButton) {
|
||||||
|
controller.saveState();
|
||||||
|
Executors.newSingleThreadExecutor().execute(ServerHandler::startServers);
|
||||||
|
} else if (actionSource == stopServerButton) {
|
||||||
|
stopServers();
|
||||||
|
} else if (actionSource == backupButton) {
|
||||||
|
//Run backup in its own thread to prevent locking up
|
||||||
|
Executors.newSingleThreadExecutor().execute(() -> BackupUtil.backup(controller.getGUI()));
|
||||||
|
} else if (actionSource == addProfileButton) {
|
||||||
|
controller.addProfile(JOptionPane.showInputDialog("Profile name: "));
|
||||||
|
updateProfiles();
|
||||||
|
} else if (actionSource == deleteProfileButton) {
|
||||||
|
deleteProfile();
|
||||||
|
} else if (actionSource == profiles) {
|
||||||
|
changeProfile();
|
||||||
|
} else if (actionSource == showConsolesButton) {
|
||||||
|
ServerConsoles.setAsVisible();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -44,6 +44,20 @@ public interface GUI {
|
|||||||
*/
|
*/
|
||||||
void showMessage(String message);
|
void showMessage(String message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs a message to the logfile
|
||||||
|
*
|
||||||
|
* @param message <p>The message to log</p>
|
||||||
|
*/
|
||||||
|
void logMessage(String message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs an error to the logfile
|
||||||
|
*
|
||||||
|
* @param error <p>The error to log</p>
|
||||||
|
*/
|
||||||
|
void logError(String error);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asks the user for a directory as a file object
|
* Asks the user for a directory as a file object
|
||||||
*
|
*
|
||||||
|
@ -1,6 +1,13 @@
|
|||||||
package net.knarcraft.minecraftserverlauncher.userinterface;
|
package net.knarcraft.minecraftserverlauncher.userinterface;
|
||||||
|
|
||||||
|
import net.knarcraft.minecraftserverlauncher.Main;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.utility.CommonFunctions;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class handles displaying messages to the user
|
* This class handles displaying messages to the user
|
||||||
@ -8,6 +15,8 @@ import javax.swing.*;
|
|||||||
public abstract class MessageHandler implements GUI {
|
public abstract class MessageHandler implements GUI {
|
||||||
|
|
||||||
private final boolean silent;
|
private final boolean silent;
|
||||||
|
private final BufferedWriter writer;
|
||||||
|
private final String logFile = Main.getApplicationWorkDirectory() + File.separator + "latestrun.log";
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Initializes a new message handler
|
* Initializes a new message handler
|
||||||
@ -16,15 +25,42 @@ public abstract class MessageHandler implements GUI {
|
|||||||
*/
|
*/
|
||||||
public MessageHandler(boolean silent) {
|
public MessageHandler(boolean silent) {
|
||||||
this.silent = silent;
|
this.silent = silent;
|
||||||
|
this.writer = new BufferedWriter(new OutputStreamWriter(System.out));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void logMessage(String message) {
|
||||||
|
try {
|
||||||
|
CommonFunctions.appendFile(logFile, "[Info]: " + message);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void logError(String message) {
|
||||||
|
try {
|
||||||
|
CommonFunctions.appendFile(logFile, "[Error]: " + message);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void showError(String title, String message) {
|
public void showError(String title, String message) {
|
||||||
if (silent) {
|
if (silent) {
|
||||||
System.out.println(message);
|
try {
|
||||||
|
writer.write("[Error]: ");
|
||||||
|
writer.write(message);
|
||||||
|
writer.newLine();
|
||||||
|
writer.flush();
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.out.println(message);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
showJOptionPane(title, message, JOptionPane.ERROR_MESSAGE);
|
showJOptionPane(title, message, JOptionPane.ERROR_MESSAGE);
|
||||||
}
|
}
|
||||||
|
logError(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -35,10 +71,17 @@ public abstract class MessageHandler implements GUI {
|
|||||||
@Override
|
@Override
|
||||||
public void showMessage(String title, String message) {
|
public void showMessage(String title, String message) {
|
||||||
if (silent) {
|
if (silent) {
|
||||||
System.out.println(message);
|
try {
|
||||||
|
writer.write("[Info]: " + message);
|
||||||
|
writer.newLine();
|
||||||
|
writer.flush();
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.out.println(message);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
showJOptionPane(title, message, JOptionPane.INFORMATION_MESSAGE);
|
showJOptionPane(title, message, JOptionPane.INFORMATION_MESSAGE);
|
||||||
}
|
}
|
||||||
|
logMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
package net.knarcraft.minecraftserverlauncher.userinterface;
|
package net.knarcraft.minecraftserverlauncher.userinterface;
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.getResourceAsStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class keeps track of all consoles
|
* This class keeps track of all consoles
|
||||||
@ -17,15 +21,27 @@ public class ServerConsoles {
|
|||||||
private static JFrame frame;
|
private static JFrame frame;
|
||||||
private static JTabbedPane consolesTabbedPane;
|
private static JTabbedPane consolesTabbedPane;
|
||||||
|
|
||||||
|
private ServerConsoles() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the server consoles frame
|
* Initializes the server consoles frame
|
||||||
*/
|
*/
|
||||||
public ServerConsoles() {
|
public static void instantiate() {
|
||||||
frame = new JFrame();
|
if (frame == null || consolesTabbedPane == null) {
|
||||||
frame.setBounds(100, 100, 450, 300);
|
frame = new JFrame();
|
||||||
frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
|
frame.setBounds(100, 100, 450, 300);
|
||||||
consolesTabbedPane = new JTabbedPane(JTabbedPane.TOP);
|
frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
|
||||||
frame.getContentPane().add(consolesTabbedPane, BorderLayout.CENTER);
|
consolesTabbedPane = new JTabbedPane(JTabbedPane.TOP);
|
||||||
|
frame.getContentPane().add(consolesTabbedPane, BorderLayout.CENTER);
|
||||||
|
ImageIcon img;
|
||||||
|
try {
|
||||||
|
img = new ImageIcon(ImageIO.read(getResourceAsStream("GUIIcon.png")));
|
||||||
|
frame.setIconImage(img.getImage());
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package net.knarcraft.minecraftserverlauncher.userinterface;
|
package net.knarcraft.minecraftserverlauncher.userinterface;
|
||||||
|
|
||||||
import net.knarcraft.minecraftserverlauncher.profile.Collection;
|
import net.knarcraft.minecraftserverlauncher.profile.Collection;
|
||||||
import net.knarcraft.minecraftserverlauncher.profile.Controller;
|
import net.knarcraft.minecraftserverlauncher.profile.ServerLauncherController;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
@ -22,16 +22,15 @@ public class ServerControlTab implements ActionListener {
|
|||||||
private JButton customCommandButton;
|
private JButton customCommandButton;
|
||||||
private JButton saveServerButton;
|
private JButton saveServerButton;
|
||||||
private JButton reloadButton;
|
private JButton reloadButton;
|
||||||
private JButton showConsolesButton;
|
|
||||||
private JTextField customCommandTextField;
|
private JTextField customCommandTextField;
|
||||||
|
|
||||||
private Controller controller = Controller.getInstance();
|
private final ServerLauncherController controller = ServerLauncherController.getInstance();
|
||||||
private final ArrayList<String> globalPlayers;
|
private final ArrayList<String> globalPlayers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new server control tab
|
* Instantiates a new server control tab
|
||||||
*
|
*
|
||||||
* @param mainFrame <p>The main frame of the GUI</p>
|
* @param mainFrame <p>The main frame of the GUI</p>
|
||||||
* @param controlServers <p>The JPanel to attach the server controls to</p>
|
* @param controlServers <p>The JPanel to attach the server controls to</p>
|
||||||
*/
|
*/
|
||||||
public ServerControlTab(JFrame mainFrame, JPanel controlServers) {
|
public ServerControlTab(JFrame mainFrame, JPanel controlServers) {
|
||||||
@ -42,7 +41,7 @@ public class ServerControlTab implements ActionListener {
|
|||||||
/**
|
/**
|
||||||
* Initializes GUI elements for the server control tab
|
* Initializes GUI elements for the server control tab
|
||||||
*
|
*
|
||||||
* @param mainFrame <p>The main frame of the GUI</p>
|
* @param mainFrame <p>The main frame of the GUI</p>
|
||||||
* @param controlServers <p>The JPanel to attach the server controls to</p>
|
* @param controlServers <p>The JPanel to attach the server controls to</p>
|
||||||
*/
|
*/
|
||||||
private void initialize(JFrame mainFrame, JPanel controlServers) {
|
private void initialize(JFrame mainFrame, JPanel controlServers) {
|
||||||
@ -134,13 +133,6 @@ public class ServerControlTab implements ActionListener {
|
|||||||
springLayout.putConstraint(SpringLayout.EAST, reloadButton, 0, SpringLayout.EAST, opButton);
|
springLayout.putConstraint(SpringLayout.EAST, reloadButton, 0, SpringLayout.EAST, opButton);
|
||||||
controlServers.add(reloadButton);
|
controlServers.add(reloadButton);
|
||||||
reloadButton.addActionListener(this);
|
reloadButton.addActionListener(this);
|
||||||
|
|
||||||
showConsolesButton = new JButton("View server consoles");
|
|
||||||
springLayout.putConstraint(SpringLayout.NORTH, showConsolesButton, 0, SpringLayout.NORTH, saveServerButton);
|
|
||||||
springLayout.putConstraint(SpringLayout.WEST, showConsolesButton, 0, SpringLayout.WEST, lblTargetServer);
|
|
||||||
springLayout.putConstraint(SpringLayout.EAST, showConsolesButton, 0, SpringLayout.EAST, targetServerCombo);
|
|
||||||
controlServers.add(showConsolesButton);
|
|
||||||
showConsolesButton.addActionListener(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -149,7 +141,7 @@ public class ServerControlTab implements ActionListener {
|
|||||||
public void update() {
|
public void update() {
|
||||||
this.targetServerCombo.removeAllItems();
|
this.targetServerCombo.removeAllItems();
|
||||||
this.targetServerCombo.addItem("All");
|
this.targetServerCombo.addItem("All");
|
||||||
for (Collection collection : Controller.getInstance().getCurrentProfile().getCollections()) {
|
for (Collection collection : ServerLauncherController.getInstance().getCurrentProfile().getCollections()) {
|
||||||
this.targetServerCombo.addItem(collection.getName());
|
this.targetServerCombo.addItem(collection.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -181,9 +173,7 @@ public class ServerControlTab implements ActionListener {
|
|||||||
//Registers actions on all commands executed on a specific server
|
//Registers actions on all commands executed on a specific server
|
||||||
handleServerCommands(actionSource, selectedServerValue);
|
handleServerCommands(actionSource, selectedServerValue);
|
||||||
|
|
||||||
if (actionSource == showConsolesButton) {
|
if (actionSource == targetServerCombo) {
|
||||||
ServerConsoles.setAsVisible();
|
|
||||||
} else if (actionSource == targetServerCombo) {
|
|
||||||
updatePlayers();
|
updatePlayers();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -232,7 +222,7 @@ public class ServerControlTab implements ActionListener {
|
|||||||
/**
|
/**
|
||||||
* Handles command buttons acting on a specific server
|
* Handles command buttons acting on a specific server
|
||||||
*
|
*
|
||||||
* @param actionSource <p>The object being interacted with</p>
|
* @param actionSource <p>The object being interacted with</p>
|
||||||
* @param selectedServerValue <p>The server currently selected</p>
|
* @param selectedServerValue <p>The server currently selected</p>
|
||||||
*/
|
*/
|
||||||
private void handleServerCommands(Object actionSource, String selectedServerValue) {
|
private void handleServerCommands(Object actionSource, String selectedServerValue) {
|
||||||
@ -252,7 +242,7 @@ public class ServerControlTab implements ActionListener {
|
|||||||
/**
|
/**
|
||||||
* Handles command buttons which act on a player
|
* Handles command buttons which act on a player
|
||||||
*
|
*
|
||||||
* @param actionSource <p>The clicked object</p>
|
* @param actionSource <p>The clicked object</p>
|
||||||
* @param selectedServerValue <p>The server currently selected</p>
|
* @param selectedServerValue <p>The server currently selected</p>
|
||||||
* @param selectedPlayerValue <p>The player currently selected</p>
|
* @param selectedPlayerValue <p>The player currently selected</p>
|
||||||
*/
|
*/
|
||||||
|
@ -2,25 +2,22 @@ package net.knarcraft.minecraftserverlauncher.userinterface;
|
|||||||
|
|
||||||
import net.knarcraft.minecraftserverlauncher.Main;
|
import net.knarcraft.minecraftserverlauncher.Main;
|
||||||
import net.knarcraft.minecraftserverlauncher.profile.Collection;
|
import net.knarcraft.minecraftserverlauncher.profile.Collection;
|
||||||
import net.knarcraft.minecraftserverlauncher.profile.Controller;
|
import net.knarcraft.minecraftserverlauncher.profile.ServerLauncherController;
|
||||||
import net.knarcraft.minecraftserverlauncher.server.Server;
|
|
||||||
import net.knarcraft.minecraftserverlauncher.utility.CommonFunctions;
|
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import javax.naming.ConfigurationException;
|
import javax.naming.ConfigurationException;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
import javax.swing.plaf.basic.BasicButtonUI;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.awt.event.MouseAdapter;
|
import java.io.File;
|
||||||
import java.awt.event.MouseEvent;
|
import java.io.FileNotFoundException;
|
||||||
import java.awt.event.WindowAdapter;
|
import java.io.IOException;
|
||||||
import java.awt.event.WindowEvent;
|
import java.util.HashMap;
|
||||||
import java.io.*;
|
import java.util.Map;
|
||||||
import java.util.*;
|
import java.util.Scanner;
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
|
|
||||||
import static java.awt.Frame.NORMAL;
|
|
||||||
import static javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE;
|
import static javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE;
|
||||||
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.getResourceAsScanner;
|
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.getResourceAsScanner;
|
||||||
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.getResourceAsStream;
|
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.getResourceAsStream;
|
||||||
@ -34,25 +31,19 @@ import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.getR
|
|||||||
*/
|
*/
|
||||||
public class ServerLauncherGUI extends MessageHandler implements ActionListener, GUI {
|
public class ServerLauncherGUI extends MessageHandler implements ActionListener, GUI {
|
||||||
|
|
||||||
private final JLabel lblStatuslabel = new JLabel("Servers are stopped");
|
private final ServerLauncherController controller;
|
||||||
private Controller controller;
|
|
||||||
private Map<String, String> textStrings;
|
private Map<String, String> textStrings;
|
||||||
private Tray applicationTray;
|
private Tray applicationTray;
|
||||||
|
|
||||||
private JFrame frame;
|
private JFrame frame;
|
||||||
private JTabbedPane tabbedPane;
|
private JTabbedPane mainTabbedPane;
|
||||||
private JTabbedPane serversPane;
|
private JTabbedPane serversPane;
|
||||||
private ServerControlTab serverControlTab;
|
private ServerControlTab serverControlTab;
|
||||||
|
private ControlPanelTab controlPanelTab;
|
||||||
private ServerLauncherMenu serverLauncherMenu;
|
private ServerLauncherMenu serverLauncherMenu;
|
||||||
|
|
||||||
//Basic controls
|
private JButton addServerTabButton;
|
||||||
private JButton startServerButton;
|
private JButton addServerPaneButton;
|
||||||
private JButton stopServerButton;
|
|
||||||
private JButton addServerButton;
|
|
||||||
private JButton backupButton;
|
|
||||||
private JButton addProfileButton;
|
|
||||||
private JButton deleteProfileButton;
|
|
||||||
private JComboBox<String> profiles;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the application window
|
* Creates the application window
|
||||||
@ -64,6 +55,20 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener,
|
|||||||
this.controller = Main.getController();
|
this.controller = Main.getController();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the application window
|
||||||
|
*
|
||||||
|
* @param silent <p>Whether to make the GUI silent (hidden, for testing)</p>
|
||||||
|
*/
|
||||||
|
public ServerLauncherGUI(boolean silent) throws IOException {
|
||||||
|
super(silent);
|
||||||
|
if (!silent) {
|
||||||
|
initialize(440, 170);
|
||||||
|
}
|
||||||
|
loadMessages();
|
||||||
|
this.controller = Main.getController();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the application window with a preferred width and height
|
* Creates the application window with a preferred width and height
|
||||||
*
|
*
|
||||||
@ -86,15 +91,19 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener,
|
|||||||
return this.serversPane;
|
return this.serversPane;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets this GUI's control panel tab
|
||||||
|
*
|
||||||
|
* @return <p>The control panel tab for this GUI</p>
|
||||||
|
*/
|
||||||
|
public ControlPanelTab getControlPanelTab() {
|
||||||
|
return this.controlPanelTab;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setStatus(String text) {
|
public void setStatus(String text) {
|
||||||
this.lblStatuslabel.setText(text);
|
controlPanelTab.setStatusText(text);
|
||||||
try (PrintWriter file = new PrintWriter(new FileWriter(Main.getApplicationWorkDirectory() +
|
this.logMessage(text);
|
||||||
File.separator + "latestrun.log", true))) {
|
|
||||||
file.println(text);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -112,18 +121,6 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener,
|
|||||||
return chooser.getSelectedFile();
|
return chooser.getSelectedFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the profiles combo
|
|
||||||
*/
|
|
||||||
public void updateProfiles() {
|
|
||||||
String selectedProfile = Main.getController().getCurrentProfile().getName();
|
|
||||||
this.profiles.removeAllItems();
|
|
||||||
for (String profile : Main.getController().getProfileNames()) {
|
|
||||||
this.profiles.addItem(profile);
|
|
||||||
}
|
|
||||||
this.profiles.setSelectedItem(selectedProfile);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the server control tab used by this GUI
|
* Gets the server control tab used by this GUI
|
||||||
*
|
*
|
||||||
@ -146,19 +143,94 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener,
|
|||||||
* Updates ServerLauncherGUI according to current profile settings
|
* Updates ServerLauncherGUI according to current profile settings
|
||||||
*/
|
*/
|
||||||
public void updateWithSavedProfileData() {
|
public void updateWithSavedProfileData() {
|
||||||
Controller controller = Main.getController();
|
ServerLauncherController controller = Main.getController();
|
||||||
serversPane.removeAll();
|
serversPane.removeAll();
|
||||||
serverLauncherMenu.update();
|
serverLauncherMenu.update();
|
||||||
serverControlTab.update();
|
serverControlTab.update();
|
||||||
for (Collection collection : controller.getCurrentProfile().getCollections()) {
|
for (Collection collection : controller.getCurrentProfile().getCollections()) {
|
||||||
serversPane.addTab(collection.getName(), collection.getServerTab().getPanel());
|
serversPane.addTab(collection.getName(), collection.getServerTab().getPanel());
|
||||||
|
addCloseButtonToServerTab(collection.getName());
|
||||||
}
|
}
|
||||||
|
addAddButtonToServerTab();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an add button to the servers tab's tabs
|
||||||
|
*/
|
||||||
|
private void addAddButtonToServerTab() {
|
||||||
|
JPanel tabPanel = new JPanel();
|
||||||
|
tabPanel.setLayout(new GridLayout());
|
||||||
|
tabPanel.setOpaque(false);
|
||||||
|
|
||||||
|
JPanel tabContentsPanel = new JPanel(new SpringLayout());
|
||||||
|
serversPane.addTab("Add tab", tabContentsPanel);
|
||||||
|
|
||||||
|
addServerTabButton = getAddServerButton(true);
|
||||||
|
addServerTabButton.addActionListener(this);
|
||||||
|
addServerPaneButton = getAddServerButton(false);
|
||||||
|
addServerPaneButton.addActionListener(this);
|
||||||
|
|
||||||
|
tabContentsPanel.add(addServerTabButton);
|
||||||
|
tabPanel.add(addServerPaneButton);
|
||||||
|
serversPane.setTabComponentAt(serversPane.getTabCount() - 1, tabPanel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a button for adding a new server
|
||||||
|
*
|
||||||
|
* @param displayButtonStyle <p>Whether to show or hide the button's style</p>
|
||||||
|
* @return <p>A new add server button</p>
|
||||||
|
*/
|
||||||
|
private JButton getAddServerButton(boolean displayButtonStyle) {
|
||||||
|
JButton addButton = new JButton("+ Add server");
|
||||||
|
if (!displayButtonStyle) {
|
||||||
|
addButton.setBorder(BorderFactory.createEtchedBorder());
|
||||||
|
addButton.setFocusable(false);
|
||||||
|
addButton.setBorderPainted(false);
|
||||||
|
addButton.setContentAreaFilled(false);
|
||||||
|
addButton.setRolloverEnabled(true);
|
||||||
|
addButton.setUI(new BasicButtonUI());
|
||||||
|
}
|
||||||
|
return addButton;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param serverName <p>The name of the server/tab to add a close button to</p>
|
||||||
|
*/
|
||||||
|
private void addCloseButtonToServerTab(String serverName) {
|
||||||
|
int index = serversPane.indexOfTab(serverName);
|
||||||
|
JPanel tabPanel = new JPanel(new GridBagLayout());
|
||||||
|
tabPanel.setOpaque(false);
|
||||||
|
JLabel serverTitleLabel = new JLabel(serverName);
|
||||||
|
JButton removeServerButton = new JButton("(X)");
|
||||||
|
removeServerButton.setBorder(BorderFactory.createEtchedBorder());
|
||||||
|
removeServerButton.setFocusable(false);
|
||||||
|
removeServerButton.setBorderPainted(false);
|
||||||
|
removeServerButton.setContentAreaFilled(false);
|
||||||
|
removeServerButton.setRolloverEnabled(true);
|
||||||
|
removeServerButton.setPreferredSize(new Dimension(18, 17));
|
||||||
|
removeServerButton.setUI(new BasicButtonUI());
|
||||||
|
|
||||||
|
GridBagConstraints gridBagConstraints = new GridBagConstraints();
|
||||||
|
gridBagConstraints.gridx = 0;
|
||||||
|
gridBagConstraints.gridy = 0;
|
||||||
|
gridBagConstraints.weightx = 1;
|
||||||
|
|
||||||
|
tabPanel.add(serverTitleLabel, gridBagConstraints);
|
||||||
|
|
||||||
|
gridBagConstraints.gridx++;
|
||||||
|
gridBagConstraints.weightx = 0;
|
||||||
|
tabPanel.add(removeServerButton, gridBagConstraints);
|
||||||
|
|
||||||
|
serversPane.setTabComponentAt(index, tabPanel);
|
||||||
|
|
||||||
|
removeServerButton.addActionListener(new CloseTabActionListener(serversPane, serverName));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the server launcher GUI
|
* Initializes the server launcher GUI
|
||||||
*
|
*
|
||||||
* @param width <p>The width of the GUI</p>
|
* @param width <p>The width of the GUI</p>
|
||||||
* @param height <p>The height of the GUI</p>
|
* @param height <p>The height of the GUI</p>
|
||||||
* @throws IOException <p>If unable to load the GUI icon</p>
|
* @throws IOException <p>If unable to load the GUI icon</p>
|
||||||
*/
|
*/
|
||||||
@ -169,7 +241,7 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener,
|
|||||||
UnsupportedLookAndFeelException |
|
UnsupportedLookAndFeelException |
|
||||||
InstantiationException |
|
InstantiationException |
|
||||||
IllegalAccessException e
|
IllegalAccessException e
|
||||||
) {
|
) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,93 +258,30 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener,
|
|||||||
|
|
||||||
this.serverLauncherMenu = new ServerLauncherMenu(menuBar, this);
|
this.serverLauncherMenu = new ServerLauncherMenu(menuBar, this);
|
||||||
|
|
||||||
tabbedPane = new JTabbedPane(JTabbedPane.TOP);
|
mainTabbedPane = new JTabbedPane(JTabbedPane.TOP);
|
||||||
frame.getContentPane().add(tabbedPane);
|
frame.getContentPane().add(mainTabbedPane);
|
||||||
|
|
||||||
JPanel panelBasic = new JPanel();
|
JPanel controlPanelPanel = new JPanel();
|
||||||
tabbedPane.addTab("Control panel", null, panelBasic, null);
|
mainTabbedPane.addTab("Control panel", null, controlPanelPanel, null);
|
||||||
SpringLayout sl_panel = new SpringLayout();
|
controlPanelTab = new ControlPanelTab(controlPanelPanel);
|
||||||
panelBasic.setLayout(sl_panel);
|
|
||||||
|
|
||||||
JLabel lblBasicControls = new JLabel("Basic controls");
|
JPanel controlServersPanel = new JPanel();
|
||||||
sl_panel.putConstraint(SpringLayout.NORTH, lblBasicControls, 10, SpringLayout.NORTH, panelBasic);
|
mainTabbedPane.addTab("Control servers", null, controlServersPanel, null);
|
||||||
panelBasic.add(lblBasicControls);
|
serverControlTab = new ServerControlTab(frame, controlServersPanel);
|
||||||
|
|
||||||
startServerButton = new JButton("Start servers");
|
JPanel serversPanel = new JPanel();
|
||||||
sl_panel.putConstraint(SpringLayout.WEST, lblBasicControls, 0, SpringLayout.WEST, startServerButton);
|
mainTabbedPane.addTab("Servers", null, serversPanel, null);
|
||||||
sl_panel.putConstraint(SpringLayout.NORTH, startServerButton, 6, SpringLayout.SOUTH, lblBasicControls);
|
SpringLayout serversPanelSpringLayout = new SpringLayout();
|
||||||
sl_panel.putConstraint(SpringLayout.WEST, startServerButton, 10, SpringLayout.WEST, panelBasic);
|
serversPanel.setLayout(serversPanelSpringLayout);
|
||||||
panelBasic.add(startServerButton);
|
|
||||||
startServerButton.addActionListener(this);
|
|
||||||
|
|
||||||
stopServerButton = new JButton("Stop servers");
|
serversPane = new JTabbedPane(JTabbedPane.TOP);
|
||||||
sl_panel.putConstraint(SpringLayout.NORTH, stopServerButton, 0, SpringLayout.NORTH, startServerButton);
|
serversPanelSpringLayout.putConstraint(SpringLayout.NORTH, serversPane, 0, SpringLayout.NORTH, serversPanel);
|
||||||
sl_panel.putConstraint(SpringLayout.WEST, stopServerButton, 6, SpringLayout.EAST, startServerButton);
|
serversPanelSpringLayout.putConstraint(SpringLayout.WEST, serversPane, 0, SpringLayout.WEST, serversPanel);
|
||||||
panelBasic.add(stopServerButton);
|
serversPanelSpringLayout.putConstraint(SpringLayout.SOUTH, serversPane, 0, SpringLayout.SOUTH, serversPanel);
|
||||||
stopServerButton.addActionListener(this);
|
serversPanelSpringLayout.putConstraint(SpringLayout.EAST, serversPane, 0, SpringLayout.EAST, serversPanel);
|
||||||
|
serversPanel.add(serversPane);
|
||||||
|
|
||||||
JLabel lblProfile = new JLabel("Profile");
|
serversPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
|
||||||
sl_panel.putConstraint(SpringLayout.NORTH, lblProfile, 6, SpringLayout.SOUTH, startServerButton);
|
|
||||||
sl_panel.putConstraint(SpringLayout.WEST, lblProfile, 10, SpringLayout.WEST, panelBasic);
|
|
||||||
panelBasic.add(lblProfile);
|
|
||||||
|
|
||||||
addProfileButton = new JButton("+");
|
|
||||||
sl_panel.putConstraint(SpringLayout.NORTH, addProfileButton, 6, SpringLayout.SOUTH, lblProfile);
|
|
||||||
sl_panel.putConstraint(SpringLayout.WEST, addProfileButton, 10, SpringLayout.WEST, panelBasic);
|
|
||||||
panelBasic.add(addProfileButton);
|
|
||||||
addProfileButton.addActionListener(this);
|
|
||||||
|
|
||||||
deleteProfileButton = new JButton("-");
|
|
||||||
sl_panel.putConstraint(SpringLayout.NORTH, deleteProfileButton, 0, SpringLayout.NORTH, addProfileButton);
|
|
||||||
sl_panel.putConstraint(SpringLayout.WEST, deleteProfileButton, 6, SpringLayout.EAST, addProfileButton);
|
|
||||||
panelBasic.add(deleteProfileButton);
|
|
||||||
deleteProfileButton.addActionListener(this);
|
|
||||||
|
|
||||||
profiles = new JComboBox<>();
|
|
||||||
sl_panel.putConstraint(SpringLayout.NORTH, profiles, 0, SpringLayout.NORTH, addProfileButton);
|
|
||||||
sl_panel.putConstraint(SpringLayout.WEST, profiles, 6, SpringLayout.EAST, deleteProfileButton);
|
|
||||||
sl_panel.putConstraint(SpringLayout.EAST, profiles, 124, SpringLayout.EAST, deleteProfileButton);
|
|
||||||
panelBasic.add(profiles);
|
|
||||||
profiles.addActionListener(this);
|
|
||||||
|
|
||||||
sl_panel.putConstraint(SpringLayout.NORTH, lblStatuslabel, 6, SpringLayout.SOUTH, addProfileButton);
|
|
||||||
sl_panel.putConstraint(SpringLayout.SOUTH, lblStatuslabel, -10, SpringLayout.SOUTH, panelBasic);
|
|
||||||
sl_panel.putConstraint(SpringLayout.WEST, lblStatuslabel, 10, SpringLayout.WEST, panelBasic);
|
|
||||||
sl_panel.putConstraint(SpringLayout.EAST, lblStatuslabel, -10, SpringLayout.EAST, panelBasic);
|
|
||||||
panelBasic.add(lblStatuslabel);
|
|
||||||
|
|
||||||
addServerButton = new JButton("Add server");
|
|
||||||
sl_panel.putConstraint(SpringLayout.NORTH, addServerButton, 0, SpringLayout.NORTH, startServerButton);
|
|
||||||
sl_panel.putConstraint(SpringLayout.WEST, addServerButton, 6, SpringLayout.EAST, stopServerButton);
|
|
||||||
panelBasic.add(addServerButton);
|
|
||||||
addServerButton.addActionListener(this);
|
|
||||||
|
|
||||||
backupButton = new JButton("Backup");
|
|
||||||
sl_panel.putConstraint(SpringLayout.NORTH, backupButton, 0, SpringLayout.NORTH, startServerButton);
|
|
||||||
sl_panel.putConstraint(SpringLayout.WEST, backupButton, 6, SpringLayout.EAST, addServerButton);
|
|
||||||
panelBasic.add(backupButton);
|
|
||||||
backupButton.addActionListener(this);
|
|
||||||
|
|
||||||
JPanel controlServers = new JPanel();
|
|
||||||
tabbedPane.addTab("Control servers", null, controlServers, null);
|
|
||||||
|
|
||||||
serverControlTab = new ServerControlTab(frame, controlServers);
|
|
||||||
|
|
||||||
|
|
||||||
JPanel panel_2 = new JPanel();
|
|
||||||
tabbedPane.addTab("Servers", null, panel_2, null);
|
|
||||||
SpringLayout sl_panel_2 = new SpringLayout();
|
|
||||||
panel_2.setLayout(sl_panel_2);
|
|
||||||
|
|
||||||
JTabbedPane tabbedPane_1 = new JTabbedPane(JTabbedPane.TOP);
|
|
||||||
sl_panel_2.putConstraint(SpringLayout.NORTH, tabbedPane_1, 0, SpringLayout.NORTH, panel_2);
|
|
||||||
sl_panel_2.putConstraint(SpringLayout.WEST, tabbedPane_1, 0, SpringLayout.WEST, panel_2);
|
|
||||||
sl_panel_2.putConstraint(SpringLayout.SOUTH, tabbedPane_1, 0, SpringLayout.SOUTH, panel_2);
|
|
||||||
sl_panel_2.putConstraint(SpringLayout.EAST, tabbedPane_1, 0, SpringLayout.EAST, panel_2);
|
|
||||||
panel_2.add(tabbedPane_1);
|
|
||||||
|
|
||||||
this.serversPane = tabbedPane_1;
|
|
||||||
tabbedPane_1.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
|
|
||||||
|
|
||||||
frame.validate();
|
frame.validate();
|
||||||
frame.pack();
|
frame.pack();
|
||||||
@ -288,63 +297,22 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener,
|
|||||||
applicationTray.hideToTray();
|
applicationTray.hideToTray();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the currently selected profile
|
|
||||||
*
|
|
||||||
* @return <p>The currently selected profile or null</p>
|
|
||||||
*/
|
|
||||||
public String getSelectedProfile() {
|
|
||||||
Object selectedProfile = profiles.getSelectedItem();
|
|
||||||
if (selectedProfile != null) {
|
|
||||||
return selectedProfile.toString();
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
Object actionSource = e.getSource();
|
Object actionSource = e.getSource();
|
||||||
//Registers actions on the main tab
|
//Register actions on the main tab
|
||||||
handleMainTabButtons(actionSource);
|
handleMainTabButtons(actionSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles buttons and the combo on the main tab
|
* Handles buttons and the combo on the main tab
|
||||||
*
|
*
|
||||||
* @param actionSource <p>The object being interacted with</p>
|
* @param actionSource <p>The object being interacted with</p>
|
||||||
*/
|
*/
|
||||||
private void handleMainTabButtons(Object actionSource) {
|
private void handleMainTabButtons(Object actionSource) {
|
||||||
if (actionSource == startServerButton) {
|
if (actionSource == addServerTabButton || actionSource == addServerPaneButton) {
|
||||||
controller.saveState();
|
|
||||||
Executors.newSingleThreadExecutor().execute(Server::startServers);
|
|
||||||
} else if (actionSource == stopServerButton) {
|
|
||||||
stopServers();
|
|
||||||
} else if (actionSource == addServerButton) {
|
|
||||||
addServer();
|
addServer();
|
||||||
} else if (actionSource == backupButton) {
|
|
||||||
CommonFunctions.backup(this);
|
|
||||||
} else if (actionSource == addProfileButton) {
|
|
||||||
controller.addProfile(JOptionPane.showInputDialog("Profile name: "));
|
|
||||||
updateProfiles();
|
|
||||||
} else if (actionSource == deleteProfileButton) {
|
|
||||||
deleteProfile();
|
|
||||||
} else if (actionSource == profiles) {
|
|
||||||
changeProfile();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes the selected profile
|
|
||||||
*/
|
|
||||||
private void deleteProfile() {
|
|
||||||
Object selected = profiles.getSelectedItem();
|
|
||||||
if (selected != null) {
|
|
||||||
controller.removeProfile(selected.toString());
|
|
||||||
updateProfiles();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -369,39 +337,9 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener,
|
|||||||
*/
|
*/
|
||||||
public void updateGUIElementsWhenServersStartOrStop(boolean running) {
|
public void updateGUIElementsWhenServersStartOrStop(boolean running) {
|
||||||
boolean stopped = !running; //Most gui is only enabled when the server is stopped rather than running.
|
boolean stopped = !running; //Most gui is only enabled when the server is stopped rather than running.
|
||||||
profiles.setEnabled(stopped);
|
mainTabbedPane.setEnabledAt(1, !stopped);
|
||||||
addProfileButton.setEnabled(stopped);
|
mainTabbedPane.setEnabledAt(2, stopped);
|
||||||
deleteProfileButton.setEnabled(stopped);
|
controlPanelTab.updateGUIElementsWhenServersStartOrStop(running);
|
||||||
startServerButton.setEnabled(stopped);
|
|
||||||
addServerButton.setEnabled(stopped);
|
|
||||||
tabbedPane.setEnabledAt(2, stopped);
|
|
||||||
stopServerButton.setEnabled(running);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Saves the previous profile and loads data from the new profile
|
|
||||||
*/
|
|
||||||
private void changeProfile() {
|
|
||||||
controller.saveState();
|
|
||||||
Object current = this.profiles.getSelectedItem();
|
|
||||||
if (current != null) {
|
|
||||||
controller.setCurrentProfile(current.toString());
|
|
||||||
}
|
|
||||||
this.updateWithSavedProfileData();
|
|
||||||
controller.getCurrentProfile().updateConsoles();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stops all servers
|
|
||||||
*/
|
|
||||||
public void stopServers() {
|
|
||||||
try {
|
|
||||||
setStatus("Servers are stopping...");
|
|
||||||
Server.stop();
|
|
||||||
} catch (IOException e1) {
|
|
||||||
showError("Could not stop server.");
|
|
||||||
e1.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
package net.knarcraft.minecraftserverlauncher.userinterface;
|
package net.knarcraft.minecraftserverlauncher.userinterface;
|
||||||
|
|
||||||
import net.knarcraft.minecraftserverlauncher.profile.Controller;
|
|
||||||
import net.knarcraft.minecraftserverlauncher.profile.Profile;
|
import net.knarcraft.minecraftserverlauncher.profile.Profile;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.profile.ServerLauncherController;
|
||||||
import net.knarcraft.minecraftserverlauncher.utility.CommonFunctions;
|
import net.knarcraft.minecraftserverlauncher.utility.CommonFunctions;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
|
import java.io.File;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -14,11 +15,14 @@ import java.util.Objects;
|
|||||||
*/
|
*/
|
||||||
public class ServerLauncherMenu implements ActionListener {
|
public class ServerLauncherMenu implements ActionListener {
|
||||||
|
|
||||||
private JMenuBar menuBar;
|
private final JMenuBar menuBar;
|
||||||
//Options
|
//Options
|
||||||
private JCheckBoxMenuItem runInBackgroundCheckBoxMenuItem;
|
private JCheckBoxMenuItem runInBackgroundCheckBoxMenuItem;
|
||||||
private JCheckBoxMenuItem delayStartupCheckBoxMenuItem;
|
private JCheckBoxMenuItem delayStartupCheckBoxMenuItem;
|
||||||
private JCheckBoxMenuItem downloadJarsCheckBoxMenuItem;
|
private JCheckBoxMenuItem downloadJarsCheckBoxMenuItem;
|
||||||
|
private JMenuItem javaCommandMenuItem;
|
||||||
|
private JMenuItem oldJavaCommandMenuItem;
|
||||||
|
private JMenuItem deleteBuiltJarsMenuItem;
|
||||||
//Help
|
//Help
|
||||||
private JMenuItem errorsMenuItem;
|
private JMenuItem errorsMenuItem;
|
||||||
private JMenuItem setupMenuItem;
|
private JMenuItem setupMenuItem;
|
||||||
@ -27,21 +31,24 @@ public class ServerLauncherMenu implements ActionListener {
|
|||||||
private JMenuItem runInBackgroundMenuItem;
|
private JMenuItem runInBackgroundMenuItem;
|
||||||
private JMenuItem delayStartupMenuItem;
|
private JMenuItem delayStartupMenuItem;
|
||||||
private JMenuItem downloadJarsMenuItem;
|
private JMenuItem downloadJarsMenuItem;
|
||||||
|
private JMenuItem javaCommandInfoMenuItem;
|
||||||
|
private JMenuItem oldJavaCommandInfoMenuItem;
|
||||||
|
private JMenuItem deleteBuiltJarsInfoMenuItem;
|
||||||
//Info/about
|
//Info/about
|
||||||
private JMenuItem aboutMenuItem;
|
private JMenuItem aboutMenuItem;
|
||||||
private JMenuItem storyMenuItem;
|
private JMenuItem storyMenuItem;
|
||||||
|
|
||||||
private Controller controller;
|
private final ServerLauncherController controller;
|
||||||
private ServerLauncherGUI serverLauncherGUI;
|
private final ServerLauncherGUI serverLauncherGUI;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes a new server launcher menu
|
* Initializes a new server launcher menu
|
||||||
*
|
*
|
||||||
* @param menuBar <p>The menu bar to attach items to</p>
|
* @param menuBar <p>The menu bar to attach items to</p>
|
||||||
* @param serverLauncherGUI <p>The server launcher GUI to use</p>
|
* @param serverLauncherGUI <p>The server launcher GUI to use</p>
|
||||||
*/
|
*/
|
||||||
public ServerLauncherMenu(JMenuBar menuBar, ServerLauncherGUI serverLauncherGUI) {
|
public ServerLauncherMenu(JMenuBar menuBar, ServerLauncherGUI serverLauncherGUI) {
|
||||||
this.controller = Controller.getInstance();
|
this.controller = ServerLauncherController.getInstance();
|
||||||
this.menuBar = menuBar;
|
this.menuBar = menuBar;
|
||||||
this.serverLauncherGUI = serverLauncherGUI;
|
this.serverLauncherGUI = serverLauncherGUI;
|
||||||
initialize();
|
initialize();
|
||||||
@ -53,64 +60,23 @@ public class ServerLauncherMenu implements ActionListener {
|
|||||||
public void initialize() {
|
public void initialize() {
|
||||||
JMenu mnOptions = new JMenu("Options");
|
JMenu mnOptions = new JMenu("Options");
|
||||||
menuBar.add(mnOptions);
|
menuBar.add(mnOptions);
|
||||||
|
generateOptionsMenuItems(mnOptions);
|
||||||
runInBackgroundCheckBoxMenuItem = new JCheckBoxMenuItem("Run in background on exit");
|
|
||||||
mnOptions.add(runInBackgroundCheckBoxMenuItem);
|
|
||||||
runInBackgroundCheckBoxMenuItem.addActionListener(this);
|
|
||||||
|
|
||||||
delayStartupCheckBoxMenuItem = new JCheckBoxMenuItem("Delay Startup");
|
|
||||||
mnOptions.add(delayStartupCheckBoxMenuItem);
|
|
||||||
delayStartupCheckBoxMenuItem.addActionListener(this);
|
|
||||||
|
|
||||||
downloadJarsCheckBoxMenuItem = new JCheckBoxMenuItem("Download jars");
|
|
||||||
mnOptions.add(downloadJarsCheckBoxMenuItem);
|
|
||||||
downloadJarsCheckBoxMenuItem.addActionListener(this);
|
|
||||||
|
|
||||||
JMenu mnHelp = new JMenu("Help");
|
JMenu mnHelp = new JMenu("Help");
|
||||||
menuBar.add(mnHelp);
|
menuBar.add(mnHelp);
|
||||||
|
|
||||||
errorsMenuItem = new JMenuItem("Errors");
|
errorsMenuItem = createMenuItem("Errors", mnHelp);
|
||||||
mnHelp.add(errorsMenuItem);
|
setupMenuItem = createMenuItem("Setup", mnHelp);
|
||||||
errorsMenuItem.addActionListener(this);
|
manualUpdateMenuItem = createMenuItem("Manual update", mnHelp);
|
||||||
|
|
||||||
setupMenuItem = new JMenuItem("Setup");
|
|
||||||
mnHelp.add(setupMenuItem);
|
|
||||||
setupMenuItem.addActionListener(this);
|
|
||||||
|
|
||||||
manualUpdateMenuItem = new JMenuItem("Manual update");
|
|
||||||
mnHelp.add(manualUpdateMenuItem);
|
|
||||||
manualUpdateMenuItem.addActionListener(this);
|
|
||||||
|
|
||||||
JMenu mnInfo = new JMenu("Info");
|
JMenu mnInfo = new JMenu("Info");
|
||||||
menuBar.add(mnInfo);
|
menuBar.add(mnInfo);
|
||||||
|
generateInfoMenuItems(mnInfo);
|
||||||
JMenu mnOptionsInfo = new JMenu("Options");
|
|
||||||
mnInfo.add(mnOptionsInfo);
|
|
||||||
|
|
||||||
runInBackgroundMenuItem = new JMenuItem("Run in background on exit");
|
|
||||||
mnOptionsInfo.add(runInBackgroundMenuItem);
|
|
||||||
runInBackgroundMenuItem.addActionListener(this);
|
|
||||||
|
|
||||||
delayStartupMenuItem = new JMenuItem("Delay Startup");
|
|
||||||
mnOptionsInfo.add(delayStartupMenuItem);
|
|
||||||
delayStartupMenuItem.addActionListener(this);
|
|
||||||
|
|
||||||
downloadJarsMenuItem = new JMenuItem("Download jars");
|
|
||||||
mnOptionsInfo.add(downloadJarsMenuItem);
|
|
||||||
downloadJarsMenuItem.addActionListener(this);
|
|
||||||
|
|
||||||
JMenu mnAbout = new JMenu("About");
|
|
||||||
mnInfo.add(mnAbout);
|
|
||||||
|
|
||||||
aboutMenuItem = new JMenuItem("About");
|
|
||||||
mnAbout.add(aboutMenuItem);
|
|
||||||
aboutMenuItem.addActionListener(this);
|
|
||||||
|
|
||||||
storyMenuItem = new JMenuItem("Story");
|
|
||||||
mnAbout.add(storyMenuItem);
|
|
||||||
storyMenuItem.addActionListener(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the state of checkboxes based on whether options are enabled
|
||||||
|
*/
|
||||||
public void update() {
|
public void update() {
|
||||||
runInBackgroundCheckBoxMenuItem.setState(controller.getRunInBackground());
|
runInBackgroundCheckBoxMenuItem.setState(controller.getRunInBackground());
|
||||||
delayStartupCheckBoxMenuItem.setState(controller.getDelayStartup() > 0);
|
delayStartupCheckBoxMenuItem.setState(controller.getDelayStartup() > 0);
|
||||||
@ -126,6 +92,12 @@ public class ServerLauncherMenu implements ActionListener {
|
|||||||
delay();
|
delay();
|
||||||
} else if (actionSource == downloadJarsCheckBoxMenuItem) {
|
} else if (actionSource == downloadJarsCheckBoxMenuItem) {
|
||||||
downloadJars();
|
downloadJars();
|
||||||
|
} else if (actionSource == javaCommandMenuItem) {
|
||||||
|
configureJava(false);
|
||||||
|
} else if (actionSource == oldJavaCommandMenuItem) {
|
||||||
|
configureJava(true);
|
||||||
|
} else if (actionSource == deleteBuiltJarsMenuItem) {
|
||||||
|
deleteBuiltJars();
|
||||||
} else if (actionSource == errorsMenuItem) {
|
} else if (actionSource == errorsMenuItem) {
|
||||||
CommonFunctions.goToURL(serverLauncherGUI.getMessage("infoURL"));
|
CommonFunctions.goToURL(serverLauncherGUI.getMessage("infoURL"));
|
||||||
} else if (actionSource == setupMenuItem) {
|
} else if (actionSource == setupMenuItem) {
|
||||||
@ -138,6 +110,12 @@ public class ServerLauncherMenu implements ActionListener {
|
|||||||
serverLauncherGUI.showMessage("Delay startup", serverLauncherGUI.getMessage("delayStartupText"));
|
serverLauncherGUI.showMessage("Delay startup", serverLauncherGUI.getMessage("delayStartupText"));
|
||||||
} else if (actionSource == downloadJarsMenuItem) {
|
} else if (actionSource == downloadJarsMenuItem) {
|
||||||
serverLauncherGUI.showMessage("Download jars", serverLauncherGUI.getMessage("downloadJarsText"));
|
serverLauncherGUI.showMessage("Download jars", serverLauncherGUI.getMessage("downloadJarsText"));
|
||||||
|
} else if (actionSource == javaCommandInfoMenuItem) {
|
||||||
|
serverLauncherGUI.showMessage("Java command", serverLauncherGUI.getMessage("javaCommandText"));
|
||||||
|
} else if (actionSource == oldJavaCommandInfoMenuItem) {
|
||||||
|
serverLauncherGUI.showMessage("Old Java command", serverLauncherGUI.getMessage("oldJavaCommandText"));
|
||||||
|
} else if (actionSource == deleteBuiltJarsInfoMenuItem) {
|
||||||
|
serverLauncherGUI.showMessage("Delete built jar files", serverLauncherGUI.getMessage("deleteBuiltJarFilesText"));
|
||||||
} else if (actionSource == aboutMenuItem) {
|
} else if (actionSource == aboutMenuItem) {
|
||||||
serverLauncherGUI.showMessage("About", serverLauncherGUI.getMessage("aboutText"));
|
serverLauncherGUI.showMessage("About", serverLauncherGUI.getMessage("aboutText"));
|
||||||
} else if (actionSource == storyMenuItem) {
|
} else if (actionSource == storyMenuItem) {
|
||||||
@ -145,11 +123,122 @@ public class ServerLauncherMenu implements ActionListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the children of the options menu
|
||||||
|
*
|
||||||
|
* @param mnOptions <p>A reference to the options menu</p>
|
||||||
|
*/
|
||||||
|
private void generateOptionsMenuItems(JMenu mnOptions) {
|
||||||
|
runInBackgroundCheckBoxMenuItem = createCheckBoxMenuItem("Run in background on exit", mnOptions);
|
||||||
|
delayStartupCheckBoxMenuItem = createCheckBoxMenuItem("Delay Startup", mnOptions);
|
||||||
|
downloadJarsCheckBoxMenuItem = createCheckBoxMenuItem("Download jars", mnOptions);
|
||||||
|
javaCommandMenuItem = createMenuItem("Java command", mnOptions);
|
||||||
|
oldJavaCommandMenuItem = createMenuItem("Old Java command", mnOptions);
|
||||||
|
deleteBuiltJarsMenuItem = createMenuItem("Delete built jar files", mnOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the children of the info menu
|
||||||
|
*
|
||||||
|
* @param mnInfo <p>A reference to the info menu</p>
|
||||||
|
*/
|
||||||
|
private void generateInfoMenuItems(JMenu mnInfo) {
|
||||||
|
JMenu mnOptionsInfo = new JMenu("Options");
|
||||||
|
mnInfo.add(mnOptionsInfo);
|
||||||
|
|
||||||
|
runInBackgroundMenuItem = createMenuItem("Run in background on exit", mnOptionsInfo);
|
||||||
|
delayStartupMenuItem = createMenuItem("Delay Startup", mnOptionsInfo);
|
||||||
|
downloadJarsMenuItem = createMenuItem("Download jars", mnOptionsInfo);
|
||||||
|
javaCommandInfoMenuItem = createMenuItem("Java command", mnOptionsInfo);
|
||||||
|
oldJavaCommandInfoMenuItem = createMenuItem("Old Java command", mnOptionsInfo);
|
||||||
|
deleteBuiltJarsInfoMenuItem = createMenuItem("Delete built jar files", mnOptionsInfo);
|
||||||
|
|
||||||
|
JMenu mnAbout = new JMenu("About");
|
||||||
|
mnInfo.add(mnAbout);
|
||||||
|
|
||||||
|
aboutMenuItem = createMenuItem("About", mnAbout);
|
||||||
|
storyMenuItem = createMenuItem("Story", mnAbout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a checkbox menu item
|
||||||
|
*
|
||||||
|
* @param itemName <p>The name of the new checkbox item</p>
|
||||||
|
* @param parent <p>The parent menu the item belongs to</p>
|
||||||
|
* @return <p>The created checkbox menu item</p>
|
||||||
|
*/
|
||||||
|
private JCheckBoxMenuItem createCheckBoxMenuItem(String itemName, JMenu parent) {
|
||||||
|
JCheckBoxMenuItem menuItem = new JCheckBoxMenuItem(itemName);
|
||||||
|
parent.add(menuItem);
|
||||||
|
menuItem.addActionListener(this);
|
||||||
|
return menuItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a menu item
|
||||||
|
*
|
||||||
|
* @param itemName <p>The name of the new item</p>
|
||||||
|
* @param parent <p>The parent menu the item belongs to</p>
|
||||||
|
* @return <p>The created menu item</p>
|
||||||
|
*/
|
||||||
|
private JMenuItem createMenuItem(String itemName, JMenu parent) {
|
||||||
|
JMenuItem menuItem = new JMenuItem(itemName);
|
||||||
|
parent.add(menuItem);
|
||||||
|
menuItem.addActionListener(this);
|
||||||
|
return menuItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asks the user for the new Java path
|
||||||
|
*
|
||||||
|
* @param old <p>Whether asking for the path to the old java version</p>
|
||||||
|
*/
|
||||||
|
private void configureJava(boolean old) {
|
||||||
|
if (old) {
|
||||||
|
String response = JOptionPane.showInputDialog("Command or path to Java: ", controller.getOldJavaCommand());
|
||||||
|
if (response != null) {
|
||||||
|
controller.setOldJavaCommand(response);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
String response = JOptionPane.showInputDialog("Command or path to Java: ", controller.getJavaCommand());
|
||||||
|
if (response != null) {
|
||||||
|
controller.setJavaCommand(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes build Spigot and Bukkit .jar files if the user accepts
|
||||||
|
*/
|
||||||
|
private void deleteBuiltJars() {
|
||||||
|
int answer = JOptionPane.showConfirmDialog(null, "This will delete built .jar files, causing them " +
|
||||||
|
"to be rebuilt on the next run. Do you want to continue?", "Delete built .jar files",
|
||||||
|
JOptionPane.YES_NO_OPTION
|
||||||
|
);
|
||||||
|
if (answer == JOptionPane.YES_NO_OPTION) {
|
||||||
|
String jarDirectory = controller.getJarDirectory();
|
||||||
|
File spigotFile = new File(jarDirectory + "SpigotLatest.jar");
|
||||||
|
File bukkitFile = new File(jarDirectory + "BukkitLatest.jar");
|
||||||
|
boolean success = true;
|
||||||
|
if (spigotFile.exists() && !spigotFile.delete()) {
|
||||||
|
serverLauncherGUI.showError("Unable to delete latest spigot .jar");
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
if (bukkitFile.exists() && !bukkitFile.delete()) {
|
||||||
|
serverLauncherGUI.showError("Unable to delete latest bukkit .jar");
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
if (success) {
|
||||||
|
serverLauncherGUI.showMessage("Deletion successful", "Deleted built .jar files");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asks the user for a delay if checked, and sets the value to the current profile
|
* Asks the user for a delay if checked, and sets the value to the current profile
|
||||||
*/
|
*/
|
||||||
private void delay() {
|
private void delay() {
|
||||||
String selectedProfile = serverLauncherGUI.getSelectedProfile();
|
String selectedProfile = serverLauncherGUI.getControlPanelTab().getSelectedProfile();
|
||||||
if (selectedProfile != null) {
|
if (selectedProfile != null) {
|
||||||
Profile profile = controller.getProfileByName(selectedProfile);
|
Profile profile = controller.getProfileByName(selectedProfile);
|
||||||
if (delayStartupCheckBoxMenuItem.isSelected()) {
|
if (delayStartupCheckBoxMenuItem.isSelected()) {
|
||||||
@ -172,7 +261,7 @@ public class ServerLauncherMenu implements ActionListener {
|
|||||||
* Saves the runInBackground setting to the current profile
|
* Saves the runInBackground setting to the current profile
|
||||||
*/
|
*/
|
||||||
private void background() {
|
private void background() {
|
||||||
String selectedProfile = serverLauncherGUI.getSelectedProfile();
|
String selectedProfile = serverLauncherGUI.getControlPanelTab().getSelectedProfile();
|
||||||
if (selectedProfile != null) {
|
if (selectedProfile != null) {
|
||||||
Profile profile = controller.getProfileByName(selectedProfile);
|
Profile profile = controller.getProfileByName(selectedProfile);
|
||||||
Objects.requireNonNull(profile).setRunInBackground(runInBackgroundCheckBoxMenuItem.isSelected());
|
Objects.requireNonNull(profile).setRunInBackground(runInBackgroundCheckBoxMenuItem.isSelected());
|
||||||
@ -185,7 +274,7 @@ public class ServerLauncherMenu implements ActionListener {
|
|||||||
* Saves the downloadJars setting to the current profile
|
* Saves the downloadJars setting to the current profile
|
||||||
*/
|
*/
|
||||||
private void downloadJars() {
|
private void downloadJars() {
|
||||||
String selectedProfile = serverLauncherGUI.getSelectedProfile();
|
String selectedProfile = serverLauncherGUI.getControlPanelTab().getSelectedProfile();
|
||||||
if (selectedProfile != null) {
|
if (selectedProfile != null) {
|
||||||
controller.setDownloadAllJars(downloadJarsCheckBoxMenuItem.isSelected());
|
controller.setDownloadAllJars(downloadJarsCheckBoxMenuItem.isSelected());
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package net.knarcraft.minecraftserverlauncher.userinterface;
|
package net.knarcraft.minecraftserverlauncher.userinterface;
|
||||||
|
|
||||||
import net.knarcraft.minecraftserverlauncher.Main;
|
import net.knarcraft.minecraftserverlauncher.Main;
|
||||||
import net.knarcraft.minecraftserverlauncher.server.Server;
|
import net.knarcraft.minecraftserverlauncher.server.ServerHandler;
|
||||||
import net.knarcraft.minecraftserverlauncher.server.ServerTypeHandler;
|
import net.knarcraft.minecraftserverlauncher.server.ServerTypeHandler;
|
||||||
import net.knarcraft.minecraftserverlauncher.server.servertypes.ServerType;
|
import net.knarcraft.minecraftserverlauncher.server.servertypes.ServerType;
|
||||||
|
|
||||||
@ -23,11 +23,9 @@ public class ServerTab implements ActionListener {
|
|||||||
private final JComboBox<String> serverVersions;
|
private final JComboBox<String> serverVersions;
|
||||||
private final JComboBox<String> maxRam;
|
private final JComboBox<String> maxRam;
|
||||||
private final JCheckBox enabledCheckbox;
|
private final JCheckBox enabledCheckbox;
|
||||||
private final JButton removeServerButton;
|
|
||||||
private final JButton browseButton;
|
private final JButton browseButton;
|
||||||
private final JTextField directory;
|
private final JTextField directory;
|
||||||
private final JPanel panel;
|
private final JPanel panel;
|
||||||
private final String name;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes a new server tab with the given name
|
* Initializes a new server tab with the given name
|
||||||
@ -36,7 +34,6 @@ public class ServerTab implements ActionListener {
|
|||||||
* @throws ConfigurationException <p>If unable to create the new tab</p>
|
* @throws ConfigurationException <p>If unable to create the new tab</p>
|
||||||
*/
|
*/
|
||||||
public ServerTab(String name) throws ConfigurationException {
|
public ServerTab(String name) throws ConfigurationException {
|
||||||
this.name = name;
|
|
||||||
panel = new JPanel();
|
panel = new JPanel();
|
||||||
Main.getController().getGUI().getPane().addTab(name, null, panel, null);
|
Main.getController().getGUI().getPane().addTab(name, null, panel, null);
|
||||||
SpringLayout sl_panel_3 = new SpringLayout();
|
SpringLayout sl_panel_3 = new SpringLayout();
|
||||||
@ -76,7 +73,7 @@ public class ServerTab implements ActionListener {
|
|||||||
sl_panel_3.putConstraint(SpringLayout.WEST, lblMaxRam, 6, SpringLayout.EAST, serverTypes);
|
sl_panel_3.putConstraint(SpringLayout.WEST, lblMaxRam, 6, SpringLayout.EAST, serverTypes);
|
||||||
panel.add(lblMaxRam);
|
panel.add(lblMaxRam);
|
||||||
|
|
||||||
maxRam = new JComboBox<>(Server.getRamList());
|
maxRam = new JComboBox<>(ServerHandler.getRamList());
|
||||||
sl_panel_3.putConstraint(SpringLayout.NORTH, maxRam, 0, SpringLayout.NORTH, serverTypes);
|
sl_panel_3.putConstraint(SpringLayout.NORTH, maxRam, 0, SpringLayout.NORTH, serverTypes);
|
||||||
sl_panel_3.putConstraint(SpringLayout.WEST, maxRam, 6, SpringLayout.EAST, lblMaxRam);
|
sl_panel_3.putConstraint(SpringLayout.WEST, maxRam, 6, SpringLayout.EAST, lblMaxRam);
|
||||||
sl_panel_3.putConstraint(SpringLayout.EAST, maxRam, -10, SpringLayout.EAST, panel);
|
sl_panel_3.putConstraint(SpringLayout.EAST, maxRam, -10, SpringLayout.EAST, panel);
|
||||||
@ -88,14 +85,6 @@ public class ServerTab implements ActionListener {
|
|||||||
panel.add(enabledCheckbox);
|
panel.add(enabledCheckbox);
|
||||||
enabledCheckbox.addActionListener(this);
|
enabledCheckbox.addActionListener(this);
|
||||||
|
|
||||||
removeServerButton = new JButton("Remove server");
|
|
||||||
sl_panel_3.putConstraint(SpringLayout.NORTH, removeServerButton, 0, SpringLayout.NORTH, serverVersions);
|
|
||||||
sl_panel_3.putConstraint(SpringLayout.SOUTH, removeServerButton, 0, SpringLayout.SOUTH, serverVersions);
|
|
||||||
sl_panel_3.putConstraint(SpringLayout.WEST, removeServerButton, 6, SpringLayout.EAST, serverVersions);
|
|
||||||
sl_panel_3.putConstraint(SpringLayout.EAST, removeServerButton, -10, SpringLayout.EAST, panel);
|
|
||||||
panel.add(removeServerButton);
|
|
||||||
removeServerButton.addActionListener(this);
|
|
||||||
|
|
||||||
JLabel lblDirectory = new JLabel("Directory");
|
JLabel lblDirectory = new JLabel("Directory");
|
||||||
sl_panel_3.putConstraint(SpringLayout.WEST, lblDirectory, 6, SpringLayout.EAST, enabledCheckbox);
|
sl_panel_3.putConstraint(SpringLayout.WEST, lblDirectory, 6, SpringLayout.EAST, enabledCheckbox);
|
||||||
panel.add(lblDirectory);
|
panel.add(lblDirectory);
|
||||||
@ -112,7 +101,7 @@ public class ServerTab implements ActionListener {
|
|||||||
|
|
||||||
browseButton = new JButton("Browse");
|
browseButton = new JButton("Browse");
|
||||||
sl_panel_3.putConstraint(SpringLayout.EAST, directory, -6, SpringLayout.WEST, browseButton);
|
sl_panel_3.putConstraint(SpringLayout.EAST, directory, -6, SpringLayout.WEST, browseButton);
|
||||||
sl_panel_3.putConstraint(SpringLayout.NORTH, browseButton, 3, SpringLayout.SOUTH, removeServerButton);
|
sl_panel_3.putConstraint(SpringLayout.NORTH, browseButton, 3, SpringLayout.SOUTH, serverVersions);
|
||||||
sl_panel_3.putConstraint(SpringLayout.EAST, browseButton, -10, SpringLayout.EAST, panel);
|
sl_panel_3.putConstraint(SpringLayout.EAST, browseButton, -10, SpringLayout.EAST, panel);
|
||||||
sl_panel_3.putConstraint(SpringLayout.SOUTH, directory, 0, SpringLayout.SOUTH, browseButton);
|
sl_panel_3.putConstraint(SpringLayout.SOUTH, directory, 0, SpringLayout.SOUTH, browseButton);
|
||||||
sl_panel_3.putConstraint(SpringLayout.NORTH, directory, 0, SpringLayout.NORTH, browseButton);
|
sl_panel_3.putConstraint(SpringLayout.NORTH, directory, 0, SpringLayout.NORTH, browseButton);
|
||||||
@ -209,9 +198,7 @@ public class ServerTab implements ActionListener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
if (e.getSource() == removeServerButton) {
|
if (e.getSource() == browseButton) {
|
||||||
remove();
|
|
||||||
} else if (e.getSource() == browseButton) {
|
|
||||||
browse();
|
browse();
|
||||||
} else if (e.getSource() == serverTypes) {
|
} else if (e.getSource() == serverTypes) {
|
||||||
try {
|
try {
|
||||||
@ -222,15 +209,6 @@ public class ServerTab implements ActionListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the collection containing this ServerTab, and updates everything necessary
|
|
||||||
*/
|
|
||||||
private void remove() {
|
|
||||||
Main.getController().getCurrentProfile().removeCollection(this.name);
|
|
||||||
Main.getController().getGUI().updateWithSavedProfileData();
|
|
||||||
Main.getController().getCurrentProfile().updateConsoles();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asks the user for server location and updates the GUI if given a valid value
|
* Asks the user for server location and updates the GUI if given a valid value
|
||||||
*/
|
*/
|
||||||
|
@ -1,13 +1,17 @@
|
|||||||
package net.knarcraft.minecraftserverlauncher.userinterface;
|
package net.knarcraft.minecraftserverlauncher.userinterface;
|
||||||
|
|
||||||
import net.knarcraft.minecraftserverlauncher.Main;
|
import net.knarcraft.minecraftserverlauncher.Main;
|
||||||
import net.knarcraft.minecraftserverlauncher.profile.Controller;
|
import net.knarcraft.minecraftserverlauncher.profile.ServerLauncherController;
|
||||||
import net.knarcraft.minecraftserverlauncher.utility.CommonFunctions;
|
import net.knarcraft.minecraftserverlauncher.utility.CommonFunctions;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.*;
|
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.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
@ -20,14 +24,14 @@ public class Tray {
|
|||||||
|
|
||||||
private SystemTray tray;
|
private SystemTray tray;
|
||||||
private TrayIcon trayIcon;
|
private TrayIcon trayIcon;
|
||||||
private Controller controller;
|
private final ServerLauncherController controller;
|
||||||
private ServerLauncherGUI serverLauncherGUI;
|
private final ServerLauncherGUI serverLauncherGUI;
|
||||||
private JFrame mainFrame;
|
private final JFrame mainFrame;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new tray
|
* Instantiates a new tray
|
||||||
*
|
*
|
||||||
* @param mainFrame <p>The main frame of the GUI</p>
|
* @param mainFrame <p>The main frame of the GUI</p>
|
||||||
* @param serverLauncherGUI <p>The server launcher GUI to use</p>
|
* @param serverLauncherGUI <p>The server launcher GUI to use</p>
|
||||||
*/
|
*/
|
||||||
public Tray(JFrame mainFrame, ServerLauncherGUI serverLauncherGUI) {
|
public Tray(JFrame mainFrame, ServerLauncherGUI serverLauncherGUI) {
|
||||||
@ -55,7 +59,7 @@ public class Tray {
|
|||||||
trayIcon = new TrayIcon(trayImage, "Minecraft Server Launcher", popup);
|
trayIcon = new TrayIcon(trayImage, "Minecraft Server Launcher", popup);
|
||||||
trayIcon.setImageAutoSize(true);
|
trayIcon.setImageAutoSize(true);
|
||||||
ActionListener exitListener = e -> {
|
ActionListener exitListener = e -> {
|
||||||
serverLauncherGUI.stopServers();
|
serverLauncherGUI.getControlPanelTab().stopServers();
|
||||||
controller.saveState();
|
controller.saveState();
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
};
|
};
|
||||||
@ -88,7 +92,7 @@ public class Tray {
|
|||||||
e1.printStackTrace();
|
e1.printStackTrace();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
serverLauncherGUI.stopServers();
|
serverLauncherGUI.getControlPanelTab().stopServers();
|
||||||
controller.saveState();
|
controller.saveState();
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
}
|
}
|
||||||
@ -110,7 +114,7 @@ public class Tray {
|
|||||||
@Override
|
@Override
|
||||||
public void windowClosing(WindowEvent e) {
|
public void windowClosing(WindowEvent e) {
|
||||||
controller.saveState();
|
controller.saveState();
|
||||||
serverLauncherGUI.stopServers();
|
serverLauncherGUI.getControlPanelTab().stopServers();
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -12,7 +12,8 @@ public class WebBrowser {
|
|||||||
private static JFrame browserFrame;
|
private static JFrame browserFrame;
|
||||||
private static JTextPane editorPane;
|
private static JTextPane editorPane;
|
||||||
|
|
||||||
private WebBrowser() {}
|
private WebBrowser() {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new web browser
|
* Instantiates a new web browser
|
||||||
@ -44,7 +45,8 @@ public class WebBrowser {
|
|||||||
editorPane.setContentType("text/html");
|
editorPane.setContentType("text/html");
|
||||||
editorPane.addHyperlinkListener(hyperlinkEvent -> {
|
editorPane.addHyperlinkListener(hyperlinkEvent -> {
|
||||||
if (hyperlinkEvent.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) {
|
if (hyperlinkEvent.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) {
|
||||||
displayPage(hyperlinkEvent.getURL().toString()); }
|
displayPage(hyperlinkEvent.getURL().toString());
|
||||||
|
}
|
||||||
});
|
});
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
editorPane.setContentType("text/html");
|
editorPane.setContentType("text/html");
|
||||||
|
@ -0,0 +1,269 @@
|
|||||||
|
package net.knarcraft.minecraftserverlauncher.utility;
|
||||||
|
|
||||||
|
import net.knarcraft.minecraftserverlauncher.Main;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.profile.Collection;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.server.Server;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.userinterface.BackupGUI;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.userinterface.GUI;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A helper class for performing server backup
|
||||||
|
*/
|
||||||
|
public final class BackupUtil {
|
||||||
|
|
||||||
|
private static boolean backupAborted;
|
||||||
|
private static boolean backupRunning = false;
|
||||||
|
|
||||||
|
private BackupUtil() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Aborts the currently running backup
|
||||||
|
*/
|
||||||
|
public static void abortBackup() {
|
||||||
|
backupAborted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively copies a folder to another location
|
||||||
|
*
|
||||||
|
* @param source <p>The folder to copy</p>
|
||||||
|
* @param destination <p>Target destination</p>
|
||||||
|
* @param backupFileSize <p>The total file size of the backup in progress</p>
|
||||||
|
* @param alreadyCopied <p>The amount of bytes already copied</p>
|
||||||
|
* @throws IOException <p>If we can't start a file stream</p>
|
||||||
|
*/
|
||||||
|
private static long backupFolder(File source, File destination, long backupFileSize,
|
||||||
|
long alreadyCopied) throws IOException {
|
||||||
|
if (backupAborted) {
|
||||||
|
return 0L;
|
||||||
|
}
|
||||||
|
if (!source.isDirectory()) {
|
||||||
|
long copiedFileSize = copyFile(source, destination);
|
||||||
|
BackupGUI.updateProgress("Copying " + source + "\n to " + destination,
|
||||||
|
(int) ((alreadyCopied + copiedFileSize) * 100 / backupFileSize));
|
||||||
|
return copiedFileSize;
|
||||||
|
} else {
|
||||||
|
if (!destination.exists() && !destination.mkdir()) {
|
||||||
|
return 0L;
|
||||||
|
}
|
||||||
|
String[] files = source.list();
|
||||||
|
long copiedFilesSize = 0;
|
||||||
|
if (files != null) {
|
||||||
|
for (String file : files) {
|
||||||
|
File srcFile = new File(source, file);
|
||||||
|
File destinationFile = new File(destination, file);
|
||||||
|
copiedFilesSize += backupFolder(srcFile, destinationFile, backupFileSize,
|
||||||
|
alreadyCopied + copiedFilesSize);
|
||||||
|
BackupGUI.updateProgress("Copying " + source + "\n to " + destination,
|
||||||
|
(int) ((alreadyCopied + copiedFilesSize) * 100 / backupFileSize));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return copiedFilesSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies a file from one location to another
|
||||||
|
*
|
||||||
|
* @param source <p>The file to copy</p>
|
||||||
|
* @param destination <p>The location of the copied file</p>
|
||||||
|
* @throws IOException <p>If reading or writing fails</p>
|
||||||
|
*/
|
||||||
|
private static long copyFile(File source, File destination) throws IOException {
|
||||||
|
InputStream in = new FileInputStream(source);
|
||||||
|
OutputStream out = new FileOutputStream(destination);
|
||||||
|
byte[] buffer = new byte[1024];
|
||||||
|
int length;
|
||||||
|
while ((length = in.read(buffer)) > 0) {
|
||||||
|
out.write(buffer, 0, length);
|
||||||
|
}
|
||||||
|
in.close();
|
||||||
|
out.close();
|
||||||
|
return Files.size(source.toPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies all server directories to a folder specified by the user
|
||||||
|
*
|
||||||
|
* @param gui <p>The GUI to use for informing the user</p>
|
||||||
|
*/
|
||||||
|
public static void backup(GUI gui) {
|
||||||
|
backupAborted = false;
|
||||||
|
if (backupRunning) {
|
||||||
|
gui.setStatus("A backup is already running");
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
backupRunning = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get the folder to save the backed up files in
|
||||||
|
File path = gui.askForDirectory("Backup folder");
|
||||||
|
if (path == null || !path.isDirectory()) {
|
||||||
|
backupRunning = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gui.setStatus("Backup running...");
|
||||||
|
List<List<File>> serverFolders = getFoldersOfEnabledServers(path);
|
||||||
|
|
||||||
|
gui.setStatus("Calculating backup size...");
|
||||||
|
long backupFileSize = getFolderSize(gui, serverFolders);
|
||||||
|
|
||||||
|
long locationFreeSpace = path.getFreeSpace();
|
||||||
|
if (locationFreeSpace < (backupFileSize + 2048000000)) {
|
||||||
|
gui.setStatus("Not enough available space. " + (backupFileSize / 1000000) + "MB necessary, but only " +
|
||||||
|
(locationFreeSpace / 1000000) + "MB available");
|
||||||
|
backupRunning = false;
|
||||||
|
backupAborted = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gui.setStatus("Backing up " + (backupFileSize / 1000000) + "MB");
|
||||||
|
|
||||||
|
performBackup(gui, serverFolders, backupFileSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs the actual backup after checks have passed and necessary info is available
|
||||||
|
*
|
||||||
|
* @param gui <p>The GUI to use for informing the user</p>
|
||||||
|
* @param serverFolders <p>The folders of the servers to backup</p>
|
||||||
|
* @param backupFileSize <p>The total size of the folders to backup</p>
|
||||||
|
*/
|
||||||
|
private static void performBackup(GUI gui, List<List<File>> serverFolders, long backupFileSize) {
|
||||||
|
new BackupGUI();
|
||||||
|
BackupGUI.updateProgress("Backup starting...", 0);
|
||||||
|
long alreadyCopied = 0;
|
||||||
|
for (List<File> serverFolder : serverFolders) {
|
||||||
|
if (backupAborted || !backupRunning) {
|
||||||
|
gui.setStatus("Backup aborted");
|
||||||
|
backupRunning = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
alreadyCopied = backupServerFiles(gui, serverFolder, backupFileSize, alreadyCopied);
|
||||||
|
}
|
||||||
|
backupRunning = false;
|
||||||
|
if (backupAborted) {
|
||||||
|
gui.setStatus("Backup aborted");
|
||||||
|
} else {
|
||||||
|
BackupGUI.destroy();
|
||||||
|
gui.setStatus("Backup finished");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Backs up the files for a single server
|
||||||
|
*
|
||||||
|
* @param gui <p>The GUI to use for informing the user</p>
|
||||||
|
* @param serverFolder <p>The server's input and output folders</p>
|
||||||
|
* @param backupFileSize <p>The total size of the files to backup</p>
|
||||||
|
* @param alreadyCopied <p>The amount of bytes already copied</p>
|
||||||
|
* @return <p>The new amount of bytes copied</p>
|
||||||
|
*/
|
||||||
|
private static long backupServerFiles(GUI gui, List<File> serverFolder, long backupFileSize, long alreadyCopied) {
|
||||||
|
File srcFolder = serverFolder.get(0);
|
||||||
|
File destinationFolder = serverFolder.get(1);
|
||||||
|
|
||||||
|
//Create child folders
|
||||||
|
if (!destinationFolder.exists() && !destinationFolder.mkdirs()) {
|
||||||
|
backupRunning = false;
|
||||||
|
gui.logError("Unable to create necessary sub-folder in the backup folder");
|
||||||
|
throw new IllegalArgumentException("Unable to create necessary sub-folder in the backup folder");
|
||||||
|
}
|
||||||
|
//Backup
|
||||||
|
try {
|
||||||
|
alreadyCopied += backupFolder(srcFolder, destinationFolder, backupFileSize, alreadyCopied);
|
||||||
|
} catch (IOException e) {
|
||||||
|
gui.showError("Backup caused an error: " + e.getMessage());
|
||||||
|
gui.logError(Arrays.toString(e.getStackTrace()));
|
||||||
|
BackupGUI.destroy();
|
||||||
|
backupRunning = false;
|
||||||
|
}
|
||||||
|
return alreadyCopied;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the size of a list of folders
|
||||||
|
*
|
||||||
|
* @param gui <p>The GUI to write any errors to</p>
|
||||||
|
* @param serverFolders <p>The folder to find the size of</p>
|
||||||
|
* @return <p>The size of the given folders</p>
|
||||||
|
*/
|
||||||
|
private static long getFolderSize(GUI gui, List<List<File>> serverFolders) {
|
||||||
|
long folderSize = 0;
|
||||||
|
for (List<File> serverFolder : serverFolders) {
|
||||||
|
File srcFolder = serverFolder.get(0);
|
||||||
|
try (Stream<Path> walk = Files.walk(srcFolder.toPath())) {
|
||||||
|
folderSize += walk.filter(Files::isRegularFile).mapToLong(BackupUtil::getFileSize).sum();
|
||||||
|
} catch (IOException e) {
|
||||||
|
gui.setStatus(String.format("IO errors %s", e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return folderSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the input and output folders for enabled servers
|
||||||
|
*
|
||||||
|
* <p>The input folders are the folders to copy, while the output folders are the folders to write the backup to.
|
||||||
|
* Each list element contains a list of exactly two File items. The first one is the input folder, and the second
|
||||||
|
* one is the output folder</p>
|
||||||
|
*
|
||||||
|
* @param path <p>The path of the backup folder, as given by the user</p>
|
||||||
|
* @return <p>The folders to copy from/to</p>
|
||||||
|
*/
|
||||||
|
private static List<List<File>> getFoldersOfEnabledServers(File path) {
|
||||||
|
List<List<File>> serverFolders = new ArrayList<>();
|
||||||
|
|
||||||
|
//Get folders of servers to back up
|
||||||
|
List<Collection> collections = Main.getController().getCurrentProfile().getCollections();
|
||||||
|
for (Collection collection : collections) {
|
||||||
|
//Ignore disabled and invalid servers
|
||||||
|
if (collection.getServer().getPath().equals("") || !collection.getServer().isEnabled()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//Decide sub-folders
|
||||||
|
Server targetServer = collection.getServer();
|
||||||
|
String name = targetServer.getName();
|
||||||
|
File srcFolder = new File(targetServer.getPath());
|
||||||
|
File destinationFolder = new File(path, name);
|
||||||
|
|
||||||
|
List<File> serverFolder = new ArrayList<>();
|
||||||
|
serverFolder.add(srcFolder);
|
||||||
|
serverFolder.add(destinationFolder);
|
||||||
|
serverFolders.add(serverFolder);
|
||||||
|
}
|
||||||
|
return serverFolders;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the size of a file given its path
|
||||||
|
*
|
||||||
|
* @param path <p>The path to a file</p>
|
||||||
|
* @return <p>The size of the file in bytes, or 0 if an exception is thrown</p>
|
||||||
|
*/
|
||||||
|
private static long getFileSize(Path path) {
|
||||||
|
try {
|
||||||
|
return Files.size(path);
|
||||||
|
} catch (IOException exception) {
|
||||||
|
System.out.printf("Failed to get size of %s%n%s", path, exception);
|
||||||
|
return 0L;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,12 +1,19 @@
|
|||||||
package net.knarcraft.minecraftserverlauncher.utility;
|
package net.knarcraft.minecraftserverlauncher.utility;
|
||||||
|
|
||||||
import net.knarcraft.minecraftserverlauncher.Main;
|
import net.knarcraft.minecraftserverlauncher.Main;
|
||||||
import net.knarcraft.minecraftserverlauncher.profile.Collection;
|
|
||||||
import net.knarcraft.minecraftserverlauncher.server.Server;
|
|
||||||
import net.knarcraft.minecraftserverlauncher.userinterface.GUI;
|
|
||||||
import net.knarcraft.minecraftserverlauncher.userinterface.WebBrowser;
|
import net.knarcraft.minecraftserverlauncher.userinterface.WebBrowser;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.BufferedReader;
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
@ -16,7 +23,7 @@ import java.nio.file.StandardCopyOption;
|
|||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A holding class for methods shared between classes.
|
* A holding class for methods shared between classes
|
||||||
*
|
*
|
||||||
* @author Kristian Knarvik <kristian.knarvik@knett.no>
|
* @author Kristian Knarvik <kristian.knarvik@knett.no>
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
@ -34,7 +41,6 @@ public final class CommonFunctions {
|
|||||||
public static void createAllFolders() throws FileNotFoundException {
|
public static void createAllFolders() throws FileNotFoundException {
|
||||||
createFolder(new File(filesDirectory));
|
createFolder(new File(filesDirectory));
|
||||||
createFolder(new File(filesDirectory + File.separator + "Jars"));
|
createFolder(new File(filesDirectory + File.separator + "Jars"));
|
||||||
createFolder(new File(filesDirectory + File.separator + "testjars"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -43,7 +49,7 @@ public final class CommonFunctions {
|
|||||||
* @param folder <p>The folder to create</p>
|
* @param folder <p>The folder to create</p>
|
||||||
* @throws FileNotFoundException <p>If unable to create the folder</p>
|
* @throws FileNotFoundException <p>If unable to create the folder</p>
|
||||||
*/
|
*/
|
||||||
private static void createFolder(File folder) throws FileNotFoundException {
|
public static void createFolder(File folder) throws FileNotFoundException {
|
||||||
if (!folder.exists()) {
|
if (!folder.exists()) {
|
||||||
if (!folder.mkdirs()) {
|
if (!folder.mkdirs()) {
|
||||||
throw new FileNotFoundException("Cannot create necessary directory.");
|
throw new FileNotFoundException("Cannot create necessary directory.");
|
||||||
@ -100,12 +106,89 @@ public final class CommonFunctions {
|
|||||||
*
|
*
|
||||||
* @param path <p>The full url of the file to readFromServer</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>
|
||||||
|
* @throws IOException <p>If unable to find or read the file</p>
|
||||||
*/
|
*/
|
||||||
public static String readFile(String path) throws IOException {
|
public static String readRemoteFile(String path) throws IOException {
|
||||||
URL url = new URL(path);
|
URL url = new URL(path);
|
||||||
return new Scanner(url.openStream()).useDelimiter("\\Z").next();
|
return new Scanner(url.openStream()).useDelimiter("\\Z").next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a buffered reader for reading a given file
|
||||||
|
*
|
||||||
|
* @param path <p>The path of the file to read</p>
|
||||||
|
* @return <p>A buffered reader for reading the file</p>
|
||||||
|
* @throws FileNotFoundException <p>If the file does not exist</p>
|
||||||
|
*/
|
||||||
|
public static BufferedReader getFileReader(String path) throws FileNotFoundException {
|
||||||
|
return new BufferedReader(new InputStreamReader(new FileInputStream(path)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a buffered writer for writing to a given file
|
||||||
|
*
|
||||||
|
* @param path <p>The path to the file to write to</p>
|
||||||
|
* @return <p>A buffered writer for writing to the file</p>
|
||||||
|
* @throws FileNotFoundException <p>If the file does not exist</p>
|
||||||
|
*/
|
||||||
|
public static BufferedWriter getFileWriter(String path) throws FileNotFoundException {
|
||||||
|
return new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a file from disk
|
||||||
|
*
|
||||||
|
* @param path <p>The path of the file to read</p>
|
||||||
|
* @return <p>The contents of the file</p>
|
||||||
|
* @throws IOException <p>If unable to find or read the file</p>
|
||||||
|
*/
|
||||||
|
public static String readFile(String path) throws IOException {
|
||||||
|
return CommonFunctions.readBufferedReader(getFileReader(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes text to a file and adds a trailing newline
|
||||||
|
*
|
||||||
|
* @param path <p>The path of the file to write to</p>
|
||||||
|
* @param text <p>The text to write</p>
|
||||||
|
* @throws IOException <p>If unable to write to the file</p>
|
||||||
|
*/
|
||||||
|
public static void writeFile(String path, String text) throws IOException {
|
||||||
|
writeFile(path, text, !text.equals(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes text to a file
|
||||||
|
*
|
||||||
|
* @param path <p>The path of the file to write to</p>
|
||||||
|
* @param text <p>The text to write</p>
|
||||||
|
* @param addTrailingNewline <p>Whether to add a new line at the end of the file</p>
|
||||||
|
* @throws IOException <p>If unable to write to the file</p>
|
||||||
|
*/
|
||||||
|
public static void writeFile(String path, String text, Boolean addTrailingNewline) throws IOException {
|
||||||
|
BufferedWriter writer = getFileWriter(path);
|
||||||
|
writer.write(text);
|
||||||
|
if (addTrailingNewline) {
|
||||||
|
writer.newLine();
|
||||||
|
}
|
||||||
|
writer.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends text to a file
|
||||||
|
*
|
||||||
|
* @param path <p>The path to the file to append to</p>
|
||||||
|
* @param text <p>The text to append</p>
|
||||||
|
* @throws IOException <p>If unable to append to the file</p>
|
||||||
|
*/
|
||||||
|
public static void appendFile(String path, String text) throws IOException {
|
||||||
|
BufferedWriter writer = new BufferedWriter(new FileWriter(path, true));
|
||||||
|
writer.write(text);
|
||||||
|
writer.newLine();
|
||||||
|
writer.close();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Downloads a file from a website and replaces the target file
|
* Downloads a file from a website and replaces the target file
|
||||||
*
|
*
|
||||||
@ -124,55 +207,6 @@ public final class CommonFunctions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Recursively copies a folder to another location
|
|
||||||
*
|
|
||||||
* @param source <p>The folder to copy</p>
|
|
||||||
* @param destination <p>Target destination</p>
|
|
||||||
* @throws IOException <p>If we can't start a file stream</p>
|
|
||||||
*/
|
|
||||||
private static void copyFolder(GUI serverLauncherGui, File source, File destination) throws IOException {
|
|
||||||
if (!source.isDirectory()) {
|
|
||||||
copyFile(serverLauncherGui, source, destination);
|
|
||||||
} else {
|
|
||||||
serverLauncherGui.setStatus("Copying directory " + source);
|
|
||||||
if (!destination.exists() && !destination.mkdir()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String[] files = source.list();
|
|
||||||
if (files != null) {
|
|
||||||
for (String file : files) {
|
|
||||||
File srcFile = new File(source, file);
|
|
||||||
File destinationFile = new File(destination, file);
|
|
||||||
copyFolder(serverLauncherGui, srcFile, destinationFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
serverLauncherGui.setStatus("Copied directory " + source);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copies a file from one location to another
|
|
||||||
*
|
|
||||||
* @param serverLauncherGui <p>The serverLauncherGui to use for alerting the user</p>
|
|
||||||
* @param source <p>The file to copy</p>
|
|
||||||
* @param destination <p>The location of the copied file</p>
|
|
||||||
* @throws IOException <p>If reading or writing fails</p>
|
|
||||||
*/
|
|
||||||
private static void copyFile(GUI serverLauncherGui, File source, File destination) throws IOException {
|
|
||||||
serverLauncherGui.setStatus("Copying file " + source + "...");
|
|
||||||
InputStream in = new FileInputStream(source);
|
|
||||||
OutputStream out = new FileOutputStream(destination);
|
|
||||||
byte[] buffer = new byte[1024];
|
|
||||||
int length;
|
|
||||||
while ((length = in.read(buffer)) > 0) {
|
|
||||||
out.write(buffer, 0, length);
|
|
||||||
}
|
|
||||||
in.close();
|
|
||||||
out.close();
|
|
||||||
serverLauncherGui.setStatus("Copied file " + source);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens an url in the user's default application.
|
* Opens an url in the user's default application.
|
||||||
*
|
*
|
||||||
@ -199,41 +233,16 @@ public final class CommonFunctions {
|
|||||||
StringBuilder text = new StringBuilder();
|
StringBuilder text = new StringBuilder();
|
||||||
char[] readCharacters = new char[1000];
|
char[] readCharacters = new char[1000];
|
||||||
while (reader.ready()) {
|
while (reader.ready()) {
|
||||||
reader.read(readCharacters);
|
if (reader.read(readCharacters) > 0) {
|
||||||
text.append(readCharacters);
|
text.append(readCharacters);
|
||||||
readCharacters = new char[1000];
|
readCharacters = new char[1000];
|
||||||
|
} else {
|
||||||
|
return text.toString().trim();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return text.toString().trim();
|
return text.toString().trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Copies all server directories to a folder specified by the user.
|
|
||||||
*/
|
|
||||||
public static void backup(GUI gui) {
|
|
||||||
File path = gui.askForDirectory("Backup folder");
|
|
||||||
for (Collection collection : Main.getController().getCurrentProfile().getCollections()) {
|
|
||||||
//Ignore disabled and invalid servers
|
|
||||||
if (collection.getServer().getPath().equals("") || !collection.getServer().isEnabled()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
//Decide sub-folders
|
|
||||||
Server targetServer = collection.getServer();
|
|
||||||
String name = targetServer.getName();
|
|
||||||
File srcFolder = new File(targetServer.getPath());
|
|
||||||
File destinationFolder = new File(path, name);
|
|
||||||
//Create child folders
|
|
||||||
if (!destinationFolder.exists() && !destinationFolder.mkdirs()) {
|
|
||||||
throw new IllegalArgumentException("Unable to create necessary sub-folder in the backup folder");
|
|
||||||
}
|
|
||||||
//Backup
|
|
||||||
try {
|
|
||||||
CommonFunctions.copyFolder(gui, srcFolder, destinationFolder);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
gui.setStatus("Backup finished");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validates that a name is not empty and does not contain invalid characters
|
* Validates that a name is not empty and does not contain invalid characters
|
||||||
@ -242,6 +251,34 @@ public final class CommonFunctions {
|
|||||||
* @return <p>True if the name is valid</p>
|
* @return <p>True if the name is valid</p>
|
||||||
*/
|
*/
|
||||||
public static boolean nameIsValid(String name) {
|
public static boolean nameIsValid(String name) {
|
||||||
return !name.equals("") && name.matches("[^!?;,]+");
|
return name != null && !name.equals("") && name.matches("[^!?;,]+");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes all files within a folder
|
||||||
|
*
|
||||||
|
* @param target <p>The folder to delete from</p>
|
||||||
|
*/
|
||||||
|
public static void removeFilesRecursively(File target) {
|
||||||
|
File[] oldFiles = target.listFiles();
|
||||||
|
if (oldFiles == null) {
|
||||||
|
throw new IllegalArgumentException("Unable to list files in directory");
|
||||||
|
}
|
||||||
|
for (File file : oldFiles) {
|
||||||
|
if (file.isFile()) {
|
||||||
|
if (!file.delete()) {
|
||||||
|
throw new IllegalArgumentException("Unable to delete a file from the directory");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (File file : oldFiles) {
|
||||||
|
if (file.isDirectory()) {
|
||||||
|
removeFilesRecursively(file);
|
||||||
|
if (!file.delete()) {
|
||||||
|
throw new IllegalArgumentException("Unable to delete a file from the directory");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -60,6 +60,9 @@ public final class JarDownloader {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (String version : type.getVersions()) {
|
for (String version : type.getVersions()) {
|
||||||
|
if ((type.getName().equals("Spigot") || type.getName().equals("Bukkit")) && version.equals("Latest")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
gui.setStatus("Downloading " + type.getName() + version + "...");
|
gui.setStatus("Downloading " + type.getName() + version + "...");
|
||||||
boolean success = type.downloadJar(jarDirectory, version);
|
boolean success = type.downloadJar(jarDirectory, version);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
|
@ -5,16 +5,18 @@ import com.google.gson.JsonElement;
|
|||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.google.gson.JsonParser;
|
import com.google.gson.JsonParser;
|
||||||
import net.knarcraft.minecraftserverlauncher.Main;
|
import net.knarcraft.minecraftserverlauncher.Main;
|
||||||
import net.knarcraft.minecraftserverlauncher.userinterface.GUI;
|
import net.knarcraft.minecraftserverlauncher.profile.ServerLauncherController;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.io.*;
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
|
|
||||||
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.downloadFile;
|
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.downloadFile;
|
||||||
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.getResourceAsScanner;
|
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.getResourceAsScanner;
|
||||||
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.readFile;
|
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.readRemoteFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A utility used for updating the software
|
* A utility used for updating the software
|
||||||
@ -27,13 +29,12 @@ public final class Updater {
|
|||||||
private static final String targetFile = "minecraft-server-launcher.jar";
|
private static final String targetFile = "minecraft-server-launcher.jar";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if a newer version is available
|
* Gets the version channel and version of this software instance
|
||||||
*
|
*
|
||||||
* @param updateURL <p>The URL used for checking for updates</p>
|
* @return <p>An array of Channel, Version</p>
|
||||||
* @param updateChannel <p>The release channel to use</p>
|
* @throws FileNotFoundException <p>If unable to find or read currentversion.csv</p>
|
||||||
* @throws IOException <p>If the update data cannot be read</p>
|
|
||||||
*/
|
*/
|
||||||
public static void checkForUpdate(String updateURL, String updateChannel) throws IOException {
|
public static String[] getCurrentVersion() throws FileNotFoundException {
|
||||||
Scanner file = getResourceAsScanner("currentversion.csv");
|
Scanner file = getResourceAsScanner("currentversion.csv");
|
||||||
if (!file.hasNextLine()) {
|
if (!file.hasNextLine()) {
|
||||||
throw new FileNotFoundException("File currentversion.csv is invalid");
|
throw new FileNotFoundException("File currentversion.csv is invalid");
|
||||||
@ -44,12 +45,26 @@ public final class Updater {
|
|||||||
}
|
}
|
||||||
String oldVer = file.nextLine();
|
String oldVer = file.nextLine();
|
||||||
file.close();
|
file.close();
|
||||||
|
return new String[]{oldType, oldVer};
|
||||||
|
}
|
||||||
|
|
||||||
String data = readFile(updateURL);
|
/**
|
||||||
|
* 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>
|
||||||
|
* @throws IOException <p>If the update data cannot be read</p>
|
||||||
|
*/
|
||||||
|
public static void checkForUpdate(String updateURL, String updateChannel) throws IOException {
|
||||||
|
String[] oldData = getCurrentVersion();
|
||||||
|
String oldType = oldData[0];
|
||||||
|
String oldVer = oldData[1];
|
||||||
|
|
||||||
|
String data = readRemoteFile(updateURL);
|
||||||
JsonObject jsonObject = new JsonParser().parse(data).getAsJsonObject();
|
JsonObject jsonObject = new JsonParser().parse(data).getAsJsonObject();
|
||||||
String latest = jsonObject.getAsJsonObject("latest").get(updateChannel).getAsString();
|
String latest = jsonObject.getAsJsonObject("latest").get(updateChannel).getAsString();
|
||||||
|
|
||||||
if (!oldType.equals(updateChannel) || !oldVer.equals(latest)) {
|
if (!oldType.equals(updateChannel) || isVersionHigher(oldVer, latest)) {
|
||||||
JsonArray versionList = jsonObject.getAsJsonArray("versions");
|
JsonArray versionList = jsonObject.getAsJsonArray("versions");
|
||||||
String url = "";
|
String url = "";
|
||||||
for (JsonElement elem : versionList) {
|
for (JsonElement elem : versionList) {
|
||||||
@ -75,6 +90,27 @@ public final class Updater {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decides whether one version number is higher than another
|
||||||
|
*
|
||||||
|
* @param oldVersion <p>The old version to check</p>
|
||||||
|
* @param newVersion <p>The new version to check</p>
|
||||||
|
* @return <p>True if the new version is higher than the old one</p>
|
||||||
|
*/
|
||||||
|
public static boolean isVersionHigher(String oldVersion, String newVersion) {
|
||||||
|
String[] oldVersionParts = oldVersion.split("\\.");
|
||||||
|
String[] newVersionParts = newVersion.split("\\.");
|
||||||
|
int versionLength = Math.max(oldVersionParts.length, newVersionParts.length);
|
||||||
|
for (int i = 0; i < versionLength; i++) {
|
||||||
|
int oldVersionNumber = oldVersionParts.length > i ? Integer.parseInt(oldVersionParts[i]) : 0;
|
||||||
|
int newVersionNumber = newVersionParts.length > i ? Integer.parseInt(newVersionParts[i]) : 0;
|
||||||
|
if (newVersionNumber != oldVersionNumber) {
|
||||||
|
return newVersionNumber > oldVersionNumber;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the software
|
* Updates the software
|
||||||
*
|
*
|
||||||
@ -82,8 +118,9 @@ public final class Updater {
|
|||||||
* @throws IOException <p>If unable to run the updater</p>
|
* @throws IOException <p>If unable to run the updater</p>
|
||||||
*/
|
*/
|
||||||
private static void runUpdater(String url) throws IOException {
|
private static void runUpdater(String url) throws IOException {
|
||||||
|
String javaCommand = ServerLauncherController.getInstance().getJavaCommand();
|
||||||
ProcessBuilder builder;
|
ProcessBuilder builder;
|
||||||
builder = new ProcessBuilder("java", "-jar", "Updater.jar", url, "yes", targetFile, "5", "nogui");
|
builder = new ProcessBuilder(javaCommand, "-jar", "Updater.jar", url, "yes", targetFile, "5", "nogui");
|
||||||
builder.directory(new File(Main.getApplicationWorkDirectory()));
|
builder.directory(new File(Main.getApplicationWorkDirectory()));
|
||||||
builder.redirectErrorStream(true);
|
builder.redirectErrorStream(true);
|
||||||
builder.start();
|
builder.start();
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
beta
|
beta
|
||||||
1.2.3
|
1.4.3
|
|
@ -5,4 +5,7 @@ downloadJarsText=This option will download all the .jar files available in the p
|
|||||||
aboutText=This software was created to start and manage several servers simultaneously._BREAK_You no longer have to do the tedious work of manually downloading different .jar files every time you want to try something new.
|
aboutText=This software was created to start and manage several servers simultaneously._BREAK_You no longer have to do the tedious work of manually downloading different .jar files every time you want to try something new.
|
||||||
infoURL=https://archive.knarcraft.net/Scripts/BungeeMinecraftServerLauncherInfo/
|
infoURL=https://archive.knarcraft.net/Scripts/BungeeMinecraftServerLauncherInfo/
|
||||||
manualUpdateURL=https://git.knarcraft.net/KnarCraft/Minecraft-Server-Launcher/releases
|
manualUpdateURL=https://git.knarcraft.net/KnarCraft/Minecraft-Server-Launcher/releases
|
||||||
storyURL=https://archive.knarcraft.net/Scripts/BungeeMinecraftServerLauncherStory/
|
storyURL=https://archive.knarcraft.net/Scripts/BungeeMinecraftServerLauncherStory/
|
||||||
|
javaCommandText=This option allows you to set a custom command/path to the Java executable used for Minecraft 1.17 and above._BREAK_If "java" is currently pointing to Java 8, you can use this to set a custom one for running new Minecraft servers and BuildTools.
|
||||||
|
oldJavaCommandText=This option allows you to set a custom command/path to the Java executable used for Minecraft 1.16 and below._BREAK_If "java" is currently pointing to Java 16, you can use this to set a custom one for running old Minecraft servers.
|
||||||
|
deleteBuiltJarFilesText=This option allows you to easily delete built Spigot and Bukkit .jar files._BREAK_You should occasionally run this option to update the built .jar files to ensure you're running the latest update.
|
Can't render this file because it contains an unexpected character in line 9 and column 136.
|
@ -1,11 +1,11 @@
|
|||||||
Vanilla;Latest,Snapshot,1.16.3,1.15.2,1.14.4,1.13.2,1.12.2,1.11.2,1.10.2,1.9.4,1.8.9,1.7.10,1.6.4,1.5.2,1.4.7,1.3.2,1.2.5;https://launchermeta.mojang.com/mc/game/version_manifest.json;"release":";";https://s3.amazonaws.com/Minecraft.Download/versions/
|
Vanilla;Latest,Snapshot,1.18.1,1.17.1,1.16.5,1.15.2,1.14.4,1.13.2,1.12.2,1.11.2,1.10.2,1.9.4,1.8.9,1.7.10,1.6.4,1.5.2,1.4.7,1.3.2,1.2.5;https://launchermeta.mojang.com/mc/game/version_manifest.json;"release":";";https://s3.amazonaws.com/Minecraft.Download/versions/
|
||||||
Spigot;1.16.3,1.15.2,1.14.4,1.13.2,1.12.2,1.11.2,1.10.2,1.9.4,1.9.4,1.8.8,1.7.10,1.6.4-R2.1,1.5.2-R1.1,1.4.7-R1.1;https://static.knarcraft.net/archive/downloads/minecraftserverjars/Spigot/;spigot-
|
Spigot;Latest,1.17.1,1.16.5,1.15.2,1.14.4,1.13.2,1.12.2,1.11.2,1.10.2,1.9.4,1.9.4,1.8.8,1.7.10,1.6.4-R2.1,1.5.2-R1.1,1.4.7-R1.1;https://static.knarcraft.net/archive/downloads/minecraftserverjars/Spigot/;spigot-
|
||||||
Paper;1.16.3,1.15.2,1.14.4,1.13.2,1.12.2,1.11.2,1.10.2,1.9.4,1.8.8;https://static.knarcraft.net/archive/downloads/minecraftserverjars/Paper/;Paper-
|
Paper;1.18.1,1.17.1,1.16.5,1.15.2,1.14.4,1.13.2,1.12.2,1.11.2,1.10.2,1.9.4,1.8.8;https://papermc.io/api/v2/projects/paper/versions/;"builds":[;];https://papermc.io/api/v2/projects/paper/versions/
|
||||||
SpongeVanilla;1.12.2,1.11.2,1.10.2,1.8.9;https://dl-api.spongepowered.org/v1/org.spongepowered/spongevanilla/downloads?type=stable&minecraft=;"version":";",;https://repo.spongepowered.org/maven/org/spongepowered/spongevanilla/;/spongevanilla-
|
#SpongeVanilla;1.12.2,1.11.2,1.10.2,1.8.9;https://dl-api.spongepowered.org/v1/org.spongepowered/spongevanilla/downloads?type=stable&minecraft=;"version":";",;https://repo.spongepowered.org/maven/org/spongepowered/spongevanilla/;/spongevanilla-
|
||||||
Craftbukkit;1.16.3,1.15.2,1.14.4,1.13.2,1.12.2,1.11.2,1.10.2,1.9.4,1.8.8,1.7.10-R0.1,1.6.4-R2.0,1.5.2-R1.0,1.4.6-R0.3,1.3.2-R3.0,1.2.5-R2.0,1.1-R6,1.0.1-R1,b1.8.1,b1.7.3;https://static.knarcraft.net/archive/downloads/minecraftserverjars/Bukkit/;craftbukkit-
|
Craftbukkit;Latest,1.17.1,1.16.5,1.15.2,1.14.4,1.13.2,1.12.2,1.11.2,1.10.2,1.9.4,1.8.8,1.7.10-R0.1,1.6.4-R2.0,1.5.2-R1.0,1.4.6-R0.3,1.3.2-R3.0,1.2.5-R2.0,1.1-R6,1.0.1-R1,b1.8.1,b1.7.3;https://static.knarcraft.net/archive/downloads/minecraftserverjars/Bukkit/;craftbukkit-
|
||||||
SpongeForge;1.12.2,1.11.2,1.10.2;https://dl-api.spongepowered.org/v1/org.spongepowered/spongeforge/downloads?type=stable&minecraft=;"version":";",;https://repo.spongepowered.org/maven/org/spongepowered/spongeforge/;/spongeforge-
|
#SpongeForge;1.12.2,1.11.2,1.10.2;https://dl-api.spongepowered.org/v1/org.spongepowered/spongeforge/downloads?type=stable&minecraft=;"version":";",;https://repo.spongepowered.org/maven/org/spongepowered/spongeforge/;/spongeforge-
|
||||||
MCPCplus;1.6.4,1.6.2,1.5.2,1.4.7;https://static.knarcraft.net/archive/downloads/minecraftserverjars/MCPC+/;mcpcplus
|
MCPCplus;1.6.4,1.6.2,1.5.2,1.4.7;https://static.knarcraft.net/archive/downloads/minecraftserverjars/MCPC+/;mcpcplus
|
||||||
Bungee;Latest,1.7.10,1.6.4,1.5.2,1.4.7;https://ci.md-5.net/job/BungeeCord/lastSuccessfulBuild/artifact/bootstrap/target/;Artifacts of BungeeCord #; ;http://ci.md-5.net/job/BungeeCord/lastSuccessfulBuild/artifact/bootstrap/target/BungeeCord.jar;https://static.knarcraft.net/archive/downloads/minecraftserverjars/BungeeCord/;BungeeCord-
|
Bungee;Latest,1.7.10,1.6.4,1.5.2,1.4.7;https://ci.md-5.net/job/BungeeCord/lastSuccessfulBuild/artifact/bootstrap/target/;Artifacts of BungeeCord #; ;http://ci.md-5.net/job/BungeeCord/lastSuccessfulBuild/artifact/bootstrap/target/BungeeCord.jar;https://static.knarcraft.net/archive/downloads/minecraftserverjars/BungeeCord/;BungeeCord-
|
||||||
Waterfall;1.16,1.15,1.14,1.13,1.12,1.11;https://papermc.io/api/v1/waterfall/;"latest":";";https://papermc.io/api/v1/waterfall/
|
Waterfall;1.18,1.17,1.16,1.15,1.14,1.13,1.12,1.11;https://papermc.io/api/v2/projects/waterfall/versions/;"builds":[;];https://papermc.io/api/v2/projects/waterfall/versions/
|
||||||
Travertine;1.16,1.15,1.14,1.13,1.12;https://papermc.io/api/v1/travertine/;"latest":";";https://papermc.io/api/v1/travertine/
|
Travertine;1.16,1.15,1.14,1.13,1.12;https://papermc.io/api/v2/projects/travertine/versions/;"builds":[;];https://papermc.io/api/v2/projects/travertine/versions/
|
||||||
Custom;
|
Custom;
|
Can't render this file because it contains an unexpected character in line 1 and column 193.
|
@ -0,0 +1,106 @@
|
|||||||
|
package net.knarcraft.minecraftserverlauncher.server;
|
||||||
|
|
||||||
|
import net.knarcraft.minecraftserverlauncher.Main;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.profile.ServerLauncherController;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.userinterface.FakeGUI;
|
||||||
|
import net.knarcraft.minecraftserverlauncher.utility.CommonFunctions;
|
||||||
|
import org.junit.jupiter.api.AfterAll;
|
||||||
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.MethodOrderer;
|
||||||
|
import org.junit.jupiter.api.Order;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.TestMethodOrder;
|
||||||
|
|
||||||
|
import javax.naming.ConfigurationException;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||||
|
public class JarBuilderTest {
|
||||||
|
|
||||||
|
private static JarBuilder jarBuilder;
|
||||||
|
private static String targetDirectory;
|
||||||
|
private static String jarDirectory;
|
||||||
|
|
||||||
|
@BeforeAll
|
||||||
|
public static void preSetUp() {
|
||||||
|
try {
|
||||||
|
ServerLauncherController.getInstance().loadState(true);
|
||||||
|
} catch (ConfigurationException | IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void setUp() {
|
||||||
|
targetDirectory = Main.getApplicationWorkDirectory() + File.separator + "files" + File.separator +
|
||||||
|
"BuildTools" + File.separator;
|
||||||
|
jarDirectory = Main.getApplicationWorkDirectory() + File.separator + "files" + File.separator +
|
||||||
|
"testjars" + File.separator;
|
||||||
|
jarBuilder = new JarBuilder(targetDirectory, jarDirectory, new FakeGUI());
|
||||||
|
removeBuildToolsFiles();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterAll
|
||||||
|
public static void tearDown() {
|
||||||
|
removeBuildToolsFiles();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(3)
|
||||||
|
public void buildLatestSpigotJarTest() {
|
||||||
|
File spigotFile = new File(jarDirectory + "SpigotLatest.jar");
|
||||||
|
if (spigotFile.exists() && !spigotFile.delete()) {
|
||||||
|
throw new IllegalArgumentException("Unable to remove existing spigot .jar");
|
||||||
|
}
|
||||||
|
jarBuilder.buildSpigotJar();
|
||||||
|
assertTrue(spigotFile.exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(4)
|
||||||
|
public void buildLatestBukkitJarTest() {
|
||||||
|
File bukkitFile = new File(jarDirectory + "BukkitLatest.jar");
|
||||||
|
if (bukkitFile.exists() && !bukkitFile.delete()) {
|
||||||
|
throw new IllegalArgumentException("Unable to remove existing bukkit .jar");
|
||||||
|
}
|
||||||
|
jarBuilder.buildBukkitJar();
|
||||||
|
assertTrue(new File(jarDirectory + "BukkitLatest.jar").exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(2)
|
||||||
|
public void downloadLatestBuildToolsJarTest() {
|
||||||
|
jarBuilder.downloadBuildTools();
|
||||||
|
assertTrue(new File(targetDirectory + "BuildTools.jar").exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(1)
|
||||||
|
public void getLatestBuildToolsVersionTest() {
|
||||||
|
try {
|
||||||
|
String latestVersion = jarBuilder.getLatestBuildToolsVersion();
|
||||||
|
assertNotEquals("", latestVersion);
|
||||||
|
int newVersion = Integer.parseInt(latestVersion);
|
||||||
|
assertNotEquals(newVersion, 0);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes build tools files
|
||||||
|
*/
|
||||||
|
private static void removeBuildToolsFiles() {
|
||||||
|
File target = new File(targetDirectory);
|
||||||
|
if (!target.exists() && !target.mkdirs()) {
|
||||||
|
throw new IllegalArgumentException("Unable to create the test files directory");
|
||||||
|
}
|
||||||
|
CommonFunctions.removeFilesRecursively(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,17 +1,17 @@
|
|||||||
package net.knarcraft.minecraftserverlauncher.server;
|
package net.knarcraft.minecraftserverlauncher.server;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import javax.naming.ConfigurationException;
|
import javax.naming.ConfigurationException;
|
||||||
|
|
||||||
import static junit.framework.TestCase.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static junit.framework.TestCase.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
|
||||||
public class ServerTest {
|
public class ServerTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void fromStringTest() throws ConfigurationException {
|
public void fromStringTest() throws ConfigurationException {
|
||||||
Server server = Server.fromString("asd;/home/;false;Bukkit;1.10.2;4G;");
|
Server server = ServerHandler.fromString("asd;/home/;false;Bukkit;1.10.2;4G;");
|
||||||
assertEquals("asd", server.getName());
|
assertEquals("asd", server.getName());
|
||||||
assertEquals("/home/", server.getPath());
|
assertEquals("/home/", server.getPath());
|
||||||
assertFalse(server.isEnabled());
|
assertFalse(server.isEnabled());
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
package net.knarcraft.minecraftserverlauncher.server;
|
package net.knarcraft.minecraftserverlauncher.server;
|
||||||
|
|
||||||
import net.knarcraft.minecraftserverlauncher.server.servertypes.ServerType;
|
import net.knarcraft.minecraftserverlauncher.server.servertypes.ServerType;
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import javax.naming.ConfigurationException;
|
import javax.naming.ConfigurationException;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import static junit.framework.TestCase.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
public class ServerTypeHandlerTest {
|
public class ServerTypeHandlerTest {
|
||||||
|
|
||||||
|
@ -2,13 +2,16 @@ package net.knarcraft.minecraftserverlauncher.server;
|
|||||||
|
|
||||||
import net.knarcraft.minecraftserverlauncher.Main;
|
import net.knarcraft.minecraftserverlauncher.Main;
|
||||||
import net.knarcraft.minecraftserverlauncher.utility.CommonFunctions;
|
import net.knarcraft.minecraftserverlauncher.utility.CommonFunctions;
|
||||||
import org.junit.Before;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import static junit.framework.TestCase.assertEquals;
|
|
||||||
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.createAllFolders;
|
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.createAllFolders;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
public class ServerVersionContainerTest {
|
public class ServerVersionContainerTest {
|
||||||
|
|
||||||
@ -16,7 +19,7 @@ public class ServerVersionContainerTest {
|
|||||||
private final String versionFile = filesDirectory + File.separator + "versions.csv";
|
private final String versionFile = filesDirectory + File.separator + "versions.csv";
|
||||||
private ServerVersionContainer serverVersionContainer;
|
private ServerVersionContainer serverVersionContainer;
|
||||||
|
|
||||||
@Before
|
@BeforeEach
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
try {
|
try {
|
||||||
createAllFolders();
|
createAllFolders();
|
||||||
@ -35,14 +38,14 @@ public class ServerVersionContainerTest {
|
|||||||
serverVersionContainer.reset();
|
serverVersionContainer.reset();
|
||||||
System.out.println(serverVersionContainer.toString());
|
System.out.println(serverVersionContainer.toString());
|
||||||
assertEquals("vanillaVersion;null\nsnapshotVersion;null\nbungeeVersion;null\nwaterfallVersions;\n" +
|
assertEquals("vanillaVersion;null\nsnapshotVersion;null\nbungeeVersion;null\nwaterfallVersions;\n" +
|
||||||
"travertineVersions;\nspongeVanillaVersions;\nspongeForgeVersions;",
|
"travertineVersions;\npaperVersions;\nspongeVanillaVersions;\nspongeForgeVersions;\ndownloadedBuildToolsVersion;null",
|
||||||
serverVersionContainer.toString());
|
serverVersionContainer.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void saveStateTest() throws IOException {
|
public void saveStateTest() throws IOException {
|
||||||
serverVersionContainer.saveState();
|
serverVersionContainer.saveState();
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(versionFile)));
|
BufferedReader reader = CommonFunctions.getFileReader(versionFile);
|
||||||
String savedData = CommonFunctions.readBufferedReader(reader);
|
String savedData = CommonFunctions.readBufferedReader(reader);
|
||||||
reader.close();
|
reader.close();
|
||||||
assertEquals(serverVersionContainer.toString(), savedData);
|
assertEquals(serverVersionContainer.toString(), savedData);
|
||||||
|
@ -1,19 +1,31 @@
|
|||||||
package net.knarcraft.minecraftserverlauncher.userinterface;
|
package net.knarcraft.minecraftserverlauncher.userinterface;
|
||||||
|
|
||||||
|
import java.io.BufferedWriter;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
|
||||||
public class FakeGUI extends MessageHandler implements GUI {
|
public class FakeGUI extends MessageHandler implements GUI {
|
||||||
|
|
||||||
|
private final BufferedWriter writer;
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Initializes a new fake gui
|
* Initializes a new fake gui
|
||||||
*/
|
*/
|
||||||
public FakeGUI() {
|
public FakeGUI() {
|
||||||
super(true);
|
super(true);
|
||||||
|
this.writer = new BufferedWriter(new OutputStreamWriter(System.out));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setStatus(String message) {
|
public void setStatus(String message) {
|
||||||
System.out.println(message);
|
try {
|
||||||
|
writer.write(message);
|
||||||
|
writer.newLine();
|
||||||
|
writer.flush();
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.out.println(message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,19 +1,12 @@
|
|||||||
package net.knarcraft.minecraftserverlauncher.utility;
|
package net.knarcraft.minecraftserverlauncher.utility;
|
||||||
|
|
||||||
import net.knarcraft.minecraftserverlauncher.Main;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.stringBetween;
|
import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.stringBetween;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
public class CommonFunctionsTest {
|
public class CommonFunctionsTest {
|
||||||
|
|
||||||
@Test
|
|
||||||
public void saveProfileTest() {
|
|
||||||
Main.getController().addProfile("Test");
|
|
||||||
Main.getController().saveState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void stringBetweenTest() {
|
public void stringBetweenTest() {
|
||||||
String substring = stringBetween("fish'nchips", "f", "'");
|
String substring = stringBetween("fish'nchips", "f", "'");
|
||||||
|
@ -4,28 +4,35 @@ import net.knarcraft.minecraftserverlauncher.Main;
|
|||||||
import net.knarcraft.minecraftserverlauncher.server.ServerTypeHandler;
|
import net.knarcraft.minecraftserverlauncher.server.ServerTypeHandler;
|
||||||
import net.knarcraft.minecraftserverlauncher.server.servertypes.ServerType;
|
import net.knarcraft.minecraftserverlauncher.server.servertypes.ServerType;
|
||||||
import net.knarcraft.minecraftserverlauncher.userinterface.FakeGUI;
|
import net.knarcraft.minecraftserverlauncher.userinterface.FakeGUI;
|
||||||
import org.junit.AfterClass;
|
import org.junit.jupiter.api.AfterAll;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import javax.naming.ConfigurationException;
|
import javax.naming.ConfigurationException;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import static junit.framework.TestCase.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
import static junit.framework.TestCase.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
|
||||||
public class JarDownloaderTest {
|
public class JarDownloaderTest {
|
||||||
private static String targetDirectory;
|
private static String targetDirectory;
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeAll
|
||||||
public static void setUp() {
|
public static void setUp() {
|
||||||
targetDirectory = Main.getApplicationWorkDirectory() + File.separator + "files" + File.separator +
|
String filesDirectory = Main.getApplicationWorkDirectory() + File.separator + "files";
|
||||||
"testjars" + File.separator;
|
try {
|
||||||
|
CommonFunctions.createFolder(new File(filesDirectory + File.separator + "testjars"));
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
targetDirectory = filesDirectory + File.separator + "testjars" + File.separator;
|
||||||
removeDownloadedFiles();
|
removeDownloadedFiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterClass
|
@AfterAll
|
||||||
public static void cleanUp() {
|
public static void cleanUp() {
|
||||||
removeDownloadedFiles();
|
removeDownloadedFiles();
|
||||||
}
|
}
|
||||||
@ -36,7 +43,7 @@ public class JarDownloaderTest {
|
|||||||
downloader.downloadJars();
|
downloader.downloadJars();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
/*@Test
|
||||||
public void spongeVanillaDownloadTest() throws IOException, ConfigurationException {
|
public void spongeVanillaDownloadTest() throws IOException, ConfigurationException {
|
||||||
singleDownloadTest(ServerTypeHandler.getByName("SpongeVanilla"));
|
singleDownloadTest(ServerTypeHandler.getByName("SpongeVanilla"));
|
||||||
}
|
}
|
||||||
@ -44,7 +51,7 @@ public class JarDownloaderTest {
|
|||||||
@Test
|
@Test
|
||||||
public void spongeForgeDownloadTest() throws IOException, ConfigurationException {
|
public void spongeForgeDownloadTest() throws IOException, ConfigurationException {
|
||||||
singleDownloadTest(ServerTypeHandler.getByName("SpongeForge"));
|
singleDownloadTest(ServerTypeHandler.getByName("SpongeForge"));
|
||||||
}
|
}*/
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void spigotDownloadTest() throws ConfigurationException, IOException {
|
public void spigotDownloadTest() throws ConfigurationException, IOException {
|
||||||
@ -57,7 +64,7 @@ public class JarDownloaderTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void craftbukkitDownloadTest() throws ConfigurationException, IOException {
|
public void craftBukkitDownloadTest() throws ConfigurationException, IOException {
|
||||||
singleDownloadTest(ServerTypeHandler.getByName("Bukkit"));
|
singleDownloadTest(ServerTypeHandler.getByName("Bukkit"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,6 +102,10 @@ public class JarDownloaderTest {
|
|||||||
private void singleDownloadTest(ServerType serverType) throws IOException {
|
private void singleDownloadTest(ServerType serverType) throws IOException {
|
||||||
assertNotNull(serverType);
|
assertNotNull(serverType);
|
||||||
for (String serverVersion : serverType.getVersions()) {
|
for (String serverVersion : serverType.getVersions()) {
|
||||||
|
if ((serverType.getName().equals("Spigot") || serverType.getName().equals("Bukkit"))
|
||||||
|
&& serverVersion.equals("Latest")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
System.out.println("Downloading " + serverType.getName() + serverVersion + ".jar");
|
System.out.println("Downloading " + serverType.getName() + serverVersion + ".jar");
|
||||||
serverType.downloadJar(targetDirectory, serverVersion);
|
serverType.downloadJar(targetDirectory, serverVersion);
|
||||||
assertTrue(new File(targetDirectory + serverType.getName() + serverVersion + ".jar").exists());
|
assertTrue(new File(targetDirectory + serverType.getName() + serverVersion + ".jar").exists());
|
||||||
@ -109,12 +120,6 @@ public class JarDownloaderTest {
|
|||||||
if (!target.exists() && !target.mkdirs()) {
|
if (!target.exists() && !target.mkdirs()) {
|
||||||
throw new IllegalArgumentException("Unable to create the test files directory");
|
throw new IllegalArgumentException("Unable to create the test files directory");
|
||||||
}
|
}
|
||||||
File[] oldFiles = target.listFiles();
|
CommonFunctions.removeFilesRecursively(target);
|
||||||
if (oldFiles == null) {
|
|
||||||
throw new IllegalArgumentException("Unable to list files in jar test directory");
|
|
||||||
}
|
|
||||||
for (File file : oldFiles) {
|
|
||||||
assertTrue(file.delete());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
package net.knarcraft.minecraftserverlauncher.utility;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
public class UpdaterTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isVersionHigherTest() {
|
||||||
|
assertTrue(Updater.isVersionHigher("1.1.1", "1.1.2"));
|
||||||
|
assertFalse(Updater.isVersionHigher("1.1.1", "1.1.1"));
|
||||||
|
assertFalse(Updater.isVersionHigher("1.1.1", "1.1.0"));
|
||||||
|
assertTrue(Updater.isVersionHigher("1.1.1", "1.2.1"));
|
||||||
|
assertFalse(Updater.isVersionHigher("1.2.1", "1.1.6"));
|
||||||
|
assertTrue(Updater.isVersionHigher("1.2.1", "2.1.6"));
|
||||||
|
assertTrue(Updater.isVersionHigher("1.2.1", "2.0.0"));
|
||||||
|
assertTrue(Updater.isVersionHigher("1.2", "1.2.1"));
|
||||||
|
assertTrue(Updater.isVersionHigher("1.1.2", "1.2"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user