From 990563fc68cee20a20dfabd6c610a47a444bd19c Mon Sep 17 00:00:00 2001 From: newt_00 Date: Thu, 19 Dec 2024 23:28:52 -0500 Subject: [PATCH] initial commit --- .gitignore | 29 + .idea/.gitignore | 3 + .idea/misc.xml | 6 + .idea/modules.xml | 8 + .idea/vcs.xml | 6 + nscp.iml | 11 + src/Configuration.java | 114 ++++ src/META-INF/MANIFEST.MF | 4 + src/MinecraftServerControl.java | 904 ++++++++++++++++++++++++++++++++ src/nscp/config.properties | 8 + src/nscp/minecraft.ttf | Bin 0 -> 12632 bytes src/nscp/server-icon.png | Bin 0 -> 8340 bytes 12 files changed, 1093 insertions(+) create mode 100644 .gitignore create mode 100644 .idea/.gitignore create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 nscp.iml create mode 100644 src/Configuration.java create mode 100644 src/META-INF/MANIFEST.MF create mode 100644 src/MinecraftServerControl.java create mode 100644 src/nscp/config.properties create mode 100644 src/nscp/minecraft.ttf create mode 100644 src/nscp/server-icon.png diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f68d109 --- /dev/null +++ b/.gitignore @@ -0,0 +1,29 @@ +### IntelliJ IDEA ### +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..31e1ebc --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..b3c9d0d --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/nscp.iml b/nscp.iml new file mode 100644 index 0000000..c90834f --- /dev/null +++ b/nscp.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/Configuration.java b/src/Configuration.java new file mode 100644 index 0000000..53779be --- /dev/null +++ b/src/Configuration.java @@ -0,0 +1,114 @@ +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +public class Configuration { + private static final String CONFIG_FILE_NAME = "nscp/config.properties"; + private final Properties properties = new Properties(); + private final File configFile = new File("nscp/config.properties"); + + public Configuration() { + if (!this.configFile.exists()) { + this.saveDefaultConfig(); + } + + this.loadConfig(); + } + + private void loadConfig() { + try { + FileInputStream var1 = new FileInputStream(this.configFile); + + try { + this.properties.load(var1); + } catch (Throwable var5) { + try { + var1.close(); + } catch (Throwable var4) { + var5.addSuppressed(var4); + } + + throw var5; + } + + var1.close(); + } catch (IOException var6) { + var6.printStackTrace(); + } + + } + + private void saveConfig() { + try { + FileOutputStream var1 = new FileOutputStream(this.configFile); + + try { + this.properties.store(var1, (String)null); + } catch (Throwable var5) { + try { + var1.close(); + } catch (Throwable var4) { + var5.addSuppressed(var4); + } + + throw var5; + } + + var1.close(); + } catch (IOException var6) { + var6.printStackTrace(); + } + + } + + private void saveDefaultConfig() { + this.configFile.getParentFile().mkdirs(); + + try { + InputStream var1 = this.getClass().getResourceAsStream("/nscp/config.properties"); + + try { + if (var1 != null) { + this.properties.load(var1); + this.saveConfig(); + } else { + System.err.println("[ERROR] Default configuration file not found in JAR!"); + } + } catch (Throwable var5) { + if (var1 != null) { + try { + var1.close(); + } catch (Throwable var4) { + var5.addSuppressed(var4); + } + } + + throw var5; + } + + if (var1 != null) { + var1.close(); + } + } catch (IOException var6) { + var6.printStackTrace(); + } + + } + + public String getString(String var1, String var2) { + return this.properties.getProperty(var1, var2); + } + + public boolean getBoolean(String var1, boolean var2) { + String var3 = String.valueOf(var2); + return Boolean.parseBoolean(this.properties.getProperty(var1, var3)); + } + + public void setString(String var1, String var2) { + this.properties.setProperty(var1, var2); + this.saveConfig(); + } +} diff --git a/src/META-INF/MANIFEST.MF b/src/META-INF/MANIFEST.MF new file mode 100644 index 0000000..801d024 --- /dev/null +++ b/src/META-INF/MANIFEST.MF @@ -0,0 +1,4 @@ +Manifest-Version: 1.0 +Main-Class: MinecraftServerControl +Created-By: 22.0.1 (Oracle Corporation) + diff --git a/src/MinecraftServerControl.java b/src/MinecraftServerControl.java new file mode 100644 index 0000000..85d50d7 --- /dev/null +++ b/src/MinecraftServerControl.java @@ -0,0 +1,904 @@ +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Cursor; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.FontFormatException; +import java.awt.image.BufferedImage; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.net.URL; +import java.net.URLConnection; +import java.text.SimpleDateFormat; +import java.util.Collections; +import java.util.Date; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.Objects; +import java.util.Properties; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import javax.imageio.ImageIO; +import javax.swing.BorderFactory; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextField; +import javax.swing.JTextPane; +import javax.swing.SwingUtilities; +import javax.swing.text.BadLocationException; +import javax.swing.text.Style; +import javax.swing.text.StyleConstants; +import javax.swing.text.StyledDocument; + +public class MinecraftServerControl extends JFrame { + private ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1); + private JButton startButton; + private JButton stopButton; + private JButton restartButton; + private JTextPane consoleArea; + private Process serverProcess; + private JTextField commandField; + private JTextField connectionField; + boolean stopped = false; + private InputStream fallback; + public String version; + public static Configuration config; + public String user; + public BufferedImage img; + public String connection; + + public MinecraftServerControl() throws IOException { + config = new Configuration(); + config.setString("version", "1.6"); + this.version = config.getString("version", "1.6"); + this.user = config.getString("user", (String)null); + this.connection = this.getIP(); + this.img = ImageIO.read(this.getClass().getResourceAsStream("/nscp/server-icon.png")); + if (!this.resources()) { + (new File("nscp")).mkdir(); + } + + try { + this.createGUI(); + this.g(); + this.addActionEvents(); + this.setApplicationIcon(); + this.setProperties(); + this.stopButton.setVisible(false); + this.restartButton.setVisible(false); + this.startButton.setVisible(true); + } catch (Exception var2) { + PrintStream var10000 = System.out; + String var10001 = var2.getMessage(); + var10000.println("ERROR\n" + var10001 + "\n" + String.valueOf(var2.getCause())); + System.exit(404); + } + + this.checkFilesAndStartServer(); + } + + private void startPeriodicTask() { + this.executorService.scheduleAtFixedRate(this.loop(), 0L, 2L, TimeUnit.SECONDS); + } + + private void checkFilesAndStartServer() { + try { + File var1 = new File(config.getString("jar", "server.jar")); + File var2 = new File("server.properties"); + if (!var1.exists()) { + this.handleMissingFile(String.valueOf(var1), var1); + } + + if (!var2.exists()) { + this.handleMissingFile("server.properties", var2); + } else { + this.sendToConsoleAlt2("Running Java version: " + System.getProperty("java.version")); + } + } catch (Exception var4) { + JOptionPane.showMessageDialog(this, "Server Control Panel Could not start.\n Error:" + var4.getMessage()); + } + + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + this.sendToConsole("Shutdown hook is running!"); + this.performCleanup(); + this.sendToConsoleAlt2("Cleanup completed successfully."); + })); + this.sendToConsole("Newt_00's Server Control Panel is running."); + + try { + Thread.sleep(1000L); + } catch (InterruptedException var3) { + this.sendToConsoleAlt("Thread was interrupted: " + var3.getMessage()); + } + + } + + private void handleMissingFile(String var1, File var2) throws IOException { + int var3 = JOptionPane.showConfirmDialog(this, "Error: The " + var1 + " file does not exist in the directory:\n" + System.getProperty("user.dir") + "/" + String.valueOf(var2) + "\n\nWould you like to close Newts Server Control Panel?", "NSCP Error", 0, 0); + if (var3 == 0) { + System.exit(0); + } else if (!var1.equals("server.properties")) { + int var4 = JOptionPane.showConfirmDialog(this, "Error: The server.properties file does not exist in the directory:\n" + System.getProperty("user.dir") + "/" + String.valueOf(var2) + "\n\nWould you like to close Newts Server Control Panel? \nIf NO you may start the server to regenerate a properties file and try again.", "NSCP Error", 0, 0); + if (var4 == 0) { + System.exit(0); + } else { + this.sendToConsoleAlt2("Running Java version: " + System.getProperty("java.version")); + this.sendToConsole("Attempting to generate necessary files with server start."); + if (var2.exists()) { + this.startServer(); + } else { + this.sendToConsoleAlt("No " + config.getString("jar", "server.jar") + " found...\n referring to fallback 1.20.4-paper not enabled"); + } + } + } + + } + + private void setApplicationIcon() { + if (this.img != null) { + ImageIcon var1 = new ImageIcon(this.img); + this.setIconImage(var1.getImage()); + this.revalidate(); + this.repaint(); + this.log("Icon successfully set from static source"); + this.sendToConsoleAlt2("Icon probably unsuccessfully set from static source"); + } else { + this.log("Could not read icon image from stream: " + String.valueOf(this.img)); + this.sendToConsoleAlt("Could not read icon image from stream"); + } + + } + + public static void main(String[] var0) { + SwingUtilities.invokeLater(() -> { + MinecraftServerControl var0 = null; + + try { + var0 = new MinecraftServerControl(); + } catch (IOException var2) { + throw new RuntimeException(var2); + } + + var0.setVisible(true); + }); + } + + private void createGUI() { + this.setTitle("Newt_00's Server Control Panel " + this.version); + this.setSize(600, 400); + this.setLocationRelativeTo((Component)null); + this.setDefaultCloseOperation(3); + this.setLayout(new BorderLayout(15, 15)); + JPanel var1 = new JPanel(new FlowLayout()); + this.startButton = new JButton(" Start "); + this.startButton.setForeground(Color.black); + this.startButton.setBackground(Color.GREEN); + this.startButton.setCursor(Cursor.getPredefinedCursor(12)); + this.startButton.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15)); + this.startButton.setBorder(BorderFactory.createBevelBorder(1, Color.BLACK, Color.WHITE)); + this.startButton.setOpaque(true); + this.startButton.setBorderPainted(false); + this.startButton.setBorder(BorderFactory.createLineBorder(Color.BLACK, 2)); + this.stopButton = new JButton(" Stop "); + this.stopButton.setForeground(Color.BLACK); + this.stopButton.setBackground(Color.RED); + this.stopButton.setCursor(Cursor.getPredefinedCursor(12)); + this.stopButton.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15)); + this.stopButton.setBorder(BorderFactory.createBevelBorder(1, Color.BLACK, Color.WHITE)); + this.stopButton.setOpaque(true); + this.stopButton.setBorderPainted(false); + this.restartButton = new JButton(" Restart "); + this.restartButton.setForeground(Color.BLACK); + this.restartButton.setBackground(Color.CYAN); + this.restartButton.setCursor(Cursor.getPredefinedCursor(12)); + this.restartButton.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15)); + this.restartButton.setBorder(BorderFactory.createBevelBorder(1, Color.BLACK, Color.WHITE)); + this.restartButton.setOpaque(true); + this.restartButton.setBorderPainted(false); + this.connectionField = new JTextField(" " + this.connection); + this.connectionField.setForeground(Color.BLACK); + this.connectionField.setBackground(Color.PINK); + this.connectionField.setEditable(false); + this.connectionField.setCursor(Cursor.getPredefinedCursor(2)); + this.connectionField.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15)); + this.connectionField.setBorder(BorderFactory.createBevelBorder(1, Color.BLACK, Color.WHITE)); + this.connectionField.setOpaque(true); + var1.add(this.startButton); + var1.add(this.stopButton); + var1.add(this.restartButton); + var1.add(this.connectionField); + this.consoleArea = new JTextPane(); + this.consoleArea.setEditable(false); + this.consoleArea.setBackground(Color.DARK_GRAY); + float[] var2 = Color.RGBtoHSB(73, 153, 73, (float[])null); + Color var3 = Color.getHSBColor(var2[0], var2[1], var2[2]); + this.consoleArea.setForeground(var3); + this.consoleArea.setOpaque(true); + this.consoleArea.setAutoscrolls(true); + JScrollPane var4 = new JScrollPane(this.consoleArea); + this.add(var4, "Center"); + this.commandField = new JTextField(); + this.commandField.addActionListener((var1x) -> { + this.sendCommand(this.commandField.getText()); + this.commandField.setText(""); + }); + this.commandField.setForeground(Color.WHITE); + this.commandField.setBackground(Color.GRAY); + this.add(this.commandField, "South"); + this.add(this.consoleArea, "Center"); + this.add(var1, "North"); + } + + public boolean fonts() { + InputStream var1 = this.getClass().getResourceAsStream("/nscp/minecraft.ttf"); + return var1 != null; + } + + public void log(String var1) { + PrintStream var10000 = System.out; + String var10001 = this.prefix(); + var10000.println(var10001 + var1); + } + + public boolean IPchange() { + return Objects.equals(this.connection, this.getIP()); + } + + private void g() { + if (!this.resources()) { + (new File("nscp")).mkdir(); + } + + if (!this.fonts()) { + this.log("successfully fetched font ttf, setting fonts to buttons, and console"); + SwingUtilities.invokeLater(() -> { + this.visibility(false); + this.startButton.setFont(this.terminalFont().deriveFont(1, 16.0F)); + this.stopButton.setFont(this.terminalFont().deriveFont(1, 16.0F)); + this.restartButton.setFont(this.terminalFont().deriveFont(1, 16.0F)); + this.consoleArea.setFont(this.terminalFont().deriveFont(1, 12.0F)); + this.commandField.setFont(this.terminalFont().deriveFont(1, 12.0F)); + this.connectionField.setFont(this.terminalFont().deriveFont(1, 16.0F)); + this.visibility(true); + }); + } else { + this.log("successfully fetched font ttf, setting fonts to buttons, and console"); + SwingUtilities.invokeLater(() -> { + this.visibility(false); + this.startButton.setFont(this.terminalFont().deriveFont(1, 16.0F)); + this.stopButton.setFont(this.terminalFont().deriveFont(1, 16.0F)); + this.restartButton.setFont(this.terminalFont().deriveFont(1, 16.0F)); + this.consoleArea.setFont(this.terminalFont().deriveFont(1, 12.0F)); + this.commandField.setFont(this.terminalFont().deriveFont(1, 12.0F)); + this.connectionField.setFont(this.terminalFont().deriveFont(1, 16.0F)); + this.visibility(true); + }); + } + + } + + private void addActionEvents() { + this.startButton.addActionListener((var1) -> { + this.startServer(); + }); + this.stopButton.addActionListener((var1) -> { + this.stopServer(); + }); + this.restartButton.addActionListener((var1) -> { + this.restartServer(); + }); + this.stopButton.setVisible(false); + this.restartButton.setVisible(false); + this.startButton.setVisible(true); + this.consoleArea.setVisible(true); + this.connectionField.setVisible(true); + this.appendColoredText(this.consoleArea, " ****************************\n", 16, Color.CYAN, true, false, false); + this.appendColoredText(this.consoleArea, " Author: Newt_00 \n", 16, Color.MAGENTA, true, false, false); + this.appendColoredText(this.consoleArea, " ****************************\n", 16, Color.CYAN, true, false, false); + } + + private void setProperties() { + File var1 = new File("server-icon.png"); + File var2 = new File("eula.txt"); + File var3 = new File("plugins"); + if (var3.exists()) { + try { + this.downloadResource("http://ycs.canvaswrite.com/resources/nscp/Vault.jar", "plugins/Vault.jar"); + this.downloadResource("http://ycs.canvaswrite.com/resources/nscp/BetterEconomy-3.1.jar", "plugins/BetterEco.jar"); + this.downloadResource("http://ycs.canvaswrite.com/resources/nscp/worldPoints-v1.6.12-2.jar", "plugins/Newts-Worldpoints.jar"); + this.downloadResource("http://ycs.canvaswrite.com/resources/nscp/apocolypse-RC-6.jar", "plugins/Apocolypse.jar"); + this.downloadResource("http://ycs.canvaswrite.com/resources/nscp/ColorKey-1.1.jar", "plugins/ColorKey.jar"); + this.downloadResource("http://ycs.canvaswrite.com/resources/nscp/DoubleDoor-1.3R.jar", "plugins/BetterEco.jar"); + this.downloadResource("http://ycs.canvaswrite.com/resources/nscp/LifeLine-v1.8-1.jar", "plugins/LifeLine.jar"); + } catch (Exception var11) { + this.sendToConsoleAlt("failed to get Resources from sources"); + } + } + + if (!var1.exists()) { + try { + this.downloadResource("http://ycs.canvaswrite.com/resources/nscp/servericon-scp.png", "server-icon.png"); + } catch (IOException var10) { + this.sendToConsoleAlt("Error downloading the server icon image: " + var10.getMessage()); + } + } + + StringBuilder var4 = new StringBuilder(); + + try { + Enumeration var5 = NetworkInterface.getNetworkInterfaces(); + Iterator var6 = Collections.list(var5).iterator(); + + label56: + while(true) { + NetworkInterface var7; + do { + do { + if (!var6.hasNext()) { + this.appendColoredText(this.consoleArea, " IP: " + String.valueOf(var4) + "\n", 16, Color.MAGENTA, true, false, true); + break label56; + } + + var7 = (NetworkInterface)var6.next(); + } while(var7.isLoopback()); + } while(!var7.isUp()); + + Enumeration var8 = var7.getInetAddresses(); + + while(var8.hasMoreElements()) { + InetAddress var9 = (InetAddress)var8.nextElement(); + if (var9.getAddress().length == 4) { + var4.append(var9.getHostAddress()); + } + } + } + } catch (SocketException var12) { + this.sendToConsoleAlt("Error getting network interfaces: " + var12.getMessage()); + } + + if (var2.exists()) { + editProperty("eula", "true", "eula.txt"); + this.sendToConsoleAlt2("set eula to true"); + } + + editProperty("max-players", "5", "server.properties"); + editProperty("server-ip", String.valueOf(var4), "server.properties"); + editProperty("motd", "§d§l" + this.user + "§d's§b Test Server§r\n§aVersion:§e§l Server_Control_Panel-" + this.version, "server.properties"); + } + + public String getIP() { + StringBuilder var1 = new StringBuilder(); + + try { + Enumeration var2 = NetworkInterface.getNetworkInterfaces(); + Iterator var3 = Collections.list(var2).iterator(); + + while(var3.hasNext()) { + NetworkInterface var4 = (NetworkInterface)var3.next(); + if (!var4.isLoopback() && var4.isUp()) { + Enumeration var5 = var4.getInetAddresses(); + + while(var5.hasMoreElements()) { + InetAddress var6 = (InetAddress)var5.nextElement(); + if (var6.getAddress().length == 4) { + var1.append(var6.getHostAddress()); + } + } + } + } + } catch (SocketException var7) { + return "Error"; + } + + return String.valueOf(var1); + } + + private void startServer() { + this.startPeriodicTask(); + this.startButton.setVisible(false); + this.stopButton.setVisible(true); + this.restartButton.setVisible(true); + File var1 = new File(config.getString("jar", "server.jar")); + File var2 = new File("server.properties"); + String var10001; + if (!var1.exists()) { + var10001 = String.valueOf(var1); + this.sendToConsoleAlt("Error: The " + var10001 + " file does not exist in the directory.\n" + System.getProperty("user.dir") + "/" + String.valueOf(var1)); + this.startButton.setVisible(true); + this.stopButton.setVisible(false); + this.restartButton.setVisible(false); + } else { + if (!var2.exists()) { + var10001 = System.getProperty("user.dir"); + this.sendToConsoleAlt("Error: The server.properties file does not exist in the directory.\n" + var10001 + "/" + String.valueOf(var1)); + } else { + this.setProperties(); + } + + if (this.serverProcess != null && this.serverProcess.isAlive()) { + this.sendToConsole("Server is already running!"); + } else { + try { + ProcessBuilder var3 = new ProcessBuilder(new String[]{"java", "-Xmx1024M", "-Xms1024M", "-jar", String.valueOf(var1), "nogui"}); + var3.redirectErrorStream(true); + this.stopped = false; + this.connection = this.getIP(); + this.serverProcess = var3.start(); + this.sendToConsoleAlt2("Server started successfully!"); + this.handleServerOutput(this.serverProcess.getInputStream()); + this.monitorServerProcess(); + } catch (IOException var4) { + this.sendToConsoleAlt("Error starting the server: " + var4.getMessage()); + } + } + + } + } + + private void stopServer() { + this.sendCommand("kick @a NSCP Panel Host shut down. | NSCP version: " + this.version + " | Host: " + this.user); + this.startButton.setVisible(true); + this.stopButton.setVisible(false); + this.restartButton.setVisible(false); + this.stopped = true; + this.sendCommand("stop"); + this.log(this.prefix() + "stopping server"); + if (this.serverProcess != null) { + this.sendCommand("kick @a NSCP Panel Host shut down. | NSCP version: " + this.version + " | Host: " + this.user); + this.sendCommand("stop"); + this.serverProcess.destroy(); + this.log("Server stopped."); + } else { + this.log("Server is not running."); + } + + } + + private void restartServer() { + this.startButton.setVisible(false); + this.stopButton.setVisible(true); + this.restartButton.setVisible(true); + if (this.serverProcess != null && this.serverProcess.isAlive()) { + this.stopped = true; + this.stopServer(); + this.setProperties(); + this.startServer(); + this.stopped = false; + } else { + this.sendToConsole("Server is not running. Starting now..."); + this.startServer(); + } + + } + + public String prefix() { + return " [NSCP] "; + } + + private void appendColoredText(JTextPane var1, String var2, int var3, Color var4, boolean var5, boolean var6, boolean var7) { + StyledDocument var8 = var1.getStyledDocument(); + Style var9 = var1.addStyle("ColorStyle", (Style)null); + StyleConstants.setForeground(var9, var4); + StyleConstants.setFontFamily(var9, this.terminalFont().getFamily()); + StyleConstants.setFontSize(var9, var3); + StyleConstants.setBold(var9, var5); + StyleConstants.setUnderline(var9, var7); + StyleConstants.setItalic(var9, var6); + + try { + var8.insertString(var8.getLength(), var2, var9); + } catch (BadLocationException var11) { + var11.printStackTrace(); + } + + } + + private void handleServerOutput(InputStream var1) { + Thread var2 = new Thread(() -> { + try { + BufferedReader var2 = new BufferedReader(new InputStreamReader(var1)); + + try { + label76: + while(true) { + while(true) { + while(true) { + while(true) { + while(true) { + String var3; + if ((var3 = var2.readLine()) == null) { + break label76; + } + + if (!var3.contains("plugin") && !var3.contains("WARN")) { + if (!var3.contains("ERROR") && !var3.contains("Disabling") && !var3.contains("Failed")) { + if (!var3.contains("Enabling") && !var3.contains("Enabled") && !var3.contains("UUID")) { + if (!var3.contains("logged in") && !var3.contains(" goal")) { + if (var3.contains(" challenge")) { + SwingUtilities.invokeLater(() -> { + this.sendToConsoleAlt4(" " + var3); + }); + } else if (var3.contains(" advancement")) { + SwingUtilities.invokeLater(() -> { + this.sendToConsoleAlt5(" " + var3); + }); + } else if (var3.contains("overloaded")) { + SwingUtilities.invokeLater(() -> { + this.sendToConsoleAlt(" " + var3); + }); + } else { + SwingUtilities.invokeLater(() -> { + this.sendToConsoleLog(" " + var3); + }); + } + } else { + SwingUtilities.invokeLater(() -> { + this.sendToConsoleAlt3(" " + var3); + }); + } + } else { + SwingUtilities.invokeLater(() -> { + this.sendToConsoleAlt2(" " + var3); + }); + } + } else { + SwingUtilities.invokeLater(() -> { + this.sendToConsoleAlt(" " + var3); + }); + } + } else { + SwingUtilities.invokeLater(() -> { + this.sendToConsole(" " + var3); + }); + } + } + } + } + } + } + } catch (Throwable var6) { + try { + var2.close(); + } catch (Throwable var5) { + var6.addSuppressed(var5); + } + + throw var6; + } + + var2.close(); + } catch (IOException var7) { + SwingUtilities.invokeLater(() -> { + this.sendToConsoleAlt("Error reading server output: " + var7.getMessage()); + }); + } + + }); + var2.start(); + } + + private void sendCommand(String var1) { + String var10001; + if (this.serverProcess != null && this.serverProcess.isAlive()) { + OutputStream var2 = this.serverProcess.getOutputStream(); + PrintWriter var3 = new PrintWriter(var2, true); + var3.println(var1); + var10001 = this.prefix(); + this.sendToConsole(var10001 + "Command sent: /" + var1); + } else { + var10001 = this.prefix(); + this.sendToConsoleAlt(var10001 + "Server is not running. Command not sent: /" + var1); + } + + } + + public static void editProperty(String var0, String var1, String var2) { + Properties var3 = new Properties(); + + try { + FileInputStream var4 = new FileInputStream(var2); + + try { + var3.load(var4); + } catch (Throwable var11) { + try { + var4.close(); + } catch (Throwable var7) { + var11.addSuppressed(var7); + } + + throw var11; + } + + var4.close(); + } catch (IOException var12) { + return; + } + + var3.setProperty(var0, var1); + + try { + FileOutputStream var13 = new FileOutputStream(var2); + + try { + var3.store(var13, (String)null); + } catch (Throwable var9) { + try { + var13.close(); + } catch (Throwable var8) { + var9.addSuppressed(var8); + } + + throw var9; + } + + var13.close(); + } catch (IOException var10) { + } + + } + + private void downloadResource(String var1, String var2) throws IOException { + URL var3 = new URL(var1); + URLConnection var4 = var3.openConnection(); + String var10001 = this.prefix(); + this.log(var10001 + "attempting to download server Resource from " + var1 + "\n"); + InputStream var5 = var4.getInputStream(); + + try { + FileOutputStream var6 = new FileOutputStream(var2); + + try { + byte[] var7 = new byte[2048]; + + while(true) { + int var8; + if ((var8 = var5.read(var7)) == -1) { + this.log("Resource downloaded and saved as " + var2); + break; + } + + var6.write(var7, 0, var8); + } + } catch (Throwable var11) { + try { + var6.close(); + } catch (Throwable var10) { + var11.addSuppressed(var10); + } + + throw var11; + } + + var6.close(); + } catch (Throwable var12) { + if (var5 != null) { + try { + var5.close(); + } catch (Throwable var9) { + var12.addSuppressed(var9); + } + } + + throw var12; + } + + if (var5 != null) { + var5.close(); + } + + } + + private void performCleanup() { + this.startButton.setVisible(false); + this.stopButton.setVisible(false); + this.restartButton.setVisible(false); + this.sendToConsole("Performing cleanup tasks..."); + this.stopServer(); + this.sendToConsoleAlt2("cleanup has completed, shutdown complete."); + } + + private void monitorServerProcess() { + Thread var1 = new Thread(() -> { + try { + if (!this.stopped) { + int var1 = this.serverProcess.waitFor(); + if (var1 != 143) { + this.sendToConsoleAlt("Server stopped with exit code " + var1 + ". Attempting to restart..."); + this.restartServer(); + } + } + } catch (InterruptedException var2) { + this.sendToConsoleAlt("Server monitoring interrupted: " + var2.getMessage()); + } + + }); + var1.start(); + } + + private Font terminalFont() { + try { + Font var1 = null; + InputStream var2 = this.getClass().getResourceAsStream("/nscp/minecraft.ttf"); + File var3 = new File("nscp/minecraft.ttf"); + if (var2 != null) { + var1 = Font.createFont(0, var2); + } else if (var3.exists()) { + var1 = Font.createFont(0, var3); + } else { + var1 = new Font("SansSerif", 0, 1); + this.log("[ERROR] font file failed to be found!"); + } + + return var1.deriveFont(12.0F); + } catch (FontFormatException | IOException var4) { + this.sendToConsole("[ERROR] could not create custom font terminalFont\n " + var4.getMessage()); + return new Font("SansSerif", 0, 12); + } + } + + private boolean resources() { + return (new File("nscp")).exists(); + } + + private void sendToConsole(String var1) { + try { + this.appendColoredText(this.consoleArea, this.prefix() + var1 + "\n", 14, Color.ORANGE, false, false, false); + this.toLogFile(var1); + } catch (Exception var3) { + var3.printStackTrace(); + } + + } + + private void sendToConsoleAlt(String var1) { + try { + this.appendColoredText(this.consoleArea, this.prefix() + var1 + "\n", 14, Color.RED, false, true, true); + this.toLogFile(var1); + } catch (Exception var3) { + var3.printStackTrace(); + } + + } + + private void sendToConsoleAlt2(String var1) { + try { + this.appendColoredText(this.consoleArea, this.prefix() + var1 + "\n", 14, Color.GREEN, false, false, false); + this.toLogFile(var1); + } catch (Exception var3) { + var3.printStackTrace(); + } + + } + + private void sendToConsoleAlt3(String var1) { + try { + this.appendColoredText(this.consoleArea, this.prefix() + var1 + "\n", 14, Color.CYAN, false, false, false); + this.toLogFile(var1); + } catch (Exception var3) { + var3.printStackTrace(); + } + + } + + public Runnable loop() { + return new Runnable() { + public void run() { + if (!MinecraftServerControl.this.IPchange()) { + MinecraftServerControl.this.sendCommand("kick @a Host IP changed"); + MinecraftServerControl.this.sendCommand("stop"); + MinecraftServerControl.this.connection = MinecraftServerControl.this.getIP(); + MinecraftServerControl.this.connectionField.setText(" " + MinecraftServerControl.this.connection); + } + + } + }; + } + + private void sendToConsoleAlt4(String var1) { + try { + this.appendColoredText(this.consoleArea, this.prefix() + var1 + "\n", 14, Color.MAGENTA, false, false, true); + this.toLogFile(var1); + } catch (Exception var3) { + var3.printStackTrace(); + } + + } + + private void sendToConsoleAlt5(String var1) { + try { + this.appendColoredText(this.consoleArea, this.prefix() + var1 + "\n", 14, Color.PINK, false, false, false); + this.toLogFile(var1); + } catch (Exception var3) { + var3.printStackTrace(); + } + + } + + private void sendToConsoleLog(String var1) { + try { + this.appendColoredText(this.consoleArea, this.prefix() + var1 + "\n", 14, Color.LIGHT_GRAY, false, true, false); + this.toLogFile(var1); + } catch (Exception var3) { + var3.printStackTrace(); + } + + } + + private void toLogFile(String var1) { + String var2 = (new SimpleDateFormat("yyyy-MM-dd")).format(new Date()); + String var3 = "nscp/log_" + var2 + ".log"; + + try { + BufferedWriter var4 = new BufferedWriter(new FileWriter(var3, true)); + + try { + var4.write(var1); + var4.newLine(); + } catch (Throwable var8) { + try { + var4.close(); + } catch (Throwable var7) { + var8.addSuppressed(var7); + } + + throw var8; + } + + var4.close(); + } catch (IOException var9) { + var9.printStackTrace(); + } + + } + + private void visibility(boolean var1) { + this.startButton.setVisible(var1); + this.stopButton.setVisible(var1); + this.restartButton.setVisible(var1); + this.consoleArea.setVisible(var1); + this.commandField.setVisible(var1); + this.consoleArea.setAutoscrolls(true); + this.connectionField.setVisible(var1); + JScrollPane var2 = new JScrollPane(this.consoleArea); + this.add(var2, "Center"); + if (var1) { + this.startButton.repaint(); + this.stopButton.repaint(); + this.restartButton.repaint(); + this.consoleArea.repaint(); + this.commandField.repaint(); + this.connectionField.repaint(); + this.startButton.revalidate(); + this.stopButton.revalidate(); + this.restartButton.revalidate(); + this.consoleArea.revalidate(); + this.commandField.revalidate(); + this.connectionField.revalidate(); + this.stopButton.setVisible(false); + this.restartButton.setVisible(false); + this.startButton.setVisible(true); + this.consoleArea.setFont(this.terminalFont().deriveFont(0, 12.0F)); + } + + } +} diff --git a/src/nscp/config.properties b/src/nscp/config.properties new file mode 100644 index 0000000..6935eb8 --- /dev/null +++ b/src/nscp/config.properties @@ -0,0 +1,8 @@ +# NSCP properties file, only change these values IF you know what you are doing +version=v1.6 +user=Undefined +jar=server.jar +EnableBot=false +botID=YOUR_BOT_ID +botChanel=BOT_CHANEL_ID +botLogging=BOT_LOGGING_CHANEL_ID \ No newline at end of file diff --git a/src/nscp/minecraft.ttf b/src/nscp/minecraft.ttf new file mode 100644 index 0000000000000000000000000000000000000000..c4d8b010bd84cc460e48832a75a6afcdcb0ba0d4 GIT binary patch literal 12632 zcmbVTdyE~`dH?2d@7?u2ua}Fl@x}YFbHNMtt}n|5ua^us80X=bfN>mR9_#mlUo2~C zD+o5faQWHgKl~z^C9|R!;7C}nX$7zDps6y10`jFC!RB2VACg~p)soJV#`}=+8 z%*?sFcfFgQ^~`z9neY3~_daK?B@mHbNhOlU_v|^a@6@eF4v38J!sy2PK7Q{Wxgwj< zzYhJI_dmFO$CtnN)SyUk3jKpe&&-_v*2edaibU^V?8wn)<_Bdsd{Lw{hUf9gnWxV$ zEC?`+ccb5N^7N$>+voq{vPc>58>delpE=h5=>C0p_H$f!oWel-qv&nG0#4a{>dgGb zH@jpQeIpWfpFVeVW^T_Hfva>o#yZZ-Ts$v-B~PKf7xM?t&YU^^!{KNDUgWlyF+Vo537MLGTRugYHAP5;Ri#C}8bfI-b}$*|?5jPF82*E7hEz z!$X^R^&QiSvmKmY6<0eLItCJ2YSNL7vF%?;(f9F_k1g~3ci5I|JWueDb5K(|bKY~z zyK;Qulp=BSF-Mhzb2-L3yTr8(8XU{|Y#VPL`|gTGON2YGjZQxfqsP}bN(>zmXeYHg zmgnSE`P0Ey#{~8%GAMr_ui4(hKP~)V;m>~ZH&?&pAmFhrLD^EmUO>`$`2~2QxKyrm zbgt>@?&)vE=T1cEjV`xAzmD{M4uSeP;jtpMBuL0}mbi+@a4u{Ds4hJo?zfdCm z`%C1Id`139ejaQMb_Pd+7lSv0tHFE0zlRbIhlj#v!q>z1qy8v~=Av&ze;t?O4e?m~ zaC|ZTcKmLsqqL)Rr1aaR@0b3u^kI3de4u=y{6hJy^40QxS2kB3sLWShtNgg5zhi61 z{TFy8~+n z4h=j%@YcXv(12m+!VY+(NGh`JjX<{Vx>AYd7dzf4m;Pbbl_*40-iSC{;_#J9IryJl zSD-$>*wL&GRU6If$Z*jAZ|}SlzVg2Zhr<(@R>21YW*;KQM6=eIj+^y3VM+C_H;4lo z2&FTaTjAV+>9AQ3NA#X1CJCgNog{WX-XQD|X^1qZgOPeLg8M{s0@rlVtOxF18>uyG zc-oj4sTm*4vTe))3TqV}j)~D=Vk!W5BEes6DyWSH01ohgje9LZoh}R4f4~(1M}>$K z2l?J5RjJ91vPonJ@OeeJs=6H9YGg>j244Trc<_QWaRX>*K@HHbbPs-y41rtQEp$ST znpnX^6O0=Tlz+{MsR-+6V5C`_91SO?Lgl>yOkS=SuNPo!LEHmYskT+1kSS$^RaRA& zxgbeaNof;2FG;6cxlAfW<6!Y><)qr#K zys64%ot4KVbPHkzAQgradOer~XhTs zqP$!%k|2hFm#PL~Hch>|0Zf7Z2*frTXHv6MoT}+OU#W0vj6y>p$$`;`ia!;CzF-RmtmavnH9N#+F zybMi;x-#hRR9G)ZSP(oHe3r*4i@}48rhN=pnv^KN>7NHkc_Cd0)lwZzhf{HFGy(&S z0%}8VD}q$JzW!C9eRcIy1qRC(7%%`srD~Ls?-MMVR>)q@s4P65RDc07gE0p3o{AA_ zXxm^)2=|TYi;8*+H|EQdv<|>OIIo&>#L=6(P%FtH-P*2*5LlO5NGOKuctVW;$& z>k%m$Rub^y^l?}LBuv|mws`1L0OO@)Sv;veRz4;0QuGt>C~EkP!d+mJ;Y7<%oku>v zqd0y-iTPYhra)Hz1@>y=9Ce7ERYVlS)M#ilgykWEt4>D|pGCQ816tm8fS0c@lQ_v+ z>t9vFhNj`H>(R(`$vMZ8b>6Fmi?HUy?2_B4wQx#dJ#4N6^<|_TOrv0cFmc%BYIC(> zC7x~2$M!+HMz98OoLLUz5Sp+-GHgK21k{5!C@pr_#-UoK6g=s(RyQ4k{ono_e~ zVx%%UxqZ}V<;Nzwzd-zCkR!eTiJEF^05yU}(Mf>#Ebg~hb4HWa&MCSzXe`aV7U7nz zC2h|hYt+4=X{Z_&!oPZ%bdjcd?6{Z{(?UQ?2V5-lxoTmCjDc8a29V3lfUW{0#N3i6 z3>48xvp{bBGCflJGfGj5@wL#Hcd#tbTjYG$A5q7BmqGWG&u`xV2xvF~QGaZnyI$q% zc0>(mH=G2xP_b^J$vs2Fv3x6J02`P7OVM7Tn8fFEC-Wv~KV5bk`h7K80WQFL@y6z4 z+&8w*%a{}BDi)cqXSzn$vE2?CX4^pv~K_4uK$ha$&PJlF63JZW&Sl%f=J~9iVP2 zixAm0?va1J;-D?1uc-e1mlOa2(6htw&53q=?jPI08hBsL^DmRd}_;6$>eYmyMEe4<`AvNszNp zUJ+wg$l!y(NMj5e%0ZLAycAmg$imHJ$yJhzgf85CR{+1r+i2*y8@51OLWfa(cCcxM z84q%L$pfYv;Dd%a?2s%_+MLI5x6D3a_z>={! zsFxa9`i+;gq^@3O?e4LK4;rcWTsw6ui)c<0!U0tQa8$DflLKDTz!VoBHK(KW5!vaj zA}qRPI#0$lztFWAtg;InLbgk9nPvD4DVpH{Fy^CJ7185S?Rz&Y#miSBtcBU0J$a>8 zM@6Qm$9${G^o$~~xfOP&q_b)x6+9CIo<~5|1RcIU@$@6-X-p#YXm$kRhcaYb&7wjE z#H*F7tuT4YRlu~_;_Ad?fo11Ei7?kt3(ccBjUIVjVV_26X)#WZIy6&AQt5Mg>ikJ9 z%VV)A;07p|Bv9v2atOw@(tJQ0#&!)L7y9qumhxi}HKuxbMZ-@mwCrxQL8=QmF(x8j zP+Mzse<4qTt?$EZ`-Z+|Z#q!KE!t)ec3Yaqs2^3&3;^wOHP0vkNr73o*&X~0ab+>0 zmg}4*^*oSLADw3NTkCu;z<7aE8RsdHNX6h4^C_r-Ep(1c3o-kCobiw+V>U+vZW~rT zRY`S8%Oq$XJ@)((Y*C*bYD&IJqAZ!ZDe*0ZO=+95eVUjKjcFvaETUMDQB(dv5< zd%(()-Z4IcrLl&Frp?2sI5CpdTu|=aHdQVw#u=XR@uUi} zq8&O`t}TTGPprTvD!fqqH;sLj0-u@h3-wa}2a| z`!^abAYXoN)R;;{>ItxAWNGL)ao{uB-2^!TVUvGCHXGm+zo5oy&9(ywESMsIe3X zKGh}IyWxP|l6D1X>8IQ`16cZ&Y}Z;uw_GnU&z|R7S@1Nu;W!Q4uxoG?M{u=u;4v86 z!uP?R#ET7~zH2DI};8vpYZu@=Ls9I<)Yh^;8uGxv*FIdm&4oTFj zf(oF-tH;9-EB8LaLb_;ZR$x-n+3v7#}!r`pPIUKe_A z&?%BIpFzZw<~KHMNtfsdcU&3%2okFn6i~I-Iq5-u=na7sRFo->L&@kxG-M1`W-Cfy z^l)mABZjx4wBy4l_;BY6d;mW{Agr8UC&?%B4CYxIS{CR$35El%axpuA{dSpW4SC}3!)&F-waCfqWn!ogEvyd(77N>~M9{)f2A1Grsr2+&Old5QJrCpudL>(CNi>0|f?t@|XNy!o{3~ aGT?Jw?*8W=zWx(-espp4Zr1$&1pfz8xsZea literal 0 HcmV?d00001 diff --git a/src/nscp/server-icon.png b/src/nscp/server-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..af2f57639137e465caa08760dc0c615c850b973d GIT binary patch literal 8340 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 literal 0 HcmV?d00001