Better code and comments

This commit is contained in:
Kristian Knarvik 2018-02-22 11:49:12 +01:00
parent 97382d035b
commit 45e2c81d05
8 changed files with 198 additions and 103 deletions

View File

@ -28,6 +28,7 @@ import static net.knarcraft.serverlauncher.Shared.stringBetween;
public class Main { public class Main {
@SuppressWarnings("CanBeFinal") @SuppressWarnings("CanBeFinal")
public static String appDir; public static String appDir;
private static boolean running = false;
static { static {
try { try {
@ -63,34 +64,45 @@ public class Main {
} }
/** /**
* Reads from server processes, and writes the output to our custom consoles. * Reads from server processes, and writes the output to consoles.
*/ */
private static void updateConsoles() { private static void updateConsoles() {
for (Collection collection : Profile.getCurrent().getCollections()) { try {
Server server = collection.getServer(); for (Collection collection : Profile.getCurrent().getCollections()) {
if (server.isEnabled() && server.getProcess() != null) { Server server = collection.getServer();
try { if (server.isEnabled() && server.getProcess() != null) {
String readText = server.read(); try {
if (!readText.equals("")) { String readText = server.read();
collection.getServerConsole().output(readText); if (!readText.equals("")) {
updatePlayerList(readText, server); collection.getServerConsole().output(readText);
updatePlayerList(readText, server);
}
} catch (IOException e) {
e.printStackTrace();
}
if (!server.getProcess().isAlive()) {
server.stopped();
} }
} catch (IOException e) {
e.printStackTrace();
}
if (!server.getProcess().isAlive()) {
server.stopped();
} }
} }
} boolean runningNew = serversRunning();
if (!serversRunning()) { if (!runningNew && running) {
Profile.getGUI().stopped(); Profile.getGUI().updateRunning(false);
Profile.getGUI().setStatus("Servers are stopped"); Profile.getGUI().setStatus("Servers are stopped");
} else { } else if (runningNew && !running) {
Profile.getGUI().running(); Profile.getGUI().updateRunning(true);
}
running = runningNew;
} catch (Exception e) {
e.printStackTrace();
} }
} }
/**
* Goes through all servers and looks for any running servers.
*
* @return Is at least one server running?
*/
private static boolean serversRunning() { private static boolean serversRunning() {
int num = 0; int num = 0;
for (Collection collection : Profile.getCurrent().getCollections()) { for (Collection collection : Profile.getCurrent().getCollections()) {
@ -105,38 +117,44 @@ public class Main {
* Looks for strings implying a player has joined or left, and updates the appropriate lists. * Looks for strings implying a player has joined or left, and updates the appropriate lists.
* *
* @param text The text to search. * @param text The text to search.
* @param server The server which sent the text. * @param server The server which sent the text.
*/ */
private static void updatePlayerList(String text, Server server) { private static void updatePlayerList(String text, Server server) {
if (!server.getTypeName().equals("Bungee")) { if (!server.getTypeName().equals("Bungee")) {
String joinedPlayer = stringBetween(text, "[Server thread/INFO]: ", " joined the game"); String joinedPlayer = getPlayer(text, true);
if (!joinedPlayer.equals("")) { String leftPlayer = getPlayer(text, false);
if (!joinedPlayer.equals("")) {
if (!server.hasPlayer(joinedPlayer)) { if (!server.hasPlayer(joinedPlayer)) {
server.addPlayer(joinedPlayer); server.addPlayer(joinedPlayer);
} }
} else { } else if (!leftPlayer.equals("")) {
joinedPlayer = stringBetween(text, "UUID of player ", " is "); if (server.hasPlayer(leftPlayer)) {
if (!joinedPlayer.equals("")) { server.removePlayer(leftPlayer);
if (!server.hasPlayer(joinedPlayer)) {
server.addPlayer(joinedPlayer);
}
}
}
if (joinedPlayer.equals("")) {
String leftPlayer = stringBetween(text, "INFO]: ", " lost connection");
if (!leftPlayer.equals("")) {
if (server.hasPlayer(leftPlayer)) {
server.removePlayer(leftPlayer);
}
} else {
leftPlayer = stringBetween(text, "[Server thread/INFO]: ", " left the game");
if (!leftPlayer.equals("")) {
if (server.hasPlayer(leftPlayer)) {
server.removePlayer(leftPlayer);
}
}
} }
} }
} }
} }
/**
* Searches a string for players joining or leaving.
*
* @param text The string to search
* @param joined Are we searching for a joining player or not
* @return The name of a player or an empty string
*/
private static String getPlayer(String text, boolean joined) {
String playerName;
if (joined) {
playerName = stringBetween(text, "[Server thread/INFO]: ", " joined the game");
if (playerName.equals("")) {
playerName = stringBetween(text, "UUID of player ", " is ");
}
} else {
playerName = stringBetween(text, "INFO]: ", " lost connection");
if (playerName.equals("")) {
playerName = stringBetween(text, "[Server thread/INFO]: ", " left the game");
}
}
return playerName;
}
} }

View File

@ -8,6 +8,13 @@ import java.nio.file.Path;
import java.nio.file.StandardCopyOption; import java.nio.file.StandardCopyOption;
import java.util.Scanner; import java.util.Scanner;
/**
* A holding class for methods shared between classes.
*
* @author Kristian Knarvik <kristian.knarvik@knett.no>
* @version 0.0.0.1
* @since 0.0.0.1
*/
public class Shared { public class Shared {
/** /**
* Finds a substring between two substrings in a string. * Finds a substring between two substrings in a string.
@ -27,7 +34,7 @@ public class Shared {
/** /**
* Reads a file from a website. * Reads a file from a website.
* This is used to find the newest version of the software. * This is used to find the newest version of jars and the software.
* *
* @param path The full url of the file to read * @param path The full url of the file to read
* @return True if successful. False otherwise * @return True if successful. False otherwise
@ -40,9 +47,9 @@ public class Shared {
/** /**
* Downloads a file from a website. * Downloads a file from a website.
* *
* @param path The full url of the file to download. * @param path The full url of the file to download.
* @param outfile The file to save to * @param outfile The file to save to
* @return True if successful. False otherwise * @return True if successful. False otherwise
*/ */
public static boolean downloadFile(String path, Path outfile) { public static boolean downloadFile(String path, Path outfile) {
try { try {

View File

@ -441,10 +441,6 @@ public class Profile {
gui.update(); gui.update();
gui.updateProfiles(); gui.updateProfiles();
current.updateConsoles(); current.updateConsoles();
if (current.runInBackground) {
gui.hide();
Executors.newSingleThreadExecutor().execute(Server::startServers);
}
if (current.downloadJars) { if (current.downloadJars) {
Executors.newSingleThreadExecutor().execute(() -> { Executors.newSingleThreadExecutor().execute(() -> {
try { try {
@ -454,6 +450,10 @@ public class Profile {
} }
}); });
} }
if (current.runInBackground) {
Executors.newSingleThreadExecutor().execute(Server::startServers);
gui.hide();
}
} }
private static Profile parseProfile(String[] profileData) { private static Profile parseProfile(String[] profileData) {

View File

@ -177,6 +177,11 @@ public class Server {
Profile.getGUI().addPlayer(name); Profile.getGUI().addPlayer(name);
} }
/**
* Removes a player with the selected name from the playerlist.
*
* @param name The name of the player to remove
*/
public void removePlayer(String name) { public void removePlayer(String name) {
for (int i = 0; i < playerList.size(); i++) { for (int i = 0; i < playerList.size(); i++) {
if (name.equals(playerList.get(i))) { if (name.equals(playerList.get(i))) {
@ -221,7 +226,7 @@ public class Server {
/** /**
* Tries to stop all enabled servers. * Tries to stop all enabled servers.
* *
* @throws IOException If a writer's process is already closed. * @throws IOException If a writer's process is already closed but not null.
*/ */
public static void stop() throws IOException { public static void stop() throws IOException {
for (Collection collection : Profile.getCurrent().getCollections()) { for (Collection collection : Profile.getCurrent().getCollections()) {
@ -252,7 +257,7 @@ public class Server {
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
Profile.getGUI().stopped(); Profile.getGUI().updateRunning(false);
return; return;
} }
} }
@ -286,36 +291,27 @@ public class Server {
} }
try { try {
ProcessBuilder builder; ProcessBuilder builder;
String serverPath;
if (Profile.getCurrent().getDownloadJars() && !type.getName().equals("Custom")) { if (Profile.getCurrent().getDownloadJars() && !type.getName().equals("Custom")) {
builder = new ProcessBuilder( serverPath = "\"" + jarDir + this.getType() + "\"";
"java", } else {
"-Xmx" + this.maxRam, serverPath = "\"" + this.path + File.separator + this.getType() + "\"";
"-Xms512M",
"-Djline.terminal=jline.UnsupportedTerminal",
"-Dcom.mojang.eula.agree=true",
"-jar",
"\"" + jarDir + this.getType() + "\"",
"nogui"
);
} else {
builder = new ProcessBuilder(
"java",
"-Xmx" + this.maxRam,
"-Xms512M",
"-Djline.terminal=jline.UnsupportedTerminal",
"-Dcom.mojang.eula.agree=true",
"-jar",
"\"" + this.path + File.separator + this.getType() + "\"",
"nogui"
);
} }
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();
OutputStream stdin = this.process.getOutputStream(); this.writer = new BufferedWriter(new OutputStreamWriter(this.process.getOutputStream()));
this.writer = new BufferedWriter(new OutputStreamWriter(stdin)); this.reader = new BufferedReader (new InputStreamReader(this.process.getInputStream()));
InputStream stdout = this.process.getInputStream();
this.reader = new BufferedReader (new InputStreamReader(stdout));
Profile.getGUI().setStatus("Servers are running"); Profile.getGUI().setStatus("Servers are running");
this.started = true; this.started = true;
return true; return true;
@ -330,6 +326,12 @@ public class Server {
} }
} }
/**
* Reads all available output from the server process.
*
* @return The server output
* @throws IOException If reading from the reader fails
*/
public String read() throws IOException { public String read() throws IOException {
String line; String line;
StringBuilder text = new StringBuilder(); StringBuilder text = new StringBuilder();

View File

@ -52,6 +52,11 @@ public class Console implements ActionListener, KeyListener {
return this.panel; return this.panel;
} }
/**
* Prints a string to the textArea.
*
* @param text The text to print
*/
public void output(String text) { public void output(String text) {
this.textOutput.setText(this.textOutput.getText() + "\n" + text); this.textOutput.setText(this.textOutput.getText() + "\n" + text);
} }

View File

@ -29,6 +29,8 @@ import static javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE;
public class GUI implements ActionListener { public class GUI implements ActionListener {
private JFrame frame; private JFrame frame;
private JTabbedPane tabbedPane;
private JTabbedPane serversPane;
//Menu //Menu
private JCheckBoxMenuItem chckbxmntmRunInBackground, chckbxmntmDelayStartup, chckbxmntmDownloadJars; //Options private JCheckBoxMenuItem chckbxmntmRunInBackground, chckbxmntmDelayStartup, chckbxmntmDownloadJars; //Options
private JMenuItem mntmErrors, mntmSetup, mntmManualUpdate; //Help private JMenuItem mntmErrors, mntmSetup, mntmManualUpdate; //Help
@ -51,13 +53,9 @@ public class GUI implements ActionListener {
private String aboutText; private String aboutText;
private final ArrayList<String> globalPlayers; private final ArrayList<String> globalPlayers;
private JTabbedPane serversPane;
private SystemTray tray; private SystemTray tray;
private TrayIcon trayIcon; private TrayIcon trayIcon;
/** /**
* Create the application window. * Create the application window.
*/ */
@ -67,25 +65,51 @@ public class GUI implements ActionListener {
this.globalPlayers = new ArrayList<>(); this.globalPlayers = new ArrayList<>();
} }
/**
* Creates the application window with a preferred width and height.
*
* @param width The preferred width
* @param height The preferred height
*/
public GUI(int width, int height) { public GUI(int width, int height) {
initialize(width, height); initialize(width, height);
loadMessages(); loadMessages();
this.globalPlayers = new ArrayList<>(); this.globalPlayers = new ArrayList<>();
} }
/**
* Gets the pane used for server configurations
*
* @return A JTabbedPane
*/
public JTabbedPane getPane() { public JTabbedPane getPane() {
return this.serversPane; return this.serversPane;
} }
/**
* Sets the text of the status label.
*
* @param text The new text
*/
public void setStatus(String text) { public void setStatus(String text) {
this.lblStatuslabel.setText(text); this.lblStatuslabel.setText(text);
} }
/**
* Adds a player to the global playerlist, and updates the players combo.
*
* @param name The name of the player to add
*/
public void addPlayer(String name) { public void addPlayer(String name) {
this.globalPlayers.add(name); this.globalPlayers.add(name);
this.updatePlayers(); this.updatePlayers();
} }
/**
* Removes a player from the global list of players.
*
* @param name The name of the player to remove.
*/
public void removePlayer(String name) { public void removePlayer(String name) {
for (int i = 0; i < this.globalPlayers.size(); i++) { for (int i = 0; i < this.globalPlayers.size(); i++) {
if (this.globalPlayers.get(i).equals(name)) { if (this.globalPlayers.get(i).equals(name)) {
@ -95,6 +119,9 @@ public class GUI implements ActionListener {
this.updatePlayers(); this.updatePlayers();
} }
/**
* Updates the profiles combo.
*/
public void updateProfiles() { public void updateProfiles() {
this.profiles.removeAllItems(); this.profiles.removeAllItems();
for (Profile profile : Profile.getProfiles()) { for (Profile profile : Profile.getProfiles()) {
@ -102,12 +129,17 @@ public class GUI implements ActionListener {
} }
} }
/**
* Gets the size of the main JFrame
*
* @return The Dimension of the frame
*/
public Dimension getSize() { public Dimension getSize() {
return frame.getContentPane().getSize(); return frame.getContentPane().getSize();
} }
/** /**
* Updates GUI according to current settings. * Updates GUI according to current profile settings.
*/ */
public void update() { public void update() {
serversPane.removeAll(); serversPane.removeAll();
@ -211,7 +243,7 @@ public class GUI implements ActionListener {
mnAbout.add(mntmStory); mnAbout.add(mntmStory);
mntmStory.addActionListener(this); mntmStory.addActionListener(this);
JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP); tabbedPane = new JTabbedPane(JTabbedPane.TOP);
frame.getContentPane().add(tabbedPane); frame.getContentPane().add(tabbedPane);
JPanel panelBasic = new JPanel(); JPanel panelBasic = new JPanel();
@ -396,6 +428,7 @@ public class GUI implements ActionListener {
frame.pack(); frame.pack();
frame.setVisible(true); frame.setVisible(true);
tray(); tray();
updateRunning(false);
} }
/** /**
@ -620,18 +653,20 @@ public class GUI implements ActionListener {
} }
} }
public void running() { /**
profiles.setEnabled(false); * Updates the GUI components to block a user from doing illegal actions.
addProfile.setEnabled(false); *
delProfile.setEnabled(false); * @param running Are the servers currently running?
btnStartServer.setEnabled(false); */
} public void updateRunning(boolean running) {
boolean stopped = !running; //Most gui is only enabled when the server is stopped rather than running.
public void stopped() { profiles.setEnabled(stopped);
profiles.setEnabled(true); addProfile.setEnabled(stopped);
addProfile.setEnabled(true); delProfile.setEnabled(stopped);
delProfile.setEnabled(true); btnStartServer.setEnabled(stopped);
btnStartServer.setEnabled(true); addServer.setEnabled(stopped);
tabbedPane.setEnabledAt(2, stopped);
btnStopServer.setEnabled(running);
} }
/** /**
@ -652,9 +687,8 @@ public class GUI implements ActionListener {
*/ */
private void stop() { private void stop() {
try { try {
setStatus("Servers are stopping"); setStatus("Servers are stopping...");
Server.stop(); Server.stop();
setStatus("Servers are stopped");
} catch (IOException e1) { } catch (IOException e1) {
JOptionPane.showMessageDialog( JOptionPane.showMessageDialog(
null, null,
@ -758,6 +792,7 @@ public class GUI implements ActionListener {
} }
} }
} }
this.setStatus("Backup finished");
} }
/** /**
@ -845,11 +880,11 @@ public class GUI implements ActionListener {
} }
in.close(); in.close();
out.close(); out.close();
this.setStatus("File copied from " + src + " to " + dest); this.setStatus("Copied file " + src);
} else { } else {
if(!dest.exists()){ if(!dest.exists()){
if (dest.mkdir()) { if (dest.mkdir()) {
this.setStatus("Directory copied from " + src + " to " + dest); this.setStatus("Copied directory " + src);
} else { } else {
return; return;
} }

View File

@ -21,7 +21,6 @@ public class ServerConsoles {
frame = new JFrame(); frame = new JFrame();
frame.setBounds(100, 100, 450, 300); frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
consolesTab = new JTabbedPane(JTabbedPane.TOP); consolesTab = new JTabbedPane(JTabbedPane.TOP);
frame.getContentPane().add(consolesTab, BorderLayout.CENTER); frame.getContentPane().add(consolesTab, BorderLayout.CENTER);
} }

View File

@ -24,6 +24,15 @@ public class ServerTab implements ActionListener {
private final JPanel panel; private final JPanel panel;
private final String name; private final String name;
/**
* Updates the server tab components according to the received parameters.
*
* @param path The new path
* @param enabled The enabled status of the server
* @param typeName The name of the selected server type
* @param serverVersion The version of the server
* @param maxRam The max usable ram for the server
*/
public void setData(String path, boolean enabled, String typeName, String serverVersion, String maxRam) { public void setData(String path, boolean enabled, String typeName, String serverVersion, String maxRam) {
this.directory.setText(path); this.directory.setText(path);
this.chckbxEnabled.setSelected(enabled); this.chckbxEnabled.setSelected(enabled);
@ -144,6 +153,11 @@ public class ServerTab implements ActionListener {
} }
} }
/**
* Gets the selected version from the serverVersion combo
*
* @return The combo value, or defaults to "Latest" on null
*/
public String getVersion() { public String getVersion() {
Object selected = this.serverVersions.getSelectedItem(); Object selected = this.serverVersions.getSelectedItem();
if (selected != null) { if (selected != null) {
@ -153,6 +167,11 @@ public class ServerTab implements ActionListener {
} }
} }
/**
* Checks if the server is enabled
*
* @return True if the checkbox is checked. False otherwise.
*/
public boolean enabled() { public boolean enabled() {
return this.chckbxEnabled.isSelected(); return this.chckbxEnabled.isSelected();
} }
@ -168,12 +187,19 @@ public class ServerTab implements ActionListener {
} }
} }
/**
* Removes the collection containing this ServerTab, and updates everything necessary.
*/
private void remove() { private void remove() {
Profile.getCurrent().removeCollection(name); Profile.getCurrent().removeCollection(this.name);
Profile.getGUI().update(); Profile.getGUI().update();
Profile.getCurrent().updateConsoles(); Profile.getCurrent().updateConsoles();
} }
/**
* Asks the user for the server folder.
* Sets the directory input's value if successful.
*/
private void browse() { private void browse() {
JFileChooser chooser = new JFileChooser(); JFileChooser chooser = new JFileChooser();
chooser.setCurrentDirectory(new java.io.File("/")); chooser.setCurrentDirectory(new java.io.File("/"));
@ -185,6 +211,9 @@ public class ServerTab implements ActionListener {
} }
} }
/**
* Updates the versions combo according to the value of the server type combo.
*/
private void serverTypes() { private void serverTypes() {
serverVersions.removeAllItems(); serverVersions.removeAllItems();
String selectedserverTypes = null; String selectedserverTypes = null;