implement GitHub resource pack auto-updater with HTTP server and configuration

This commit is contained in:
Lars Behrends
2025-12-30 00:17:46 +01:00
parent 3305388f1c
commit e0dbca8d51
6 changed files with 432 additions and 5 deletions

View File

@@ -0,0 +1,101 @@
package ceratic.projectvollidioten.http;
import ceratic.projectvollidioten.config.GithubResourcePackConfig;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import net.minecraft.server.MinecraftServer;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.nio.file.Files;
import java.nio.file.Path;
public class ResourcePackHttpServer {
private final HttpServer server;
private final Path resourcePacksDir;
private final String expectedFileName;
private final int port;
public ResourcePackHttpServer(MinecraftServer mcServer, String expectedFileName, int port) throws IOException {
this.resourcePacksDir = mcServer.getRunDirectory().resolve("server-resource-packs");
this.expectedFileName = expectedFileName;
this.port = port;
Files.createDirectories(resourcePacksDir);
this.server = HttpServer.create(new InetSocketAddress("0.0.0.0", port), 0);
this.server.createContext("/resourcepacks", new ResourcePackHandler());
this.server.setExecutor(null); // Uses default executor
}
public void start() {
server.start();
System.out.println("[GithubRP] 🌐 HTTP server started on http://0.0.0.0:" + port + "/resourcepacks/");
}
public void stop() {
server.stop(1);
System.out.println("[GithubRP] 🌐 HTTP server stopped.");
}
// Returns URL clients should use — e.g. http://192.168.1.100:25585/resourcepacks/my-pack.zip
public String getPackUrl() {
// Try to get LAN IP (optional: replace with public IP if port-forwarded)
String host = "127.0.0.1"; // fallback
try {
java.net.InetAddress addr = java.net.InetAddress.getLocalHost();
if (!addr.isLoopbackAddress() && addr.isSiteLocalAddress()) {
host = addr.getHostAddress();
}
} catch (Exception ignored) {}
return String.format("http://%s:%d/resourcepacks/%s", host, port, expectedFileName);
}
private class ResourcePackHandler implements HttpHandler {
@Override
public void handle(HttpExchange exchange) throws IOException {
String path = exchange.getRequestURI().getPath();
String targetFile = path.substring("/resourcepacks/".length());
// Security: only allow configured pack filename
if (!targetFile.equals(expectedFileName)) {
sendResponse(exchange, 403, "Forbidden: unknown resource pack");
return;
}
Path packFile = resourcePacksDir.resolve(targetFile);
if (!Files.exists(packFile) || !Files.isRegularFile(packFile)) {
sendResponse(exchange, 404, "Resource pack not found");
return;
}
// Set headers
exchange.getResponseHeaders().set("Content-Type", "application/zip");
exchange.getResponseHeaders().set("Content-Length", String.valueOf(Files.size(packFile)));
exchange.getResponseHeaders().set("Cache-Control", "public, max-age=3600");
exchange.getResponseHeaders().set("Access-Control-Allow-Origin", "*");
// Send file
exchange.sendResponseHeaders(200, 0); // chunked
try (OutputStream os = exchange.getResponseBody();
var fis = Files.newInputStream(packFile)) {
fis.transferTo(os);
} catch (IOException e) {
System.err.println("[GithubRP] Client disconnected during pack download.");
}
}
private void sendResponse(HttpExchange exchange, int code, String msg) throws IOException {
byte[] data = msg.getBytes(java.nio.charset.StandardCharsets.UTF_8);
exchange.getResponseHeaders().set("Content-Type", "text/plain; charset=utf-8");
exchange.sendResponseHeaders(code, data.length);
exchange.getResponseBody().write(data);
exchange.close();
}
}
}