From 30c1a3eb9de255874c5fd05f44c089a9bee28826 Mon Sep 17 00:00:00 2001 From: rattatwinko Date: Mon, 14 Jul 2025 01:37:50 +0200 Subject: [PATCH] shitfuckanalsex. --- pom.xml | 20 + .../mcmanage/EnhancedServerManagerUI.java | 495 ++++++++++++++---- src/main/java/mcmanage/JSONManager.java | 25 + src/main/java/mcmanage/ServerManager.java | 34 +- 4 files changed, 465 insertions(+), 109 deletions(-) diff --git a/pom.xml b/pom.xml index f4a08ac..d0c890e 100644 --- a/pom.xml +++ b/pom.xml @@ -64,6 +64,26 @@ mcmanage.Main + + org.apache.maven.plugins + maven-shade-plugin + 3.2.4 + + + package + + shade + + + + + mcmanage.Main + + + + + + diff --git a/src/main/java/mcmanage/EnhancedServerManagerUI.java b/src/main/java/mcmanage/EnhancedServerManagerUI.java index 0f78335..e2cd2f8 100644 --- a/src/main/java/mcmanage/EnhancedServerManagerUI.java +++ b/src/main/java/mcmanage/EnhancedServerManagerUI.java @@ -7,6 +7,86 @@ import java.util.List; import java.util.ArrayList; import java.util.concurrent.ExecutionException; import com.formdev.flatlaf.FlatLightLaf; +import javax.swing.border.TitledBorder; +import java.io.File; +import java.util.HashSet; +import java.util.Set; +import java.util.Map; +import java.util.HashMap; +import javax.swing.ListCellRenderer; +import java.awt.image.BufferedImage; + +class AddServerWizard extends JDialog { + private JTextField nameField = new JTextField(15); + private JTextField portField = new JTextField(5); + private JTextField ramField = new JTextField(3); + private JComboBox versionsComboBox; + private boolean confirmed = false; + + // Standard wizard for normal use + public AddServerWizard(JFrame parent, List versions) { + this(parent, versions, null); + } + // Recovery wizard with version + public AddServerWizard(JFrame parent, List versions, String fixedVersion) { + super(parent, "Add Server", true); + setLayout(new BorderLayout(10, 10)); + JPanel panel = new JPanel(); + panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); + panel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15)); + panel.add(new JLabel("Server Name:")); + panel.add(nameField); + panel.add(Box.createRigidArea(new Dimension(0, 5))); + panel.add(new JLabel("Port:")); + panel.add(portField); + panel.add(Box.createRigidArea(new Dimension(0, 5))); + panel.add(new JLabel("RAM (GB):")); + panel.add(ramField); + panel.add(Box.createRigidArea(new Dimension(0, 5))); + panel.add(new JLabel("Paper Version:")); + versionsComboBox = new JComboBox<>(versions.toArray(new String[0])); + panel.add(versionsComboBox); + if (fixedVersion != null) { + boolean found = false; + for (int i = 0; i < versionsComboBox.getItemCount(); i++) { + if (fixedVersion.equals(versionsComboBox.getItemAt(i))) { + versionsComboBox.setSelectedItem(fixedVersion); + found = true; + break; + } + } + if (!found) { + versionsComboBox.addItem(fixedVersion); + versionsComboBox.setSelectedItem(fixedVersion); + } + versionsComboBox.setEnabled(false); + } + panel.add(Box.createRigidArea(new Dimension(0, 10))); + JButton confirmButton = new JButton("Create"); + confirmButton.addActionListener(e -> { + boolean versionRequired = versionsComboBox.isEnabled(); + if (nameField.getText().trim().isEmpty() || + portField.getText().trim().isEmpty() || + ramField.getText().trim().isEmpty() || + (versionRequired && versionsComboBox.getSelectedItem() == null)) { + JOptionPane.showMessageDialog(this, "Please fill all fields" + (versionRequired ? " and select a version" : ""), "Input Error", JOptionPane.ERROR_MESSAGE); + return; + } + confirmed = true; + setVisible(false); + }); + panel.add(confirmButton); + add(panel, BorderLayout.CENTER); + pack(); + setLocationRelativeTo(parent); + } + public boolean isConfirmed() { return confirmed; } + public String getNameField() { return nameField.getText().trim(); } + public String getPortField() { return portField.getText().trim(); } + public String getRamField() { return ramField.getText().trim(); } + public String getVersion() { return (String) versionsComboBox.getSelectedItem(); } + public void setNameField(String name) { nameField.setText(name); } +} public class EnhancedServerManagerUI extends JFrame { static { @@ -26,70 +106,122 @@ public class EnhancedServerManagerUI extends JFrame { private JButton addButton = new JButton("Add Server"); private JButton saveButton = new JButton("Save Servers"); private JButton fetchVersionsButton = new JButton("Fetch Paper Versions"); - private JButton downloadJarButton = new JButton("Download JAR"); private JButton startServerButton = new JButton("Start Server"); private JButton stopServerButton = new JButton("Stop Server"); private JButton sendCommandButton = new JButton("Send Command"); private JTextField commandField = new JTextField(20); private JTextArea consoleOutput = new JTextArea(20, 60); private JScrollPane consoleScrollPane = new JScrollPane(consoleOutput); + private JButton playerManagerButton = new JButton("Player Manager"); + + private final Map> playerListCache = new HashMap<>(); + private final Map> playerListListeners = new HashMap<>(); + + private static class ServerStatusCellRenderer extends JLabel implements ListCellRenderer { + private static final Icon ICON_RUNNING = createStatusIcon(new Color(0, 180, 0), '✔'); + private static final Icon ICON_STOPPED = createStatusIcon(new Color(160, 160, 160), '●'); + private static final Icon ICON_CRASHED = createStatusIcon(new Color(200, 0, 0), '✖'); + public ServerStatusCellRenderer() { + setOpaque(true); + setFont(new Font(Font.SANS_SERIF, Font.PLAIN, 14)); + setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); + } + @Override + public Component getListCellRendererComponent(JList list, ServerManager.ServerInstance value, int index, boolean isSelected, boolean cellHasFocus) { + setText(value.name + " (" + value.version + ":" + value.port + ", " + value.ramGB + "GB)"); + if (value.isRunning) { + setIcon(ICON_RUNNING); + } else { + setIcon(ICON_STOPPED); + } + setBackground(isSelected ? new Color(220, 240, 255) : Color.WHITE); + setForeground(Color.BLACK); + return this; + } + private static Icon createStatusIcon(Color color, char symbol) { + int size = 18; + BufferedImage img = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB); + Graphics2D g = img.createGraphics(); + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g.setColor(color); + g.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 16)); + if (symbol == '✔') { + g.drawString("✔", 2, size-4); + } else if (symbol == '✖') { + g.drawString("✖", 2, size-4); + } else { + g.fillOval(3, 3, size-6, size-6); + } + g.dispose(); + return new ImageIcon(img); + } + } public EnhancedServerManagerUI() { super("Enhanced Minecraft Server Manager"); - - setLayout(new BorderLayout()); + setLayout(new BorderLayout(10, 10)); + getContentPane().setBackground(new Color(245, 245, 245)); // Initialize directories ServerManager.initializeDirectories(); + // Fetch Paper versions at startup + fetchVersionsAtStartup(); + // Left panel - server list and controls - JPanel leftPanel = new JPanel(new BorderLayout()); - - // Server list - leftPanel.add(new JLabel("Server Instances:"), BorderLayout.NORTH); - leftPanel.add(new JScrollPane(serverList), BorderLayout.CENTER); - - // Control buttons - JPanel controlPanel = new JPanel(new GridLayout(2, 2, 5, 5)); + JPanel leftPanel = new JPanel(new BorderLayout(10, 10)); + leftPanel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 10)); + leftPanel.setBackground(new Color(250, 250, 250)); + + JLabel serverListLabel = new JLabel("Server Instances:"); + serverListLabel.setFont(serverListLabel.getFont().deriveFont(Font.BOLD, 16f)); + leftPanel.add(serverListLabel, BorderLayout.NORTH); + + JScrollPane serverListScroll = new JScrollPane(serverList); + serverListScroll.setBorder(BorderFactory.createTitledBorder("Servers")); + leftPanel.add(serverListScroll, BorderLayout.CENTER); + + JPanel controlPanel = new JPanel(new GridLayout(2, 2, 10, 10)); + controlPanel.setBorder(BorderFactory.createTitledBorder("Server Controls")); + controlPanel.setBackground(new Color(250, 250, 250)); controlPanel.add(startServerButton); controlPanel.add(stopServerButton); - controlPanel.add(downloadJarButton); controlPanel.add(sendCommandButton); + controlPanel.add(playerManagerButton); leftPanel.add(controlPanel, BorderLayout.SOUTH); // Right panel - input and console - JPanel rightPanel = new JPanel(new BorderLayout()); - + JPanel rightPanel = new JPanel(new BorderLayout(10, 10)); + rightPanel.setBorder(BorderFactory.createEmptyBorder(15, 10, 15, 15)); + rightPanel.setBackground(new Color(245, 245, 245)); + // Input panel JPanel inputPanel = new JPanel(); inputPanel.setLayout(new BoxLayout(inputPanel, BoxLayout.Y_AXIS)); - inputPanel.add(new JLabel("Server Name:")); - inputPanel.add(nameField); - inputPanel.add(new JLabel("Port:")); - inputPanel.add(portField); - inputPanel.add(new JLabel("RAM (GB):")); - inputPanel.add(ramField); - inputPanel.add(new JLabel("Paper Version:")); - inputPanel.add(versionsComboBox); - - JPanel buttonPanel = new JPanel(new GridLayout(3, 1, 5, 5)); + inputPanel.setBorder(BorderFactory.createTitledBorder("Server Actions")); + inputPanel.setBackground(new Color(250, 250, 250)); + inputPanel.add(Box.createRigidArea(new Dimension(0, 10))); + JPanel buttonPanel = new JPanel(new GridLayout(1, 3, 10, 10)); + buttonPanel.setBackground(new Color(250, 250, 250)); buttonPanel.add(addButton); buttonPanel.add(saveButton); buttonPanel.add(fetchVersionsButton); inputPanel.add(buttonPanel); - rightPanel.add(inputPanel, BorderLayout.NORTH); - + // Console panel - JPanel consolePanel = new JPanel(new BorderLayout()); - consolePanel.add(new JLabel("Server Console:"), BorderLayout.NORTH); + JPanel consolePanel = new JPanel(new BorderLayout(5, 5)); + consolePanel.setBorder(BorderFactory.createTitledBorder("Server Console")); + consolePanel.setBackground(new Color(250, 250, 250)); + JLabel consoleHeader = new JLabel("Console Output"); + consoleHeader.setFont(consoleHeader.getFont().deriveFont(Font.BOLD, 15f)); + consolePanel.add(consoleHeader, BorderLayout.NORTH); consolePanel.add(consoleScrollPane, BorderLayout.CENTER); - - JPanel commandPanel = new JPanel(new BorderLayout()); + JPanel commandPanel = new JPanel(new BorderLayout(5, 5)); + commandPanel.setBackground(new Color(250, 250, 250)); commandPanel.add(new JLabel("Command:"), BorderLayout.WEST); commandPanel.add(commandField, BorderLayout.CENTER); consolePanel.add(commandPanel, BorderLayout.SOUTH); - rightPanel.add(consolePanel, BorderLayout.CENTER); add(leftPanel, BorderLayout.WEST); @@ -98,15 +230,17 @@ public class EnhancedServerManagerUI extends JFrame { // Load saved servers List savedServers = JSONManager.loadServerInstances(); savedServers.forEach(serverListModel::addElement); + // Autodiscover unsaved servers + SwingUtilities.invokeLater(this::recoverUnsavedServers); // Button listeners - addButton.addActionListener(e -> addServer()); + addButton.addActionListener(e -> openAddServerWizard()); saveButton.addActionListener(e -> saveServers()); fetchVersionsButton.addActionListener(e -> fetchVersions()); - downloadJarButton.addActionListener(e -> downloadJar()); startServerButton.addActionListener(e -> startServer()); stopServerButton.addActionListener(e -> stopServer()); sendCommandButton.addActionListener(e -> sendCommand()); + playerManagerButton.addActionListener(e -> openPlayerManager()); // Enter key in command field commandField.addKeyListener(new KeyAdapter() { @@ -122,10 +256,10 @@ public class EnhancedServerManagerUI extends JFrame { addButton.setToolTipText("Add a new server instance"); saveButton.setToolTipText("Save all server configurations"); fetchVersionsButton.setToolTipText("Fetch available PaperMC versions"); - downloadJarButton.setToolTipText("Download the selected PaperMC JAR"); startServerButton.setToolTipText("Start the selected server"); stopServerButton.setToolTipText("Send 'stop' command to the selected server"); sendCommandButton.setToolTipText("Send a command to the server console"); + playerManagerButton.setToolTipText("Manage online players (kick/ban)"); nameField.setToolTipText("Server name (used as directory)"); portField.setToolTipText("Server port (default 25565)"); ramField.setToolTipText("RAM in GB (e.g. 2, 4, 8)"); @@ -137,34 +271,49 @@ public class EnhancedServerManagerUI extends JFrame { setSize(1200, 800); setLocationRelativeTo(null); setVisible(true); + + // Set cell renderer and fixed height for the server list + serverList.setCellRenderer(new ServerStatusCellRenderer()); + serverList.setFixedCellHeight(28); + serverList.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); + + // Add a Swing Timer to refresh the server list state every 10 minutes (600,000 ms): + new javax.swing.Timer(600_000, e -> { + // Optionally, check process state for each server and update isRunning if needed + for (int i = 0; i < serverListModel.size(); i++) { + ServerManager.ServerInstance s = serverListModel.getElementAt(i); + if (s.process != null) { + boolean running = s.process.isAlive(); + if (s.isRunning != running) { + s.isRunning = running; + } + } else { + s.isRunning = false; + } + } + serverList.repaint(); + }).start(); } - private void addServer() { - String name = nameField.getText().trim(); - String portStr = portField.getText().trim(); - String ramStr = ramField.getText().trim(); - String version = (String) versionsComboBox.getSelectedItem(); - - if (name.isEmpty() || portStr.isEmpty() || ramStr.isEmpty() || version == null) { - JOptionPane.showMessageDialog(this, "Please fill all fields and select a version", "Input Error", JOptionPane.ERROR_MESSAGE); - return; + private void openAddServerWizard() { + List versions = new ArrayList<>(); + for (int i = 0; i < versionsComboBox.getItemCount(); i++) { + versions.add(versionsComboBox.getItemAt(i)); } - - int port, ram; - try { - port = Integer.parseInt(portStr); - ram = Integer.parseInt(ramStr); - } catch (NumberFormatException ex) { - JOptionPane.showMessageDialog(this, "Invalid port or RAM number", "Input Error", JOptionPane.ERROR_MESSAGE); - return; + AddServerWizard wizard = new AddServerWizard(this, versions); + wizard.setVisible(true); + if (wizard.isConfirmed()) { + try { + int port = Integer.parseInt(wizard.getPortField()); + int ram = Integer.parseInt(wizard.getRamField()); + ServerManager.ServerInstance server = new ServerManager.ServerInstance(wizard.getNameField(), wizard.getVersion(), port, ram); + serverListModel.addElement(server); + autosaveServers(); + JOptionPane.showMessageDialog(this, "Server added and autosaved!", "Success", JOptionPane.INFORMATION_MESSAGE); + } catch (NumberFormatException ex) { + JOptionPane.showMessageDialog(this, "Invalid port or RAM number", "Input Error", JOptionPane.ERROR_MESSAGE); + } } - - ServerManager.ServerInstance server = new ServerManager.ServerInstance(name, version, port, ram); - serverListModel.addElement(server); - - nameField.setText(""); - portField.setText(""); - ramField.setText(""); } private void saveServers() { @@ -202,72 +351,41 @@ public class EnhancedServerManagerUI extends JFrame { worker.execute(); } - private void downloadJar() { - ServerManager.ServerInstance selected = serverList.getSelectedValue(); - if (selected == null) { - JOptionPane.showMessageDialog(this, "Please select a server first", "Error", JOptionPane.ERROR_MESSAGE); - return; - } - - downloadJarButton.setEnabled(false); - consoleOutput.append("Downloading JAR for version " + selected.version + "...\n"); - - SwingWorker worker = new SwingWorker() { - @Override - protected String doInBackground() throws Exception { - return ServerManager.downloadPaperJar(selected.version); - } - - @Override - protected void done() { - try { - String jarPath = get(); - selected.jarPath = jarPath; - consoleOutput.append("JAR downloaded successfully: " + jarPath + "\n"); - - // Setup server directory - ServerManager.setupServerDirectory(selected); - consoleOutput.append("Server directory setup complete for: " + selected.name + "\n"); - - } catch (Exception e) { - consoleOutput.append("Error downloading JAR: " + e.getMessage() + "\n"); - e.printStackTrace(); - } finally { - downloadJarButton.setEnabled(true); - } - } - }; - - worker.execute(); - } - private void startServer() { ServerManager.ServerInstance selected = serverList.getSelectedValue(); if (selected == null) { JOptionPane.showMessageDialog(this, "Please select a server first", "Error", JOptionPane.ERROR_MESSAGE); return; } - if (selected.jarPath == null || selected.jarPath.isEmpty()) { - JOptionPane.showMessageDialog(this, "Please download the JAR first", "Error", JOptionPane.ERROR_MESSAGE); - return; + // Determine expected JAR path + String expectedJar = "jars/paper-" + selected.version + "-latest.jar"; // or use build if available + selected.jarPath = expectedJar; } - + File jarFile = new File(selected.jarPath); + if (!jarFile.exists()) { + JOptionPane.showMessageDialog(this, "JAR not found, downloading...", "Info", JOptionPane.INFORMATION_MESSAGE); + try { + selected.jarPath = ServerManager.downloadPaperJar(selected.version); + autosaveServers(); // Save the new jarPath + JOptionPane.showMessageDialog(this, "JAR downloaded successfully!", "Success", JOptionPane.INFORMATION_MESSAGE); + } catch (Exception e) { + JOptionPane.showMessageDialog(this, "Failed to download JAR: " + e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); + return; + } + } + // Now start the server as before startServerButton.setEnabled(false); consoleOutput.append("Starting server: " + selected.name + "\n"); - SwingWorker worker = new SwingWorker() { @Override protected Void doInBackground() throws Exception { ServerManager.startServer(selected, consoleOutput); return null; } - @Override protected void done() { - try { - get(); - } catch (Exception e) { + try { get(); } catch (Exception e) { consoleOutput.append("Error starting server: " + e.getMessage() + "\n"); e.printStackTrace(); } finally { @@ -275,7 +393,6 @@ public class EnhancedServerManagerUI extends JFrame { } } }; - worker.execute(); } @@ -307,6 +424,170 @@ public class EnhancedServerManagerUI extends JFrame { commandField.setText(""); } + private void autosaveServers() { + List servers = new ArrayList<>(); + for (int i = 0; i < serverListModel.size(); i++) { + servers.add(serverListModel.getElementAt(i)); + } + JSONManager.saveServerInstances(servers); + } + + private void fetchVersionsAtStartup() { + fetchVersionsButton.setEnabled(false); + versionsComboBox.removeAllItems(); + SwingWorker, Void> worker = new SwingWorker, Void>() { + @Override + protected List doInBackground() throws Exception { + return PaperAPIClient.fetchPaperVersions(); + } + @Override + protected void done() { + try { + List versions = get(); + versions.forEach(versionsComboBox::addItem); + } catch (Exception e) { + JOptionPane.showMessageDialog(EnhancedServerManagerUI.this, "Failed to fetch Paper versions at startup: " + e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); + } finally { + fetchVersionsButton.setEnabled(true); + } + } + }; + worker.execute(); + } + + private void recoverUnsavedServers() { + File serversDir = new File("servers"); + if (!serversDir.exists() || !serversDir.isDirectory()) return; + // Build a set of known server names + Set knownNames = new HashSet<>(); + for (int i = 0; i < serverListModel.size(); i++) { + knownNames.add(serverListModel.getElementAt(i).name); + } + File[] dirs = serversDir.listFiles(File::isDirectory); + if (dirs == null) return; + for (File dir : dirs) { + if (!knownNames.contains(dir.getName())) { + // Try to find a paper--.jar + String foundVersion = null; + File[] files = dir.listFiles((d, name) -> name.startsWith("paper-") && name.endsWith(".jar")); + if (files != null && files.length > 0) { + String jarName = files[0].getName(); + // Extract version from paper--.jar + // e.g. paper-1.20.1-123.jar + int dash1 = jarName.indexOf('-'); + int dash2 = jarName.indexOf('-', dash1 + 1); + int dotJar = jarName.lastIndexOf(".jar"); + if (dash1 != -1 && dash2 != -1 && dotJar != -1) { + foundVersion = jarName.substring(dash1 + 1, dash2); + } + } + List versions = new ArrayList<>(); + for (int i = 0; i < versionsComboBox.getItemCount(); i++) { + versions.add(versionsComboBox.getItemAt(i)); + } + AddServerWizard wizard = new AddServerWizard(this, versions, foundVersion); + wizard.setNameField(dir.getName()); + JOptionPane.showMessageDialog(this, "Recovered server directory: " + dir.getName() + "\nPlease enter the missing info." + (foundVersion != null ? "\nVersion detected: " + foundVersion : "\nNo JAR found, please select version."), "Recovery", JOptionPane.WARNING_MESSAGE); + wizard.setVisible(true); + if (wizard.isConfirmed()) { + try { + int port = Integer.parseInt(wizard.getPortField()); + int ram = Integer.parseInt(wizard.getRamField()); + ServerManager.ServerInstance server = new ServerManager.ServerInstance(wizard.getNameField(), wizard.getVersion(), port, ram); + serverListModel.addElement(server); + autosaveServers(); + JOptionPane.showMessageDialog(this, "Recovered and saved server: " + dir.getName(), "Recovery Success", JOptionPane.INFORMATION_MESSAGE); + } catch (NumberFormatException ex) { + JOptionPane.showMessageDialog(this, "Invalid port or RAM number for recovered server: " + dir.getName(), "Input Error", JOptionPane.ERROR_MESSAGE); + } + } + } + } + } + + private void openPlayerManager() { + ServerManager.ServerInstance selected = serverList.getSelectedValue(); + if (selected == null || !selected.isRunning) { + JOptionPane.showMessageDialog(this, "Please select a running server first", "Error", JOptionPane.ERROR_MESSAGE); + return; + } + JDialog dialog = new JDialog(this, "Player Manager", true); + dialog.setLayout(new BorderLayout(10, 10)); + dialog.setSize(350, 300); + dialog.setLocationRelativeTo(this); + JPanel panel = new JPanel(); + panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); + panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + JLabel label = new JLabel("Online players:"); + DefaultListModel playerListModel = new DefaultListModel<>(); + JList playerList = new JList<>(playerListModel); + JScrollPane playerScroll = new JScrollPane(playerList); + playerScroll.setPreferredSize(new Dimension(200, 100)); + JButton refreshButton = new JButton("Refresh"); + JButton kickButton = new JButton("Kick"); + JButton banButton = new JButton("Ban"); + panel.add(label); + panel.add(playerScroll); + panel.add(Box.createRigidArea(new Dimension(0, 10))); + JPanel btnPanel = new JPanel(new GridLayout(1, 3, 10, 10)); + btnPanel.add(refreshButton); + btnPanel.add(kickButton); + btnPanel.add(banButton); + panel.add(btnPanel); + dialog.add(panel, BorderLayout.CENTER); + // Loading indicator + label.setText("Loading player list..."); + playerListModel.clear(); + // Register a listener for player list update + playerListListeners.computeIfAbsent(selected, k -> new ArrayList<>()).add(() -> { + List players = playerListCache.getOrDefault(selected, List.of()); + SwingUtilities.invokeLater(() -> { + label.setText("Online players:"); + playerListModel.clear(); + for (String p : players) playerListModel.addElement(p); + }); + }); + // Send 'list' command to server + ServerManager.sendCommand(selected, "list"); + // Refresh button re-sends 'list' + refreshButton.addActionListener(ev -> { + label.setText("Loading player list..."); + playerListModel.clear(); + playerListListeners.computeIfAbsent(selected, k -> new ArrayList<>()).add(() -> { + List players = playerListCache.getOrDefault(selected, List.of()); + SwingUtilities.invokeLater(() -> { + label.setText("Online players:"); + playerListModel.clear(); + for (String p : players) playerListModel.addElement(p); + }); + }); + ServerManager.sendCommand(selected, "list"); + }); + kickButton.addActionListener(ev -> { + String player = playerList.getSelectedValue(); + if (player != null && !player.isEmpty()) { + ServerManager.sendCommand(selected, "kick " + player); + JOptionPane.showMessageDialog(dialog, "Kick command sent for: " + player, "Info", JOptionPane.INFORMATION_MESSAGE); + } + }); + banButton.addActionListener(ev -> { + String player = playerList.getSelectedValue(); + if (player != null && !player.isEmpty()) { + ServerManager.sendCommand(selected, "ban " + player); + JOptionPane.showMessageDialog(dialog, "Ban command sent for: " + player, "Info", JOptionPane.INFORMATION_MESSAGE); + } + }); + dialog.setVisible(true); + } + + public void updatePlayerList(ServerManager.ServerInstance server, List players) { + playerListCache.put(server, players); + if (playerListListeners.containsKey(server)) { + for (Runnable r : playerListListeners.get(server)) r.run(); + playerListListeners.get(server).clear(); + } + } + public static void main(String[] args) { SwingUtilities.invokeLater(EnhancedServerManagerUI::new); } diff --git a/src/main/java/mcmanage/JSONManager.java b/src/main/java/mcmanage/JSONManager.java index c55d684..4521a9e 100644 --- a/src/main/java/mcmanage/JSONManager.java +++ b/src/main/java/mcmanage/JSONManager.java @@ -9,6 +9,8 @@ import java.io.File; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; +import java.util.HashSet; +import java.util.Set; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; @@ -73,4 +75,27 @@ public class JSONManager { System.err.println("Failed to rename temp file to server_instances.json"); } } + + private static final String DOWNLOADED_JARS_FILE = "downloaded_jars.json"; + public static Set loadDownloadedJars() { + File file = new File(DOWNLOADED_JARS_FILE); + if (!file.exists()) return new HashSet<>(); + try (Reader reader = new FileReader(file)) { + Gson gson = new Gson(); + Type setType = new TypeToken>(){}.getType(); + Set set = gson.fromJson(reader, setType); + return set != null ? set : new HashSet<>(); + } catch (Exception e) { + e.printStackTrace(); + return new HashSet<>(); + } + } + public static void saveDownloadedJars(Set jars) { + try (Writer writer = new FileWriter(DOWNLOADED_JARS_FILE)) { + Gson gson = new Gson(); + gson.toJson(jars, writer); + } catch (IOException e) { + e.printStackTrace(); + } + } } diff --git a/src/main/java/mcmanage/ServerManager.java b/src/main/java/mcmanage/ServerManager.java index 9f6685f..92be5b2 100644 --- a/src/main/java/mcmanage/ServerManager.java +++ b/src/main/java/mcmanage/ServerManager.java @@ -7,6 +7,7 @@ import java.nio.file.*; import java.util.*; import java.util.concurrent.*; import javax.swing.*; +import java.awt.Frame; public class ServerManager { @@ -35,8 +36,7 @@ public class ServerManager { @Override public String toString() { - String status = isRunning ? " [RUNNING]" : " [STOPPED]"; - return name + " (" + version + ":" + port + ", " + ramGB + "GB)" + status; + return name; } } @@ -181,12 +181,42 @@ public class ServerManager { CompletableFuture.runAsync(() -> { try { String line; + boolean[] expectPlayerListLine = {false}; while ((line = server.consoleReader.readLine()) != null) { final String outputLine = line; SwingUtilities.invokeLater(() -> { consoleOutput.append(outputLine + "\n"); consoleOutput.setCaretPosition(consoleOutput.getDocument().getLength()); }); + // Add logic to detect and parse player list lines, and call updatePlayerList on the main UI if found. + // Example: + if (outputLine.matches(".*There are \\d+/\\d+ players online:.*")) { + expectPlayerListLine[0] = true; + // Optionally, clear previous player list + SwingUtilities.invokeLater(() -> { + for (Frame f : Frame.getFrames()) { + if (f instanceof EnhancedServerManagerUI) { + ((EnhancedServerManagerUI) f).updatePlayerList(server, new ArrayList<>()); + } + } + }); + } else if (expectPlayerListLine[0]) { + String names = outputLine.replaceFirst("^\\[[^\\]]*\\] \\w+: ", "").trim(); + if (!names.isEmpty()) { + List players = new ArrayList<>(); + for (String p : names.split(", ")) { + if (!p.isBlank()) players.add(p.trim()); + } + SwingUtilities.invokeLater(() -> { + for (Frame f : Frame.getFrames()) { + if (f instanceof EnhancedServerManagerUI) { + ((EnhancedServerManagerUI) f).updatePlayerList(server, players); + } + } + }); + } + expectPlayerListLine[0] = false; + } } } catch (IOException e) { System.err.println("Error reading console output: " + e.getMessage());