This commit is contained in:
JFronny 2020-09-07 15:03:15 +02:00
parent 0a170a36a6
commit 7bc94e645b
7 changed files with 87 additions and 41 deletions

View File

@ -5,6 +5,7 @@ variables:
before_script: before_script:
- export GRADLE_USER_HOME=`pwd`/.gradle - export GRADLE_USER_HOME=`pwd`/.gradle
- chmod a+x gradlew
deploy: deploy:
stage: deploy stage: deploy

View File

@ -16,11 +16,12 @@ dependencies {
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
// Fabric API. This is technically optional, but you probably want it anyway.
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
// PSA: Some older mods, compiled on Loom 0.2.1, might have outdated Maven POMs. modApi("me.sargunvohra.mcmods:autoconfig1u:3.2.2") {
// You may need to force-disable transitiveness on them. exclude(group: "net.fabricmc.fabric-api")
}
include "me.sargunvohra.mcmods:autoconfig1u:3.2.2"
} }
processResources { processResources {

View File

@ -0,0 +1,20 @@
package io.gitlab.jfronny.dynres;
import me.sargunvohra.mcmods.autoconfig1u.ConfigData;
import me.sargunvohra.mcmods.autoconfig1u.annotation.Config;
import me.sargunvohra.mcmods.autoconfig1u.shadowed.blue.endless.jankson.Comment;
@Config(name = "dynres")
public class Cfg implements ConfigData {
@Comment("The port to use for hosting the file. Use 0 for a random one")
public int port = 0;
@Comment("The number of allowed concurrent downloads. Higher values prevent errors on clients but can increase load")
public int maxConnections = 20;
@Comment("The relative path to the resources zip. Expect strange behaviour if changed")
public String resourcesFile = "resources.zip";
@Comment("Set to true to provide a hash to clients. Changes to the pack will require a server restart with this")
public boolean hashResources = false;
}

View File

@ -3,49 +3,66 @@ package io.gitlab.jfronny.dynres;
import com.mojang.brigadier.Command; import com.mojang.brigadier.Command;
import io.gitlab.jfronny.dynres.web.RequestHandler; import io.gitlab.jfronny.dynres.web.RequestHandler;
import io.gitlab.jfronny.dynres.web.bluemapcore.WebServer; import io.gitlab.jfronny.dynres.web.bluemapcore.WebServer;
import me.sargunvohra.mcmods.autoconfig1u.AutoConfig;
import me.sargunvohra.mcmods.autoconfig1u.serializer.JanksonConfigSerializer;
import net.fabricmc.api.DedicatedServerModInitializer; import net.fabricmc.api.DedicatedServerModInitializer;
import net.fabricmc.api.EnvType; import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment; import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback; import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback;
import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.gui.FabricGuiEntry; import net.fabricmc.loader.gui.FabricGuiEntry;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.CommandManager;
import net.minecraft.server.dedicated.MinecraftDedicatedServer;
import net.minecraft.text.LiteralText; import net.minecraft.text.LiteralText;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.util.Arrays; import java.util.Arrays;
//TODO host the pack
@Environment(EnvType.SERVER) @Environment(EnvType.SERVER)
public class DynRes implements DedicatedServerModInitializer { public class DynRes implements DedicatedServerModInitializer {
static WebServer server; static WebServer server;
public static final String resFile = "resources.zip"; public static File resFile;
public static Cfg cfg;
public static final String baseLink = "http://127.0.0.1/"; public static final String baseLink = "http://127.0.0.1/";
static {
AutoConfig.register(Cfg.class, JanksonConfigSerializer::new);
cfg = AutoConfig.getConfigHolder(Cfg.class).getConfig();
resFile = new File(FabricLoader.getInstance().getGameDir().toFile(), cfg.resourcesFile);
if (!resFile.isFile()) {
FabricGuiEntry.displayCriticalError(new FileNotFoundException("The file " + resFile + " does not exist in the game directory but is required"), true);
}
}
@Override @Override
public void onInitializeServer() { public void onInitializeServer() {
//TODO allow setting max connections or fixed port server = new WebServer(cfg.port, cfg.maxConnections, null, new RequestHandler("resources.zip"));
//TODO allow setting custom resources path
File f = new File(FabricLoader.getInstance().getGameDir().toFile(), resFile);
if (!f.isFile()) {
FabricGuiEntry.displayCriticalError(new FileNotFoundException("The file resources.zip does not exist in the game directory but is required"), true);
return;
}
server = new WebServer(0, 20, null, new RequestHandler(f, resFile));
server.start(); server.start();
CommandRegistrationCallback.EVENT.register((dispatcher, dedicated) -> { CommandRegistrationCallback.EVENT.register((dispatcher, dedicated) -> {
if (dedicated) { if (dedicated) {
dispatcher.register(CommandManager.literal("dynres").executes(context -> { dispatcher.register(CommandManager.literal("dynres").executes(context -> {
context.getSource().sendFeedback(new LiteralText("DynRes is active. Use dynres restart if it breaks"), false); context.getSource().sendFeedback(new LiteralText("DynRes is active. Use dynres restart to reload"), false);
return Command.SINGLE_SUCCESS; return Command.SINGLE_SUCCESS;
})); }));
dispatcher.register(CommandManager.literal("dynres").then(CommandManager.literal("restart")).executes(context -> { dispatcher.register(CommandManager.literal("dynres").then(CommandManager.literal("restart").executes(context -> {
context.getSource().sendFeedback(new LiteralText("Restarting DynRes"), true); try {
server.start(); context.getSource().sendFeedback(new LiteralText("Restarting DynRes"), true);
context.getSource().sendFeedback(new LiteralText("DynRes restarted"), true); cfg = AutoConfig.getConfigHolder(Cfg.class).getConfig();
server.setPort(cfg.port);
server.setMaxConnections(cfg.maxConnections);
resFile = new File(FabricLoader.getInstance().getGameDir().toFile(), cfg.resourcesFile);
server.close();
server.start();
context.getSource().sendFeedback(new LiteralText("DynRes restarted"), true);
}
catch (Exception e) {
e.printStackTrace();
context.getSource().sendError(new LiteralText(e.getMessage()));
}
return Command.SINGLE_SUCCESS; return Command.SINGLE_SUCCESS;
})); })));
} }
else { else {
System.err.println("DYNRES SHOULD NOT BE RUN ON INTERNAL SERVERS!"); System.err.println("DYNRES SHOULD NOT BE RUN ON INTERNAL SERVERS!");

View File

@ -3,12 +3,15 @@ package io.gitlab.jfronny.dynres.mixin;
import io.gitlab.jfronny.dynres.DynRes; import io.gitlab.jfronny.dynres.DynRes;
import net.minecraft.server.dedicated.ServerPropertiesHandler; import net.minecraft.server.dedicated.ServerPropertiesHandler;
import net.minecraft.util.registry.DynamicRegistryManager; import net.minecraft.util.registry.DynamicRegistryManager;
import org.apache.commons.codec.digest.DigestUtils;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties; import java.util.Properties;
@Mixin(ServerPropertiesHandler.class) @Mixin(ServerPropertiesHandler.class)
@ -21,17 +24,21 @@ public class ServerPropertiesHandlerMixin {
@Inject(at = @At("RETURN"), method = "<init>(Ljava/util/Properties;Lnet/minecraft/util/registry/DynamicRegistryManager;)V") @Inject(at = @At("RETURN"), method = "<init>(Ljava/util/Properties;Lnet/minecraft/util/registry/DynamicRegistryManager;)V")
public void init(Properties properties, DynamicRegistryManager dynamicRegistryManager, CallbackInfo info) { public void init(Properties properties, DynamicRegistryManager dynamicRegistryManager, CallbackInfo info) {
System.err.println(resourcePack); resourcePack = DynRes.removePort(DynRes.simplifyElement(DynRes.baseLink)) + ":" + DynRes.getPort() + "/resources.zip";
System.err.println(resourcePackHash); System.out.println("Pack link: " + resourcePack);
System.err.println(resourcePackSha1);
resourcePack = DynRes.removePort(DynRes.simplifyElement(DynRes.baseLink)) + ":" + DynRes.getPort() + "/" + DynRes.simplifyElement(DynRes.resFile);
//TODO hash the pack //TODO hash the pack
resourcePackSha1 = ""; resourcePackSha1 = "";
if (DynRes.cfg.hashResources) {
try {
FileInputStream fs = new FileInputStream(DynRes.resFile);
resourcePackSha1 = DigestUtils.sha1Hex(fs);
System.out.println("Set hash to " + resourcePackSha1);
fs.close();
} catch (IOException e) {
System.err.println("Failed to get hash, continuing with empty");
e.printStackTrace();
}
}
resourcePackHash = resourcePackSha1; resourcePackHash = resourcePackSha1;
System.err.println(resourcePack);
System.err.println(resourcePackHash);
System.err.println(resourcePackSha1);
} }
} }

View File

@ -5,20 +5,13 @@ import io.gitlab.jfronny.dynres.web.bluemapcore.HttpRequest;
import io.gitlab.jfronny.dynres.web.bluemapcore.HttpRequestHandler; import io.gitlab.jfronny.dynres.web.bluemapcore.HttpRequestHandler;
import io.gitlab.jfronny.dynres.web.bluemapcore.HttpResponse; import io.gitlab.jfronny.dynres.web.bluemapcore.HttpResponse;
import io.gitlab.jfronny.dynres.web.bluemapcore.HttpStatusCode; import io.gitlab.jfronny.dynres.web.bluemapcore.HttpStatusCode;
import org.apache.http.HttpException;
import org.apache.http.MethodNotSupportedException;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.FileEntity;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Locale;
import java.util.Objects; import java.util.Objects;
public class RequestHandler implements HttpRequestHandler { public class RequestHandler implements HttpRequestHandler {
File f;
String r; String r;
@Override @Override
public HttpResponse handle(HttpRequest request) { public HttpResponse handle(HttpRequest request) {
@ -38,7 +31,7 @@ public class RequestHandler implements HttpRequestHandler {
resp.addHeader("Content-Type", "application/zip"); resp.addHeader("Content-Type", "application/zip");
try { try {
FileInputStream fs = new FileInputStream(f); FileInputStream fs = new FileInputStream(DynRes.resFile);
resp.setData(fs); resp.setData(fs);
return resp; return resp;
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
@ -49,8 +42,7 @@ public class RequestHandler implements HttpRequestHandler {
return new HttpResponse(HttpStatusCode.NOT_FOUND); return new HttpResponse(HttpStatusCode.NOT_FOUND);
} }
public RequestHandler(File file, String relativePath) { public RequestHandler(String relativePath) {
f = file;
r = relativePath; r = relativePath;
} }
} }

View File

@ -36,8 +36,8 @@ import java.util.concurrent.TimeUnit;
public class WebServer extends Thread { public class WebServer extends Thread {
private final int port; private int port;
private final int maxConnections; private int maxConnections;
private final InetAddress bindAdress; private final InetAddress bindAdress;
private HttpRequestHandler handler; private HttpRequestHandler handler;
@ -101,6 +101,14 @@ public class WebServer extends Thread {
public int getPort() { public int getPort() {
return server.getLocalPort(); return server.getLocalPort();
} }
public void setPort(int port) {
this.port = port;
}
public void setMaxConnections(int maxConnections) {
this.maxConnections = maxConnections;
}
public void close(){ public void close(){
if (connectionThreads != null) connectionThreads.shutdown(); if (connectionThreads != null) connectionThreads.shutdown();