first shit
This commit is contained in:
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"java.configuration.updateBuildConfiguration": "automatic"
|
||||
}
|
||||
136
README.md
136
README.md
@@ -1,3 +1,139 @@
|
||||
<<<<<<< HEAD
|
||||
# mvn_MCMANAGE
|
||||
|
||||
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
69
pom.xml
Normal 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
1
server_instances.json
Normal file
@@ -0,0 +1 @@
|
||||
[{"name":"shit","version":"1.12.2","port":25565,"ramGB":8}]
|
||||
313
src/main/java/mcmanage/EnhancedServerManagerUI.java
Normal file
313
src/main/java/mcmanage/EnhancedServerManagerUI.java
Normal 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);
|
||||
}
|
||||
}
|
||||
76
src/main/java/mcmanage/JSONManager.java
Normal file
76
src/main/java/mcmanage/JSONManager.java
Normal 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
11
src/main/java/mcmanage/Main.java
Normal file
11
src/main/java/mcmanage/Main.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package mcmanage;
|
||||
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
public class Main
|
||||
{
|
||||
public static void main( String[] args )
|
||||
{
|
||||
SwingUtilities.invokeLater(() -> new EnhancedServerManagerUI());
|
||||
}
|
||||
}
|
||||
47
src/main/java/mcmanage/PaperAPIClient.java
Normal file
47
src/main/java/mcmanage/PaperAPIClient.java
Normal 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;
|
||||
}
|
||||
}
|
||||
18
src/main/java/mcmanage/ServerLocation.java
Normal file
18
src/main/java/mcmanage/ServerLocation.java
Normal 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 + ")";
|
||||
}
|
||||
}
|
||||
226
src/main/java/mcmanage/ServerManager.java
Normal file
226
src/main/java/mcmanage/ServerManager.java
Normal 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
141
src/main/java/mcmanage/ServerManagerUI.java
Normal file
141
src/main/java/mcmanage/ServerManagerUI.java
Normal 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);
|
||||
}
|
||||
}
|
||||
38
src/test/java/mcmanage/AppTest.java
Normal file
38
src/test/java/mcmanage/AppTest.java
Normal 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
272
steps.md
Normal 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.
|
||||
|
||||
---
|
||||
BIN
target/classes/mcmanage/EnhancedServerManagerUI$1.class
Normal file
BIN
target/classes/mcmanage/EnhancedServerManagerUI$1.class
Normal file
Binary file not shown.
BIN
target/classes/mcmanage/EnhancedServerManagerUI$2.class
Normal file
BIN
target/classes/mcmanage/EnhancedServerManagerUI$2.class
Normal file
Binary file not shown.
BIN
target/classes/mcmanage/EnhancedServerManagerUI$3.class
Normal file
BIN
target/classes/mcmanage/EnhancedServerManagerUI$3.class
Normal file
Binary file not shown.
BIN
target/classes/mcmanage/EnhancedServerManagerUI$4.class
Normal file
BIN
target/classes/mcmanage/EnhancedServerManagerUI$4.class
Normal file
Binary file not shown.
BIN
target/classes/mcmanage/EnhancedServerManagerUI.class
Normal file
BIN
target/classes/mcmanage/EnhancedServerManagerUI.class
Normal file
Binary file not shown.
BIN
target/classes/mcmanage/JSONManager$1.class
Normal file
BIN
target/classes/mcmanage/JSONManager$1.class
Normal file
Binary file not shown.
BIN
target/classes/mcmanage/JSONManager$2.class
Normal file
BIN
target/classes/mcmanage/JSONManager$2.class
Normal file
Binary file not shown.
BIN
target/classes/mcmanage/JSONManager.class
Normal file
BIN
target/classes/mcmanage/JSONManager.class
Normal file
Binary file not shown.
BIN
target/classes/mcmanage/Main.class
Normal file
BIN
target/classes/mcmanage/Main.class
Normal file
Binary file not shown.
BIN
target/classes/mcmanage/PaperAPIClient.class
Normal file
BIN
target/classes/mcmanage/PaperAPIClient.class
Normal file
Binary file not shown.
BIN
target/classes/mcmanage/ServerLocation.class
Normal file
BIN
target/classes/mcmanage/ServerLocation.class
Normal file
Binary file not shown.
BIN
target/classes/mcmanage/ServerManager$ServerInstance.class
Normal file
BIN
target/classes/mcmanage/ServerManager$ServerInstance.class
Normal file
Binary file not shown.
BIN
target/classes/mcmanage/ServerManager.class
Normal file
BIN
target/classes/mcmanage/ServerManager.class
Normal file
Binary file not shown.
BIN
target/classes/mcmanage/ServerManagerUI$1.class
Normal file
BIN
target/classes/mcmanage/ServerManagerUI$1.class
Normal file
Binary file not shown.
BIN
target/classes/mcmanage/ServerManagerUI.class
Normal file
BIN
target/classes/mcmanage/ServerManagerUI.class
Normal file
Binary file not shown.
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user