shitfuckanalsex.
All checks were successful
Maven Build / build (push) Successful in 10m24s

This commit is contained in:
2025-07-14 01:37:50 +02:00
parent 9e47ffc8cb
commit 30c1a3eb9d
4 changed files with 465 additions and 109 deletions

20
pom.xml
View File

@@ -64,6 +64,26 @@
<mainClass>mcmanage.Main</mainClass>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>mcmanage.Main</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -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<String> versionsComboBox;
private boolean confirmed = false;
// Standard wizard for normal use
public AddServerWizard(JFrame parent, List<String> versions) {
this(parent, versions, null);
}
// Recovery wizard with version
public AddServerWizard(JFrame parent, List<String> 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<ServerManager.ServerInstance, List<String>> playerListCache = new HashMap<>();
private final Map<ServerManager.ServerInstance, List<Runnable>> playerListListeners = new HashMap<>();
private static class ServerStatusCellRenderer extends JLabel implements ListCellRenderer<ServerManager.ServerInstance> {
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<? extends ServerManager.ServerInstance> 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<ServerManager.ServerInstance> 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<String> 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<String, Void> worker = new SwingWorker<String, Void>() {
@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<Void, Void> worker = new SwingWorker<Void, Void>() {
@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<ServerManager.ServerInstance> 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<List<String>, Void> worker = new SwingWorker<List<String>, Void>() {
@Override
protected List<String> doInBackground() throws Exception {
return PaperAPIClient.fetchPaperVersions();
}
@Override
protected void done() {
try {
List<String> 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<String> 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-<version>-<build>.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-<version>-<build>.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<String> 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<String> playerListModel = new DefaultListModel<>();
JList<String> 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<String> 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<String> 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<String> 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);
}

View File

@@ -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<String> 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<Set<String>>(){}.getType();
Set<String> set = gson.fromJson(reader, setType);
return set != null ? set : new HashSet<>();
} catch (Exception e) {
e.printStackTrace();
return new HashSet<>();
}
}
public static void saveDownloadedJars(Set<String> jars) {
try (Writer writer = new FileWriter(DOWNLOADED_JARS_FILE)) {
Gson gson = new Gson();
gson.toJson(jars, writer);
} catch (IOException e) {
e.printStackTrace();
}
}
}

View File

@@ -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<String> 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());