first shit

This commit is contained in:
2025-07-14 00:50:47 +02:00
parent 93fba2993f
commit e32a27d4e1
30 changed files with 1374 additions and 1 deletions

3
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,3 @@
{
"java.configuration.updateBuildConfiguration": "automatic"
}

138
README.md
View File

@@ -1,3 +1,139 @@
<<<<<<< HEAD
# mvn_MCMANAGE
manage mc servers with java
manage mc servers with java
=======
# Enhanced Minecraft Server Manager
A comprehensive Java Swing application for managing Minecraft Paper servers with automatic JAR downloading, server launching, and console management.
## Features
- **Server Management**: Create and manage multiple Minecraft server instances
- **Paper Integration**: Fetch and download Paper versions automatically from the official API
- **JAR Management**: Automatic downloading of Paper JAR files with latest builds
- **Server Launching**: Start servers with custom RAM allocation and port configuration
- **Console Integration**: Real-time server console output and command input
- **EULA Handling**: Automatic EULA acceptance and server.properties generation
- **Persistent Storage**: JSON-based configuration saving in the root directory
- **Multi-Server Support**: Manage multiple servers simultaneously
## Requirements
- Java 11 or higher
- Maven 3.6 or higher
- Internet connection (for JAR downloads)
## Building the Project
```bash
mvn clean compile
```
## Running the Application
### Option 1: Using Maven
```bash
mvn exec:java
```
### Option 2: Using JAR file
```bash
mvn clean package
java -jar target/minecraft-server-manager-1.0-SNAPSHOT.jar
```
## Usage Guide
### 1. Creating a Server
1. **Fetch Versions**: Click "Fetch Paper Versions" to load available Paper versions
2. **Add Server**: Fill in the server details:
- **Name**: Server instance name
- **Port**: Server port (default: 25565)
- **RAM**: Memory allocation in GB
- **Version**: Select a Paper version from the dropdown
3. **Save**: Click "Save Servers" to persist your configuration
### 2. Setting Up a Server
1. **Select Server**: Choose a server from the list
2. **Download JAR**: Click "Download JAR" to fetch the Paper server JAR
3. **Automatic Setup**: The system will:
- Create server directory structure
- Generate `eula.txt` (automatically accepted)
- Create `server.properties` with your port
- Copy the JAR to the server directory
### 3. Running a Server
1. **Select Server**: Choose the server you want to start
2. **Start Server**: Click "Start Server" to launch the Minecraft server
3. **Monitor Console**: Watch real-time output in the console area
4. **Send Commands**: Use the command field to send server commands
5. **Stop Server**: Click "Stop Server" to shut down the server
## Project Structure
- `Main.java` - Application entry point
- `EnhancedServerManagerUI.java` - Main GUI interface with server management
- `ServerManager.java` - Core server management and JAR downloading logic
- `ServerLocation.java` - Legacy server location model
- `JSONManager.java` - JSON persistence utilities
- `PaperAPIClient.java` - API client for fetching Paper versions
## Directory Structure
```
minecraft-server-manager/
├── servers.json # Legacy server locations
├── server_instances.json # Enhanced server configurations
├── servers/ # Server instance directories
│ ├── server1/
│ │ ├── paper-1.20.1-123.jar
│ │ ├── eula.txt
│ │ ├── server.properties
│ │ └── world/
│ └── server2/
└── jars/ # Downloaded JAR files
├── paper-1.20.1-123.jar
└── paper-1.21.1-456.jar
```
## Server Configuration
### Automatic Files Generated
- **eula.txt**: Automatically set to `eula=true`
- **server.properties**: Basic configuration with your specified port
- **JAR files**: Downloaded from Paper API with latest builds
### Memory Configuration
- **Xmx**: Maximum heap size (RAM GB × 1024 MB)
- **Xms**: Initial heap size (RAM GB × 512 MB)
## API Integration
The application integrates with the official Paper API:
- **Versions**: Fetches available Paper versions
- **Builds**: Downloads latest builds for selected versions
- **JARs**: Automatic JAR file management
## Troubleshooting
### Common Issues
1. **Port Already in Use**: Change the port number in server configuration
2. **Insufficient Memory**: Reduce RAM allocation or close other applications
3. **JAR Download Fails**: Check internet connection and try again
4. **Server Won't Start**: Check console output for specific error messages
### Console Commands
Use the command field to send server commands:
- `stop` - Stop the server gracefully
- `save-all` - Save all worlds
- `list` - List online players
- `op <player>` - Give operator status
- `whitelist add <player>` - Add player to whitelist
## Data Storage
- **Server Configurations**: Stored in `server_instances.json` in the root directory
- **Server Files**: Each server has its own directory under `servers/`
- **JAR Files**: Cached in `jars/` directory to avoid re-downloading
>>>>>>> df9ed6a (first shit)

69
pom.xml Normal file
View File

@@ -0,0 +1,69 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>mcmanage</groupId>
<artifactId>minecraft-server-manager</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>minecraft-server-manager</name>
<url>http://maven.apache.org</url>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.13.1</version>
</dependency>
<dependency>
<groupId>com.formdev</groupId>
<artifactId>flatlaf</artifactId>
<version>3.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<archive>
<manifest>
<mainClass>mcmanage.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<mainClass>mcmanage.Main</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>

1
server_instances.json Normal file
View File

@@ -0,0 +1 @@
[{"name":"shit","version":"1.12.2","port":25565,"ramGB":8}]

View File

@@ -0,0 +1,313 @@
package mcmanage;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.List;
import java.util.ArrayList;
import java.util.concurrent.ExecutionException;
import com.formdev.flatlaf.FlatLightLaf;
public class EnhancedServerManagerUI extends JFrame {
static {
try {
UIManager.setLookAndFeel(new FlatLightLaf());
} catch (Exception e) {
System.err.println("Failed to initialize FlatLaf");
}
}
private DefaultListModel<ServerManager.ServerInstance> serverListModel = new DefaultListModel<>();
private JList<ServerManager.ServerInstance> serverList = new JList<>(serverListModel);
private JTextField nameField = new JTextField(15);
private JTextField portField = new JTextField(5);
private JTextField ramField = new JTextField(3);
private JComboBox<String> versionsComboBox = new JComboBox<>();
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);
public EnhancedServerManagerUI() {
super("Enhanced Minecraft Server Manager");
setLayout(new BorderLayout());
// Initialize directories
ServerManager.initializeDirectories();
// 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));
controlPanel.add(startServerButton);
controlPanel.add(stopServerButton);
controlPanel.add(downloadJarButton);
controlPanel.add(sendCommandButton);
leftPanel.add(controlPanel, BorderLayout.SOUTH);
// Right panel - input and console
JPanel rightPanel = new JPanel(new BorderLayout());
// 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));
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);
consolePanel.add(consoleScrollPane, BorderLayout.CENTER);
JPanel commandPanel = new JPanel(new BorderLayout());
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);
add(rightPanel, BorderLayout.CENTER);
// Load saved servers
List<ServerManager.ServerInstance> savedServers = JSONManager.loadServerInstances();
savedServers.forEach(serverListModel::addElement);
// Button listeners
addButton.addActionListener(e -> addServer());
saveButton.addActionListener(e -> saveServers());
fetchVersionsButton.addActionListener(e -> fetchVersions());
downloadJarButton.addActionListener(e -> downloadJar());
startServerButton.addActionListener(e -> startServer());
stopServerButton.addActionListener(e -> stopServer());
sendCommandButton.addActionListener(e -> sendCommand());
// Enter key in command field
commandField.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
sendCommand();
}
}
});
// Add tooltips and padding to buttons and fields
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");
nameField.setToolTipText("Server name (used as directory)");
portField.setToolTipText("Server port (default 25565)");
ramField.setToolTipText("RAM in GB (e.g. 2, 4, 8)");
versionsComboBox.setToolTipText("Select PaperMC version");
consoleOutput.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12));
inputPanel.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(1200, 800);
setLocationRelativeTo(null);
setVisible(true);
}
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;
}
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;
}
ServerManager.ServerInstance server = new ServerManager.ServerInstance(name, version, port, ram);
serverListModel.addElement(server);
nameField.setText("");
portField.setText("");
ramField.setText("");
}
private void saveServers() {
List<ServerManager.ServerInstance> servers = new ArrayList<>();
for (int i = 0; i < serverListModel.size(); i++) {
servers.add(serverListModel.getElementAt(i));
}
JSONManager.saveServerInstances(servers);
JOptionPane.showMessageDialog(this, "Servers saved!");
}
private void fetchVersions() {
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 (InterruptedException | ExecutionException e) {
JOptionPane.showMessageDialog(EnhancedServerManagerUI.this, "Failed to fetch versions: " + e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
} finally {
fetchVersionsButton.setEnabled(true);
}
}
};
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;
}
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) {
consoleOutput.append("Error starting server: " + e.getMessage() + "\n");
e.printStackTrace();
} finally {
startServerButton.setEnabled(true);
}
}
};
worker.execute();
}
private void stopServer() {
ServerManager.ServerInstance selected = serverList.getSelectedValue();
if (selected == null) {
JOptionPane.showMessageDialog(this, "Please select a server first", "Error", JOptionPane.ERROR_MESSAGE);
return;
}
ServerManager.stopServer(selected);
consoleOutput.append("Stopping server: " + selected.name + "\n");
}
private void sendCommand() {
ServerManager.ServerInstance selected = serverList.getSelectedValue();
if (selected == null) {
JOptionPane.showMessageDialog(this, "Please select a server first", "Error", JOptionPane.ERROR_MESSAGE);
return;
}
String command = commandField.getText().trim();
if (command.isEmpty()) {
return;
}
ServerManager.sendCommand(selected, command);
consoleOutput.append("> " + command + "\n");
commandField.setText("");
}
public static void main(String[] args) {
SwingUtilities.invokeLater(EnhancedServerManagerUI::new);
}
}

View File

@@ -0,0 +1,76 @@
package mcmanage;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.io.File;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
public class JSONManager {
private static final String FILE = "servers.json";
public static List<ServerLocation> load() {
File file = new File(FILE);
if (!file.exists()) {
return new ArrayList<>();
}
try (Reader reader = new FileReader(file)) {
Gson gson = new Gson();
Type listType = new TypeToken<List<ServerLocation>>(){}.getType();
return gson.fromJson(reader, listType);
} catch (IOException e) {
e.printStackTrace();
return new ArrayList<>();
}
}
public static void save(List<ServerLocation> servers) {
try (Writer writer = new FileWriter(FILE)) {
Gson gson = new Gson();
gson.toJson(servers, writer);
} catch (IOException e) {
e.printStackTrace();
}
}
public static List<ServerManager.ServerInstance> loadServerInstances() {
File file = new File("server_instances.json");
if (!file.exists() || file.length() == 0) {
return new ArrayList<>();
}
try (Reader reader = new FileReader(file)) {
Gson gson = new Gson();
Type listType = new TypeToken<List<ServerManager.ServerInstance>>(){}.getType();
List<ServerManager.ServerInstance> list = gson.fromJson(reader, listType);
return list != null ? list : new ArrayList<>();
} catch (Exception e) {
e.printStackTrace();
// If parsing fails, return an empty list and optionally log a warning
return new ArrayList<>();
}
}
public static void saveServerInstances(List<ServerManager.ServerInstance> servers) {
File tempFile = new File("server_instances.json.tmp");
File targetFile = new File("server_instances.json");
try (Writer writer = new FileWriter(tempFile)) {
Gson gson = new Gson();
gson.toJson(servers != null ? servers : new ArrayList<>(), writer);
} catch (IOException e) {
e.printStackTrace();
return;
}
// Atomic move to avoid partial/corrupt files
if (!tempFile.renameTo(targetFile)) {
System.err.println("Failed to rename temp file to server_instances.json");
}
}
}

View File

@@ -0,0 +1,11 @@
package mcmanage;
import javax.swing.SwingUtilities;
public class Main
{
public static void main( String[] args )
{
SwingUtilities.invokeLater(() -> new EnhancedServerManagerUI());
}
}

View File

@@ -0,0 +1,47 @@
package mcmanage;
import com.google.gson.*;
import java.io.IOException;
import java.net.URI;
import java.net.http.*;
import java.util.ArrayList;
import java.util.List;
public class PaperAPIClient {
private static final String API_URL = "https://api.papermc.io/v2/projects/paper";
public static List<String> fetchPaperVersions() throws IOException, InterruptedException {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(API_URL))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
List<String> versions = new ArrayList<>();
if (response.statusCode() == 200) {
try {
JsonObject json = JsonParser.parseString(response.body()).getAsJsonObject();
if (json.has("versions")) {
JsonArray versionsJson = json.getAsJsonArray("versions");
for (JsonElement v : versionsJson) {
String version = v.getAsString();
versions.add(version);
}
}
} catch (Exception e) {
System.err.println("Error parsing JSON: " + e.getMessage());
e.printStackTrace();
}
} else {
System.err.println("HTTP Error: " + response.statusCode());
}
return versions;
}
}

View File

@@ -0,0 +1,18 @@
package mcmanage;
public class ServerLocation {
public String name;
public String ip;
public int port;
public ServerLocation(String name, String ip, int port) {
this.name = name;
this.ip = ip;
this.port = port;
}
@Override
public String toString() {
return name + " (" + ip + ":" + port + ")";
}
}

View File

@@ -0,0 +1,226 @@
package mcmanage;
import java.io.*;
import java.net.URI;
import java.net.http.*;
import java.nio.file.*;
import java.util.*;
import java.util.concurrent.*;
import javax.swing.*;
public class ServerManager {
private static final String PAPER_API_BASE = "https://api.papermc.io/v2/projects/paper";
private static final String SERVERS_DIR = "servers";
private static final String JARS_DIR = "jars";
public static class ServerInstance {
public String name;
public String version;
public int port;
public int ramGB;
public String jarPath;
public transient Process process;
public transient BufferedReader consoleReader;
public transient boolean isRunning;
public ServerInstance(String name, String version, int port, int ramGB) {
this.name = name;
this.version = version;
this.port = port;
this.ramGB = ramGB;
this.isRunning = false;
}
@Override
public String toString() {
String status = isRunning ? " [RUNNING]" : " [STOPPED]";
return name + " (" + version + ":" + port + ", " + ramGB + "GB)" + status;
}
}
public static void initializeDirectories() {
try {
Files.createDirectories(Paths.get(SERVERS_DIR));
Files.createDirectories(Paths.get(JARS_DIR));
} catch (IOException e) {
System.err.println("Error creating directories: " + e.getMessage());
}
}
public static String downloadPaperJar(String version) throws IOException, InterruptedException {
// First, get the builds for the version
String buildsUrl = PAPER_API_BASE + "/versions/" + version + "/builds";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(buildsUrl))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() != 200) {
throw new IOException("Failed to get builds for version " + version + ": " + response.statusCode());
}
// Parse the builds response to get the latest build number
com.google.gson.JsonObject buildsJson = com.google.gson.JsonParser.parseString(response.body()).getAsJsonObject();
com.google.gson.JsonArray builds = buildsJson.getAsJsonArray("builds");
if (builds.size() == 0) {
throw new IOException("No builds found for version " + version);
}
// Get the latest build (last in the array)
com.google.gson.JsonObject latestBuild = builds.get(builds.size() - 1).getAsJsonObject();
int buildNumber = latestBuild.get("build").getAsInt();
// Download the JAR
String jarName = "paper-" + version + "-" + buildNumber + ".jar";
String jarUrl = PAPER_API_BASE + "/versions/" + version + "/builds/" + buildNumber + "/downloads/" + jarName;
String jarPath = JARS_DIR + "/" + jarName;
Path jarFile = Paths.get(jarPath);
if (Files.exists(jarFile)) {
System.out.println("JAR already exists: " + jarPath);
return jarPath;
}
System.out.println("Downloading JAR: " + jarUrl);
HttpRequest downloadRequest = HttpRequest.newBuilder()
.uri(URI.create(jarUrl))
.GET()
.build();
HttpResponse<InputStream> downloadResponse = client.send(downloadRequest, HttpResponse.BodyHandlers.ofInputStream());
if (downloadResponse.statusCode() != 200) {
throw new IOException("Failed to download JAR: " + downloadResponse.statusCode());
}
Files.copy(downloadResponse.body(), jarFile, StandardCopyOption.REPLACE_EXISTING);
System.out.println("Downloaded JAR to: " + jarPath);
return jarPath;
}
public static void setupServerDirectory(ServerInstance server) throws IOException {
String serverDir = SERVERS_DIR + "/" + server.name;
Path serverPath = Paths.get(serverDir);
Files.createDirectories(serverPath);
// Copy JAR to server directory
Path jarSource = Paths.get(server.jarPath);
Path jarDest = serverPath.resolve(jarSource.getFileName());
Files.copy(jarSource, jarDest, StandardCopyOption.REPLACE_EXISTING);
// Create eula.txt if it doesn't exist
Path eulaFile = serverPath.resolve("eula.txt");
if (!Files.exists(eulaFile)) {
String eulaContent = "#By changing the setting below to TRUE you are indicating your agreement to our EULA (https://account.mojang.com/documents/minecraft_eula).\n" +
"#Generated on " + new Date() + "\n" +
"eula=true\n";
Files.write(eulaFile, eulaContent.getBytes());
System.out.println("Created eula.txt for server: " + server.name);
}
// Create server.properties if it doesn't exist
Path propertiesFile = serverPath.resolve("server.properties");
if (!Files.exists(propertiesFile)) {
String propertiesContent = "#Minecraft server properties\n" +
"#Generated on " + new Date() + "\n" +
"server-port=" + server.port + "\n" +
"gamemode=survival\n" +
"difficulty=easy\n" +
"max-players=20\n" +
"online-mode=false\n" +
"enable-command-block=false\n" +
"spawn-protection=16\n";
Files.write(propertiesFile, propertiesContent.getBytes());
System.out.println("Created server.properties for server: " + server.name);
}
}
public static void startServer(ServerInstance server, JTextArea consoleOutput) throws IOException {
if (server.isRunning) {
consoleOutput.append("Server " + server.name + " is already running!\n");
return;
}
String serverDir = SERVERS_DIR + "/" + server.name;
Path jarFile = Paths.get(serverDir).resolve(Paths.get(server.jarPath).getFileName());
if (!Files.exists(jarFile)) {
throw new IOException("Server JAR not found: " + jarFile);
}
// Build the command
List<String> command = new ArrayList<>();
command.add("java");
command.add("-Xmx" + (server.ramGB * 1024) + "M");
command.add("-Xms" + (server.ramGB * 512) + "M");
command.add("-jar");
command.add(jarFile.toAbsolutePath().toString());
command.add("nogui");
ProcessBuilder pb = new ProcessBuilder(command);
pb.directory(new File(serverDir));
pb.redirectErrorStream(true);
consoleOutput.append("Starting server " + server.name + " with " + server.ramGB + "GB RAM...\n");
consoleOutput.append("Command: " + String.join(" ", command) + "\n");
server.process = pb.start();
server.isRunning = true;
// Start console reader
server.consoleReader = new BufferedReader(new InputStreamReader(server.process.getInputStream()));
// Start a thread to read console output
CompletableFuture.runAsync(() -> {
try {
String line;
while ((line = server.consoleReader.readLine()) != null) {
final String outputLine = line;
SwingUtilities.invokeLater(() -> {
consoleOutput.append(outputLine + "\n");
consoleOutput.setCaretPosition(consoleOutput.getDocument().getLength());
});
}
} catch (IOException e) {
System.err.println("Error reading console output: " + e.getMessage());
} finally {
server.isRunning = false;
SwingUtilities.invokeLater(() -> {
consoleOutput.append("Server " + server.name + " has stopped.\n");
});
}
});
}
public static void stopServer(ServerInstance server) {
if (server.process != null && server.isRunning) {
try {
PrintWriter writer = new PrintWriter(server.process.getOutputStream(), true);
writer.println("stop");
writer.flush();
System.out.println("Sent 'stop' command to server: " + server.name);
} catch (Exception e) {
System.err.println("Error sending 'stop' command: " + e.getMessage());
}
}
}
public static void sendCommand(ServerInstance server, String command) {
if (server.process != null && server.isRunning) {
try {
PrintWriter writer = new PrintWriter(server.process.getOutputStream());
writer.println(command);
writer.flush();
} catch (Exception e) {
System.err.println("Error sending command: " + e.getMessage());
}
}
}
}

View File

@@ -0,0 +1,141 @@
package mcmanage;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.List;
import java.util.ArrayList;
import java.util.concurrent.ExecutionException;
public class ServerManagerUI extends JFrame {
private DefaultListModel<ServerLocation> serverListModel = new DefaultListModel<>();
private JList<ServerLocation> serverList = new JList<>(serverListModel);
private JTextField nameField = new JTextField(15);
private JTextField ipField = new JTextField(15);
private JTextField portField = new JTextField(5);
private JButton addButton = new JButton("Add Server");
private JButton saveButton = new JButton("Save Servers");
private JButton fetchVersionsButton = new JButton("Fetch Paper Versions");
private JComboBox<String> versionsComboBox = new JComboBox<>();
public ServerManagerUI() {
super("Minecraft Server Manager");
setLayout(new BorderLayout());
// Left panel - list of servers
JPanel leftPanel = new JPanel(new BorderLayout());
leftPanel.add(new JLabel("Saved Servers:"), BorderLayout.NORTH);
leftPanel.add(new JScrollPane(serverList), BorderLayout.CENTER);
// Right panel - input and buttons
JPanel rightPanel = new JPanel();
rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.Y_AXIS));
rightPanel.add(new JLabel("Name:"));
rightPanel.add(nameField);
rightPanel.add(new JLabel("IP Address:"));
rightPanel.add(ipField);
rightPanel.add(new JLabel("Port:"));
rightPanel.add(portField);
rightPanel.add(addButton);
rightPanel.add(saveButton);
rightPanel.add(new JLabel("Paper Versions:"));
rightPanel.add(versionsComboBox);
rightPanel.add(fetchVersionsButton);
add(leftPanel, BorderLayout.CENTER);
add(rightPanel, BorderLayout.EAST);
// Load saved servers
List<ServerLocation> savedServers = JSONManager.load();
savedServers.forEach(serverListModel::addElement);
// Button listeners
addButton.addActionListener(e -> addServer());
saveButton.addActionListener(e -> saveServers());
fetchVersionsButton.addActionListener(e -> fetchVersions());
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(600, 400);
setLocationRelativeTo(null);
setVisible(true);
}
private void addServer() {
String name = nameField.getText().trim();
String ip = ipField.getText().trim();
String portStr = portField.getText().trim();
if (name.isEmpty() || ip.isEmpty() || portStr.isEmpty()) {
JOptionPane.showMessageDialog(this, "Please fill all fields", "Input Error", JOptionPane.ERROR_MESSAGE);
return;
}
int port;
try {
port = Integer.parseInt(portStr);
} catch (NumberFormatException ex) {
JOptionPane.showMessageDialog(this, "Invalid port number", "Input Error", JOptionPane.ERROR_MESSAGE);
return;
}
ServerLocation server = new ServerLocation(name, ip, port);
serverListModel.addElement(server);
nameField.setText("");
ipField.setText("");
portField.setText("");
}
private void saveServers() {
List<ServerLocation> servers = new ArrayList<>();
for (int i = 0; i < serverListModel.size(); i++) {
servers.add(serverListModel.getElementAt(i));
}
JSONManager.save(servers);
JOptionPane.showMessageDialog(this, "Servers saved!");
}
private void fetchVersions() {
System.out.println("Fetch versions button clicked");
fetchVersionsButton.setEnabled(false);
versionsComboBox.removeAllItems();
SwingWorker<List<String>, Void> worker = new SwingWorker<List<String>, Void>() {
@Override
protected List<String> doInBackground() throws Exception {
System.out.println("Starting background task to fetch versions");
List<String> versions = PaperAPIClient.fetchPaperVersions();
System.out.println("Background task completed, fetched " + versions.size() + " versions");
return versions;
}
@Override
protected void done() {
try {
System.out.println("SwingWorker done() called");
List<String> versions = get();
System.out.println("Retrieved " + versions.size() + " versions from SwingWorker");
versions.forEach(versionsComboBox::addItem);
System.out.println("Added " + versions.size() + " items to combo box");
} catch (InterruptedException | ExecutionException e) {
System.err.println("Error in SwingWorker done(): " + e.getMessage());
e.printStackTrace();
JOptionPane.showMessageDialog(ServerManagerUI.this, "Failed to fetch versions: " + e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
} finally {
fetchVersionsButton.setEnabled(true);
System.out.println("Fetch versions button re-enabled");
}
}
};
worker.execute();
System.out.println("SwingWorker executed");
}
public static void main(String[] args) {
SwingUtilities.invokeLater(ServerManagerUI::new);
}
}

View File

@@ -0,0 +1,38 @@
package mcmanage;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
/**
* Unit test for simple App.
*/
public class AppTest
extends TestCase
{
/**
* Create the test case
*
* @param testName name of the test case
*/
public AppTest( String testName )
{
super( testName );
}
/**
* @return the suite of tests being tested
*/
public static Test suite()
{
return new TestSuite( AppTest.class );
}
/**
* Rigourous Test :-)
*/
public void testApp()
{
assertTrue( true );
}
}

272
steps.md Normal file
View File

@@ -0,0 +1,272 @@
## Step 1: Set up your project
* Use Java 11 or higher (for built-in HttpClient)
* Add **Gson** to your build:
* If using Maven or Gradle, add Gson as explained before.
* If plain, download gson JAR and add it to classpath.
* Create your package, e.g., `mcmanage`.
---
## Step 2: Create ServerLocation class
```java
package mcmanage;
public class ServerLocation {
public String name;
public String ip;
public int port;
public ServerLocation(String name, String ip, int port) {
this.name = name;
this.ip = ip;
this.port = port;
}
@Override
public String toString() {
return name + " (" + ip + ":" + port + ")";
}
}
```
---
## Step 3: Create JSON utility to load/save server locations
```java
package mcmanage;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.io.*;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
public class ServerLocationStorage {
private static final String FILE = "servers.json";
public static List<ServerLocation> load() {
File file = new File(FILE);
if (!file.exists()) {
return new ArrayList<>();
}
try (Reader reader = new FileReader(file)) {
Gson gson = new Gson();
Type listType = new TypeToken<List<ServerLocation>>(){}.getType();
return gson.fromJson(reader, listType);
} catch (IOException e) {
e.printStackTrace();
return new ArrayList<>();
}
}
public static void save(List<ServerLocation> servers) {
try (Writer writer = new FileWriter(FILE)) {
Gson gson = new Gson();
gson.toJson(servers, writer);
} catch (IOException e) {
e.printStackTrace();
}
}
}
```
---
## Step 4: Create PaperAPI client to fetch versions
```java
package mcmanage;
import com.google.gson.*;
import java.io.IOException;
import java.net.URI;
import java.net.http.*;
import java.util.ArrayList;
import java.util.List;
public class PaperAPIClient {
private static final String API_URL = "https://api.papermc.io/v2/projects/paper";
public static List<String> fetchPaperVersions() throws IOException, InterruptedException {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(API_URL))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
List<String> versions = new ArrayList<>();
if (response.statusCode() == 200) {
JsonObject json = JsonParser.parseString(response.body()).getAsJsonObject();
JsonArray versionsJson = json.getAsJsonArray("versions");
for (JsonElement v : versionsJson) {
versions.add(v.getAsString());
}
}
return versions;
}
}
```
---
## Step 5: Build the Swing GUI
```java
package mcmanage;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.List;
import java.util.concurrent.ExecutionException;
public class ServerManagerUI extends JFrame {
private DefaultListModel<ServerLocation> serverListModel = new DefaultListModel<>();
private JList<ServerLocation> serverList = new JList<>(serverListModel);
private JTextField nameField = new JTextField(15);
private JTextField ipField = new JTextField(15);
private JTextField portField = new JTextField(5);
private JButton addButton = new JButton("Add Server");
private JButton saveButton = new JButton("Save Servers");
private JButton fetchVersionsButton = new JButton("Fetch Paper Versions");
private JComboBox<String> versionsComboBox = new JComboBox<>();
public ServerManagerUI() {
super("Minecraft Server Manager");
setLayout(new BorderLayout());
// Left panel - list of servers
JPanel leftPanel = new JPanel(new BorderLayout());
leftPanel.add(new JLabel("Saved Servers:"), BorderLayout.NORTH);
leftPanel.add(new JScrollPane(serverList), BorderLayout.CENTER);
// Right panel - input and buttons
JPanel rightPanel = new JPanel();
rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.Y_AXIS));
rightPanel.add(new JLabel("Name:"));
rightPanel.add(nameField);
rightPanel.add(new JLabel("IP Address:"));
rightPanel.add(ipField);
rightPanel.add(new JLabel("Port:"));
rightPanel.add(portField);
rightPanel.add(addButton);
rightPanel.add(saveButton);
rightPanel.add(new JLabel("Paper Versions:"));
rightPanel.add(versionsComboBox);
rightPanel.add(fetchVersionsButton);
add(leftPanel, BorderLayout.CENTER);
add(rightPanel, BorderLayout.EAST);
// Load saved servers
List<ServerLocation> savedServers = ServerLocationStorage.load();
savedServers.forEach(serverListModel::addElement);
// Button listeners
addButton.addActionListener(e -> addServer());
saveButton.addActionListener(e -> saveServers());
fetchVersionsButton.addActionListener(e -> fetchVersions());
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(600, 400);
setLocationRelativeTo(null);
setVisible(true);
}
private void addServer() {
String name = nameField.getText().trim();
String ip = ipField.getText().trim();
String portStr = portField.getText().trim();
if (name.isEmpty() || ip.isEmpty() || portStr.isEmpty()) {
JOptionPane.showMessageDialog(this, "Please fill all fields", "Input Error", JOptionPane.ERROR_MESSAGE);
return;
}
int port;
try {
port = Integer.parseInt(portStr);
} catch (NumberFormatException ex) {
JOptionPane.showMessageDialog(this, "Invalid port number", "Input Error", JOptionPane.ERROR_MESSAGE);
return;
}
ServerLocation server = new ServerLocation(name, ip, port);
serverListModel.addElement(server);
nameField.setText("");
ipField.setText("");
portField.setText("");
}
private void saveServers() {
List<ServerLocation> servers = serverListModel.elements().asIterator().toList();
ServerLocationStorage.save(servers);
JOptionPane.showMessageDialog(this, "Servers saved!");
}
private void fetchVersions() {
fetchVersionsButton.setEnabled(false);
versionsComboBox.removeAllItems();
SwingWorker<List<String>, Void> worker = new SwingWorker<>() {
@Override
protected List<String> doInBackground() throws Exception {
return PaperAPIClient.fetchPaperVersions();
}
@Override
protected void done() {
try {
List<String> versions = get();
versions.forEach(versionsComboBox::addItem);
} catch (InterruptedException | ExecutionException e) {
JOptionPane.showMessageDialog(ServerManagerUI.this, "Failed to fetch versions", "Error", JOptionPane.ERROR_MESSAGE);
} finally {
fetchVersionsButton.setEnabled(true);
}
}
};
worker.execute();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(ServerManagerUI::new);
}
}
```
---
## Step 6: Run & test
* Launch your `ServerManagerUI` main class.
* Add servers manually and save them.
* Click “Fetch Paper Versions” to load versions from Paper API.
* The versions appear in the combo box dynamically.
---
## Summary
* You have JSON save/load with Gson.
* You fetch Paper versions dynamically using Java 11 HttpClient.
* You use Swing for a simple GUI to manage your servers and versions.
---

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,15 @@
mcmanage/ServerManager.class
mcmanage/JSONManager$1.class
mcmanage/EnhancedServerManagerUI$2.class
mcmanage/ServerManagerUI$1.class
mcmanage/EnhancedServerManagerUI$1.class
mcmanage/JSONManager.class
mcmanage/JSONManager$2.class
mcmanage/EnhancedServerManagerUI.class
mcmanage/PaperAPIClient.class
mcmanage/Main.class
mcmanage/EnhancedServerManagerUI$4.class
mcmanage/ServerLocation.class
mcmanage/ServerManagerUI.class
mcmanage/EnhancedServerManagerUI$3.class
mcmanage/ServerManager$ServerInstance.class

View File

@@ -0,0 +1,7 @@
/home/rattatwinko/Documents/gitproj/mvn_MCMANAGE/src/main/java/mcmanage/JSONManager.java
/home/rattatwinko/Documents/gitproj/mvn_MCMANAGE/src/main/java/mcmanage/ServerLocation.java
/home/rattatwinko/Documents/gitproj/mvn_MCMANAGE/src/main/java/mcmanage/ServerManager.java
/home/rattatwinko/Documents/gitproj/mvn_MCMANAGE/src/main/java/mcmanage/ServerManagerUI.java
/home/rattatwinko/Documents/gitproj/mvn_MCMANAGE/src/main/java/mcmanage/EnhancedServerManagerUI.java
/home/rattatwinko/Documents/gitproj/mvn_MCMANAGE/src/main/java/mcmanage/PaperAPIClient.java
/home/rattatwinko/Documents/gitproj/mvn_MCMANAGE/src/main/java/mcmanage/Main.java