feat(web): move main port hooking to lightweight separate library for interoperability
This commit is contained in:
parent
3acc4b2420
commit
915f60b6b4
|
@ -0,0 +1,12 @@
|
||||||
|
plugins {
|
||||||
|
id("jfmod.module")
|
||||||
|
}
|
||||||
|
|
||||||
|
base {
|
||||||
|
archivesName.set("libjf-mainhttp-v0")
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
val fabricVersion: String by rootProject.extra
|
||||||
|
implementation(fabricApi.module("fabric-api-base", fabricVersion))
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
package io.gitlab.jfronny.libjf.mainhttp.api.v0;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
public interface MainHttpHandler {
|
||||||
|
default boolean isActive() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte @Nullable [] handle(byte[] request);
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
package io.gitlab.jfronny.libjf.mainhttp.api.v0;
|
||||||
|
|
||||||
|
import io.gitlab.jfronny.libjf.mainhttp.impl.MainHttp;
|
||||||
|
|
||||||
|
public interface ServerState {
|
||||||
|
static void onActivate(Runnable listener) {
|
||||||
|
MainHttp.ON_ACTIVATE.register(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean isActive() {
|
||||||
|
return !MainHttp.GAME_PORT.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getPort() {
|
||||||
|
return MainHttp.GAME_PORT.getTopmost();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,16 +1,11 @@
|
||||||
package io.gitlab.jfronny.libjf.web.impl.variant.shared;
|
package io.gitlab.jfronny.libjf.mainhttp.impl;
|
||||||
|
|
||||||
import io.gitlab.jfronny.libjf.LibJf;
|
import io.gitlab.jfronny.libjf.mainhttp.impl.util.Trie;
|
||||||
import io.gitlab.jfronny.libjf.web.api.v1.HttpRequest;
|
|
||||||
import io.gitlab.jfronny.libjf.web.api.v1.HttpResponse;
|
|
||||||
import io.gitlab.jfronny.libjf.web.impl.JfWeb;
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
import io.netty.channel.*;
|
import io.netty.channel.*;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class HttpDecoder extends ChannelInboundHandlerAdapter {
|
public class HttpDecoder extends ChannelInboundHandlerAdapter {
|
||||||
|
@ -45,20 +40,13 @@ public class HttpDecoder extends ChannelInboundHandlerAdapter {
|
||||||
byte[] data = new byte[buf.readableBytes()];
|
byte[] data = new byte[buf.readableBytes()];
|
||||||
buf.readBytes(data);
|
buf.readBytes(data);
|
||||||
buf.release();
|
buf.release();
|
||||||
// Parse and process request
|
// Process request
|
||||||
try (ByteArrayInputStream is = new ByteArrayInputStream(data);
|
ctx.pipeline()
|
||||||
HttpResponse response = JfWeb.getHandler().handle(HttpRequest.read(is));
|
.firstContext()
|
||||||
ByteArrayOutputStream os = new ByteArrayOutputStream()) {
|
.writeAndFlush(Unpooled.wrappedBuffer(MainHttp.handle(data)))
|
||||||
// Write and send response
|
.addListener(ChannelFutureListener.CLOSE);
|
||||||
response.write(os);
|
|
||||||
os.flush();
|
|
||||||
ctx.pipeline()
|
|
||||||
.firstContext()
|
|
||||||
.writeAndFlush(Unpooled.wrappedBuffer(os.toByteArray()))
|
|
||||||
.addListener(ChannelFutureListener.CLOSE);
|
|
||||||
}
|
|
||||||
} catch (RuntimeException re) {
|
} catch (RuntimeException re) {
|
||||||
LibJf.LOGGER.error("Could not process HTTP", re);
|
MainHttp.LOGGER.error("Could not process HTTP", re);
|
||||||
} finally {
|
} finally {
|
||||||
if (passOn) {
|
if (passOn) {
|
||||||
buf.resetReaderIndex();
|
buf.resetReaderIndex();
|
|
@ -0,0 +1,42 @@
|
||||||
|
package io.gitlab.jfronny.libjf.mainhttp.impl;
|
||||||
|
|
||||||
|
import io.gitlab.jfronny.libjf.mainhttp.api.v0.MainHttpHandler;
|
||||||
|
import io.gitlab.jfronny.libjf.mainhttp.impl.util.ClaimPool;
|
||||||
|
import net.fabricmc.fabric.api.event.Event;
|
||||||
|
import net.fabricmc.fabric.api.event.EventFactory;
|
||||||
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class MainHttp {
|
||||||
|
public static final Event<Runnable> ON_ACTIVATE = EventFactory.createArrayBacked(Runnable.class, listeners -> () -> {
|
||||||
|
for (Runnable listener : listeners) listener.run();
|
||||||
|
});
|
||||||
|
public static final ClaimPool<Integer> GAME_PORT = new ClaimPool<>();
|
||||||
|
public static final String MOD_ID = "libjf-mainhttp";
|
||||||
|
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
|
||||||
|
private static final List<MainHttpHandler> activeHandlers = FabricLoader.getInstance()
|
||||||
|
.getEntrypoints(MOD_ID + ":v0", MainHttpHandler.class)
|
||||||
|
.stream()
|
||||||
|
.filter(MainHttpHandler::isActive)
|
||||||
|
.toList();
|
||||||
|
private static final byte[] NOT_FOUND = """
|
||||||
|
HTTP/1.1 404 Not Found
|
||||||
|
Connection: keep-alive
|
||||||
|
Content-Length: 0
|
||||||
|
""".getBytes();
|
||||||
|
|
||||||
|
public static boolean isEnabled() {
|
||||||
|
return !activeHandlers.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] handle(byte[] request) {
|
||||||
|
for (MainHttpHandler handler : activeHandlers) {
|
||||||
|
byte[] option = handler.handle(request);
|
||||||
|
if (option != null) return option;
|
||||||
|
}
|
||||||
|
return NOT_FOUND;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
package io.gitlab.jfronny.libjf.web.impl.mixin;
|
package io.gitlab.jfronny.libjf.mainhttp.impl.mixin;
|
||||||
|
|
||||||
import io.gitlab.jfronny.libjf.web.impl.JfWebConfig;
|
import io.gitlab.jfronny.libjf.mainhttp.impl.MainHttp;
|
||||||
import org.objectweb.asm.tree.ClassNode;
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
|
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
|
||||||
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
|
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
|
||||||
|
@ -8,8 +8,8 @@ import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class JfWebMixinPlugin implements IMixinConfigPlugin {
|
public class JfMainHTTPMixinPlugin implements IMixinConfigPlugin {
|
||||||
private static final String MIXIN_PACKAGE = "io.gitlab.jfronny.libjf.web.impl.mixin.";
|
private static final String MIXIN_PACKAGE = "io.gitlab.jfronny.libjf.mainhttp.impl.mixin.";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoad(String mixinPackage) {
|
public void onLoad(String mixinPackage) {
|
||||||
|
@ -23,7 +23,7 @@ public class JfWebMixinPlugin implements IMixinConfigPlugin {
|
||||||
@Override
|
@Override
|
||||||
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
|
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
|
||||||
return switch (mixinClassName) {
|
return switch (mixinClassName) {
|
||||||
case MIXIN_PACKAGE + "ServerNetworkIoMixin", MIXIN_PACKAGE + "ServerNetworkIo$1Mixin" -> JfWebConfig.port == -1;
|
case MIXIN_PACKAGE + "ServerNetworkIoMixin", MIXIN_PACKAGE + "ServerNetworkIo$1Mixin" -> MainHttp.isEnabled();
|
||||||
default -> throw new IllegalArgumentException("Unexpected mixin: " + mixinClassName);
|
default -> throw new IllegalArgumentException("Unexpected mixin: " + mixinClassName);
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
package io.gitlab.jfronny.libjf.web.impl.mixin;
|
package io.gitlab.jfronny.libjf.mainhttp.impl.mixin;
|
||||||
|
|
||||||
import io.gitlab.jfronny.libjf.web.impl.variant.shared.HttpDecoder;
|
import io.gitlab.jfronny.libjf.mainhttp.impl.HttpDecoder;
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
|
@ -1,7 +1,7 @@
|
||||||
package io.gitlab.jfronny.libjf.web.impl.mixin;
|
package io.gitlab.jfronny.libjf.mainhttp.impl.mixin;
|
||||||
|
|
||||||
import io.gitlab.jfronny.libjf.web.impl.util.ClaimPool;
|
import io.gitlab.jfronny.libjf.mainhttp.impl.MainHttp;
|
||||||
import io.gitlab.jfronny.libjf.web.impl.variant.shared.SharedWebServer;
|
import io.gitlab.jfronny.libjf.mainhttp.impl.util.ClaimPool;
|
||||||
import net.minecraft.server.ServerNetworkIo;
|
import net.minecraft.server.ServerNetworkIo;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Unique;
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
|
@ -15,12 +15,13 @@ import java.util.Set;
|
||||||
|
|
||||||
@Mixin(ServerNetworkIo.class)
|
@Mixin(ServerNetworkIo.class)
|
||||||
public class ServerNetworkIoMixin {
|
public class ServerNetworkIoMixin {
|
||||||
@Unique private final Set<ClaimPool<Integer>.Claim> libjf$portClaim = new HashSet<>();
|
@Unique
|
||||||
|
private final Set<ClaimPool<Integer>.Claim> libjf$portClaim = new HashSet<>();
|
||||||
|
|
||||||
@Inject(method = "bind(Ljava/net/InetAddress;I)V", at = @At("HEAD"))
|
@Inject(method = "bind(Ljava/net/InetAddress;I)V", at = @At("HEAD"))
|
||||||
void onBind(InetAddress address, int port, CallbackInfo ci) {
|
void onBind(InetAddress address, int port, CallbackInfo ci) {
|
||||||
libjf$portClaim.add(SharedWebServer.gamePort.claim(port));
|
libjf$portClaim.add(MainHttp.GAME_PORT.claim(port));
|
||||||
SharedWebServer.emitActive();
|
MainHttp.ON_ACTIVATE.invoker().run();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(method = "stop()V", at = @At("HEAD"))
|
@Inject(method = "stop()V", at = @At("HEAD"))
|
|
@ -1,4 +1,4 @@
|
||||||
package io.gitlab.jfronny.libjf.web.impl.util;
|
package io.gitlab.jfronny.libjf.mainhttp.impl.util;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
|
@ -1,4 +1,4 @@
|
||||||
package io.gitlab.jfronny.libjf.web.impl.variant.shared;
|
package io.gitlab.jfronny.libjf.mainhttp.impl.util;
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.chars.Char2ObjectArrayMap;
|
import it.unimi.dsi.fastutil.chars.Char2ObjectArrayMap;
|
||||||
import it.unimi.dsi.fastutil.chars.Char2ObjectMap;
|
import it.unimi.dsi.fastutil.chars.Char2ObjectMap;
|
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"id": "libjf-mainhttp-v0",
|
||||||
|
"name": "LibJF MainHTTP",
|
||||||
|
"version": "${version}",
|
||||||
|
"authors": [
|
||||||
|
"JFronny"
|
||||||
|
],
|
||||||
|
"contact": {
|
||||||
|
"email": "projects.contact@frohnmeyer-wds.de",
|
||||||
|
"homepage": "https://jfronny.gitlab.io",
|
||||||
|
"issues": "https://git.frohnmeyer-wds.de/JfMods/LibJF/issues",
|
||||||
|
"sources": "https://git.frohnmeyer-wds.de/JfMods/LibJF"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"environment": "*",
|
||||||
|
"mixins": ["libjf-mainhttp-v0.mixins.json"],
|
||||||
|
"depends": {
|
||||||
|
"fabricloader": ">=0.12.0",
|
||||||
|
"minecraft": "*"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"modmenu": {
|
||||||
|
"parent": "libjf",
|
||||||
|
"badges": ["library"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,9 @@
|
||||||
{
|
{
|
||||||
"required": true,
|
"required": true,
|
||||||
"minVersion": "0.8",
|
"minVersion": "0.8",
|
||||||
"package": "io.gitlab.jfronny.libjf.web.impl.mixin",
|
"package": "io.gitlab.jfronny.libjf.mainhttp.impl.mixin",
|
||||||
"compatibilityLevel": "JAVA_16",
|
"compatibilityLevel": "JAVA_16",
|
||||||
"plugin": "io.gitlab.jfronny.libjf.web.impl.mixin.JfWebMixinPlugin",
|
"plugin": "io.gitlab.jfronny.libjf.mainhttp.impl.mixin.JfMainHTTPMixinPlugin",
|
||||||
"server": [
|
"server": [
|
||||||
"ServerNetworkIo$1Mixin",
|
"ServerNetworkIo$1Mixin",
|
||||||
"ServerNetworkIoMixin"
|
"ServerNetworkIoMixin"
|
|
@ -12,6 +12,7 @@ dependencies {
|
||||||
val fabricVersion: String by rootProject.extra
|
val fabricVersion: String by rootProject.extra
|
||||||
api(devProject(":libjf-base"))
|
api(devProject(":libjf-base"))
|
||||||
api(devProject(":libjf-config-core-v2"))
|
api(devProject(":libjf-config-core-v2"))
|
||||||
|
api(devProject(":libjf-mainhttp-v0"))
|
||||||
include(modImplementation(fabricApi.module("fabric-command-api-v2", fabricVersion))!!)
|
include(modImplementation(fabricApi.module("fabric-command-api-v2", fabricVersion))!!)
|
||||||
|
|
||||||
annotationProcessor(project(":libjf-config-compiler-plugin-v2"))
|
annotationProcessor(project(":libjf-config-compiler-plugin-v2"))
|
||||||
|
|
|
@ -44,7 +44,7 @@ public class HttpResponseImpl implements HttpResponse {
|
||||||
this.version = "HTTP/1.1";
|
this.version = "HTTP/1.1";
|
||||||
this.statusCode = statusCode;
|
this.statusCode = statusCode;
|
||||||
|
|
||||||
this.header = new HashMap<>();
|
this.header = new LinkedHashMap<>();
|
||||||
|
|
||||||
addHeader("Connection", "keep-alive");
|
addHeader("Connection", "keep-alive");
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ public class HttpResponseImpl implements HttpResponse {
|
||||||
@Override
|
@Override
|
||||||
public HttpResponseImpl addHeader(String key, String value) {
|
public HttpResponseImpl addHeader(String key, String value) {
|
||||||
ensureOpen();
|
ensureOpen();
|
||||||
Set<String> valueSet = header.computeIfAbsent(key, k -> new HashSet<>());
|
Set<String> valueSet = header.computeIfAbsent(key, k -> new LinkedHashSet<>());
|
||||||
valueSet.add(value);
|
valueSet.add(value);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ public class HttpResponseImpl implements HttpResponse {
|
||||||
@Override
|
@Override
|
||||||
public HttpResponseImpl removeHeader(String key, String value) {
|
public HttpResponseImpl removeHeader(String key, String value) {
|
||||||
ensureOpen();
|
ensureOpen();
|
||||||
Set<String> valueSet = header.computeIfAbsent(key, k -> new HashSet<>());
|
Set<String> valueSet = header.computeIfAbsent(key, k -> new LinkedHashSet<>());
|
||||||
valueSet.remove(value);
|
valueSet.remove(value);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -88,14 +88,15 @@ public class HttpResponseImpl implements HttpResponse {
|
||||||
public void write(OutputStream out) throws IOException {
|
public void write(OutputStream out) throws IOException {
|
||||||
OutputStreamWriter writer = new OutputStreamWriter(out, StandardCharsets.UTF_8);
|
OutputStreamWriter writer = new OutputStreamWriter(out, StandardCharsets.UTF_8);
|
||||||
|
|
||||||
|
Map<String, Set<String>> finalHeaders = new LinkedHashMap<>(header);
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
addHeader("Transfer-Encoding", "chunked");
|
finalHeaders.computeIfAbsent("Transfer-Encoding", k -> new LinkedHashSet<>()).add("chunked");
|
||||||
} else {
|
} else {
|
||||||
addHeader("Content-Length", "0");
|
finalHeaders.computeIfAbsent("Content-Length", k -> new LinkedHashSet<>()).add("0");
|
||||||
}
|
}
|
||||||
|
|
||||||
writeLine(writer, version + " " + statusCode.getCode() + " " + statusCode.getMessage());
|
writeLine(writer, version + " " + statusCode.getCode() + " " + statusCode.getMessage());
|
||||||
for (Entry<String, Set<String>> e : header.entrySet()) {
|
for (Entry<String, Set<String>> e : finalHeaders.entrySet()) {
|
||||||
if (e.getValue().isEmpty()) continue;
|
if (e.getValue().isEmpty()) continue;
|
||||||
writeLine(writer, e.getKey() + ": " + StringUtils.join(e.getValue(), ", "));
|
writeLine(writer, e.getKey() + ": " + StringUtils.join(e.getValue(), ", "));
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
package io.gitlab.jfronny.libjf.web.impl.variant.shared;
|
||||||
|
|
||||||
|
import io.gitlab.jfronny.libjf.mainhttp.api.v0.MainHttpHandler;
|
||||||
|
import io.gitlab.jfronny.libjf.mainhttp.api.v0.ServerState;
|
||||||
|
import io.gitlab.jfronny.libjf.web.api.v1.*;
|
||||||
|
import io.gitlab.jfronny.libjf.web.impl.JfWeb;
|
||||||
|
import io.gitlab.jfronny.libjf.web.impl.JfWebConfig;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public class MainHttpHandlerImpl implements MainHttpHandler {
|
||||||
|
public MainHttpHandlerImpl() {
|
||||||
|
ServerState.onActivate(SharedWebServer::emitActive);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isActive() {
|
||||||
|
return JfWebConfig.port == -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte @Nullable [] handle(byte[] request) {
|
||||||
|
// Parse and process request
|
||||||
|
try (ByteArrayInputStream is = new ByteArrayInputStream(request);
|
||||||
|
HttpResponse response = JfWeb.getHandler().handle(HttpRequest.read(is))) {
|
||||||
|
if (response.getStatusCode() == HttpStatusCode.NOT_FOUND) return null;
|
||||||
|
// Write and send response
|
||||||
|
try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
|
||||||
|
response.write(os);
|
||||||
|
os.flush();
|
||||||
|
return os.toByteArray();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,13 +1,12 @@
|
||||||
package io.gitlab.jfronny.libjf.web.impl.variant.shared;
|
package io.gitlab.jfronny.libjf.web.impl.variant.shared;
|
||||||
|
|
||||||
|
import io.gitlab.jfronny.libjf.mainhttp.api.v0.ServerState;
|
||||||
import io.gitlab.jfronny.libjf.web.impl.host.RequestHandler;
|
import io.gitlab.jfronny.libjf.web.impl.host.RequestHandler;
|
||||||
import io.gitlab.jfronny.libjf.web.impl.util.ClaimPool;
|
|
||||||
import io.gitlab.jfronny.libjf.web.impl.variant.AbstractWebServer;
|
import io.gitlab.jfronny.libjf.web.impl.variant.AbstractWebServer;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class SharedWebServer extends AbstractWebServer {
|
public class SharedWebServer extends AbstractWebServer {
|
||||||
public static final ClaimPool<Integer> gamePort = new ClaimPool<>();
|
|
||||||
public static final Set<Runnable> onActive = new LinkedHashSet<>();
|
public static final Set<Runnable> onActive = new LinkedHashSet<>();
|
||||||
|
|
||||||
public static void emitActive() {
|
public static void emitActive() {
|
||||||
|
@ -23,9 +22,8 @@ public class SharedWebServer extends AbstractWebServer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getServerRoot() {
|
public String getServerRoot() {
|
||||||
Integer gamePort = this.gamePort.getTopmost();
|
if (!ServerState.isActive()) throw new UnsupportedOperationException("Attempted to get server root on unhosted server");
|
||||||
if (gamePort == null) throw new UnsupportedOperationException("Attempted to get server root on unhosted server");
|
else return getServerRoot(ServerState.getPort());
|
||||||
else return getServerRoot(gamePort);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -47,6 +45,6 @@ public class SharedWebServer extends AbstractWebServer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isActive() {
|
public boolean isActive() {
|
||||||
return !gamePort.isEmpty();
|
return ServerState.isActive();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,17 +15,18 @@
|
||||||
},
|
},
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"environment": "*",
|
"environment": "*",
|
||||||
"mixins": ["libjf-web-v1.mixins.json"],
|
|
||||||
"entrypoints": {
|
"entrypoints": {
|
||||||
"main": ["io.gitlab.jfronny.libjf.web.impl.JfWeb"],
|
"main": ["io.gitlab.jfronny.libjf.web.impl.JfWeb"],
|
||||||
"libjf:coprocess": ["io.gitlab.jfronny.libjf.web.impl.JfWeb"],
|
"libjf:coprocess": ["io.gitlab.jfronny.libjf.web.impl.JfWeb"],
|
||||||
"libjf:config": ["io.gitlab.jfronny.libjf.web.impl.JFC_JfWebConfig"]
|
"libjf:config": ["io.gitlab.jfronny.libjf.web.impl.JFC_JfWebConfig"],
|
||||||
|
"libjf-mainhttp:v0": ["io.gitlab.jfronny.libjf.web.impl.variant.shared.MainHttpHandlerImpl"]
|
||||||
},
|
},
|
||||||
"depends": {
|
"depends": {
|
||||||
"fabricloader": ">=0.12.0",
|
"fabricloader": ">=0.12.0",
|
||||||
"minecraft": "*",
|
"minecraft": "*",
|
||||||
"libjf-base": ">=${version}",
|
"libjf-base": ">=${version}",
|
||||||
"libjf-config-core-v2": ">=${version}",
|
"libjf-config-core-v2": ">=${version}",
|
||||||
|
"libjf-mainhttp-v0": ">=${version}",
|
||||||
"fabric-command-api-v2": "*"
|
"fabric-command-api-v2": "*"
|
||||||
},
|
},
|
||||||
"custom": {
|
"custom": {
|
||||||
|
|
|
@ -17,11 +17,16 @@ include("libjf-base")
|
||||||
include("libjf-config-core-v2")
|
include("libjf-config-core-v2")
|
||||||
include("libjf-config-commands")
|
include("libjf-config-commands")
|
||||||
include("libjf-config-ui-tiny")
|
include("libjf-config-ui-tiny")
|
||||||
|
include("libjf-config-compiler-plugin-v2")
|
||||||
|
|
||||||
include("libjf-data-v0")
|
include("libjf-data-v0")
|
||||||
include("libjf-data-manipulation-v0")
|
include("libjf-data-manipulation-v0")
|
||||||
include("libjf-devutil")
|
|
||||||
include("libjf-translate-v1")
|
|
||||||
include("libjf-unsafe-v0")
|
|
||||||
include("libjf-web-v1")
|
|
||||||
|
|
||||||
include("libjf-config-compiler-plugin-v2")
|
include("libjf-devutil")
|
||||||
|
|
||||||
|
include("libjf-translate-v1")
|
||||||
|
|
||||||
|
include("libjf-unsafe-v0")
|
||||||
|
|
||||||
|
include("libjf-mainhttp-v0")
|
||||||
|
include("libjf-web-v1")
|
||||||
|
|
Loading…
Reference in New Issue