diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 4d2090f..ab70455 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -5,15 +5,10 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
@@ -23,8 +18,8 @@
@@ -61,7 +56,7 @@
1779565206518
-
+
diff --git a/pom.xml b/pom.xml
index e8ac751..634d649 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,7 +7,7 @@
org.strassburger
mc-run
- 0.0.7
+ 0.0.8
maven-plugin
MCRun Maven Plugin
diff --git a/src/main/java/org/strassburger/mcrun/downloader/ServerJarDownloader.java b/src/main/java/org/strassburger/mcrun/downloader/ServerJarDownloader.java
index a6d04bd..f1dec5e 100644
--- a/src/main/java/org/strassburger/mcrun/downloader/ServerJarDownloader.java
+++ b/src/main/java/org/strassburger/mcrun/downloader/ServerJarDownloader.java
@@ -41,12 +41,18 @@ public abstract class ServerJarDownloader {
return new File(serverDirectory, serverJarName);
}
+ protected File getServerDirectory() {
+ return serverDirectory;
+ }
+
protected abstract void downloadServerJar() throws ServerJarDownloadException;
public static Builder forServerSoftware(String serverSoftware) throws ServerJarDownloadException {
- return switch (serverSoftware) {
- case "paper" -> new Builder(b ->
+ return switch (serverSoftware.toLowerCase()) {
+ case "paper", "papermc" -> new Builder(b ->
new PaperServerJarDownloader(b.log, b.serverDirectory, b.serverJarName, b.mcVersion));
+ case "spigot" -> new Builder(b ->
+ new SpigotServerJarDownloader(b.log, b.serverDirectory, b.serverJarName, b.mcVersion));
default -> throw new ServerJarDownloadException("Invalid server software: " + serverSoftware);
};
}
diff --git a/src/main/java/org/strassburger/mcrun/downloader/SpigotServerJarDownloader.java b/src/main/java/org/strassburger/mcrun/downloader/SpigotServerJarDownloader.java
new file mode 100644
index 0000000..53884c1
--- /dev/null
+++ b/src/main/java/org/strassburger/mcrun/downloader/SpigotServerJarDownloader.java
@@ -0,0 +1,123 @@
+package org.strassburger.mcrun.downloader;
+
+import org.apache.maven.plugin.logging.Log;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.file.Files;
+import java.nio.file.StandardCopyOption;
+
+public class SpigotServerJarDownloader extends ServerJarDownloader {
+ private static final String BUILD_TOOLS_URL =
+ "https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar";
+
+ public SpigotServerJarDownloader(Log log, File serverDirectory, String serverJarName, String mcVersion) {
+ super(log, serverDirectory, serverJarName, mcVersion);
+ }
+
+ @Override
+ protected void downloadServerJar() throws ServerJarDownloadException {
+ File spigotBuildDir = new File(getServerDirectory(), "spigot-build");
+ spigotBuildDir.mkdirs();
+ File buildToolsJar = new File(spigotBuildDir, "BuildTools.jar");
+ File builtJar = new File(spigotBuildDir, "spigot-" + getMcVersion() + ".jar");
+
+ try {
+ checkGitAvailable();
+ downloadBuildTools(buildToolsJar);
+ runBuildTools(buildToolsJar);
+ moveBuiltJar(builtJar);
+ cleanup(spigotBuildDir);
+ } catch (ServerJarDownloadException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new ServerJarDownloadException("Failed to build Spigot: " + e.getMessage(), e);
+ }
+ }
+
+ private void checkGitAvailable() throws ServerJarDownloadException {
+ try {
+ new ProcessBuilder("git", "--version").start().waitFor();
+ } catch (Exception e) {
+ throw new ServerJarDownloadException("Git is not installed or not on PATH. Required for BuildTools.");
+ }
+ }
+
+ private void downloadBuildTools(File dest) throws ServerJarDownloadException {
+ getLog().info("Downloading BuildTools...");
+ try (var in = new java.net.URI(BUILD_TOOLS_URL).toURL().openStream()) {
+ Files.copy(in, dest.toPath(), StandardCopyOption.REPLACE_EXISTING);
+ } catch (Exception e) {
+ throw new ServerJarDownloadException("Failed to download BuildTools: " + e.getMessage(), e);
+ }
+ getLog().info("BuildTools downloaded to: " + dest.getAbsolutePath());
+ }
+
+ private void runBuildTools(File buildToolsJar) throws ServerJarDownloadException {
+ getLog().info("Running BuildTools for Minecraft " + getMcVersion() + " (this may take several minutes)...");
+
+ ProcessBuilder pb = new ProcessBuilder(
+ "java", "-jar", buildToolsJar.getAbsolutePath(),
+ "--rev", getMcVersion(),
+ "--compile", "spigot"
+ );
+ pb.directory(buildToolsJar.getParentFile());
+ pb.redirectErrorStream(true);
+
+ try {
+ Process process = pb.start();
+
+ // Stream BuildTools output to the Maven log
+ try (var reader = new BufferedReader(
+ new InputStreamReader(process.getInputStream()))) {
+ String line;
+ while ((line = reader.readLine()) != null) {
+ getLog().info("[Spigot-BuildTools] " + line);
+ }
+ }
+
+ int exitCode = process.waitFor();
+ if (exitCode != 0) {
+ throw new ServerJarDownloadException("BuildTools exited with code " + exitCode);
+ }
+ } catch (IOException | InterruptedException e) {
+ if (e instanceof InterruptedException) Thread.currentThread().interrupt();
+ throw new ServerJarDownloadException("BuildTools process failed: " + e.getMessage(), e);
+ }
+
+ getLog().info("BuildTools finished successfully.");
+ }
+
+ private void moveBuiltJar(File builtJar) throws ServerJarDownloadException {
+ if (!builtJar.exists()) {
+ throw new ServerJarDownloadException(
+ "Expected built jar not found: " + builtJar.getAbsolutePath() +
+ ". Check BuildTools output above for errors."
+ );
+ }
+
+ File dest = getServerJar();
+ try {
+ Files.move(builtJar.toPath(), dest.toPath(), StandardCopyOption.REPLACE_EXISTING);
+ } catch (IOException e) {
+ throw new ServerJarDownloadException("Failed to move built jar: " + e.getMessage(), e);
+ }
+
+ getLog().info("Spigot jar ready at: " + dest.getAbsolutePath());
+ }
+
+ private void cleanup(File spigotBuildDir) {
+ getLog().info("Cleaning up Spigot-Build-tools...");
+ try {
+ Files.walk(spigotBuildDir.toPath())
+ .sorted(java.util.Comparator.reverseOrder())
+ .map(java.nio.file.Path::toFile)
+ .forEach(File::delete);
+ getLog().info("Cleaned up " + spigotBuildDir.getAbsolutePath());
+ } catch (IOException e) {
+ getLog().warn("Failed to clean up build directory: " + e.getMessage());
+ }
+ }
+}
\ No newline at end of file