now downloads the whole modpack server (also needs to be used as serverstarter soon)
This commit is contained in:
@@ -15,4 +15,5 @@ dependencies {
|
||||
|
||||
implementation("org.apache.logging.log4j:log4j-api:2.24.0")
|
||||
implementation("org.apache.logging.log4j:log4j-core:2.24.0")
|
||||
implementation("com.google.code.gson:gson:2.8.8")
|
||||
}
|
||||
|
@@ -4,6 +4,7 @@ import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
@@ -11,17 +12,26 @@ import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.Comparator;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
public class BoundlessServer {
|
||||
private static final Logger logger = LogManager.getLogger(BoundlessServer.class);
|
||||
|
||||
public static void main(String[] args) {
|
||||
private static final String currentDir = System.getProperty("user.dir");
|
||||
public static void main(String[] args) throws IOException {
|
||||
logger.info("Downloading and installing NeoForge Server");
|
||||
String neoForgeVersion = "21.1.62";
|
||||
downloadAndExecuteJar(
|
||||
"https://maven.neoforged.net/releases/net/neoforged/neoforge/" + neoForgeVersion + "/neoforge-" + neoForgeVersion + "-installer.jar",
|
||||
"installer.jar", new String[]{"--install-server"});
|
||||
logger.info("↑ Yeah no I'll do that for you automatically...");
|
||||
Files.deleteIfExists(Path.of(currentDir,"installer.jar"));
|
||||
downloadMrPack("https://cdn.modrinth.com/data/ScTwzzH2/versions/IImtmTWG/Boundless%20Horizons%200.2.0.mrpack");
|
||||
}
|
||||
|
||||
public static void downloadAndExecuteJar(String fileURL, String fileName, String[] jarArgs) {
|
||||
@@ -72,6 +82,187 @@ public class BoundlessServer {
|
||||
}
|
||||
}
|
||||
|
||||
public static void downloadMrPack(String fileURL) {
|
||||
String outputFile = "modrinth.index.json";
|
||||
|
||||
try {
|
||||
logger.info("Downloading .mrpack file from: {}", fileURL);
|
||||
URI uri = new URI(fileURL);
|
||||
URL url = uri.toURL();
|
||||
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
|
||||
httpConn.setRequestMethod("GET");
|
||||
httpConn.setConnectTimeout(5000);
|
||||
httpConn.setReadTimeout(5000);
|
||||
|
||||
int responseCode = httpConn.getResponseCode();
|
||||
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||
InputStream inputStream = httpConn.getInputStream();
|
||||
Path outputPath = Path.of(currentDir, "temp.mrpack");
|
||||
Files.copy(inputStream, outputPath, StandardCopyOption.REPLACE_EXISTING);
|
||||
inputStream.close();
|
||||
logger.info("Download completed successfully: {}", outputPath);
|
||||
|
||||
unzipMrPack(outputPath.toString());
|
||||
|
||||
if (!Files.exists(Path.of(currentDir, outputFile))) {
|
||||
logger.error("An error occurred: temp.mrpack does not contain a valid modrinth.index.json file.");
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info("Extraction completed. Processing {}...", outputFile);
|
||||
processModrinthIndex(outputFile);
|
||||
|
||||
copyOverrides();
|
||||
|
||||
Files.deleteIfExists(outputPath);
|
||||
Files.deleteIfExists(Path.of(currentDir,"modrinth.index.json"));
|
||||
logger.info("Temporary file temp.mrpack deleted.");
|
||||
} else {
|
||||
logger.error("Failed to download the file: Server returned response code {}", responseCode);
|
||||
}
|
||||
httpConn.disconnect();
|
||||
} catch (IOException | URISyntaxException e) {
|
||||
logger.error("Error downloading or extracting the .mrpack file: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static void processModrinthIndex(String jsonFile) {
|
||||
logger.info("Processing {}...", jsonFile);
|
||||
|
||||
try (Reader reader = Files.newBufferedReader(Path.of(jsonFile))) {
|
||||
JsonObject jsonObject = JsonParser.parseReader(reader).getAsJsonObject();
|
||||
String name = jsonObject.get("name").getAsString();
|
||||
String versionId = jsonObject.get("versionId").getAsString();
|
||||
|
||||
logger.info("Installing modpack {} version {}...", name, versionId);
|
||||
|
||||
JsonArray files = jsonObject.getAsJsonArray("files");
|
||||
|
||||
for (int i = 0; i < files.size(); i++) {
|
||||
JsonObject fileObject = files.get(i).getAsJsonObject();
|
||||
String downloadUrl = fileObject.getAsJsonArray("downloads").get(0).getAsString();
|
||||
String path = fileObject.get("path").getAsString();
|
||||
|
||||
JsonObject env = fileObject.getAsJsonObject("env");
|
||||
|
||||
if (path.contains("mods/") && "required".equals(env.get("server").getAsString())) {
|
||||
Path outputPath = Path.of(System.getProperty("user.dir"), path);
|
||||
Files.createDirectories(outputPath.getParent());
|
||||
|
||||
logger.info("Downloading {}...", path);
|
||||
try (InputStream in = new URL(downloadUrl).openStream()) {
|
||||
Files.copy(in, outputPath, StandardCopyOption.REPLACE_EXISTING);
|
||||
logger.info("Downloaded {} to {}", path, outputPath);
|
||||
} catch (IOException e) {
|
||||
logger.error("Failed to download {}: {}", path, e.getMessage());
|
||||
}
|
||||
} else {
|
||||
logger.info("Skipping {}: not a required mod or does not belong to mods directory.", path);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.error("Error processing {}: {}", jsonFile, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static void copyOverrides() {
|
||||
Path modsSource = Path.of(currentDir, "overrides", "mods");
|
||||
Path configSource = Path.of(currentDir, "overrides", "config");
|
||||
Path modsDestination = Path.of(currentDir, "mods");
|
||||
Path configDestination = Path.of(currentDir, "config");
|
||||
Path overridesSource = Path.of(currentDir, "overrides");
|
||||
|
||||
try {
|
||||
if (Files.exists(modsSource)) {
|
||||
if (!Files.exists(modsDestination)) {
|
||||
Files.createDirectories(modsDestination);
|
||||
}
|
||||
Files.walk(modsSource).forEach(source -> {
|
||||
Path dest = modsDestination.resolve(modsSource.relativize(source));
|
||||
try {
|
||||
if (Files.isDirectory(source)) {
|
||||
Files.createDirectories(dest);
|
||||
} else {
|
||||
Files.copy(source, dest, StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
logger.info("Copied mod: {}", dest);
|
||||
} catch (IOException e) {
|
||||
logger.error("Failed to copy mod {}: {}", source, e.getMessage());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
logger.warn("Mods source directory does not exist: {}", modsSource);
|
||||
}
|
||||
|
||||
if (Files.exists(configSource)) {
|
||||
if (!Files.exists(configDestination)) {
|
||||
Files.createDirectories(configDestination);
|
||||
}
|
||||
Files.walk(configSource).forEach(source -> {
|
||||
Path dest = configDestination.resolve(configSource.relativize(source));
|
||||
try {
|
||||
if (Files.isDirectory(source)) {
|
||||
Files.createDirectories(dest);
|
||||
} else {
|
||||
Files.copy(source, dest, StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
logger.info("Copied config: {}", dest);
|
||||
} catch (IOException e) {
|
||||
logger.error("Failed to copy config {}: {}", source, e.getMessage());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
logger.warn("Config source directory does not exist: {}", configSource);
|
||||
}
|
||||
|
||||
deleteDirectoryRecursively(overridesSource);
|
||||
logger.info("Deleted the overrides directory successfully.");
|
||||
|
||||
} catch (IOException e) {
|
||||
logger.error("Error while copying / deleting overrides: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static void deleteDirectoryRecursively(Path dirPath) throws IOException {
|
||||
Files.walk(dirPath)
|
||||
.sorted(Comparator.reverseOrder())
|
||||
.forEach(path -> {
|
||||
try {
|
||||
Files.delete(path);
|
||||
} catch (IOException e) {
|
||||
logger.error("Failed to delete {}: {}", path, e.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void unzipMrPack(String mrPackFilePath) {
|
||||
try (ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(mrPackFilePath))) {
|
||||
ZipEntry entry;
|
||||
while ((entry = zipInputStream.getNextEntry()) != null) {
|
||||
File file = new File(currentDir, entry.getName());
|
||||
if (entry.isDirectory()) {
|
||||
if (!file.isDirectory() && !file.mkdirs()) {
|
||||
logger.warn("Failed to create directory: {}", file);
|
||||
}
|
||||
} else {
|
||||
file.getParentFile().mkdirs();
|
||||
|
||||
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file))) {
|
||||
byte[] buffer = new byte[1024];
|
||||
int bytesRead;
|
||||
while ((bytesRead = zipInputStream.read(buffer)) != -1) {
|
||||
bos.write(buffer, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
logger.info("Extracted file: {}", file);
|
||||
}
|
||||
zipInputStream.closeEntry();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.error("Error while extracting .mrpack file: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static class StreamGobbler extends Thread {
|
||||
private final InputStream inputStream;
|
||||
private final String streamType;
|
||||
|
Reference in New Issue
Block a user