From 10527ec2bb94b40cf3b6f3adcca92a2ab32dc262 Mon Sep 17 00:00:00 2001 From: JFronny Date: Sun, 20 Aug 2023 12:13:11 +0200 Subject: [PATCH 1/7] feat(data-manipulation): reverse order of FIND_RESOURCE application to make more sense --- .../libjf/data/manipulation/api/UserResourceEvents.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libjf-data-manipulation-v0/src/main/java/io/gitlab/jfronny/libjf/data/manipulation/api/UserResourceEvents.java b/libjf-data-manipulation-v0/src/main/java/io/gitlab/jfronny/libjf/data/manipulation/api/UserResourceEvents.java index ea42e55..308ea49 100644 --- a/libjf-data-manipulation-v0/src/main/java/io/gitlab/jfronny/libjf/data/manipulation/api/UserResourceEvents.java +++ b/libjf-data-manipulation-v0/src/main/java/io/gitlab/jfronny/libjf/data/manipulation/api/UserResourceEvents.java @@ -57,8 +57,8 @@ public class UserResourceEvents { public static final Event FIND_RESOURCE = EventFactory.createArrayBacked(FindResource.class, listeners -> (type, namespace, prefix, previous, pack) -> { ResourcePack.ResultConsumer lazy = previous; - for (FindResource listener : listeners) { - lazy = listener.findResources(type, namespace, prefix, lazy, pack); + for (int i = listeners.length - 1; i >= 0; i--) { + lazy = listeners[i].findResources(type, namespace, prefix, lazy, pack); } return lazy; }); From a759d200647e6f8902968ccf0ffa6ad5530bd860 Mon Sep 17 00:00:00 2001 From: JFronny Date: Sun, 20 Aug 2023 12:18:38 +0200 Subject: [PATCH 2/7] chore(config-ui): remove deprecated APIs --- .../config/api/v1/ui/ConfigScreenFactory.java | 16 -------- .../impl/ui/ConfigScreenFactory1To2.java | 29 -------------- .../impl/ui/ConfigScreenFactory2To1.java | 17 --------- .../impl/ui/ConfigScreenFactoryDiscovery.java | 38 +++---------------- .../libjf/config/api/v1/EntryInfo.java | 13 ------- .../config/api/v1/ui/tiny/ConfigScreen.java | 13 ------- .../config/impl/ui/tiny/TinyConfigTab.java | 2 +- .../ui/tiny/entry/EntryInfoWidgetBuilder.java | 1 - .../ui/tiny/entry}/WidgetFactory.java | 4 +- .../impl/ui/tiny/entry/WidgetState.java | 1 - 10 files changed, 7 insertions(+), 127 deletions(-) delete mode 100644 libjf-config-core-v1/src/client/java/io/gitlab/jfronny/libjf/config/api/v1/ui/ConfigScreenFactory.java delete mode 100644 libjf-config-core-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/ConfigScreenFactory1To2.java delete mode 100644 libjf-config-core-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/ConfigScreenFactory2To1.java delete mode 100644 libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/api/v1/ui/tiny/ConfigScreen.java rename libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/{api/v1/ui/tiny => impl/ui/tiny/entry}/WidgetFactory.java (78%) diff --git a/libjf-config-core-v1/src/client/java/io/gitlab/jfronny/libjf/config/api/v1/ui/ConfigScreenFactory.java b/libjf-config-core-v1/src/client/java/io/gitlab/jfronny/libjf/config/api/v1/ui/ConfigScreenFactory.java deleted file mode 100644 index e97fcd8..0000000 --- a/libjf-config-core-v1/src/client/java/io/gitlab/jfronny/libjf/config/api/v1/ui/ConfigScreenFactory.java +++ /dev/null @@ -1,16 +0,0 @@ -package io.gitlab.jfronny.libjf.config.api.v1.ui; - -import io.gitlab.jfronny.libjf.config.api.v1.ConfigInstance; -import io.gitlab.jfronny.libjf.config.impl.ui.ConfigScreenFactoryDiscovery; -import net.minecraft.client.gui.screen.Screen; - -@Deprecated -public interface ConfigScreenFactory { - static ConfigScreenFactory getInstance() { - return ConfigScreenFactoryDiscovery.getConfigured(); - } - - S create(ConfigInstance config, Screen parent); - - int getPriority(); -} diff --git a/libjf-config-core-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/ConfigScreenFactory1To2.java b/libjf-config-core-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/ConfigScreenFactory1To2.java deleted file mode 100644 index 1643f82..0000000 --- a/libjf-config-core-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/ConfigScreenFactory1To2.java +++ /dev/null @@ -1,29 +0,0 @@ -package io.gitlab.jfronny.libjf.config.impl.ui; - -import io.gitlab.jfronny.libjf.config.api.v1.ConfigInstance; -import io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory; -import net.minecraft.client.gui.screen.Screen; - -public record ConfigScreenFactory1To2(io.gitlab.jfronny.libjf.config.api.v1.ui.ConfigScreenFactory impl) implements ConfigScreenFactory> { - @Override - public Built create(ConfigInstance config, Screen parent) { - return new Built<>(impl.create(config, parent)); - } - - @Override - public int getPriority() { - return impl.getPriority(); - } - - public record Built(S screen) implements ConfigScreenFactory.Built { - @Override - public S get() { - return null; - } - - @Override - public void onSave(Runnable action) { - throw new UnsupportedOperationException(); - } - } -} diff --git a/libjf-config-core-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/ConfigScreenFactory2To1.java b/libjf-config-core-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/ConfigScreenFactory2To1.java deleted file mode 100644 index 3e45b29..0000000 --- a/libjf-config-core-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/ConfigScreenFactory2To1.java +++ /dev/null @@ -1,17 +0,0 @@ -package io.gitlab.jfronny.libjf.config.impl.ui; - -import io.gitlab.jfronny.libjf.config.api.v1.ConfigInstance; -import io.gitlab.jfronny.libjf.config.api.v1.ui.ConfigScreenFactory; -import net.minecraft.client.gui.screen.Screen; - -public record ConfigScreenFactory2To1>(io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory impl) implements ConfigScreenFactory { - @Override - public S create(ConfigInstance config, Screen parent) { - return impl.create(config, parent).get(); - } - - @Override - public int getPriority() { - return impl.getPriority(); - } -} diff --git a/libjf-config-core-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/ConfigScreenFactoryDiscovery.java b/libjf-config-core-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/ConfigScreenFactoryDiscovery.java index 48214e7..ba5e9fe 100644 --- a/libjf-config-core-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/ConfigScreenFactoryDiscovery.java +++ b/libjf-config-core-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/ConfigScreenFactoryDiscovery.java @@ -1,50 +1,22 @@ package io.gitlab.jfronny.libjf.config.impl.ui; -import io.gitlab.jfronny.libjf.config.api.v1.ui.ConfigScreenFactory; +import io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory; import net.fabricmc.loader.api.FabricLoader; import java.util.Comparator; import java.util.List; public class ConfigScreenFactoryDiscovery { - private static ConfigScreenFactory discovered1 = null; - private static io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory discovered2 = null; - - @Deprecated - public static ConfigScreenFactory getConfigured() { - if (discovered1 == null) { - List entrypoints = getEntrypoints(); - discovered1 = entrypoints - .stream() - .filter(it -> it instanceof io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory) - .map(it -> (io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory) it) - .max(Comparator.comparing(io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory::getPriority)) - .map(ConfigScreenFactory2To1::new) - .orElseGet(() -> entrypoints - .stream() - .filter(it -> it instanceof ConfigScreenFactory) - .map(it -> (ConfigScreenFactory) it) - .max(Comparator.comparing(ConfigScreenFactory::getPriority)) - .orElseGet(() -> new ConfigScreenFactory2To1(new PlaceholderScreenFactory()))); - } - return discovered1; - } + private static ConfigScreenFactory discovered2 = null; public static io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory getConfigured2() { if (discovered2 == null) { - List entrypoints = getEntrypoints(); - discovered2 = entrypoints + discovered2 = getEntrypoints() .stream() .filter(it -> it instanceof io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory) - .map(it -> (io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory) it) + .>map(it -> (ConfigScreenFactory) it) .max(Comparator.comparing(io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory::getPriority)) - .orElseGet(() -> entrypoints - .stream() - .filter(it -> it instanceof ConfigScreenFactory) - .map(it -> (ConfigScreenFactory) it) - .map(ConfigScreenFactory1To2::new) - .max(Comparator.comparing(io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory::getPriority)) - .orElseGet(PlaceholderScreenFactory::new)); + .orElseGet(PlaceholderScreenFactory::new); } return discovered2; } diff --git a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/EntryInfo.java b/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/EntryInfo.java index cc2cfbb..b991f8d 100644 --- a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/EntryInfo.java +++ b/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/EntryInfo.java @@ -58,19 +58,6 @@ public interface EntryInfo { */ void fix(); - /** - * Set this entry's value to that of the element - * @param element The element to read from - */ - @Deprecated - default void loadFromJson(JsonElement element) throws IllegalAccessException { - try { - loadFromJson(new JsonTreeReader(element)); - } catch (IOException e) { - throw new JsonParseException("Could not read Json", e); - } - } - /** * Set this entry's value to that of the element * @param reader The reader to read from diff --git a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/api/v1/ui/tiny/ConfigScreen.java b/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/api/v1/ui/tiny/ConfigScreen.java deleted file mode 100644 index b18477a..0000000 --- a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/api/v1/ui/tiny/ConfigScreen.java +++ /dev/null @@ -1,13 +0,0 @@ -package io.gitlab.jfronny.libjf.config.api.v1.ui.tiny; - -import io.gitlab.jfronny.libjf.config.api.v1.ConfigInstance; -import io.gitlab.jfronny.libjf.config.impl.ui.tiny.TinyConfigScreenFactory; -import net.minecraft.client.gui.screen.Screen; - -@Deprecated -public interface ConfigScreen { - TinyConfigScreenFactory FACTORY = new TinyConfigScreenFactory(); - static Screen create(ConfigInstance config, Screen parent) { - return FACTORY.create(config, parent).get(); - } -} diff --git a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/TinyConfigTab.java b/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/TinyConfigTab.java index 70d879e..cb4adae 100644 --- a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/TinyConfigTab.java +++ b/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/TinyConfigTab.java @@ -2,7 +2,7 @@ package io.gitlab.jfronny.libjf.config.impl.ui.tiny; import io.gitlab.jfronny.libjf.config.api.v1.ConfigCategory; import io.gitlab.jfronny.libjf.config.api.v1.ConfigInstance; -import io.gitlab.jfronny.libjf.config.api.v1.ui.tiny.WidgetFactory; +import io.gitlab.jfronny.libjf.config.impl.ui.tiny.entry.WidgetFactory; import io.gitlab.jfronny.libjf.config.impl.entrypoint.JfConfigSafe; import io.gitlab.jfronny.libjf.config.impl.ui.tiny.entry.*; import io.gitlab.jfronny.libjf.config.impl.ui.tiny.presets.PresetsScreen; diff --git a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/EntryInfoWidgetBuilder.java b/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/EntryInfoWidgetBuilder.java index b437d57..7613bde 100644 --- a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/EntryInfoWidgetBuilder.java +++ b/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/EntryInfoWidgetBuilder.java @@ -7,7 +7,6 @@ import io.gitlab.jfronny.libjf.LibJf; import io.gitlab.jfronny.libjf.config.api.v1.ConfigCategory; import io.gitlab.jfronny.libjf.config.api.v1.EntryInfo; import io.gitlab.jfronny.libjf.config.api.v1.type.Type; -import io.gitlab.jfronny.libjf.config.api.v1.ui.tiny.WidgetFactory; import io.gitlab.jfronny.libjf.config.impl.ui.tiny.EditorScreen; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; diff --git a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/api/v1/ui/tiny/WidgetFactory.java b/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/WidgetFactory.java similarity index 78% rename from libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/api/v1/ui/tiny/WidgetFactory.java rename to libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/WidgetFactory.java index adaafd9..e50403f 100644 --- a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/api/v1/ui/tiny/WidgetFactory.java +++ b/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/WidgetFactory.java @@ -1,8 +1,6 @@ -package io.gitlab.jfronny.libjf.config.api.v1.ui.tiny; +package io.gitlab.jfronny.libjf.config.impl.ui.tiny.entry; import io.gitlab.jfronny.libjf.config.impl.ui.tiny.TinyConfigScreen; -import io.gitlab.jfronny.libjf.config.impl.ui.tiny.entry.Reflowable; -import io.gitlab.jfronny.libjf.config.impl.ui.tiny.entry.WidgetState; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.widget.ClickableWidget; diff --git a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/WidgetState.java b/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/WidgetState.java index 25d5735..d4f45fe 100644 --- a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/WidgetState.java +++ b/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/WidgetState.java @@ -3,7 +3,6 @@ package io.gitlab.jfronny.libjf.config.impl.ui.tiny.entry; import io.gitlab.jfronny.commons.ref.R; import io.gitlab.jfronny.libjf.LibJf; import io.gitlab.jfronny.libjf.config.api.v1.EntryInfo; -import io.gitlab.jfronny.libjf.config.api.v1.ui.tiny.WidgetFactory; import net.minecraft.text.Text; import org.jetbrains.annotations.Nullable; From f03f1c306de452d1221e19a85b9308b41af9cdd4 Mon Sep 17 00:00:00 2001 From: JFronny Date: Sun, 20 Aug 2023 13:33:23 +0200 Subject: [PATCH 3/7] feat: update to 1.20.2 snapshots --- build.gradle.kts | 21 ++++++---- .../config/impl/ui/PlaceholderScreen.java | 11 ++---- .../lang/en_us.json | 3 ++ .../libjf-config-core-v1/lang/en_us.json | 5 --- .../config/impl/ui/tiny/EditorScreen.java | 34 ++++++++--------- .../config/impl/ui/tiny/Placeholder.java | 5 +-- .../config/impl/ui/tiny/TinyConfigScreen.java | 12 +----- .../config/impl/ui/tiny/TinyConfigTab.java | 5 --- .../impl/ui/tiny/entry/EntryListWidget.java | 1 - .../impl/ui/tiny/presets/PresetsScreen.java | 14 ++----- .../test/tiny/mixin/OptionsScreenMixin.java | 38 +++++++++++++++++++ .../src/testmod/resources/fabric.mod.json | 1 + ...ibjf-config-ui-tiny-v1-testmod.mixins.json | 14 +++++++ 13 files changed, 97 insertions(+), 67 deletions(-) rename libjf-config-core-v1/src/client/resources/assets/{libjf-config-ui-tiny-v1 => libjf-config-core-v1}/lang/en_us.json (60%) delete mode 100644 libjf-config-core-v1/src/main/resources/assets/libjf-config-core-v1/lang/en_us.json create mode 100644 libjf-config-ui-tiny-v1/src/testmod/java/io/gitlab/jfronny/libjf/config/test/tiny/mixin/OptionsScreenMixin.java create mode 100644 libjf-config-ui-tiny-v1/src/testmod/resources/libjf-config-ui-tiny-v1-testmod.mixins.json diff --git a/build.gradle.kts b/build.gradle.kts index d9b8c27..5336942 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,8 +6,8 @@ allprojects { group = "io.gitlab.jfronny.libjf" } -val fabricVersion by extra("0.86.1+1.20.1") -val commonsVersion by extra("1.3-SNAPSHOT") +val fabricVersion by extra("0.87.1+1.20.2") +val commonsVersion by extra("1.4-SNAPSHOT") val gsonCompileVersion by extra("1.3-SNAPSHOT") val modmenuVersion by extra("7.2.1") @@ -15,8 +15,8 @@ val annotationsVersion by extra("24.0.1") val javapoetVersion by extra("1.13.0") jfMod { - minecraftVersion = "1.20.1" - yarn("build.10") + minecraftVersion = "23w33a" + yarn("build.3") loaderVersion = "0.14.22" modrinth { @@ -37,11 +37,18 @@ allprojects { } dependencies { - modLocalRuntime("com.terraformersmc:modmenu:$modmenuVersion") { - exclude("net.fabricmc") // required to work around duplicate fabric loaders - } + // Temporarily disabled since modmenu doesn't support snapshots +// modLocalRuntime("com.terraformersmc:modmenu:$modmenuVersion") { +// exclude("net.fabricmc") // required to work around duplicate fabric loaders +// } modLocalRuntime(fabricApi.module("fabric-command-api-v2", fabricVersion)) compileOnly("io.gitlab.jfronny:commons:$commonsVersion") compileOnly("io.gitlab.jfronny:commons-gson:$commonsVersion") + + // temporary workaround for snapshot versions since these were previously provided by modmenu. Remove once out of use! + modLocalRuntime(fabricApi.module("fabric-resource-loader-v0", fabricVersion)) + modLocalRuntime(fabricApi.module("fabric-lifecycle-events-v1", fabricVersion)) + modLocalRuntime(fabricApi.module("fabric-screen-api-v1", fabricVersion)) + modLocalRuntime(fabricApi.module("fabric-key-binding-api-v1", fabricVersion)) } } diff --git a/libjf-config-core-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/PlaceholderScreen.java b/libjf-config-core-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/PlaceholderScreen.java index ffed03b..7c4ff55 100644 --- a/libjf-config-core-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/PlaceholderScreen.java +++ b/libjf-config-core-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/PlaceholderScreen.java @@ -1,6 +1,5 @@ package io.gitlab.jfronny.libjf.config.impl.ui; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.text.Text; @@ -13,13 +12,9 @@ public class PlaceholderScreen extends Screen { protected PlaceholderScreen(Screen parent) { super(Text.translatable("libjf-config-core-v1.no-screen")); this.parent = parent; - } - - @Override - public void render(DrawContext context, int mouseX, int mouseY, float delta) { - renderBackground(context); - context.drawCenteredTextWithShadow(textRenderer, description, width / 2, (height - textRenderer.fontHeight) / 2, 0xFFFFFF); - super.render(context, mouseX, mouseY, delta); + addDrawable((context, mouseX, mouseY, delta) -> { + context.drawCenteredTextWithShadow(textRenderer, description, width / 2, (height - textRenderer.fontHeight) / 2, 0xFFFFFF); + }); } @Override diff --git a/libjf-config-core-v1/src/client/resources/assets/libjf-config-ui-tiny-v1/lang/en_us.json b/libjf-config-core-v1/src/client/resources/assets/libjf-config-core-v1/lang/en_us.json similarity index 60% rename from libjf-config-core-v1/src/client/resources/assets/libjf-config-ui-tiny-v1/lang/en_us.json rename to libjf-config-core-v1/src/client/resources/assets/libjf-config-core-v1/lang/en_us.json index c30f9b2..a5678ab 100644 --- a/libjf-config-core-v1/src/client/resources/assets/libjf-config-ui-tiny-v1/lang/en_us.json +++ b/libjf-config-core-v1/src/client/resources/assets/libjf-config-core-v1/lang/en_us.json @@ -1,4 +1,7 @@ { + "libjf-config-core-v1.jfconfig.title": "LibJF Config", + "libjf-config-core-v1.jfconfig.watchForChanges": "Watch for changes", + "libjf-config-core-v1.jfconfig.watchForChanges.tooltip": "Automatically reload configs when they are changed", "libjf-config-v1.presets": "Presets", "libjf-config-v1.default": "Default", "libjf-config-v1.see-also": "See also: %s", diff --git a/libjf-config-core-v1/src/main/resources/assets/libjf-config-core-v1/lang/en_us.json b/libjf-config-core-v1/src/main/resources/assets/libjf-config-core-v1/lang/en_us.json deleted file mode 100644 index 91b2da2..0000000 --- a/libjf-config-core-v1/src/main/resources/assets/libjf-config-core-v1/lang/en_us.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "libjf-config-core-v1.jfconfig.title": "LibJF Config", - "libjf-config-core-v1.jfconfig.watchForChanges": "Watch for changes", - "libjf-config-core-v1.jfconfig.watchForChanges.tooltip": "Automatically reload configs when they are changed" -} \ No newline at end of file diff --git a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/EditorScreen.java b/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/EditorScreen.java index ae15b8a..a935af8 100644 --- a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/EditorScreen.java +++ b/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/EditorScreen.java @@ -11,6 +11,7 @@ import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.render.RenderLayer; import net.minecraft.client.util.NarratorManager; import net.minecraft.client.util.SelectionManager; import net.minecraft.client.util.math.Rect2i; @@ -283,7 +284,7 @@ public class EditorScreen extends ScreenWithSaveHook { @Override public void render(DrawContext context, int mouseX, int mouseY, float delta) { - renderBackground(context); + super.render(context, mouseX, mouseY, delta); if (subtitle == null) { context.drawCenteredTextWithShadow(textRenderer, title, width / 2, (HEADER_SIZE - textRenderer.fontHeight) / 2, 0xFFFFFF); } else { @@ -292,9 +293,12 @@ public class EditorScreen extends ScreenWithSaveHook { } this.setFocused(null); + final int maxScroll = this.getMaxScroll(); + final boolean showScrollbar = maxScroll > 0; + if (client.world == null) { RenderSystem.setShaderColor(0.125f, 0.125f, 0.125f, 1.0f); - context.drawTexture(Screen.OPTIONS_BACKGROUND_TEXTURE, 0, HEADER_SIZE, width - SCROLLBAR_SIZE, height - FOOTER_SIZE + (int)scrollAmount, width - SCROLLBAR_SIZE, height - HEADER_SIZE - FOOTER_SIZE, 32, 32); + context.drawTexture(Screen.OPTIONS_BACKGROUND_TEXTURE, 0, HEADER_SIZE, showScrollbar ? width - SCROLLBAR_SIZE : width, height - FOOTER_SIZE + (int)scrollAmount, width - SCROLLBAR_SIZE, height - HEADER_SIZE - FOOTER_SIZE, 32, 32); RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f); } @@ -307,20 +311,17 @@ public class EditorScreen extends ScreenWithSaveHook { this.drawCursor(context, pageContent.position); context.disableScissor(); - int i = this.getScrollbarPositionX(); - int j = i + 6; - int m; - if ((m = this.getMaxScroll()) > 0) { + int scrollbarX = this.getScrollbarPositionX(); + int scrollbarXEnd = scrollbarX + 6; + if (showScrollbar) { int n = (getViewportHeight() * getViewportHeight()) / getMaxPosition(); n = MathHelper.clamp(n, 32, getViewportHeight() - 8); - int o = (int)scrollAmount * (getViewportHeight() - n) / m + HEADER_SIZE; + int o = (int)scrollAmount * (getViewportHeight() - n) / maxScroll + HEADER_SIZE; if (o < HEADER_SIZE) o = HEADER_SIZE; - context.fill(i, HEADER_SIZE, j, height - FOOTER_SIZE, 0xFF000000); - context.fill(i, o, j, o + n, 0xFF808080); - context.fill(i, o, j - 1, o + n - 1, 0xFFC0C0C0); + context.fill(scrollbarX, HEADER_SIZE, scrollbarXEnd, height - FOOTER_SIZE, 0xFF000000); + context.fill(scrollbarX, o, scrollbarXEnd, o + n, 0xFF808080); + context.fill(scrollbarX, o, scrollbarXEnd - 1, o + n - 1, 0xFFC0C0C0); } - - super.render(context, mouseX, mouseY, delta); } private void drawCursor(DrawContext context, Position position) { @@ -331,16 +332,13 @@ public class EditorScreen extends ScreenWithSaveHook { } private void drawSelection(DrawContext context, Rect2i[] selectionRectangles) { - RenderSystem.enableColorLogicOp(); - RenderSystem.logicOp(GlStateManager.LogicOp.OR_REVERSE); for (Rect2i rect2i : selectionRectangles) { int i = rect2i.getX(); int j = rect2i.getY(); int k = i + rect2i.getWidth(); int l = j + rect2i.getHeight(); - context.fill(i, j, k, l, 0xFF0000FF); + context.fill(RenderLayer.getGuiTextHighlight(), i, j, k, l, 0xFF0000FF); } - RenderSystem.disableColorLogicOp(); } private Position screenPositionToAbsolutePosition(Position position) { @@ -409,8 +407,8 @@ public class EditorScreen extends ScreenWithSaveHook { } @Override - public boolean mouseScrolled(double mouseX, double mouseY, double amount) { - setScrollAmount(scrollAmount - amount * textRenderer.fontHeight * 2); + public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { + setScrollAmount(scrollAmount - verticalAmount * textRenderer.fontHeight * 2); return true; } diff --git a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/Placeholder.java b/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/Placeholder.java index 27bb6e2..9a39524 100644 --- a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/Placeholder.java +++ b/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/Placeholder.java @@ -4,7 +4,6 @@ import net.minecraft.client.gui.*; import net.minecraft.client.gui.navigation.GuiNavigation; import net.minecraft.client.gui.navigation.GuiNavigationPath; import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; -import net.minecraft.client.util.math.MatrixStack; import org.jetbrains.annotations.Nullable; public final class Placeholder implements Element, Selectable, Drawable { @@ -63,8 +62,8 @@ public final class Placeholder implem } @Override - public boolean mouseScrolled(double mouseX, double mouseY, double amount) { - return child.mouseScrolled(mouseX, mouseY, amount); + public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { + return child.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount); } @Override diff --git a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/TinyConfigScreen.java b/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/TinyConfigScreen.java index beea5b9..e0f5837 100644 --- a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/TinyConfigScreen.java +++ b/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/TinyConfigScreen.java @@ -63,12 +63,6 @@ public class TinyConfigScreen extends ScreenWithSaveHook { && JfConfigSafe.TRANSLATION_SUPPLIER.apply(config.getTranslationPrefix() + "tooltip") == null; } - @Override - public void tick() { - super.tick(); - tabManager.tick(); - } - @Override protected void init() { super.init(); @@ -110,7 +104,7 @@ public class TinyConfigScreen extends ScreenWithSaveHook { .build()); } - this.addSelectableChild(this.placeholder); + this.addDrawableChild(this.placeholder); // Sizing is also done in TinyConfigTab. Keep these in sync! tabManager.setTabArea(new ScreenRect(0, 32, width, height - 68)); @@ -159,8 +153,7 @@ public class TinyConfigScreen extends ScreenWithSaveHook { @Override public void render(DrawContext context, int mouseX, int mouseY, float delta) { - this.renderBackground(context); - this.placeholder.render(context, mouseX, mouseY, delta); + super.render(context, mouseX, mouseY, delta); if (tabs.size() == 1) context.drawCenteredTextWithShadow(textRenderer, title, width / 2, 16 - textRenderer.fontHeight, 0xFFFFFF); @@ -184,7 +177,6 @@ public class TinyConfigScreen extends ScreenWithSaveHook { } } } - super.render(context, mouseX, mouseY, delta); } @Override diff --git a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/TinyConfigTab.java b/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/TinyConfigTab.java index cb4adae..759b708 100644 --- a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/TinyConfigTab.java +++ b/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/TinyConfigTab.java @@ -91,11 +91,6 @@ public class TinyConfigTab implements Tab { list.refreshGrid(tabArea); } - @Override - public void tick() { - Tab.super.tick(); - } - public EntryListWidget getList() { return list; } diff --git a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/EntryListWidget.java b/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/EntryListWidget.java index f470c32..cde8610 100644 --- a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/EntryListWidget.java +++ b/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/EntryListWidget.java @@ -27,7 +27,6 @@ public class EntryListWidget extends ElementListWidget entry : config.getPresets().entrySet()) { - this.list.addButton(ButtonWidget.builder(Text.translatable(entry.getKey()), + list.addButton(ButtonWidget.builder(Text.translatable(entry.getKey()), button -> { LibJf.LOGGER.info("Preset selected: " + entry.getKey()); entry.getValue().run(); @@ -43,7 +41,7 @@ public class PresetsScreen extends Screen { .dimensions(width / 2 - 100, 0, 200, 20) .build()); } - this.addSelectableChild(this.list); + this.addDrawableChild(list); } @Override @@ -53,11 +51,7 @@ public class PresetsScreen extends Screen { @Override public void render(DrawContext context, int mouseX, int mouseY, float delta) { - this.renderBackground(context); - this.list.render(context, mouseX, mouseY, delta); - - context.drawCenteredTextWithShadow(textRenderer, title, width / 2, 16 - textRenderer.fontHeight / 2, 0xFFFFFF); - super.render(context, mouseX, mouseY, delta); + context.drawCenteredTextWithShadow(textRenderer, title, width / 2, 16 - textRenderer.fontHeight / 2, 0xFFFFFF); } } diff --git a/libjf-config-ui-tiny-v1/src/testmod/java/io/gitlab/jfronny/libjf/config/test/tiny/mixin/OptionsScreenMixin.java b/libjf-config-ui-tiny-v1/src/testmod/java/io/gitlab/jfronny/libjf/config/test/tiny/mixin/OptionsScreenMixin.java new file mode 100644 index 0000000..d6c34f2 --- /dev/null +++ b/libjf-config-ui-tiny-v1/src/testmod/java/io/gitlab/jfronny/libjf/config/test/tiny/mixin/OptionsScreenMixin.java @@ -0,0 +1,38 @@ +package io.gitlab.jfronny.libjf.config.test.tiny.mixin; + +import io.gitlab.jfronny.libjf.config.api.v1.ConfigHolder; +import io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.option.OptionsScreen; +import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.gui.widget.GridWidget; +import net.minecraft.text.Text; +import org.spongepowered.asm.mixin.*; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +import java.util.function.Supplier; + +@Mixin(OptionsScreen.class) +public abstract class OptionsScreenMixin extends Screen { + @Shadow @Final private Screen parent; + + @Shadow protected abstract ButtonWidget createButton(Text message, Supplier screenSupplier); + + protected OptionsScreenMixin(Text title) { + super(title); + } + + @Inject(method = "init()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/widget/GridWidget;refreshPositions()V"), locals = LocalCapture.CAPTURE_FAILHARD) + void injectButton(CallbackInfo ci, GridWidget gridWidget, GridWidget.Adder adder) { + ConfigHolder.getInstance().getRegistered().forEach((key, config) -> { + adder.add( + createButton(Text.translatable(key + ".jfconfig.title"), () -> ConfigScreenFactory.getInstance() + .create(config, this) + .get()) + ); + }); + } +} diff --git a/libjf-config-ui-tiny-v1/src/testmod/resources/fabric.mod.json b/libjf-config-ui-tiny-v1/src/testmod/resources/fabric.mod.json index e3315aa..53546bd 100644 --- a/libjf-config-ui-tiny-v1/src/testmod/resources/fabric.mod.json +++ b/libjf-config-ui-tiny-v1/src/testmod/resources/fabric.mod.json @@ -4,6 +4,7 @@ "name": "LibJF Config UI: Tiny", "version": "1.0", "environment": "*", + "mixins": ["libjf-config-ui-tiny-v1-testmod.mixins.json"], "entrypoints": { "libjf:config": [ "io.gitlab.jfronny.libjf.config.test.tiny.TestConfig" diff --git a/libjf-config-ui-tiny-v1/src/testmod/resources/libjf-config-ui-tiny-v1-testmod.mixins.json b/libjf-config-ui-tiny-v1/src/testmod/resources/libjf-config-ui-tiny-v1-testmod.mixins.json new file mode 100644 index 0000000..6253d36 --- /dev/null +++ b/libjf-config-ui-tiny-v1/src/testmod/resources/libjf-config-ui-tiny-v1-testmod.mixins.json @@ -0,0 +1,14 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "io.gitlab.jfronny.libjf.config.test.tiny.mixin", + "compatibilityLevel": "JAVA_16", + "mixins": [ + ], + "client": [ + "OptionsScreenMixin" + ], + "injectors": { + "defaultRequire": 1 + } +} From 09466ce8971299c6efb38a0aaec2a27b305ccbe0 Mon Sep 17 00:00:00 2001 From: JFronny Date: Wed, 30 Aug 2023 14:14:20 +0200 Subject: [PATCH 4/7] chore: clean up config modules --- docs/README.md | 4 +- docs/SUMMARY.md | 9 +- docs/config/README.md | 4 +- ...ommands-v1.md => libjf-config-commands.md} | 2 +- ...fig-core-v1.md => libjf-config-core-v2.md} | 2 +- docs/config/libjf-config-reflect-v1.md | 8 -- docs/config/libjf-config-ui-tiny-v1.md | 4 - docs/config/libjf-config-ui-tiny.md | 4 + docs/libjf-web-v0.md | 2 +- .../build.gradle.kts | 4 +- .../config/impl/commands/JfConfigCommand.java | 38 +++++---- .../src/main/resources/fabric.mod.json | 4 +- .../build.gradle.kts | 2 +- .../libjf/config/plugin/ConfigProcessor.java | 6 +- .../libjf/config/plugin/test/PluginTest.java | 2 +- .../libjf-config-core-v1/lang/en_us.json | 12 --- .../build.gradle.kts | 2 +- .../config/api/v2/ui/ConfigScreenFactory.java | 2 +- .../impl/ui/ConfigScreenFactoryDiscovery.java | 0 .../libjf/config/impl/ui/ModMenuAdapter.java | 4 +- .../config/impl/ui/PlaceholderScreen.java | 4 +- .../impl/ui/PlaceholderScreenFactory.java | 2 +- .../assets/libjf-config-core/lang/en_us.json | 12 +++ .../libjf/config/api/v2}/Category.java | 2 +- .../libjf/config/api/v2}/ConfigCategory.java | 2 +- .../libjf/config/api/v2}/ConfigHolder.java | 2 +- .../libjf/config/api/v2}/ConfigInstance.java | 2 +- .../jfronny/libjf/config/api/v2}/Entry.java | 2 +- .../libjf/config/api/v2}/EntryInfo.java | 6 +- .../libjf/config/api/v2}/JfConfig.java | 2 +- .../libjf/config/api/v2}/JfCustomConfig.java | 4 +- .../jfronny/libjf/config/api/v2}/Preset.java | 2 +- .../libjf/config/api/v2}/Verifier.java | 2 +- .../config/api/v2}/dsl/CategoryBuilder.java | 9 +- .../config/api/v2}/dsl/ConfigBuilder.java | 4 +- .../jfronny/libjf/config/api/v2}/dsl/DSL.java | 6 +- .../libjf/config/api/v2}/dsl/Migration.java | 2 +- .../libjf/config/api/v2}/type/Type.java | 2 +- .../libjf/config/impl/AuxiliaryMetadata.java | 6 +- .../jfronny/libjf/config/impl/ConfigCore.java | 6 +- .../libjf/config/impl/ConfigHolderImpl.java | 4 +- .../config/impl/dsl/CategoryBuilderImpl.java | 8 +- .../config/impl/dsl/ConfigBuilderImpl.java | 4 +- .../libjf/config/impl/dsl/DSLImpl.java | 8 +- .../config/impl/dsl/DefaultConfigIO.java | 2 +- .../config/impl/dsl/DslConfigCategory.java | 4 +- .../config/impl/dsl/DslConfigInstance.java | 4 +- .../libjf/config/impl/dsl/DslEntryInfo.java | 6 +- .../config/impl/entrypoint/JfConfigSafe.java | 4 +- .../impl/watch/JfConfigWatchService.java | 0 .../impl/watch/JfConfigWatchServiceImpl.java | 2 +- .../watch/ToggleableConfigWatchService.java | 0 .../src/main/resources/fabric.mod.json | 2 +- libjf-config-reflect-v1/build.gradle.kts | 15 ---- .../v1/reflect/ReflectiveConfigBuilder.java | 10 --- .../reflect/ReflectiveConfigBuilderImpl.java | 84 ------------------- .../entrypoint/JfConfigReflectSafe.java | 37 -------- .../reflect/entrypoint/JfConfigUnsafe.java | 16 ---- .../src/main/resources/fabric.mod.json | 36 -------- .../libjf/config/test/reflect/TestConfig.java | 57 ------------- .../test/reflect/TestConfigTweaker.java | 16 ---- .../libjf-config-v0-testmod/lang/en_us.json | 15 ---- .../src/testmod/resources/fabric.mod.json | 17 ---- .../libjf-config-ui-tiny-v1/lang/en_us.json | 4 - .../lang/en_us.json | 21 ----- .../build.gradle.kts | 4 +- .../config/impl/ui/tiny/EditorScreen.java | 0 .../config/impl/ui/tiny/Placeholder.java | 0 .../impl/ui/tiny/ScreenWithSaveHook.java | 0 .../config/impl/ui/tiny/TinyConfigScreen.java | 7 +- .../impl/ui/tiny/TinyConfigScreenFactory.java | 12 +-- .../config/impl/ui/tiny/TinyConfigTab.java | 11 +-- .../impl/ui/tiny/TinyConfigTabWrapper.java | 0 .../impl/ui/tiny/entry/CustomSlider.java | 0 .../ui/tiny/entry/EntryInfoWidgetBuilder.java | 16 ++-- .../impl/ui/tiny/entry/EntryListWidget.java | 0 .../config/impl/ui/tiny/entry/Reflowable.java | 0 .../impl/ui/tiny/entry/WidgetFactory.java | 0 .../impl/ui/tiny/entry/WidgetState.java | 2 +- .../ui/tiny/presets/PresetListWidget.java | 0 .../impl/ui/tiny/presets/PresetsScreen.java | 5 +- .../libjf-config-ui-tiny/lang/en_us.json | 4 + .../src/main/resources/fabric.mod.json | 4 +- .../libjf/config/test/tiny/TestConfig.java | 4 +- .../test/tiny/mixin/OptionsScreenMixin.java | 2 +- .../lang/en_us.json | 21 +++++ .../src/testmod/resources/fabric.mod.json | 4 +- .../libjf-config-ui-tiny-testmod.mixins.json | 0 libjf-translate-v1/build.gradle.kts | 2 +- .../libjf/translate/impl/TranslateConfig.java | 4 +- libjf-web-v0/build.gradle.kts | 2 +- .../jfronny/libjf/web/impl/JfWebConfig.java | 2 +- .../src/main/resources/fabric.mod.json | 2 +- settings.gradle.kts | 7 +- 94 files changed, 190 insertions(+), 495 deletions(-) rename docs/config/{libjf-config-commands-v1.md => libjf-config-commands.md} (90%) rename docs/config/{libjf-config-core-v1.md => libjf-config-core-v2.md} (99%) delete mode 100644 docs/config/libjf-config-reflect-v1.md delete mode 100644 docs/config/libjf-config-ui-tiny-v1.md create mode 100644 docs/config/libjf-config-ui-tiny.md rename {libjf-config-commands-v1 => libjf-config-commands}/build.gradle.kts (74%) rename {libjf-config-commands-v1 => libjf-config-commands}/src/main/java/io/gitlab/jfronny/libjf/config/impl/commands/JfConfigCommand.java (80%) rename {libjf-config-commands-v1 => libjf-config-commands}/src/main/resources/fabric.mod.json (90%) delete mode 100644 libjf-config-core-v1/src/client/resources/assets/libjf-config-core-v1/lang/en_us.json rename {libjf-config-core-v1 => libjf-config-core-v2}/build.gradle.kts (84%) rename {libjf-config-core-v1 => libjf-config-core-v2}/src/client/java/io/gitlab/jfronny/libjf/config/api/v2/ui/ConfigScreenFactory.java (90%) rename {libjf-config-core-v1 => libjf-config-core-v2}/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/ConfigScreenFactoryDiscovery.java (100%) rename {libjf-config-core-v1 => libjf-config-core-v2}/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/ModMenuAdapter.java (90%) rename {libjf-config-core-v1 => libjf-config-core-v2}/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/PlaceholderScreen.java (87%) rename {libjf-config-core-v1 => libjf-config-core-v2}/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/PlaceholderScreenFactory.java (93%) create mode 100644 libjf-config-core-v2/src/client/resources/assets/libjf-config-core/lang/en_us.json rename {libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1 => libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2}/Category.java (92%) rename {libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1 => libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2}/ConfigCategory.java (95%) rename {libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1 => libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2}/ConfigHolder.java (97%) rename {libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1 => libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2}/ConfigInstance.java (90%) rename {libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1 => libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2}/Entry.java (87%) rename {libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1 => libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2}/EntryInfo.java (91%) rename {libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1 => libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2}/JfConfig.java (91%) rename {libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1 => libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2}/JfCustomConfig.java (60%) rename {libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1 => libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2}/Preset.java (83%) rename {libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1 => libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2}/Verifier.java (86%) rename {libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1 => libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2}/dsl/CategoryBuilder.java (89%) rename {libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1 => libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2}/dsl/ConfigBuilder.java (87%) rename {libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1 => libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2}/dsl/DSL.java (86%) rename {libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1 => libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2}/dsl/Migration.java (78%) rename {libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1 => libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2}/type/Type.java (99%) rename {libjf-config-core-v1 => libjf-config-core-v2}/src/main/java/io/gitlab/jfronny/libjf/config/impl/AuxiliaryMetadata.java (93%) rename {libjf-config-core-v1 => libjf-config-core-v2}/src/main/java/io/gitlab/jfronny/libjf/config/impl/ConfigCore.java (71%) rename {libjf-config-core-v1 => libjf-config-core-v2}/src/main/java/io/gitlab/jfronny/libjf/config/impl/ConfigHolderImpl.java (95%) rename {libjf-config-core-v1 => libjf-config-core-v2}/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/CategoryBuilderImpl.java (97%) rename {libjf-config-core-v1 => libjf-config-core-v2}/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/ConfigBuilderImpl.java (93%) rename {libjf-config-core-v1 => libjf-config-core-v2}/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/DSLImpl.java (86%) rename {libjf-config-core-v1 => libjf-config-core-v2}/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/DefaultConfigIO.java (99%) rename {libjf-config-core-v1 => libjf-config-core-v2}/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/DslConfigCategory.java (96%) rename {libjf-config-core-v1 => libjf-config-core-v2}/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/DslConfigInstance.java (93%) rename {libjf-config-core-v1 => libjf-config-core-v2}/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/DslEntryInfo.java (97%) rename {libjf-config-core-v1 => libjf-config-core-v2}/src/main/java/io/gitlab/jfronny/libjf/config/impl/entrypoint/JfConfigSafe.java (91%) rename {libjf-config-core-v1 => libjf-config-core-v2}/src/main/java/io/gitlab/jfronny/libjf/config/impl/watch/JfConfigWatchService.java (100%) rename {libjf-config-core-v1 => libjf-config-core-v2}/src/main/java/io/gitlab/jfronny/libjf/config/impl/watch/JfConfigWatchServiceImpl.java (98%) rename {libjf-config-core-v1 => libjf-config-core-v2}/src/main/java/io/gitlab/jfronny/libjf/config/impl/watch/ToggleableConfigWatchService.java (100%) rename {libjf-config-core-v1 => libjf-config-core-v2}/src/main/resources/fabric.mod.json (96%) delete mode 100644 libjf-config-reflect-v1/build.gradle.kts delete mode 100644 libjf-config-reflect-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/reflect/ReflectiveConfigBuilder.java delete mode 100644 libjf-config-reflect-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/reflect/ReflectiveConfigBuilderImpl.java delete mode 100644 libjf-config-reflect-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/reflect/entrypoint/JfConfigReflectSafe.java delete mode 100644 libjf-config-reflect-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/reflect/entrypoint/JfConfigUnsafe.java delete mode 100644 libjf-config-reflect-v1/src/main/resources/fabric.mod.json delete mode 100644 libjf-config-reflect-v1/src/testmod/java/io/gitlab/jfronny/libjf/config/test/reflect/TestConfig.java delete mode 100644 libjf-config-reflect-v1/src/testmod/java/io/gitlab/jfronny/libjf/config/test/reflect/TestConfigTweaker.java delete mode 100644 libjf-config-reflect-v1/src/testmod/resources/assets/libjf-config-v0-testmod/lang/en_us.json delete mode 100644 libjf-config-reflect-v1/src/testmod/resources/fabric.mod.json delete mode 100644 libjf-config-ui-tiny-v1/src/client/resources/assets/libjf-config-ui-tiny-v1/lang/en_us.json delete mode 100644 libjf-config-ui-tiny-v1/src/testmod/resources/assets/libjf-config-ui-tiny-v1-testmod/lang/en_us.json rename {libjf-config-ui-tiny-v1 => libjf-config-ui-tiny}/build.gradle.kts (73%) rename {libjf-config-ui-tiny-v1 => libjf-config-ui-tiny}/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/EditorScreen.java (100%) rename {libjf-config-ui-tiny-v1 => libjf-config-ui-tiny}/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/Placeholder.java (100%) rename {libjf-config-ui-tiny-v1 => libjf-config-ui-tiny}/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/ScreenWithSaveHook.java (100%) rename {libjf-config-ui-tiny-v1 => libjf-config-ui-tiny}/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/TinyConfigScreen.java (97%) rename {libjf-config-ui-tiny-v1 => libjf-config-ui-tiny}/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/TinyConfigScreenFactory.java (90%) rename {libjf-config-ui-tiny-v1 => libjf-config-ui-tiny}/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/TinyConfigTab.java (88%) rename {libjf-config-ui-tiny-v1 => libjf-config-ui-tiny}/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/TinyConfigTabWrapper.java (100%) rename {libjf-config-ui-tiny-v1 => libjf-config-ui-tiny}/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/CustomSlider.java (100%) rename {libjf-config-ui-tiny-v1 => libjf-config-ui-tiny}/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/EntryInfoWidgetBuilder.java (96%) rename {libjf-config-ui-tiny-v1 => libjf-config-ui-tiny}/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/EntryListWidget.java (100%) rename {libjf-config-ui-tiny-v1 => libjf-config-ui-tiny}/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/Reflowable.java (100%) rename {libjf-config-ui-tiny-v1 => libjf-config-ui-tiny}/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/WidgetFactory.java (100%) rename {libjf-config-ui-tiny-v1 => libjf-config-ui-tiny}/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/WidgetState.java (96%) rename {libjf-config-ui-tiny-v1 => libjf-config-ui-tiny}/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/presets/PresetListWidget.java (100%) rename {libjf-config-ui-tiny-v1 => libjf-config-ui-tiny}/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/presets/PresetsScreen.java (91%) create mode 100644 libjf-config-ui-tiny/src/client/resources/assets/libjf-config-ui-tiny/lang/en_us.json rename {libjf-config-ui-tiny-v1 => libjf-config-ui-tiny}/src/main/resources/fabric.mod.json (90%) rename {libjf-config-ui-tiny-v1 => libjf-config-ui-tiny}/src/testmod/java/io/gitlab/jfronny/libjf/config/test/tiny/TestConfig.java (91%) rename {libjf-config-ui-tiny-v1 => libjf-config-ui-tiny}/src/testmod/java/io/gitlab/jfronny/libjf/config/test/tiny/mixin/OptionsScreenMixin.java (96%) create mode 100644 libjf-config-ui-tiny/src/testmod/resources/assets/libjf-config-ui-tiny-testmod/lang/en_us.json rename {libjf-config-ui-tiny-v1 => libjf-config-ui-tiny}/src/testmod/resources/fabric.mod.json (73%) rename libjf-config-ui-tiny-v1/src/testmod/resources/libjf-config-ui-tiny-v1-testmod.mixins.json => libjf-config-ui-tiny/src/testmod/resources/libjf-config-ui-tiny-testmod.mixins.json (100%) diff --git a/docs/README.md b/docs/README.md index 806746c..9550e8c 100644 --- a/docs/README.md +++ b/docs/README.md @@ -20,8 +20,8 @@ repositories { and include LibJF modules like this: ```groovy dependencies { - include modImplementation("io.gitlab.jfronny.libjf:libjf-config-core-v1:${project.libjf_version}") - include modRuntimeOnly("io.gitlab.jfronny.libjf:libjf-config-ui-tiny-v1:${project.libjf_version}") + include modImplementation("io.gitlab.jfronny.libjf:libjf-config-core-v2:${project.libjf_version}") + include modRuntimeOnly("io.gitlab.jfronny.libjf:libjf-config-ui-tiny:${project.libjf_version}") include("io.gitlab.jfronny.libjf:libjf-base:${project.libjf_version}") modLocalRuntime("io.gitlab.jfronny.libjf:libjf-config-reflect-v1:${project.libjf_version}") diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index 9ed830a..b24fe64 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -6,11 +6,10 @@ - [libjf-base](./libjf-base.md) - [Config](./config/README.md) - - [libjf-config-core-v1](./config/libjf-config-core-v1.md) - - [libjf-config-reflect-v1](./config/libjf-config-reflect-v1.md) - - [libjf-config-compiler-plugin](./config/libjf-config-compiler-plugin.md) - - [libjf-config-commands-v1](./config/libjf-config-commands-v1.md) - - [libjf-config-ui-tiny-v1](./config/libjf-config-ui-tiny-v1.md) + - [libjf-config-core-v2](./config/libjf-config-core-v2.md) + - [libjf-config-compiler-plugin-v2](./config/libjf-config-compiler-plugin-v2.md) + - [libjf-config-commands](./config/libjf-config-commands.md) + - [libjf-config-ui-tiny](./config/libjf-config-ui-tiny.md) - [libjf-devutil](./libjf-devutil.md) - [libjf-data-v0](./libjf-data-v0.md) - [libjf-data-manipulation-v0](./libjf-data-manipulation-v0.md) diff --git a/docs/config/README.md b/docs/config/README.md index d438c94..3654f66 100644 --- a/docs/config/README.md +++ b/docs/config/README.md @@ -11,8 +11,8 @@ repositories { } dependencies { - include modImplementation("io.gitlab.jfronny.libjf:libjf-config-core-v1:${project.libjf_version}") - include modRuntimeOnly("io.gitlab.jfronny.libjf:libjf-config-ui-tiny-v1:${project.libjf_version}") + include modImplementation("io.gitlab.jfronny.libjf:libjf-config-core-v2:${project.libjf_version}") + include modRuntimeOnly("io.gitlab.jfronny.libjf:libjf-config-ui-tiny:${project.libjf_version}") include("io.gitlab.jfronny.libjf:libjf-base:${project.libjf_version}") annotationProcessor("io.gitlab.jfronny.libjf:libjf-config-compiler-plugin-v2:${project.libjf_version}") diff --git a/docs/config/libjf-config-commands-v1.md b/docs/config/libjf-config-commands.md similarity index 90% rename from docs/config/libjf-config-commands-v1.md rename to docs/config/libjf-config-commands.md index 4f0983f..7b5fc03 100644 --- a/docs/config/libjf-config-commands-v1.md +++ b/docs/config/libjf-config-commands.md @@ -1,4 +1,4 @@ -# libjf-config-commands-v1 +# libjf-config-commands This serverside module provides commands for modifying configs using this library. If you are developing a serverside mod, you may wish to include it to enable easier configuration. The commands are available under `/libjf config`, using auto-complete is recommended. \ No newline at end of file diff --git a/docs/config/libjf-config-core-v1.md b/docs/config/libjf-config-core-v2.md similarity index 99% rename from docs/config/libjf-config-core-v1.md rename to docs/config/libjf-config-core-v2.md index 0dfdd91..6eabb3b 100644 --- a/docs/config/libjf-config-core-v1.md +++ b/docs/config/libjf-config-core-v2.md @@ -1,4 +1,4 @@ -# libjf-config-core-v1 +# libjf-config-core-v2 The core module contains the abstractions and annotations used by other modules to interact with configs. It also contains the code for registering configs to mods, serialization and automatic reloads on change. diff --git a/docs/config/libjf-config-reflect-v1.md b/docs/config/libjf-config-reflect-v1.md deleted file mode 100644 index ed0d08b..0000000 --- a/docs/config/libjf-config-reflect-v1.md +++ /dev/null @@ -1,8 +0,0 @@ -# libjf-config-reflect-v1 -This module uses reflection to register configs from files using the annotations as presented [here](./libjf-config-core-v1.md) -In order to register a config, simply add the class annotated as `@JfConfig` to the `libjf:config` entrypoint. -Please be aware that this module may load your config class before the game classes are available. -Using them there WILL result in problems! - -Instead of using this implementation, you should use the [compiler plugin](./libjf-config-compiler-plugin-v2.md), -which removes the runtime overhead of this implementation. \ No newline at end of file diff --git a/docs/config/libjf-config-ui-tiny-v1.md b/docs/config/libjf-config-ui-tiny-v1.md deleted file mode 100644 index 6cd3f47..0000000 --- a/docs/config/libjf-config-ui-tiny-v1.md +++ /dev/null @@ -1,4 +0,0 @@ -# libjf-config-ui-tiny-v1 -This module provides an automatically registered, TinyConfig-based UI for all mods using libjf-config. -Embedding this is recommended when developing client-side mods. -Manually generating config screens is also possible through `ConfigScreen.create(config, parent)` \ No newline at end of file diff --git a/docs/config/libjf-config-ui-tiny.md b/docs/config/libjf-config-ui-tiny.md new file mode 100644 index 0000000..6aab4c6 --- /dev/null +++ b/docs/config/libjf-config-ui-tiny.md @@ -0,0 +1,4 @@ +# libjf-config-ui-tiny +This module provides an automatically registered, TinyConfig-based UI for all mods using libjf-config. +Embedding this is recommended when developing client-side mods. +libjf-config-ui-tiny implements the config-core-provided `ConfigScreenFactory`, so you can `ConfigScreenFactory.getInstance().create(config, parent).get()` to obtain a screen for your config. \ No newline at end of file diff --git a/docs/libjf-web-v0.md b/docs/libjf-web-v0.md index 6928e3b..b71a110 100644 --- a/docs/libjf-web-v0.md +++ b/docs/libjf-web-v0.md @@ -1,7 +1,7 @@ # libjf-web-v0 libjf-web-v0 provides an HTTP web server you can use in your serverside (and technically also clientside) mods to serve web content through a unified port. -libjf-web-v0 depends on libjf-config-v1 to provide its config, libjf-base, fabric-lifecycle-events-v1 and fabric-command-api-v1 +libjf-web-v0 depends on libjf-config-core-v2 to provide its config, libjf-base, fabric-lifecycle-events-v1 and fabric-command-api-v1 ### Getting started Implement WebInit and register it as a libjf:web entrypoint. To enable the server, also add the following to your fabric.mod.json: diff --git a/libjf-config-commands-v1/build.gradle.kts b/libjf-config-commands/build.gradle.kts similarity index 74% rename from libjf-config-commands-v1/build.gradle.kts rename to libjf-config-commands/build.gradle.kts index 923c36f..695d0e8 100644 --- a/libjf-config-commands-v1/build.gradle.kts +++ b/libjf-config-commands/build.gradle.kts @@ -5,12 +5,12 @@ plugins { } base { - archivesName.set("libjf-config-commands-v1") + archivesName.set("libjf-config-commands") } dependencies { val fabricVersion: String by rootProject.extra api(devProject(":libjf-base")) - api(devProject(":libjf-config-core-v1")) + api(devProject(":libjf-config-core-v2")) include(modImplementation(fabricApi.module("fabric-command-api-v2", fabricVersion))!!) } diff --git a/libjf-config-commands-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/commands/JfConfigCommand.java b/libjf-config-commands/src/main/java/io/gitlab/jfronny/libjf/config/impl/commands/JfConfigCommand.java similarity index 80% rename from libjf-config-commands-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/commands/JfConfigCommand.java rename to libjf-config-commands/src/main/java/io/gitlab/jfronny/libjf/config/impl/commands/JfConfigCommand.java index 597d027..3edd15a 100644 --- a/libjf-config-commands-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/commands/JfConfigCommand.java +++ b/libjf-config-commands/src/main/java/io/gitlab/jfronny/libjf/config/impl/commands/JfConfigCommand.java @@ -8,11 +8,12 @@ import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; import io.gitlab.jfronny.commons.throwable.ThrowingRunnable; import io.gitlab.jfronny.commons.throwable.ThrowingSupplier; import io.gitlab.jfronny.libjf.LibJf; -import io.gitlab.jfronny.libjf.config.api.v1.*; -import io.gitlab.jfronny.libjf.config.api.v1.type.Type; +import io.gitlab.jfronny.libjf.config.api.v2.*; +import io.gitlab.jfronny.libjf.config.api.v2.type.Type; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.MutableText; import net.minecraft.text.Text; import java.util.function.Consumer; @@ -22,6 +23,12 @@ import static net.minecraft.server.command.CommandManager.argument; import static net.minecraft.server.command.CommandManager.literal; public class JfConfigCommand implements ModInitializer { + private static final String MOD_ID = "libjf-config-commands"; + + private MutableText text(String text) { + return Text.literal("[" + MOD_ID + "] " + text); + } + @Override public void onInitialize() { CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> { @@ -29,25 +36,24 @@ public class JfConfigCommand implements ModInitializer { LiteralArgumentBuilder c_config = literal("config") .requires((serverCommandSource) -> serverCommandSource.hasPermissionLevel(4)) .executes(context -> { - context.getSource().sendFeedback(() -> Text.literal("[libjf-config-v1] Loaded configs for:"), false); - ConfigHolder.getInstance().getRegistered().forEach((s, config) -> { - context.getSource().sendFeedback(() -> Text.literal("- " + s), false); - }); + MutableText text = text("Loaded configs for:"); + ConfigHolder.getInstance().getRegistered().forEach((s, config) -> text.append("\n- " + s)); + context.getSource().sendFeedback(() -> text, false); return Command.SINGLE_SUCCESS; }); LiteralArgumentBuilder c_reload = literal("reload").executes(context -> { ConfigHolder.getInstance().getRegistered().forEach((mod, config) -> config.load()); - context.getSource().sendFeedback(() -> Text.literal("[libjf-config-v1] Reloaded configs"), true); + context.getSource().sendFeedback(() -> text("Reloaded configs"), true); return Command.SINGLE_SUCCESS; }); LiteralArgumentBuilder c_reset = literal("reset").executes(context -> { - context.getSource().sendError(Text.literal("[libjf-config-v1] Please specify a config to reset")); + context.getSource().sendError(text("Please specify a config to reset")); return Command.SINGLE_SUCCESS; }); ConfigHolder.getInstance().getRegistered().forEach((id, config) -> { c_reload.then(literal(id).executes(context -> { config.load(); - context.getSource().sendFeedback(() -> Text.literal("[libjf-config-v1] Reloaded config for " + id), true); + context.getSource().sendFeedback(() -> text("Reloaded config for " + id), true); return Command.SINGLE_SUCCESS; })); registerEntries(config, id, c_config, c_reset, cns -> { @@ -63,7 +69,7 @@ public class JfConfigCommand implements ModInitializer { private void registerEntries(ConfigCategory config, String subpath, LiteralArgumentBuilder c_config, LiteralArgumentBuilder c_reset, Function>, LiteralArgumentBuilder> pathGen) { c_config.then(pathGen.apply(cns -> { cns.executes(context -> { - context.getSource().sendFeedback(() -> Text.literal("[libjf-config-v1] " + subpath + " is a category"), false); + context.getSource().sendFeedback(() -> text(subpath + " is a category"), false); return Command.SINGLE_SUCCESS; }); for (EntryInfo entry : config.getEntries()) { @@ -73,13 +79,13 @@ public class JfConfigCommand implements ModInitializer { c_reset.then(pathGen.apply(cns -> { cns.executes(context -> { config.reset(); - context.getSource().sendFeedback(() -> Text.literal("[libjf-config-v1] Reset config for " + subpath), true); + context.getSource().sendFeedback(() -> text("Reset config for " + subpath), true); return Command.SINGLE_SUCCESS; }); config.getPresets().forEach((id2, preset) -> { cns.then(literal(id2).executes(context -> { preset.run(); - context.getSource().sendFeedback(() -> Text.literal("[libjf-config-v1] Loaded preset " + id2 + " for " + subpath), true); + context.getSource().sendFeedback(() -> text("Loaded preset " + id2 + " for " + subpath), true); return Command.SINGLE_SUCCESS; })); }); @@ -103,8 +109,8 @@ public class JfConfigCommand implements ModInitializer { private void registerEntry(ConfigCategory config, String subpath, LiteralArgumentBuilder cns, EntryInfo entry) { LiteralArgumentBuilder c_entry = literal(entry.getName()).executes(context -> { - String msg = "[libjf-config-v1] The value of " + subpath + "." + entry.getName() + " is " + tryRun(entry::getValue); - context.getSource().sendFeedback(() -> Text.literal(msg), false); + String msg = "The value of " + subpath + "." + entry.getName() + " is " + tryRun(entry::getValue); + context.getSource().sendFeedback(() -> text(msg), false); return Command.SINGLE_SUCCESS; }); ArgumentType type = getType(entry); @@ -115,7 +121,7 @@ public class JfConfigCommand implements ModInitializer { entry.setValue(value); config.getRoot().write(); }); - context.getSource().sendFeedback(() -> Text.literal("[libjf-config-v1] Set " + subpath + "." + entry.getName() + " to " + value), true); + context.getSource().sendFeedback(() -> text("Set " + subpath + "." + entry.getName() + " to " + value), true); return Command.SINGLE_SUCCESS; })); } @@ -126,7 +132,7 @@ public class JfConfigCommand implements ModInitializer { entry.setValue(enumConstant); config.getRoot().write(); }); - context.getSource().sendFeedback(() -> Text.literal("[libjf-config-v1] Set " + subpath + "." + entry.getName() + " to " + enumConstant), true); + context.getSource().sendFeedback(() -> text("Set " + subpath + "." + entry.getName() + " to " + enumConstant), true); return Command.SINGLE_SUCCESS; })); } diff --git a/libjf-config-commands-v1/src/main/resources/fabric.mod.json b/libjf-config-commands/src/main/resources/fabric.mod.json similarity index 90% rename from libjf-config-commands-v1/src/main/resources/fabric.mod.json rename to libjf-config-commands/src/main/resources/fabric.mod.json index eba5d9b..e5a8dff 100644 --- a/libjf-config-commands-v1/src/main/resources/fabric.mod.json +++ b/libjf-config-commands/src/main/resources/fabric.mod.json @@ -1,6 +1,6 @@ { "schemaVersion": 1, - "id": "libjf-config-commands-v1", + "id": "libjf-config-commands", "name": "LibJF Config Commands", "version": "${version}", "authors": ["JFronny"], @@ -20,7 +20,7 @@ "minecraft": "*", "fabric-command-api-v2": "*", "libjf-base": ">=${version}", - "libjf-config-core-v1": ">=${version}" + "libjf-config-core-v2": ">=${version}" }, "custom": { "modmenu": { diff --git a/libjf-config-compiler-plugin-v2/build.gradle.kts b/libjf-config-compiler-plugin-v2/build.gradle.kts index 2e791ee..338e9a8 100644 --- a/libjf-config-compiler-plugin-v2/build.gradle.kts +++ b/libjf-config-compiler-plugin-v2/build.gradle.kts @@ -22,7 +22,7 @@ dependencies { val annotationsVersion: String by rootProject.extra val javapoetVersion: String by rootProject.extra implementation("io.gitlab.jfronny.gson:gson-compile-processor-core:$gsonCompileVersion") - implementation(devProject(":libjf-config-core-v1")) + implementation(devProject(":libjf-config-core-v2")) implementation("org.jetbrains:annotations:$annotationsVersion") implementation("io.gitlab.jfronny:commons:$commonsVersion") implementation("io.gitlab.jfronny:commons-gson:$commonsVersion") diff --git a/libjf-config-compiler-plugin-v2/src/main/java/io/gitlab/jfronny/libjf/config/plugin/ConfigProcessor.java b/libjf-config-compiler-plugin-v2/src/main/java/io/gitlab/jfronny/libjf/config/plugin/ConfigProcessor.java index 5c96300..e2568b1 100644 --- a/libjf-config-compiler-plugin-v2/src/main/java/io/gitlab/jfronny/libjf/config/plugin/ConfigProcessor.java +++ b/libjf-config-compiler-plugin-v2/src/main/java/io/gitlab/jfronny/libjf/config/plugin/ConfigProcessor.java @@ -4,9 +4,9 @@ import com.squareup.javapoet.*; import io.gitlab.jfronny.commons.StringFormatter; import io.gitlab.jfronny.gson.compile.processor.core.*; import io.gitlab.jfronny.gson.reflect.TypeToken; -import io.gitlab.jfronny.libjf.config.api.v1.*; -import io.gitlab.jfronny.libjf.config.api.v1.dsl.DSL; -import io.gitlab.jfronny.libjf.config.api.v1.type.Type; +import io.gitlab.jfronny.libjf.config.api.v2.*; +import io.gitlab.jfronny.libjf.config.api.v2.dsl.DSL; +import io.gitlab.jfronny.libjf.config.api.v2.type.Type; import javax.annotation.processing.*; import javax.lang.model.SourceVersion; diff --git a/libjf-config-compiler-plugin-v2/src/test/java/io/gitlab/jfronny/libjf/config/plugin/test/PluginTest.java b/libjf-config-compiler-plugin-v2/src/test/java/io/gitlab/jfronny/libjf/config/plugin/test/PluginTest.java index abfa073..2307750 100644 --- a/libjf-config-compiler-plugin-v2/src/test/java/io/gitlab/jfronny/libjf/config/plugin/test/PluginTest.java +++ b/libjf-config-compiler-plugin-v2/src/test/java/io/gitlab/jfronny/libjf/config/plugin/test/PluginTest.java @@ -1,6 +1,6 @@ package io.gitlab.jfronny.libjf.config.plugin.test; -import io.gitlab.jfronny.libjf.config.api.v1.*; +import io.gitlab.jfronny.libjf.config.api.v2.*; import java.util.Map; diff --git a/libjf-config-core-v1/src/client/resources/assets/libjf-config-core-v1/lang/en_us.json b/libjf-config-core-v1/src/client/resources/assets/libjf-config-core-v1/lang/en_us.json deleted file mode 100644 index a5678ab..0000000 --- a/libjf-config-core-v1/src/client/resources/assets/libjf-config-core-v1/lang/en_us.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "libjf-config-core-v1.jfconfig.title": "LibJF Config", - "libjf-config-core-v1.jfconfig.watchForChanges": "Watch for changes", - "libjf-config-core-v1.jfconfig.watchForChanges.tooltip": "Automatically reload configs when they are changed", - "libjf-config-v1.presets": "Presets", - "libjf-config-v1.default": "Default", - "libjf-config-v1.see-also": "See also: %s", - "libjf-config-v1.reset": "Reset", - "libjf-config-core-v1.no-screen": "No screen", - "libjf-config-core-v1.no-screen.description": "No mod for rendering config UIs was discovered. Install LibJF to add one.", - "libjf-config-core-v1.edit": "Edit" -} \ No newline at end of file diff --git a/libjf-config-core-v1/build.gradle.kts b/libjf-config-core-v2/build.gradle.kts similarity index 84% rename from libjf-config-core-v1/build.gradle.kts rename to libjf-config-core-v2/build.gradle.kts index 4bcc048..794dfb7 100644 --- a/libjf-config-core-v1/build.gradle.kts +++ b/libjf-config-core-v2/build.gradle.kts @@ -5,7 +5,7 @@ plugins { } base { - archivesName.set("libjf-config-core-v1") + archivesName.set("libjf-config-core-v2") } dependencies { diff --git a/libjf-config-core-v1/src/client/java/io/gitlab/jfronny/libjf/config/api/v2/ui/ConfigScreenFactory.java b/libjf-config-core-v2/src/client/java/io/gitlab/jfronny/libjf/config/api/v2/ui/ConfigScreenFactory.java similarity index 90% rename from libjf-config-core-v1/src/client/java/io/gitlab/jfronny/libjf/config/api/v2/ui/ConfigScreenFactory.java rename to libjf-config-core-v2/src/client/java/io/gitlab/jfronny/libjf/config/api/v2/ui/ConfigScreenFactory.java index e8a65e8..01b9b41 100644 --- a/libjf-config-core-v1/src/client/java/io/gitlab/jfronny/libjf/config/api/v2/ui/ConfigScreenFactory.java +++ b/libjf-config-core-v2/src/client/java/io/gitlab/jfronny/libjf/config/api/v2/ui/ConfigScreenFactory.java @@ -1,6 +1,6 @@ package io.gitlab.jfronny.libjf.config.api.v2.ui; -import io.gitlab.jfronny.libjf.config.api.v1.ConfigInstance; +import io.gitlab.jfronny.libjf.config.api.v2.ConfigInstance; import io.gitlab.jfronny.libjf.config.impl.ui.ConfigScreenFactoryDiscovery; import net.minecraft.client.gui.screen.Screen; diff --git a/libjf-config-core-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/ConfigScreenFactoryDiscovery.java b/libjf-config-core-v2/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/ConfigScreenFactoryDiscovery.java similarity index 100% rename from libjf-config-core-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/ConfigScreenFactoryDiscovery.java rename to libjf-config-core-v2/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/ConfigScreenFactoryDiscovery.java diff --git a/libjf-config-core-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/ModMenuAdapter.java b/libjf-config-core-v2/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/ModMenuAdapter.java similarity index 90% rename from libjf-config-core-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/ModMenuAdapter.java rename to libjf-config-core-v2/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/ModMenuAdapter.java index dd34880..b906054 100644 --- a/libjf-config-core-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/ModMenuAdapter.java +++ b/libjf-config-core-v2/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/ModMenuAdapter.java @@ -3,8 +3,8 @@ package io.gitlab.jfronny.libjf.config.impl.ui; import com.terraformersmc.modmenu.api.ConfigScreenFactory; import com.terraformersmc.modmenu.api.ModMenuApi; import io.gitlab.jfronny.libjf.LibJf; -import io.gitlab.jfronny.libjf.config.api.v1.ConfigHolder; -import io.gitlab.jfronny.libjf.config.api.v1.ConfigInstance; +import io.gitlab.jfronny.libjf.config.api.v2.ConfigHolder; +import io.gitlab.jfronny.libjf.config.api.v2.ConfigInstance; import io.gitlab.jfronny.libjf.config.impl.ConfigCore; import java.util.HashMap; diff --git a/libjf-config-core-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/PlaceholderScreen.java b/libjf-config-core-v2/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/PlaceholderScreen.java similarity index 87% rename from libjf-config-core-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/PlaceholderScreen.java rename to libjf-config-core-v2/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/PlaceholderScreen.java index 7c4ff55..406c466 100644 --- a/libjf-config-core-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/PlaceholderScreen.java +++ b/libjf-config-core-v2/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/PlaceholderScreen.java @@ -7,10 +7,10 @@ import java.util.Objects; public class PlaceholderScreen extends Screen { private final Screen parent; - private final Text description = Text.translatable("libjf-config-core-v1.no-screen.description"); + private final Text description = Text.translatable("libjf-config-core-v2.no-screen.description"); protected PlaceholderScreen(Screen parent) { - super(Text.translatable("libjf-config-core-v1.no-screen")); + super(Text.translatable("libjf-config-core-v2.no-screen")); this.parent = parent; addDrawable((context, mouseX, mouseY, delta) -> { context.drawCenteredTextWithShadow(textRenderer, description, width / 2, (height - textRenderer.fontHeight) / 2, 0xFFFFFF); diff --git a/libjf-config-core-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/PlaceholderScreenFactory.java b/libjf-config-core-v2/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/PlaceholderScreenFactory.java similarity index 93% rename from libjf-config-core-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/PlaceholderScreenFactory.java rename to libjf-config-core-v2/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/PlaceholderScreenFactory.java index c3d580e..b9300fc 100644 --- a/libjf-config-core-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/PlaceholderScreenFactory.java +++ b/libjf-config-core-v2/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/PlaceholderScreenFactory.java @@ -1,6 +1,6 @@ package io.gitlab.jfronny.libjf.config.impl.ui; -import io.gitlab.jfronny.libjf.config.api.v1.ConfigInstance; +import io.gitlab.jfronny.libjf.config.api.v2.ConfigInstance; import io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory; import net.minecraft.client.gui.screen.Screen; diff --git a/libjf-config-core-v2/src/client/resources/assets/libjf-config-core/lang/en_us.json b/libjf-config-core-v2/src/client/resources/assets/libjf-config-core/lang/en_us.json new file mode 100644 index 0000000..bfe56a3 --- /dev/null +++ b/libjf-config-core-v2/src/client/resources/assets/libjf-config-core/lang/en_us.json @@ -0,0 +1,12 @@ +{ + "libjf-config-core-v2.jfconfig.title": "LibJF Config", + "libjf-config-core-v2.jfconfig.watchForChanges": "Watch for changes", + "libjf-config-core-v2.jfconfig.watchForChanges.tooltip": "Automatically reload configs when they are changed", + "libjf-config-core-v2.presets": "Presets", + "libjf-config-core-v2.default": "Default", + "libjf-config-core-v2.see-also": "See also: %s", + "libjf-config-core-v2.reset": "Reset", + "libjf-config-core-v2.no-screen": "No screen", + "libjf-config-core-v2.no-screen.description": "No mod for rendering config UIs was discovered. Install LibJF to add one.", + "libjf-config-core-v2.edit": "Edit" +} \ No newline at end of file diff --git a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/Category.java b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/Category.java similarity index 92% rename from libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/Category.java rename to libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/Category.java index b24fd31..816260b 100644 --- a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/Category.java +++ b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/Category.java @@ -1,4 +1,4 @@ -package io.gitlab.jfronny.libjf.config.api.v1; +package io.gitlab.jfronny.libjf.config.api.v2; import java.lang.annotation.*; diff --git a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/ConfigCategory.java b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/ConfigCategory.java similarity index 95% rename from libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/ConfigCategory.java rename to libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/ConfigCategory.java index 4d35dc1..f4f0c02 100644 --- a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/ConfigCategory.java +++ b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/ConfigCategory.java @@ -1,4 +1,4 @@ -package io.gitlab.jfronny.libjf.config.api.v1; +package io.gitlab.jfronny.libjf.config.api.v2; import io.gitlab.jfronny.libjf.LibJf; diff --git a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/ConfigHolder.java b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/ConfigHolder.java similarity index 97% rename from libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/ConfigHolder.java rename to libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/ConfigHolder.java index c18fe67..2d43a2e 100644 --- a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/ConfigHolder.java +++ b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/ConfigHolder.java @@ -1,4 +1,4 @@ -package io.gitlab.jfronny.libjf.config.api.v1; +package io.gitlab.jfronny.libjf.config.api.v2; import io.gitlab.jfronny.libjf.LibJf; import io.gitlab.jfronny.libjf.config.impl.ConfigHolderImpl; diff --git a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/ConfigInstance.java b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/ConfigInstance.java similarity index 90% rename from libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/ConfigInstance.java rename to libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/ConfigInstance.java index 38fd34e..e3173a4 100644 --- a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/ConfigInstance.java +++ b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/ConfigInstance.java @@ -1,4 +1,4 @@ -package io.gitlab.jfronny.libjf.config.api.v1; +package io.gitlab.jfronny.libjf.config.api.v2; import java.nio.file.Path; import java.util.Optional; diff --git a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/Entry.java b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/Entry.java similarity index 87% rename from libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/Entry.java rename to libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/Entry.java index 6c6b18c..1a1ce01 100644 --- a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/Entry.java +++ b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/Entry.java @@ -1,4 +1,4 @@ -package io.gitlab.jfronny.libjf.config.api.v1; +package io.gitlab.jfronny.libjf.config.api.v2; import java.lang.annotation.*; diff --git a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/EntryInfo.java b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/EntryInfo.java similarity index 91% rename from libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/EntryInfo.java rename to libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/EntryInfo.java index b991f8d..c3e6290 100644 --- a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/EntryInfo.java +++ b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/EntryInfo.java @@ -1,9 +1,7 @@ -package io.gitlab.jfronny.libjf.config.api.v1; +package io.gitlab.jfronny.libjf.config.api.v2; -import io.gitlab.jfronny.gson.JsonElement; -import io.gitlab.jfronny.gson.JsonParseException; import io.gitlab.jfronny.gson.stream.*; -import io.gitlab.jfronny.libjf.config.api.v1.type.Type; +import io.gitlab.jfronny.libjf.config.api.v2.type.Type; import io.gitlab.jfronny.libjf.config.impl.dsl.DslEntryInfo; import org.jetbrains.annotations.ApiStatus; diff --git a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/JfConfig.java b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/JfConfig.java similarity index 91% rename from libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/JfConfig.java rename to libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/JfConfig.java index 983c646..bee1994 100644 --- a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/JfConfig.java +++ b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/JfConfig.java @@ -1,4 +1,4 @@ -package io.gitlab.jfronny.libjf.config.api.v1; +package io.gitlab.jfronny.libjf.config.api.v2; import java.lang.annotation.*; diff --git a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/JfCustomConfig.java b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/JfCustomConfig.java similarity index 60% rename from libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/JfCustomConfig.java rename to libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/JfCustomConfig.java index f4b8d1f..d43b7fd 100644 --- a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/JfCustomConfig.java +++ b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/JfCustomConfig.java @@ -1,6 +1,6 @@ -package io.gitlab.jfronny.libjf.config.api.v1; +package io.gitlab.jfronny.libjf.config.api.v2; -import io.gitlab.jfronny.libjf.config.api.v1.dsl.DSL; +import io.gitlab.jfronny.libjf.config.api.v2.dsl.DSL; /** * The interface for entrypoints performing custom config registrations diff --git a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/Preset.java b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/Preset.java similarity index 83% rename from libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/Preset.java rename to libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/Preset.java index ed45ae6..7f7ddf4 100644 --- a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/Preset.java +++ b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/Preset.java @@ -1,4 +1,4 @@ -package io.gitlab.jfronny.libjf.config.api.v1; +package io.gitlab.jfronny.libjf.config.api.v2; import java.lang.annotation.*; diff --git a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/Verifier.java b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/Verifier.java similarity index 86% rename from libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/Verifier.java rename to libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/Verifier.java index e23d6a8..c659494 100644 --- a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/Verifier.java +++ b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/Verifier.java @@ -1,4 +1,4 @@ -package io.gitlab.jfronny.libjf.config.api.v1; +package io.gitlab.jfronny.libjf.config.api.v2; import java.lang.annotation.*; diff --git a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/dsl/CategoryBuilder.java b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/dsl/CategoryBuilder.java similarity index 89% rename from libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/dsl/CategoryBuilder.java rename to libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/dsl/CategoryBuilder.java index 45378fa..af74762 100644 --- a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/dsl/CategoryBuilder.java +++ b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/dsl/CategoryBuilder.java @@ -1,8 +1,9 @@ -package io.gitlab.jfronny.libjf.config.api.v1.dsl; +package io.gitlab.jfronny.libjf.config.api.v2.dsl; import io.gitlab.jfronny.commons.SamWithReceiver; -import io.gitlab.jfronny.libjf.config.api.v1.*; -import io.gitlab.jfronny.libjf.config.api.v1.type.Type; +import io.gitlab.jfronny.libjf.config.api.v2.*; +import io.gitlab.jfronny.libjf.config.api.v2.type.Type; +import io.gitlab.jfronny.libjf.config.impl.ConfigCore; import org.jetbrains.annotations.ApiStatus; import java.util.List; @@ -14,7 +15,7 @@ import java.util.function.Supplier; * @param The class implementing this builder */ public interface CategoryBuilder> { - String CONFIG_PRESET_DEFAULT = "libjf-config-v1.default"; + String CONFIG_PRESET_DEFAULT = ConfigCore.MOD_ID + ".default"; Builder setTranslationPrefix(String translationPrefix); String getTranslationPrefix(); diff --git a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/dsl/ConfigBuilder.java b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/dsl/ConfigBuilder.java similarity index 87% rename from libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/dsl/ConfigBuilder.java rename to libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/dsl/ConfigBuilder.java index f7755ff..4266c9f 100644 --- a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/dsl/ConfigBuilder.java +++ b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/dsl/ConfigBuilder.java @@ -1,7 +1,7 @@ -package io.gitlab.jfronny.libjf.config.api.v1.dsl; +package io.gitlab.jfronny.libjf.config.api.v2.dsl; import io.gitlab.jfronny.commons.SamWithReceiver; -import io.gitlab.jfronny.libjf.config.api.v1.ConfigInstance; +import io.gitlab.jfronny.libjf.config.api.v2.ConfigInstance; import java.nio.file.Path; import java.util.function.Consumer; diff --git a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/dsl/DSL.java b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/dsl/DSL.java similarity index 86% rename from libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/dsl/DSL.java rename to libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/dsl/DSL.java index b43bd0e..55e7e64 100644 --- a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/dsl/DSL.java +++ b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/dsl/DSL.java @@ -1,7 +1,7 @@ -package io.gitlab.jfronny.libjf.config.api.v1.dsl; +package io.gitlab.jfronny.libjf.config.api.v2.dsl; -import io.gitlab.jfronny.libjf.config.api.v1.ConfigHolder; -import io.gitlab.jfronny.libjf.config.api.v1.ConfigInstance; +import io.gitlab.jfronny.libjf.config.api.v2.ConfigHolder; +import io.gitlab.jfronny.libjf.config.api.v2.ConfigInstance; import io.gitlab.jfronny.libjf.config.impl.dsl.DSLImpl; /** diff --git a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/dsl/Migration.java b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/dsl/Migration.java similarity index 78% rename from libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/dsl/Migration.java rename to libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/dsl/Migration.java index 01973d8..31c752c 100644 --- a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/dsl/Migration.java +++ b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/dsl/Migration.java @@ -1,4 +1,4 @@ -package io.gitlab.jfronny.libjf.config.api.v1.dsl; +package io.gitlab.jfronny.libjf.config.api.v2.dsl; import io.gitlab.jfronny.gson.stream.JsonReader; diff --git a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/type/Type.java b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/type/Type.java similarity index 99% rename from libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/type/Type.java rename to libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/type/Type.java index bdf3cae..c92ca32 100644 --- a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/type/Type.java +++ b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/api/v2/type/Type.java @@ -1,4 +1,4 @@ -package io.gitlab.jfronny.libjf.config.api.v1.type; +package io.gitlab.jfronny.libjf.config.api.v2.type; import org.jetbrains.annotations.Nullable; diff --git a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/AuxiliaryMetadata.java b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/AuxiliaryMetadata.java similarity index 93% rename from libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/AuxiliaryMetadata.java rename to libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/AuxiliaryMetadata.java index fb5d2ab..53e5637 100644 --- a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/AuxiliaryMetadata.java +++ b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/AuxiliaryMetadata.java @@ -1,9 +1,9 @@ package io.gitlab.jfronny.libjf.config.impl; import io.gitlab.jfronny.commons.serialize.gson.api.v1.GsonHolders; -import io.gitlab.jfronny.libjf.config.api.v1.Category; -import io.gitlab.jfronny.libjf.config.api.v1.JfConfig; -import io.gitlab.jfronny.libjf.config.api.v1.dsl.CategoryBuilder; +import io.gitlab.jfronny.libjf.config.api.v2.Category; +import io.gitlab.jfronny.libjf.config.api.v2.JfConfig; +import io.gitlab.jfronny.libjf.config.api.v2.dsl.CategoryBuilder; import io.gitlab.jfronny.libjf.gson.FabricLoaderGsonGenerator; import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.metadata.CustomValue; diff --git a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/ConfigCore.java b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/ConfigCore.java similarity index 71% rename from libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/ConfigCore.java rename to libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/ConfigCore.java index bff80d2..fd97734 100644 --- a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/ConfigCore.java +++ b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/ConfigCore.java @@ -1,10 +1,10 @@ package io.gitlab.jfronny.libjf.config.impl; -import io.gitlab.jfronny.libjf.config.api.v1.ConfigInstance; -import io.gitlab.jfronny.libjf.config.api.v1.dsl.DSL; +import io.gitlab.jfronny.libjf.config.api.v2.ConfigInstance; +import io.gitlab.jfronny.libjf.config.api.v2.dsl.DSL; public class ConfigCore { - public static final String MOD_ID = "libjf-config-core-v1"; + public static final String MOD_ID = "libjf-config-core-v2"; public static final String MODULE_ID = "libjf:config"; public static boolean watchForChanges = true; public static final ConfigInstance CONFIG_INSTANCE; diff --git a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/ConfigHolderImpl.java b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/ConfigHolderImpl.java similarity index 95% rename from libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/ConfigHolderImpl.java rename to libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/ConfigHolderImpl.java index f5c7b04..6bf2d22 100644 --- a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/ConfigHolderImpl.java +++ b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/ConfigHolderImpl.java @@ -2,8 +2,8 @@ package io.gitlab.jfronny.libjf.config.impl; import com.google.common.collect.ImmutableMap; import io.gitlab.jfronny.libjf.LibJf; -import io.gitlab.jfronny.libjf.config.api.v1.ConfigHolder; -import io.gitlab.jfronny.libjf.config.api.v1.ConfigInstance; +import io.gitlab.jfronny.libjf.config.api.v2.ConfigHolder; +import io.gitlab.jfronny.libjf.config.api.v2.ConfigInstance; import net.fabricmc.loader.api.FabricLoader; import org.jetbrains.annotations.ApiStatus; diff --git a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/CategoryBuilderImpl.java b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/CategoryBuilderImpl.java similarity index 97% rename from libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/CategoryBuilderImpl.java rename to libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/CategoryBuilderImpl.java index eb5bb9a..4babb6e 100644 --- a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/CategoryBuilderImpl.java +++ b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/CategoryBuilderImpl.java @@ -3,10 +3,10 @@ package io.gitlab.jfronny.libjf.config.impl.dsl; import io.gitlab.jfronny.commons.throwable.Coerce; import io.gitlab.jfronny.gson.stream.JsonReader; import io.gitlab.jfronny.libjf.LibJf; -import io.gitlab.jfronny.libjf.config.api.v1.*; -import io.gitlab.jfronny.libjf.config.api.v1.dsl.CategoryBuilder; -import io.gitlab.jfronny.libjf.config.api.v1.dsl.Migration; -import io.gitlab.jfronny.libjf.config.api.v1.type.Type; +import io.gitlab.jfronny.libjf.config.api.v2.*; +import io.gitlab.jfronny.libjf.config.api.v2.dsl.CategoryBuilder; +import io.gitlab.jfronny.libjf.config.api.v2.dsl.Migration; +import io.gitlab.jfronny.libjf.config.api.v2.type.Type; import java.util.*; import java.util.function.Consumer; diff --git a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/ConfigBuilderImpl.java b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/ConfigBuilderImpl.java similarity index 93% rename from libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/ConfigBuilderImpl.java rename to libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/ConfigBuilderImpl.java index b395e19..625bb2a 100644 --- a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/ConfigBuilderImpl.java +++ b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/ConfigBuilderImpl.java @@ -1,7 +1,7 @@ package io.gitlab.jfronny.libjf.config.impl.dsl; -import io.gitlab.jfronny.libjf.config.api.v1.ConfigInstance; -import io.gitlab.jfronny.libjf.config.api.v1.dsl.ConfigBuilder; +import io.gitlab.jfronny.libjf.config.api.v2.ConfigInstance; +import io.gitlab.jfronny.libjf.config.api.v2.dsl.ConfigBuilder; import net.fabricmc.loader.api.FabricLoader; import java.nio.file.Path; diff --git a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/DSLImpl.java b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/DSLImpl.java similarity index 86% rename from libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/DSLImpl.java rename to libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/DSLImpl.java index 369f7a0..9a4587f 100644 --- a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/DSLImpl.java +++ b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/DSLImpl.java @@ -1,9 +1,9 @@ package io.gitlab.jfronny.libjf.config.impl.dsl; -import io.gitlab.jfronny.libjf.config.api.v1.ConfigHolder; -import io.gitlab.jfronny.libjf.config.api.v1.ConfigInstance; -import io.gitlab.jfronny.libjf.config.api.v1.dsl.ConfigBuilder; -import io.gitlab.jfronny.libjf.config.api.v1.dsl.DSL; +import io.gitlab.jfronny.libjf.config.api.v2.ConfigHolder; +import io.gitlab.jfronny.libjf.config.api.v2.ConfigInstance; +import io.gitlab.jfronny.libjf.config.api.v2.dsl.ConfigBuilder; +import io.gitlab.jfronny.libjf.config.api.v2.dsl.DSL; public class DSLImpl implements DSL { @Override diff --git a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/DefaultConfigIO.java b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/DefaultConfigIO.java similarity index 99% rename from libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/DefaultConfigIO.java rename to libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/DefaultConfigIO.java index 8369290..8db48d2 100644 --- a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/DefaultConfigIO.java +++ b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/DefaultConfigIO.java @@ -4,7 +4,7 @@ import io.gitlab.jfronny.commons.serialize.gson.api.v1.GsonHolders; import io.gitlab.jfronny.gson.*; import io.gitlab.jfronny.gson.stream.*; import io.gitlab.jfronny.libjf.LibJf; -import io.gitlab.jfronny.libjf.config.api.v1.*; +import io.gitlab.jfronny.libjf.config.api.v2.*; import io.gitlab.jfronny.libjf.config.impl.entrypoint.JfConfigSafe; import io.gitlab.jfronny.libjf.config.impl.watch.JfConfigWatchService; diff --git a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/DslConfigCategory.java b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/DslConfigCategory.java similarity index 96% rename from libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/DslConfigCategory.java rename to libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/DslConfigCategory.java index b5e3d85..9eb471e 100644 --- a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/DslConfigCategory.java +++ b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/DslConfigCategory.java @@ -1,8 +1,8 @@ package io.gitlab.jfronny.libjf.config.impl.dsl; import io.gitlab.jfronny.gson.stream.JsonReader; -import io.gitlab.jfronny.libjf.config.api.v1.*; -import io.gitlab.jfronny.libjf.config.api.v1.dsl.CategoryBuilder; +import io.gitlab.jfronny.libjf.config.api.v2.*; +import io.gitlab.jfronny.libjf.config.api.v2.dsl.CategoryBuilder; import org.jetbrains.annotations.ApiStatus; import java.util.*; diff --git a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/DslConfigInstance.java b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/DslConfigInstance.java similarity index 93% rename from libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/DslConfigInstance.java rename to libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/DslConfigInstance.java index d997e68..6e7a294 100644 --- a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/DslConfigInstance.java +++ b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/DslConfigInstance.java @@ -1,8 +1,8 @@ package io.gitlab.jfronny.libjf.config.impl.dsl; import io.gitlab.jfronny.gson.stream.JsonReader; -import io.gitlab.jfronny.libjf.config.api.v1.*; -import io.gitlab.jfronny.libjf.config.api.v1.dsl.CategoryBuilder; +import io.gitlab.jfronny.libjf.config.api.v2.*; +import io.gitlab.jfronny.libjf.config.api.v2.dsl.CategoryBuilder; import org.jetbrains.annotations.Nullable; import java.nio.file.Path; diff --git a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/DslEntryInfo.java b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/DslEntryInfo.java similarity index 97% rename from libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/DslEntryInfo.java rename to libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/DslEntryInfo.java index 18498ab..efa7ab1 100644 --- a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/DslEntryInfo.java +++ b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/DslEntryInfo.java @@ -5,9 +5,9 @@ import io.gitlab.jfronny.commons.throwable.ThrowingConsumer; import io.gitlab.jfronny.commons.throwable.ThrowingSupplier; import io.gitlab.jfronny.gson.stream.*; import io.gitlab.jfronny.libjf.LibJf; -import io.gitlab.jfronny.libjf.config.api.v1.Entry; -import io.gitlab.jfronny.libjf.config.api.v1.EntryInfo; -import io.gitlab.jfronny.libjf.config.api.v1.type.Type; +import io.gitlab.jfronny.libjf.config.api.v2.Entry; +import io.gitlab.jfronny.libjf.config.api.v2.EntryInfo; +import io.gitlab.jfronny.libjf.config.api.v2.type.Type; import io.gitlab.jfronny.libjf.config.impl.entrypoint.JfConfigSafe; import java.io.IOException; diff --git a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/entrypoint/JfConfigSafe.java b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/entrypoint/JfConfigSafe.java similarity index 91% rename from libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/entrypoint/JfConfigSafe.java rename to libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/entrypoint/JfConfigSafe.java index 636a934..948dffe 100644 --- a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/entrypoint/JfConfigSafe.java +++ b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/entrypoint/JfConfigSafe.java @@ -1,8 +1,8 @@ package io.gitlab.jfronny.libjf.config.impl.entrypoint; import io.gitlab.jfronny.libjf.LibJf; -import io.gitlab.jfronny.libjf.config.api.v1.JfCustomConfig; -import io.gitlab.jfronny.libjf.config.api.v1.dsl.DSL; +import io.gitlab.jfronny.libjf.config.api.v2.JfCustomConfig; +import io.gitlab.jfronny.libjf.config.api.v2.dsl.DSL; import io.gitlab.jfronny.libjf.config.impl.ConfigCore; import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.entrypoint.EntrypointContainer; diff --git a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/watch/JfConfigWatchService.java b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/watch/JfConfigWatchService.java similarity index 100% rename from libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/watch/JfConfigWatchService.java rename to libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/watch/JfConfigWatchService.java diff --git a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/watch/JfConfigWatchServiceImpl.java b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/watch/JfConfigWatchServiceImpl.java similarity index 98% rename from libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/watch/JfConfigWatchServiceImpl.java rename to libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/watch/JfConfigWatchServiceImpl.java index 58e4ed0..05475e7 100644 --- a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/watch/JfConfigWatchServiceImpl.java +++ b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/watch/JfConfigWatchServiceImpl.java @@ -2,7 +2,7 @@ package io.gitlab.jfronny.libjf.config.impl.watch; import io.gitlab.jfronny.commons.throwable.ThrowingRunnable; import io.gitlab.jfronny.libjf.LibJf; -import io.gitlab.jfronny.libjf.config.api.v1.ConfigHolder; +import io.gitlab.jfronny.libjf.config.api.v2.ConfigHolder; import net.fabricmc.loader.api.FabricLoader; import java.io.IOException; diff --git a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/watch/ToggleableConfigWatchService.java b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/watch/ToggleableConfigWatchService.java similarity index 100% rename from libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/watch/ToggleableConfigWatchService.java rename to libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/watch/ToggleableConfigWatchService.java diff --git a/libjf-config-core-v1/src/main/resources/fabric.mod.json b/libjf-config-core-v2/src/main/resources/fabric.mod.json similarity index 96% rename from libjf-config-core-v1/src/main/resources/fabric.mod.json rename to libjf-config-core-v2/src/main/resources/fabric.mod.json index 7c378cb..624a8b6 100644 --- a/libjf-config-core-v1/src/main/resources/fabric.mod.json +++ b/libjf-config-core-v2/src/main/resources/fabric.mod.json @@ -1,6 +1,6 @@ { "schemaVersion": 1, - "id": "libjf-config-core-v1", + "id": "libjf-config-core-v2", "name": "LibJF Config", "version": "${version}", "authors": ["JFronny"], diff --git a/libjf-config-reflect-v1/build.gradle.kts b/libjf-config-reflect-v1/build.gradle.kts deleted file mode 100644 index 745747a..0000000 --- a/libjf-config-reflect-v1/build.gradle.kts +++ /dev/null @@ -1,15 +0,0 @@ -import io.gitlab.jfronny.scripts.* - -plugins { - id("jfmod.module") -} - -base { - archivesName.set("libjf-config-reflect-v1") -} - -dependencies { - api(devProject(":libjf-base")) - api(devProject(":libjf-unsafe-v0")) - api(devProject(":libjf-config-core-v1")) -} diff --git a/libjf-config-reflect-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/reflect/ReflectiveConfigBuilder.java b/libjf-config-reflect-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/reflect/ReflectiveConfigBuilder.java deleted file mode 100644 index c0ac31a..0000000 --- a/libjf-config-reflect-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/reflect/ReflectiveConfigBuilder.java +++ /dev/null @@ -1,10 +0,0 @@ -package io.gitlab.jfronny.libjf.config.api.v1.reflect; - -import io.gitlab.jfronny.libjf.config.api.v1.dsl.ConfigBuilder; -import io.gitlab.jfronny.libjf.config.impl.reflect.ReflectiveConfigBuilderImpl; - -public interface ReflectiveConfigBuilder extends ConfigBuilder.ConfigBuilderFunction { - static ReflectiveConfigBuilder of(String id, Class klazz) { - return new ReflectiveConfigBuilderImpl(id, klazz); - } -} diff --git a/libjf-config-reflect-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/reflect/ReflectiveConfigBuilderImpl.java b/libjf-config-reflect-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/reflect/ReflectiveConfigBuilderImpl.java deleted file mode 100644 index 9639cd9..0000000 --- a/libjf-config-reflect-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/reflect/ReflectiveConfigBuilderImpl.java +++ /dev/null @@ -1,84 +0,0 @@ -package io.gitlab.jfronny.libjf.config.impl.reflect; - -import io.gitlab.jfronny.commons.reflect.Reflect; -import io.gitlab.jfronny.commons.throwable.ThrowingConsumer; -import io.gitlab.jfronny.libjf.LibJf; -import io.gitlab.jfronny.libjf.config.api.v1.*; -import io.gitlab.jfronny.libjf.config.api.v1.dsl.CategoryBuilder; -import io.gitlab.jfronny.libjf.config.api.v1.dsl.ConfigBuilder; -import io.gitlab.jfronny.libjf.config.api.v1.reflect.ReflectiveConfigBuilder; -import io.gitlab.jfronny.libjf.config.impl.AuxiliaryMetadata; -import io.gitlab.jfronny.libjf.config.impl.dsl.DslEntryInfo; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.Objects; -import java.util.function.Function; - -public class ReflectiveConfigBuilderImpl implements ReflectiveConfigBuilder { - private final AuxiliaryMetadata rootMeta; - private final Class rootClass; - private final Class rootTweaker; - private final String id; - - public ReflectiveConfigBuilderImpl(String id, Class klazz) { - this.id = id; - this.rootClass = Objects.requireNonNull(klazz); - JfConfig annotation = klazz.getAnnotation(JfConfig.class); - rootTweaker = annotation.tweaker(); - this.rootMeta = AuxiliaryMetadata.of(annotation).merge(AuxiliaryMetadata.forMod(id)); - } - - @Override - public ConfigBuilder apply(ConfigBuilder builder) { - return applyCategory(builder, rootClass, findTweaker(rootTweaker, ConfigBuilder.class), rootMeta); - } - - private > T applyCategory(T builder, Class configClass, Function tweaker, AuxiliaryMetadata meta) { - meta.applyTo(builder); - for (Field field : configClass.getFields()) { - if (field.isAnnotationPresent(Entry.class)) { - builder.value(DslEntryInfo.ofField(field)); - } - } - for (Method method : configClass.getMethods()) { - try { - if (method.isAnnotationPresent(Preset.class)) { - builder.addPreset(builder.getTranslationPrefix() + method.getName(), ReflectiveConfigBuilderImpl.staticToConsumer(configClass, method).addHandler(e -> LibJf.LOGGER.error("Could not apply preset", e))); - } else if (method.isAnnotationPresent(Verifier.class)) { - builder.addVerifier(ReflectiveConfigBuilderImpl.staticToConsumer(configClass, method).addHandler(e -> LibJf.LOGGER.error("Could not run verifier", e))); - } - } catch (Throwable t) { - LibJf.LOGGER.error("Could not process method " + method.getName() + " of config class " + configClass.getName()); - } - } - - for (Class categoryClass : configClass.getClasses()) { - if (categoryClass.isAnnotationPresent(Category.class)) { - Category annotation = categoryClass.getAnnotation(Category.class); - String name = categoryClass.getSimpleName(); - name = Character.toLowerCase(name.charAt(0)) + name.substring(1); // camelCase - var categoryTweaker = findTweaker(annotation.tweaker(), CategoryBuilder.class); - builder.category(name, builder1 -> applyCategory(builder1, categoryClass, categoryTweaker, AuxiliaryMetadata.of(categoryClass.getAnnotation(Category.class)))); - } - } - - return tweaker.apply(builder); - } - - private Function findTweaker(Class targetClass, Class tweakedClass) { - try { - return Objects.equals(targetClass, void.class) - ? Function.identity() - : Reflect.staticFunction(targetClass, "tweak", tweakedClass, tweakedClass); - } catch (Throwable t) { - LibJf.LOGGER.error("Could not find tweaker " + targetClass + " for mod " + id, t); - return Function.identity(); - } - } - - public static ThrowingConsumer staticToConsumer(Class klazz, Method method) throws Throwable { - Runnable rn = Reflect.staticProcedure(klazz, method.getName()); - return c -> rn.run(); - } -} diff --git a/libjf-config-reflect-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/reflect/entrypoint/JfConfigReflectSafe.java b/libjf-config-reflect-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/reflect/entrypoint/JfConfigReflectSafe.java deleted file mode 100644 index 36dcb9c..0000000 --- a/libjf-config-reflect-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/reflect/entrypoint/JfConfigReflectSafe.java +++ /dev/null @@ -1,37 +0,0 @@ -package io.gitlab.jfronny.libjf.config.impl.reflect.entrypoint; - -import io.gitlab.jfronny.libjf.LibJf; -import io.gitlab.jfronny.libjf.config.api.v1.*; -import io.gitlab.jfronny.libjf.config.api.v1.dsl.DSL; -import io.gitlab.jfronny.libjf.config.api.v1.reflect.ReflectiveConfigBuilder; -import io.gitlab.jfronny.libjf.config.impl.ConfigCore; -import io.gitlab.jfronny.libjf.config.impl.entrypoint.JfConfigSafe; -import net.fabricmc.loader.api.FabricLoader; -import net.fabricmc.loader.api.entrypoint.EntrypointContainer; -import net.fabricmc.loader.api.entrypoint.PreLaunchEntrypoint; - -public class JfConfigReflectSafe implements PreLaunchEntrypoint { - @Override - public void onPreLaunch() { - LibJf.setup(); - for (EntrypointContainer config : FabricLoader.getInstance().getEntrypointContainers(ConfigCore.MODULE_ID, Object.class)) { - registerIfMissing(config.getProvider().getMetadata().getId(), config.getEntrypoint()); - } - } - - public static void registerIfMissing(String modId, Object config) { - if (JfConfigSafe.REGISTERED_MODS.add(modId)) { - ConfigHolder.getInstance().migrateFiles(modId); - if (config instanceof JfCustomConfig cfg) { - cfg.register(DSL.create(modId)); - } else { - Class klazz = config.getClass(); - if (klazz.isAnnotationPresent(JfConfig.class)) { - DSL.create(modId).register(ReflectiveConfigBuilder.of(modId, klazz)); - } else { - LibJf.LOGGER.error("Attempted to register improper config for mod " + modId + " (missing @JfConfig annotation or JfCustomConfig interface)"); - } - } - } - } -} diff --git a/libjf-config-reflect-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/reflect/entrypoint/JfConfigUnsafe.java b/libjf-config-reflect-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/reflect/entrypoint/JfConfigUnsafe.java deleted file mode 100644 index dce4269..0000000 --- a/libjf-config-reflect-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/reflect/entrypoint/JfConfigUnsafe.java +++ /dev/null @@ -1,16 +0,0 @@ -package io.gitlab.jfronny.libjf.config.impl.reflect.entrypoint; - -import io.gitlab.jfronny.libjf.LibJf; -import io.gitlab.jfronny.libjf.config.impl.ConfigCore; -import io.gitlab.jfronny.libjf.unsafe.DynamicEntry; -import io.gitlab.jfronny.libjf.unsafe.UltraEarlyInit; - -public class JfConfigUnsafe implements UltraEarlyInit { - @Override - public void init() { - DynamicEntry.execute(ConfigCore.MODULE_ID, Object.class, - s -> JfConfigReflectSafe.registerIfMissing(s.modId(), s.instance()) - ); - LibJf.LOGGER.info("Finished LibJF config entrypoint"); - } -} diff --git a/libjf-config-reflect-v1/src/main/resources/fabric.mod.json b/libjf-config-reflect-v1/src/main/resources/fabric.mod.json deleted file mode 100644 index 98c1618..0000000 --- a/libjf-config-reflect-v1/src/main/resources/fabric.mod.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "schemaVersion": 1, - "id": "libjf-config-reflect-v1", - "name": "LibJF Config Reflect", - "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": "*", - "entrypoints": { - "libjf:preEarly": [ - "io.gitlab.jfronny.libjf.config.impl.reflect.entrypoint.JfConfigUnsafe" - ], - "preLaunch": [ - "io.gitlab.jfronny.libjf.config.impl.reflect.entrypoint.JfConfigReflectSafe" - ] - }, - "depends": { - "fabricloader": ">=0.12.0", - "minecraft": "*", - "libjf-base": ">=${version}", - "libjf-unsafe-v0": ">=${version}", - "libjf-config-core-v1": ">=${version}" - }, - "custom": { - "modmenu": { - "badges": ["library"], - "parent": "libjf" - } - } -} diff --git a/libjf-config-reflect-v1/src/testmod/java/io/gitlab/jfronny/libjf/config/test/reflect/TestConfig.java b/libjf-config-reflect-v1/src/testmod/java/io/gitlab/jfronny/libjf/config/test/reflect/TestConfig.java deleted file mode 100644 index 091eff2..0000000 --- a/libjf-config-reflect-v1/src/testmod/java/io/gitlab/jfronny/libjf/config/test/reflect/TestConfig.java +++ /dev/null @@ -1,57 +0,0 @@ -package io.gitlab.jfronny.libjf.config.test.reflect; - -import io.gitlab.jfronny.commons.serialize.gson.api.v1.Ignore; -import io.gitlab.jfronny.libjf.config.api.v1.*; - -import java.util.ArrayList; -import java.util.List; - -@JfConfig(referencedConfigs = {"libjf-web-v0"}, tweaker = TestConfigTweaker.class) -public class TestConfig { - @Entry public static boolean disablePacks = false; - @Entry public static Boolean disablePacks2 = false; - @Entry public static int intTest = 20; - @Entry(min = -5, max = 12) public static int intTestB = 20; - @Entry(min = -6) public static float floatTest = -5; - @Entry(min = 2, max = 21) public static double doubleTest = 20; - @Entry public static String dieStr = "lolz"; - @Entry @Ignore public static String guiOnlyStr = "lolz"; - public static String gsonOnlyStr = "lolz"; - @Entry public static Test enumTest = Test.Test; - @Entry public static List stringList; - - @Preset - public static void moskau() { - disablePacks = true; - disablePacks2 = true; - intTest = -5; - floatTest = -6; - doubleTest = 4; - dieStr = "Moskau"; - } - - @Verifier - public static void setIntTestIfDisable() { - if (disablePacks) intTest = 0; - } - - @Verifier - public static void stringListVerifier() { - if (stringList == null) stringList = new ArrayList<>(List.of("Obama")); - } - - public enum Test { - Test, ER - } - - @Category - public static class Subcategory { - @Entry public static boolean boolInSub = false; - @Entry public static int intIbSub = 15; - - @Category - public static class Inception { - @Entry public static Test yesEnum = Test.ER; - } - } -} diff --git a/libjf-config-reflect-v1/src/testmod/java/io/gitlab/jfronny/libjf/config/test/reflect/TestConfigTweaker.java b/libjf-config-reflect-v1/src/testmod/java/io/gitlab/jfronny/libjf/config/test/reflect/TestConfigTweaker.java deleted file mode 100644 index f1c74f3..0000000 --- a/libjf-config-reflect-v1/src/testmod/java/io/gitlab/jfronny/libjf/config/test/reflect/TestConfigTweaker.java +++ /dev/null @@ -1,16 +0,0 @@ -package io.gitlab.jfronny.libjf.config.test.reflect; - -import io.gitlab.jfronny.libjf.LibJf; -import io.gitlab.jfronny.libjf.config.api.v1.dsl.ConfigBuilder; - -import java.util.Objects; - -public class TestConfigTweaker { - public static ConfigBuilder tweak(ConfigBuilder builder) { - if (!Objects.equals("libjf-config-reflect-v1-testmod", builder.getId())) throw new IllegalStateException("No!"); - LibJf.LOGGER.info("Called config tweaker"); - return builder.addMigration("joe", reader -> { - TestConfig.disablePacks = reader.nextBoolean(); - }); - } -} diff --git a/libjf-config-reflect-v1/src/testmod/resources/assets/libjf-config-v0-testmod/lang/en_us.json b/libjf-config-reflect-v1/src/testmod/resources/assets/libjf-config-v0-testmod/lang/en_us.json deleted file mode 100644 index 464230d..0000000 --- a/libjf-config-reflect-v1/src/testmod/resources/assets/libjf-config-v0-testmod/lang/en_us.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "libjf-config-reflect-v1-testmod.jfconfig.title": "JfConfig example", - "libjf-config-reflect-v1-testmod.jfconfig.disablePacks": "Disable resource packs", - "libjf-config-reflect-v1-testmod.jfconfig.intTest": "Int Test", - "libjf-config-reflect-v1-testmod.jfconfig.decimalTest": "Decimal Test", - "libjf-config-reflect-v1-testmod.jfconfig.dieStr": "String Test", - "libjf-config-reflect-v1-testmod.jfconfig.gsonOnlyStr.tooltip": "George", - "libjf-config-reflect-v1-testmod.jfconfig.enumTest": "Enum Test", - "libjf-config-reflect-v1-testmod.jfconfig.enumTest.tooltip": "Enum Test Tooltip", - "libjf-config-reflect-v1-testmod.jfconfig.enum.Test.Test": "Test", - "libjf-config-reflect-v1-testmod.jfconfig.enum.Test.ER": "ER", - "libjf-config-reflect-v1-testmod.jfconfig.moskau": "Moskau", - "libjf-config-reflect-v1-testmod.jfconfig.stringList": "String list", - "libjf-config-reflect-v1-testmod.jfconfig.stringList.tooltip": "Tooltip of the String list" -} \ No newline at end of file diff --git a/libjf-config-reflect-v1/src/testmod/resources/fabric.mod.json b/libjf-config-reflect-v1/src/testmod/resources/fabric.mod.json deleted file mode 100644 index 9cacc7e..0000000 --- a/libjf-config-reflect-v1/src/testmod/resources/fabric.mod.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "schemaVersion": 1, - "id": "libjf-config-reflect-v1-testmod", - "name": "LibJF Config Reflect", - "version": "1.0", - "environment": "*", - "entrypoints": { - "libjf:config": [ - "io.gitlab.jfronny.libjf.config.test.reflect.TestConfig" - ] - }, - "custom": { - "modmenu": { - "parent": "libjf-testmod" - } - } -} \ No newline at end of file diff --git a/libjf-config-ui-tiny-v1/src/client/resources/assets/libjf-config-ui-tiny-v1/lang/en_us.json b/libjf-config-ui-tiny-v1/src/client/resources/assets/libjf-config-ui-tiny-v1/lang/en_us.json deleted file mode 100644 index e33841b..0000000 --- a/libjf-config-ui-tiny-v1/src/client/resources/assets/libjf-config-ui-tiny-v1/lang/en_us.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "libjf-config-ui-tiny-v1.entry.json.read.fail.title": "Could not read", - "libjf-config-ui-tiny-v1.entry.json.read.fail.description": "The given entry could not be stringified. Please edit the config manually" -} \ No newline at end of file diff --git a/libjf-config-ui-tiny-v1/src/testmod/resources/assets/libjf-config-ui-tiny-v1-testmod/lang/en_us.json b/libjf-config-ui-tiny-v1/src/testmod/resources/assets/libjf-config-ui-tiny-v1-testmod/lang/en_us.json deleted file mode 100644 index 407c994..0000000 --- a/libjf-config-ui-tiny-v1/src/testmod/resources/assets/libjf-config-ui-tiny-v1-testmod/lang/en_us.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "libjf-config-ui-tiny-v1-testmod.jfconfig.title": "JfConfig example", - "libjf-config-ui-tiny-v1-testmod.jfconfig.ca1.title": "Category 1", - "libjf-config-ui-tiny-v1-testmod.jfconfig.ca1.tooltip": "This is category 1\nIt has an excessively long description to test multiline descriptions and wrapping, which are required for this to look good.\nThis is supported btw.", - "libjf-config-ui-tiny-v1-testmod.jfconfig.ca1.value1": "Value 1", - "libjf-config-ui-tiny-v1-testmod.jfconfig.ca2.title": "Category 2", - "libjf-config-ui-tiny-v1-testmod.jfconfig.ca2.tooltip": "This is category 2", - "libjf-config-ui-tiny-v1-testmod.jfconfig.ca2.value2": "Value 2", - "libjf-config-ui-tiny-v1-testmod.jfconfig.ca3.title": "Category 3", - "libjf-config-ui-tiny-v1-testmod.jfconfig.ca3.tooltip": "This is category 3", - "libjf-config-ui-tiny-v1-testmod.jfconfig.ca3.value3": "Value 3", - "libjf-config-ui-tiny-v1-testmod.jfconfig.ca4.title": "Category 4", - "libjf-config-ui-tiny-v1-testmod.jfconfig.ca4.tooltip": "This is category 4", - "libjf-config-ui-tiny-v1-testmod.jfconfig.ca4.value4": "Value 4", - "libjf-config-ui-tiny-v1-testmod.jfconfig.ca5.title": "Category 5", - "libjf-config-ui-tiny-v1-testmod.jfconfig.ca5.tooltip": "This is category 5", - "libjf-config-ui-tiny-v1-testmod.jfconfig.ca5.value5": "Value 5", - "libjf-config-ui-tiny-v1-testmod.jfconfig.ca6.title": "Category 6", - "libjf-config-ui-tiny-v1-testmod.jfconfig.ca6.tooltip": "This is category 6", - "libjf-config-ui-tiny-v1-testmod.jfconfig.ca6.value6": "Value 6" -} \ No newline at end of file diff --git a/libjf-config-ui-tiny-v1/build.gradle.kts b/libjf-config-ui-tiny/build.gradle.kts similarity index 73% rename from libjf-config-ui-tiny-v1/build.gradle.kts rename to libjf-config-ui-tiny/build.gradle.kts index a8fd5ce..4cfa50c 100644 --- a/libjf-config-ui-tiny-v1/build.gradle.kts +++ b/libjf-config-ui-tiny/build.gradle.kts @@ -5,12 +5,12 @@ plugins { } base { - archivesName.set("libjf-config-ui-tiny-v1") + archivesName.set("libjf-config-ui-tiny") } dependencies { val fabricVersion: String by rootProject.extra api(devProject(":libjf-base")) - api(devProject(":libjf-config-core-v1")) + api(devProject(":libjf-config-core-v2")) include(fabricApi.module("fabric-resource-loader-v0", fabricVersion)) } diff --git a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/EditorScreen.java b/libjf-config-ui-tiny/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/EditorScreen.java similarity index 100% rename from libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/EditorScreen.java rename to libjf-config-ui-tiny/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/EditorScreen.java diff --git a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/Placeholder.java b/libjf-config-ui-tiny/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/Placeholder.java similarity index 100% rename from libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/Placeholder.java rename to libjf-config-ui-tiny/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/Placeholder.java diff --git a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/ScreenWithSaveHook.java b/libjf-config-ui-tiny/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/ScreenWithSaveHook.java similarity index 100% rename from libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/ScreenWithSaveHook.java rename to libjf-config-ui-tiny/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/ScreenWithSaveHook.java diff --git a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/TinyConfigScreen.java b/libjf-config-ui-tiny/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/TinyConfigScreen.java similarity index 97% rename from libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/TinyConfigScreen.java rename to libjf-config-ui-tiny/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/TinyConfigScreen.java index e0f5837..d39d492 100644 --- a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/TinyConfigScreen.java +++ b/libjf-config-ui-tiny/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/TinyConfigScreen.java @@ -2,8 +2,9 @@ package io.gitlab.jfronny.libjf.config.impl.ui.tiny; import io.gitlab.jfronny.commons.throwable.Try; import io.gitlab.jfronny.libjf.LibJf; -import io.gitlab.jfronny.libjf.config.api.v1.ConfigCategory; -import io.gitlab.jfronny.libjf.config.api.v1.dsl.CategoryBuilder; +import io.gitlab.jfronny.libjf.config.api.v2.ConfigCategory; +import io.gitlab.jfronny.libjf.config.api.v2.dsl.CategoryBuilder; +import io.gitlab.jfronny.libjf.config.impl.ConfigCore; import io.gitlab.jfronny.libjf.config.impl.entrypoint.JfConfigSafe; import io.gitlab.jfronny.libjf.config.impl.ui.tiny.entry.EntryListWidget; import io.gitlab.jfronny.libjf.config.impl.ui.tiny.entry.WidgetState; @@ -98,7 +99,7 @@ public class TinyConfigScreen extends ScreenWithSaveHook { this.addDrawableChild(done); if (tabs.size() == 1 && !config.getPresets().isEmpty()) { - this.addDrawableChild(ButtonWidget.builder(Text.translatable("libjf-config-v1.presets"), + this.addDrawableChild(ButtonWidget.builder(Text.translatable(ConfigCore.MOD_ID + ".presets"), button -> Objects.requireNonNull(client).setScreen(new PresetsScreen(this, config, this::afterSelectPreset))) .dimensions(4, 6, 80, 20) .build()); diff --git a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/TinyConfigScreenFactory.java b/libjf-config-ui-tiny/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/TinyConfigScreenFactory.java similarity index 90% rename from libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/TinyConfigScreenFactory.java rename to libjf-config-ui-tiny/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/TinyConfigScreenFactory.java index 9902980..b51421d 100644 --- a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/TinyConfigScreenFactory.java +++ b/libjf-config-ui-tiny/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/TinyConfigScreenFactory.java @@ -2,10 +2,10 @@ package io.gitlab.jfronny.libjf.config.impl.ui.tiny; import io.gitlab.jfronny.commons.serialize.gson.api.v1.GsonHolders; import io.gitlab.jfronny.libjf.LibJf; -import io.gitlab.jfronny.libjf.config.api.v1.ConfigInstance; -import io.gitlab.jfronny.libjf.config.api.v1.EntryInfo; -import io.gitlab.jfronny.libjf.config.api.v1.dsl.CategoryBuilder; -import io.gitlab.jfronny.libjf.config.api.v1.type.Type; +import io.gitlab.jfronny.libjf.config.api.v2.ConfigInstance; +import io.gitlab.jfronny.libjf.config.api.v2.EntryInfo; +import io.gitlab.jfronny.libjf.config.api.v2.dsl.CategoryBuilder; +import io.gitlab.jfronny.libjf.config.api.v2.type.Type; import io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.Screen; @@ -45,8 +45,8 @@ public class TinyConfigScreenFactory implements ConfigScreenFactory new PresetsScreen(screen, config, screen::afterSelectPreset)); } } for (WidgetState info : widgets) { MutableText name = Text.translatable(config.getTranslationPrefix() + info.entry.getName()); WidgetFactory.Widget control = info.factory == null ? null : info.factory.build(screen, textRenderer); - ButtonWidget resetButton = ButtonWidget.builder(Text.translatable("libjf-config-v1.reset"), (button -> info.reset())) + ButtonWidget resetButton = ButtonWidget.builder(Text.translatable(ConfigCore.MOD_ID + ".reset"), (button -> info.reset())) .dimensions(screen.width - 155, 0, 40, 20) .build(); BooleanSupplier resetVisible = () -> { @@ -70,7 +71,7 @@ public class TinyConfigTab implements Tab { } for (ConfigInstance ci : config.getReferencedConfigs()) { if (ci != null) { - this.list.addReference(Text.translatable("libjf-config-v1.see-also", TinyConfigScreen.getTitle(ci.getTranslationPrefix())), + this.list.addReference(Text.translatable(ConfigCore.MOD_ID + ".see-also", TinyConfigScreen.getTitle(ci.getTranslationPrefix())), () -> new TinyConfigScreen(ci, screen)); } } diff --git a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/TinyConfigTabWrapper.java b/libjf-config-ui-tiny/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/TinyConfigTabWrapper.java similarity index 100% rename from libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/TinyConfigTabWrapper.java rename to libjf-config-ui-tiny/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/TinyConfigTabWrapper.java diff --git a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/CustomSlider.java b/libjf-config-ui-tiny/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/CustomSlider.java similarity index 100% rename from libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/CustomSlider.java rename to libjf-config-ui-tiny/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/CustomSlider.java diff --git a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/EntryInfoWidgetBuilder.java b/libjf-config-ui-tiny/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/EntryInfoWidgetBuilder.java similarity index 96% rename from libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/EntryInfoWidgetBuilder.java rename to libjf-config-ui-tiny/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/EntryInfoWidgetBuilder.java index 7613bde..8ce50f4 100644 --- a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/EntryInfoWidgetBuilder.java +++ b/libjf-config-ui-tiny/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/EntryInfoWidgetBuilder.java @@ -4,9 +4,9 @@ import io.gitlab.jfronny.commons.ref.R; import io.gitlab.jfronny.commons.serialize.gson.api.v1.GsonHolders; import io.gitlab.jfronny.commons.throwable.Try; import io.gitlab.jfronny.libjf.LibJf; -import io.gitlab.jfronny.libjf.config.api.v1.ConfigCategory; -import io.gitlab.jfronny.libjf.config.api.v1.EntryInfo; -import io.gitlab.jfronny.libjf.config.api.v1.type.Type; +import io.gitlab.jfronny.libjf.config.api.v2.ConfigCategory; +import io.gitlab.jfronny.libjf.config.api.v2.EntryInfo; +import io.gitlab.jfronny.libjf.config.api.v2.type.Type; import io.gitlab.jfronny.libjf.config.impl.ui.tiny.EditorScreen; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; @@ -156,7 +156,7 @@ public class EntryInfoWidgetBuilder { state.managedTemp = false; state.tempValue = null; return (screen, textRenderer) -> { - final ButtonWidget button = ButtonWidget.builder(Text.translatable("libjf-config-core-v1.edit"), $ -> { + final ButtonWidget button = ButtonWidget.builder(Text.translatable("libjf-config-core-v2.edit"), $ -> { final String jsonified; if (state.tempValue == null) { try { @@ -166,8 +166,8 @@ public class EntryInfoWidgetBuilder { SystemToast.add( screen.getClient().getToastManager(), SystemToast.Type.PACK_LOAD_FAILURE, - Text.translatable("libjf-config-ui-tiny-v1.entry.json.read.fail.title"), - Text.translatable("libjf-config-ui-tiny-v1.entry.json.read.fail.description") + Text.translatable("libjf-config-ui-tiny.entry.json.read.fail.title"), + Text.translatable("libjf-config-ui-tiny.entry.json.read.fail.description") ); return; } @@ -189,8 +189,8 @@ public class EntryInfoWidgetBuilder { SystemToast.add( screen.getClient().getToastManager(), SystemToast.Type.PACK_LOAD_FAILURE, - Text.translatable("libjf-config-ui-tiny-v1.entry.json.write.fail.title"), - Text.translatable("libjf-config-ui-tiny-v1.entry.json.write.fail.description") + Text.translatable("libjf-config-ui-tiny.entry.json.write.fail.title"), + Text.translatable("libjf-config-ui-tiny.entry.json.write.fail.description") ); state.tempValue = json; } diff --git a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/EntryListWidget.java b/libjf-config-ui-tiny/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/EntryListWidget.java similarity index 100% rename from libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/EntryListWidget.java rename to libjf-config-ui-tiny/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/EntryListWidget.java diff --git a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/Reflowable.java b/libjf-config-ui-tiny/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/Reflowable.java similarity index 100% rename from libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/Reflowable.java rename to libjf-config-ui-tiny/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/Reflowable.java diff --git a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/WidgetFactory.java b/libjf-config-ui-tiny/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/WidgetFactory.java similarity index 100% rename from libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/WidgetFactory.java rename to libjf-config-ui-tiny/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/WidgetFactory.java diff --git a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/WidgetState.java b/libjf-config-ui-tiny/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/WidgetState.java similarity index 96% rename from libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/WidgetState.java rename to libjf-config-ui-tiny/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/WidgetState.java index d4f45fe..8044c72 100644 --- a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/WidgetState.java +++ b/libjf-config-ui-tiny/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/WidgetState.java @@ -2,7 +2,7 @@ package io.gitlab.jfronny.libjf.config.impl.ui.tiny.entry; import io.gitlab.jfronny.commons.ref.R; import io.gitlab.jfronny.libjf.LibJf; -import io.gitlab.jfronny.libjf.config.api.v1.EntryInfo; +import io.gitlab.jfronny.libjf.config.api.v2.EntryInfo; import net.minecraft.text.Text; import org.jetbrains.annotations.Nullable; diff --git a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/presets/PresetListWidget.java b/libjf-config-ui-tiny/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/presets/PresetListWidget.java similarity index 100% rename from libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/presets/PresetListWidget.java rename to libjf-config-ui-tiny/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/presets/PresetListWidget.java diff --git a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/presets/PresetsScreen.java b/libjf-config-ui-tiny/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/presets/PresetsScreen.java similarity index 91% rename from libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/presets/PresetsScreen.java rename to libjf-config-ui-tiny/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/presets/PresetsScreen.java index 09d3ef9..28db33f 100644 --- a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/presets/PresetsScreen.java +++ b/libjf-config-ui-tiny/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/presets/PresetsScreen.java @@ -1,7 +1,8 @@ package io.gitlab.jfronny.libjf.config.impl.ui.tiny.presets; import io.gitlab.jfronny.libjf.LibJf; -import io.gitlab.jfronny.libjf.config.api.v1.ConfigCategory; +import io.gitlab.jfronny.libjf.config.api.v2.ConfigCategory; +import io.gitlab.jfronny.libjf.config.impl.ConfigCore; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.gui.DrawContext; @@ -19,7 +20,7 @@ public class PresetsScreen extends Screen { private final Runnable afterSelect; public PresetsScreen(Screen parent, ConfigCategory config, Runnable afterSelect) { - super(Text.translatable("libjf-config-v1.presets")); + super(Text.translatable(ConfigCore.MOD_ID + ".presets")); this.parent = parent; this.config = config; this.afterSelect = afterSelect; diff --git a/libjf-config-ui-tiny/src/client/resources/assets/libjf-config-ui-tiny/lang/en_us.json b/libjf-config-ui-tiny/src/client/resources/assets/libjf-config-ui-tiny/lang/en_us.json new file mode 100644 index 0000000..1bd4da7 --- /dev/null +++ b/libjf-config-ui-tiny/src/client/resources/assets/libjf-config-ui-tiny/lang/en_us.json @@ -0,0 +1,4 @@ +{ + "libjf-config-ui-tiny.entry.json.read.fail.title": "Could not read", + "libjf-config-ui-tiny.entry.json.read.fail.description": "The given entry could not be stringified. Please edit the config manually" +} \ No newline at end of file diff --git a/libjf-config-ui-tiny-v1/src/main/resources/fabric.mod.json b/libjf-config-ui-tiny/src/main/resources/fabric.mod.json similarity index 90% rename from libjf-config-ui-tiny-v1/src/main/resources/fabric.mod.json rename to libjf-config-ui-tiny/src/main/resources/fabric.mod.json index a1ff522..65c4e50 100644 --- a/libjf-config-ui-tiny-v1/src/main/resources/fabric.mod.json +++ b/libjf-config-ui-tiny/src/main/resources/fabric.mod.json @@ -1,6 +1,6 @@ { "schemaVersion": 1, - "id": "libjf-config-ui-tiny-v1", + "id": "libjf-config-ui-tiny", "name": "LibJF Config UI: Tiny", "version": "${version}", "authors": ["JFronny"], @@ -20,7 +20,7 @@ "minecraft": "*", "fabric-resource-loader-v0": "*", "libjf-base": ">=${version}", - "libjf-config-core-v1": ">=${version}" + "libjf-config-core-v2": ">=${version}" }, "custom": { "modmenu": { diff --git a/libjf-config-ui-tiny-v1/src/testmod/java/io/gitlab/jfronny/libjf/config/test/tiny/TestConfig.java b/libjf-config-ui-tiny/src/testmod/java/io/gitlab/jfronny/libjf/config/test/tiny/TestConfig.java similarity index 91% rename from libjf-config-ui-tiny-v1/src/testmod/java/io/gitlab/jfronny/libjf/config/test/tiny/TestConfig.java rename to libjf-config-ui-tiny/src/testmod/java/io/gitlab/jfronny/libjf/config/test/tiny/TestConfig.java index 6238207..ef92773 100644 --- a/libjf-config-ui-tiny-v1/src/testmod/java/io/gitlab/jfronny/libjf/config/test/tiny/TestConfig.java +++ b/libjf-config-ui-tiny/src/testmod/java/io/gitlab/jfronny/libjf/config/test/tiny/TestConfig.java @@ -1,7 +1,7 @@ package io.gitlab.jfronny.libjf.config.test.tiny; -import io.gitlab.jfronny.libjf.config.api.v1.JfCustomConfig; -import io.gitlab.jfronny.libjf.config.api.v1.dsl.DSL; +import io.gitlab.jfronny.libjf.config.api.v2.JfCustomConfig; +import io.gitlab.jfronny.libjf.config.api.v2.dsl.DSL; public class TestConfig implements JfCustomConfig { private int value1 = 0; diff --git a/libjf-config-ui-tiny-v1/src/testmod/java/io/gitlab/jfronny/libjf/config/test/tiny/mixin/OptionsScreenMixin.java b/libjf-config-ui-tiny/src/testmod/java/io/gitlab/jfronny/libjf/config/test/tiny/mixin/OptionsScreenMixin.java similarity index 96% rename from libjf-config-ui-tiny-v1/src/testmod/java/io/gitlab/jfronny/libjf/config/test/tiny/mixin/OptionsScreenMixin.java rename to libjf-config-ui-tiny/src/testmod/java/io/gitlab/jfronny/libjf/config/test/tiny/mixin/OptionsScreenMixin.java index d6c34f2..e195779 100644 --- a/libjf-config-ui-tiny-v1/src/testmod/java/io/gitlab/jfronny/libjf/config/test/tiny/mixin/OptionsScreenMixin.java +++ b/libjf-config-ui-tiny/src/testmod/java/io/gitlab/jfronny/libjf/config/test/tiny/mixin/OptionsScreenMixin.java @@ -1,6 +1,6 @@ package io.gitlab.jfronny.libjf.config.test.tiny.mixin; -import io.gitlab.jfronny.libjf.config.api.v1.ConfigHolder; +import io.gitlab.jfronny.libjf.config.api.v2.ConfigHolder; import io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.option.OptionsScreen; diff --git a/libjf-config-ui-tiny/src/testmod/resources/assets/libjf-config-ui-tiny-testmod/lang/en_us.json b/libjf-config-ui-tiny/src/testmod/resources/assets/libjf-config-ui-tiny-testmod/lang/en_us.json new file mode 100644 index 0000000..82fd1d0 --- /dev/null +++ b/libjf-config-ui-tiny/src/testmod/resources/assets/libjf-config-ui-tiny-testmod/lang/en_us.json @@ -0,0 +1,21 @@ +{ + "libjf-config-ui-tiny-testmod.jfconfig.title": "JfConfig example", + "libjf-config-ui-tiny-testmod.jfconfig.ca1.title": "Category 1", + "libjf-config-ui-tiny-testmod.jfconfig.ca1.tooltip": "This is category 1\nIt has an excessively long description to test multiline descriptions and wrapping, which are required for this to look good.\nThis is supported btw.", + "libjf-config-ui-tiny-testmod.jfconfig.ca1.value1": "Value 1", + "libjf-config-ui-tiny-testmod.jfconfig.ca2.title": "Category 2", + "libjf-config-ui-tiny-testmod.jfconfig.ca2.tooltip": "This is category 2", + "libjf-config-ui-tiny-testmod.jfconfig.ca2.value2": "Value 2", + "libjf-config-ui-tiny-testmod.jfconfig.ca3.title": "Category 3", + "libjf-config-ui-tiny-testmod.jfconfig.ca3.tooltip": "This is category 3", + "libjf-config-ui-tiny-testmod.jfconfig.ca3.value3": "Value 3", + "libjf-config-ui-tiny-testmod.jfconfig.ca4.title": "Category 4", + "libjf-config-ui-tiny-testmod.jfconfig.ca4.tooltip": "This is category 4", + "libjf-config-ui-tiny-testmod.jfconfig.ca4.value4": "Value 4", + "libjf-config-ui-tiny-testmod.jfconfig.ca5.title": "Category 5", + "libjf-config-ui-tiny-testmod.jfconfig.ca5.tooltip": "This is category 5", + "libjf-config-ui-tiny-testmod.jfconfig.ca5.value5": "Value 5", + "libjf-config-ui-tiny-testmod.jfconfig.ca6.title": "Category 6", + "libjf-config-ui-tiny-testmod.jfconfig.ca6.tooltip": "This is category 6", + "libjf-config-ui-tiny-testmod.jfconfig.ca6.value6": "Value 6" +} \ No newline at end of file diff --git a/libjf-config-ui-tiny-v1/src/testmod/resources/fabric.mod.json b/libjf-config-ui-tiny/src/testmod/resources/fabric.mod.json similarity index 73% rename from libjf-config-ui-tiny-v1/src/testmod/resources/fabric.mod.json rename to libjf-config-ui-tiny/src/testmod/resources/fabric.mod.json index 53546bd..d7c5c53 100644 --- a/libjf-config-ui-tiny-v1/src/testmod/resources/fabric.mod.json +++ b/libjf-config-ui-tiny/src/testmod/resources/fabric.mod.json @@ -1,10 +1,10 @@ { "schemaVersion": 1, - "id": "libjf-config-ui-tiny-v1-testmod", + "id": "libjf-config-ui-tiny-testmod", "name": "LibJF Config UI: Tiny", "version": "1.0", "environment": "*", - "mixins": ["libjf-config-ui-tiny-v1-testmod.mixins.json"], + "mixins": ["libjf-config-ui-tiny-testmod.mixins.json"], "entrypoints": { "libjf:config": [ "io.gitlab.jfronny.libjf.config.test.tiny.TestConfig" diff --git a/libjf-config-ui-tiny-v1/src/testmod/resources/libjf-config-ui-tiny-v1-testmod.mixins.json b/libjf-config-ui-tiny/src/testmod/resources/libjf-config-ui-tiny-testmod.mixins.json similarity index 100% rename from libjf-config-ui-tiny-v1/src/testmod/resources/libjf-config-ui-tiny-v1-testmod.mixins.json rename to libjf-config-ui-tiny/src/testmod/resources/libjf-config-ui-tiny-testmod.mixins.json diff --git a/libjf-translate-v1/build.gradle.kts b/libjf-translate-v1/build.gradle.kts index 2bbd137..3e400d0 100644 --- a/libjf-translate-v1/build.gradle.kts +++ b/libjf-translate-v1/build.gradle.kts @@ -10,5 +10,5 @@ base { dependencies { api(devProject(":libjf-base")) - api(devProject(":libjf-config-core-v1")) + api(devProject(":libjf-config-core-v2")) } diff --git a/libjf-translate-v1/src/main/java/io/gitlab/jfronny/libjf/translate/impl/TranslateConfig.java b/libjf-translate-v1/src/main/java/io/gitlab/jfronny/libjf/translate/impl/TranslateConfig.java index 9a93c47..329f80a 100644 --- a/libjf-translate-v1/src/main/java/io/gitlab/jfronny/libjf/translate/impl/TranslateConfig.java +++ b/libjf-translate-v1/src/main/java/io/gitlab/jfronny/libjf/translate/impl/TranslateConfig.java @@ -1,7 +1,7 @@ package io.gitlab.jfronny.libjf.translate.impl; -import io.gitlab.jfronny.libjf.config.api.v1.JfCustomConfig; -import io.gitlab.jfronny.libjf.config.api.v1.dsl.DSL; +import io.gitlab.jfronny.libjf.config.api.v2.JfCustomConfig; +import io.gitlab.jfronny.libjf.config.api.v2.dsl.DSL; import io.gitlab.jfronny.libjf.translate.api.TranslateService; import io.gitlab.jfronny.libjf.translate.impl.google.GoogleTranslateService; import io.gitlab.jfronny.libjf.translate.impl.libretranslate.LibreTranslateService; diff --git a/libjf-web-v0/build.gradle.kts b/libjf-web-v0/build.gradle.kts index ed9bac7..c5e453a 100644 --- a/libjf-web-v0/build.gradle.kts +++ b/libjf-web-v0/build.gradle.kts @@ -11,7 +11,7 @@ base { dependencies { val fabricVersion: String by rootProject.extra api(devProject(":libjf-base")) - api(devProject(":libjf-config-core-v1")) + api(devProject(":libjf-config-core-v2")) include(modImplementation(fabricApi.module("fabric-command-api-v2", fabricVersion))!!) annotationProcessor(project(":libjf-config-compiler-plugin-v2")) diff --git a/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/JfWebConfig.java b/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/JfWebConfig.java index 424dad3..3d1e3b7 100644 --- a/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/JfWebConfig.java +++ b/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/JfWebConfig.java @@ -1,7 +1,7 @@ package io.gitlab.jfronny.libjf.web.impl; import io.gitlab.jfronny.libjf.LibJf; -import io.gitlab.jfronny.libjf.config.api.v1.*; +import io.gitlab.jfronny.libjf.config.api.v2.*; import java.io.IOException; import java.net.ServerSocket; diff --git a/libjf-web-v0/src/main/resources/fabric.mod.json b/libjf-web-v0/src/main/resources/fabric.mod.json index 59e1042..d9bb8e4 100644 --- a/libjf-web-v0/src/main/resources/fabric.mod.json +++ b/libjf-web-v0/src/main/resources/fabric.mod.json @@ -23,7 +23,7 @@ "fabricloader": ">=0.12.0", "minecraft": "*", "libjf-base": ">=${version}", - "libjf-config-core-v1": ">=${version}", + "libjf-config-core-v2": ">=${version}", "fabric-command-api-v2": "*" }, "custom": { diff --git a/settings.gradle.kts b/settings.gradle.kts index 2f8c2cd..db592b1 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -14,10 +14,9 @@ rootProject.name = "libjf" include("libjf-base") -include("libjf-config-core-v1") -include("libjf-config-reflect-v1") -include("libjf-config-commands-v1") -include("libjf-config-ui-tiny-v1") +include("libjf-config-core-v2") +include("libjf-config-commands") +include("libjf-config-ui-tiny") include("libjf-data-v0") include("libjf-data-manipulation-v0") include("libjf-devutil") From f54f8d59c4eda19100a5237076b3df624c92dcec Mon Sep 17 00:00:00 2001 From: JFronny Date: Wed, 30 Aug 2023 17:24:14 +0200 Subject: [PATCH 5/7] feat(web): support hosting on game port --- build.gradle.kts | 2 +- docs/SUMMARY.md | 2 +- docs/{libjf-web-v0.md => libjf-web-v1.md} | 6 +- .../libjf/coprocess/CoProcessManager.java | 7 +- .../jfronny/libjf/config/impl/ConfigCore.java | 2 + .../src/main/resources/fabric.mod.json | 1 + .../libjf/web/api/ContentProvider.java | 10 - .../jfronny/libjf/web/api/SubServer.java | 10 - .../impl/util/bluemapcore/HttpRequest.java | 231 ---------------- .../assets/libjf-web-v0/lang/en_us.json | 13 - .../build.gradle.kts | 2 +- .../libjf/web/api/v1}/AdvancedSubServer.java | 2 +- .../libjf/web/api/v1/ContentProvider.java | 7 + .../jfronny/libjf/web/api/v1/HttpRequest.java | 30 +++ .../libjf/web/api/v1/HttpResponse.java | 24 ++ .../libjf/web/api/v1}/HttpStatusCode.java | 2 +- .../jfronny/libjf/web/api/v1/SubServer.java | 7 + .../jfronny/libjf/web/api/v1}/WebInit.java | 2 +- .../jfronny/libjf/web/api/v1}/WebServer.java | 8 +- .../libjf/web/impl/DefaultFileHost.java | 4 +- .../gitlab/jfronny/libjf/web/impl/JfWeb.java | 32 ++- .../jfronny/libjf/web/impl/JfWebConfig.java | 19 +- .../libjf/web/impl/RequestHandler.java | 17 +- .../web/impl/mixin/JfWebMixinPlugin.java | 47 ++++ .../impl/mixin/ServerNetworkIo$1Mixin.java | 16 ++ .../web/impl/mixin/ServerNetworkIoMixin.java | 30 +++ .../libjf/web/impl/util/ClaimPool.java | 37 +++ .../libjf/web/impl/util/HttpRequestImpl.java | 249 ++++++++++++++++++ .../libjf/web/impl/util/HttpResponseImpl.java | 51 +++- .../jfronny/libjf/web/impl/util/WebPaths.java | 8 + .../web/impl/variant/AbstractWebServer.java | 102 ++----- .../impl/variant/hosted/HostedWebServer.java | 64 +++++ .../impl/variant/hosted}/HttpConnection.java | 12 +- .../variant/hosted}/HttpRequestHandler.java | 7 +- .../web/impl/variant/hosted}/HttpServer.java | 2 +- .../web/impl/variant/shared/HttpDecoder.java | 68 +++++ .../impl/variant/shared/SharedWebServer.java | 51 ++++ .../libjf/web/impl/variant/shared/Trie.java | 38 +++ .../assets/libjf-web-v1/lang/en_us.json | 13 + .../src/main/resources/fabric.mod.json | 4 +- .../main/resources/libjf-web-v1.mixins.json | 14 + .../jfronny/libjf/web/test/WebTest.java | 13 +- .../src/testmod/resources/fabric.mod.json | 2 +- .../src/testmod/resources/test.html | 0 settings.gradle.kts | 2 +- 45 files changed, 863 insertions(+), 407 deletions(-) rename docs/{libjf-web-v0.md => libjf-web-v1.md} (82%) delete mode 100644 libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/api/ContentProvider.java delete mode 100644 libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/api/SubServer.java delete mode 100644 libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/bluemapcore/HttpRequest.java delete mode 100644 libjf-web-v0/src/main/resources/assets/libjf-web-v0/lang/en_us.json rename {libjf-web-v0 => libjf-web-v1}/build.gradle.kts (92%) rename {libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/api => libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1}/AdvancedSubServer.java (68%) create mode 100644 libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/ContentProvider.java create mode 100644 libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/HttpRequest.java create mode 100644 libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/HttpResponse.java rename {libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/bluemapcore => libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1}/HttpStatusCode.java (97%) create mode 100644 libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/SubServer.java rename {libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/api => libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1}/WebInit.java (59%) rename {libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/api => libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1}/WebServer.java (73%) rename {libjf-web-v0 => libjf-web-v1}/src/main/java/io/gitlab/jfronny/libjf/web/impl/DefaultFileHost.java (88%) rename {libjf-web-v0 => libjf-web-v1}/src/main/java/io/gitlab/jfronny/libjf/web/impl/JfWeb.java (65%) rename {libjf-web-v0 => libjf-web-v1}/src/main/java/io/gitlab/jfronny/libjf/web/impl/JfWebConfig.java (62%) rename {libjf-web-v0 => libjf-web-v1}/src/main/java/io/gitlab/jfronny/libjf/web/impl/RequestHandler.java (75%) create mode 100644 libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/mixin/JfWebMixinPlugin.java create mode 100644 libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/mixin/ServerNetworkIo$1Mixin.java create mode 100644 libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/mixin/ServerNetworkIoMixin.java create mode 100644 libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/ClaimPool.java create mode 100644 libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/HttpRequestImpl.java rename libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/bluemapcore/HttpResponse.java => libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/HttpResponseImpl.java (73%) rename {libjf-web-v0 => libjf-web-v1}/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/WebPaths.java (89%) rename libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/JfWebServer.java => libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/AbstractWebServer.java (66%) create mode 100644 libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/hosted/HostedWebServer.java rename {libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/bluemapcore => libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/hosted}/HttpConnection.java (90%) rename {libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/bluemapcore => libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/hosted}/HttpRequestHandler.java (82%) rename {libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/bluemapcore => libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/hosted}/HttpServer.java (98%) create mode 100644 libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/shared/HttpDecoder.java create mode 100644 libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/shared/SharedWebServer.java create mode 100644 libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/shared/Trie.java create mode 100644 libjf-web-v1/src/main/resources/assets/libjf-web-v1/lang/en_us.json rename {libjf-web-v0 => libjf-web-v1}/src/main/resources/fabric.mod.json (90%) create mode 100644 libjf-web-v1/src/main/resources/libjf-web-v1.mixins.json rename {libjf-web-v0 => libjf-web-v1}/src/testmod/java/io/gitlab/jfronny/libjf/web/test/WebTest.java (60%) rename {libjf-web-v0 => libjf-web-v1}/src/testmod/resources/fabric.mod.json (90%) rename {libjf-web-v0 => libjf-web-v1}/src/testmod/resources/test.html (100%) diff --git a/build.gradle.kts b/build.gradle.kts index 5336942..9e94fa2 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -16,7 +16,7 @@ val javapoetVersion by extra("1.13.0") jfMod { minecraftVersion = "23w33a" - yarn("build.3") + yarn("build.7") loaderVersion = "0.14.22" modrinth { diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index b24fe64..6a73656 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -15,4 +15,4 @@ - [libjf-data-manipulation-v0](./libjf-data-manipulation-v0.md) - [libjf-translate-v1](./libjf-translate-v1.md) - [libjf-unsafe-v0](./libjf-unsafe-v0.md) -- [libjf-web-v0](./libjf-web-v0.md) \ No newline at end of file +- [libjf-web-v1](./libjf-web-v1.md) \ No newline at end of file diff --git a/docs/libjf-web-v0.md b/docs/libjf-web-v1.md similarity index 82% rename from docs/libjf-web-v0.md rename to docs/libjf-web-v1.md index b71a110..5a9e1b3 100644 --- a/docs/libjf-web-v0.md +++ b/docs/libjf-web-v1.md @@ -1,7 +1,7 @@ -# libjf-web-v0 -libjf-web-v0 provides an HTTP web server you can use in your serverside (and technically also clientside) mods +# libjf-web-v1 +libjf-web-v1 provides an HTTP web server you can use in your serverside (and technically also clientside) mods to serve web content through a unified port. -libjf-web-v0 depends on libjf-config-core-v2 to provide its config, libjf-base, fabric-lifecycle-events-v1 and fabric-command-api-v1 +libjf-web-v1 depends on libjf-config-core-v2 to provide its config, libjf-base, fabric-lifecycle-events-v1 and fabric-command-api-v1 ### Getting started Implement WebInit and register it as a libjf:web entrypoint. To enable the server, also add the following to your fabric.mod.json: diff --git a/libjf-base/src/main/java/io/gitlab/jfronny/libjf/coprocess/CoProcessManager.java b/libjf-base/src/main/java/io/gitlab/jfronny/libjf/coprocess/CoProcessManager.java index 06127c0..7023655 100644 --- a/libjf-base/src/main/java/io/gitlab/jfronny/libjf/coprocess/CoProcessManager.java +++ b/libjf-base/src/main/java/io/gitlab/jfronny/libjf/coprocess/CoProcessManager.java @@ -27,9 +27,8 @@ public class CoProcessManager implements ModInitializer { } private void stop() { - Iterator procs = coProcesses.iterator(); - while (procs.hasNext()) { - CoProcess coProcess = procs.next(); + for (Iterator iter = coProcesses.iterator(); iter.hasNext(); ) { + CoProcess coProcess = iter.next(); coProcess.stop(); if (coProcess instanceof Closeable cl) { try { @@ -38,7 +37,7 @@ public class CoProcessManager implements ModInitializer { LibJf.LOGGER.error("Could not close co-process", e); } } - procs.remove(); + iter.remove(); } } } diff --git a/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/ConfigCore.java b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/ConfigCore.java index fd97734..75112d0 100644 --- a/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/ConfigCore.java +++ b/libjf-config-core-v2/src/main/java/io/gitlab/jfronny/libjf/config/impl/ConfigCore.java @@ -1,5 +1,6 @@ package io.gitlab.jfronny.libjf.config.impl; +import io.gitlab.jfronny.libjf.config.api.v2.ConfigHolder; import io.gitlab.jfronny.libjf.config.api.v2.ConfigInstance; import io.gitlab.jfronny.libjf.config.api.v2.dsl.DSL; @@ -10,6 +11,7 @@ public class ConfigCore { public static final ConfigInstance CONFIG_INSTANCE; static { + ConfigHolder.getInstance().migrateFiles(MOD_ID); CONFIG_INSTANCE = DSL.create(MOD_ID).register(builder -> builder .value("watchForChanges", watchForChanges, () -> watchForChanges, b -> watchForChanges = b) ); diff --git a/libjf-config-core-v2/src/main/resources/fabric.mod.json b/libjf-config-core-v2/src/main/resources/fabric.mod.json index 624a8b6..3a54a89 100644 --- a/libjf-config-core-v2/src/main/resources/fabric.mod.json +++ b/libjf-config-core-v2/src/main/resources/fabric.mod.json @@ -1,6 +1,7 @@ { "schemaVersion": 1, "id": "libjf-config-core-v2", + "provides": ["libjf-config-core-v1"], "name": "LibJF Config", "version": "${version}", "authors": ["JFronny"], diff --git a/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/api/ContentProvider.java b/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/api/ContentProvider.java deleted file mode 100644 index 1687919..0000000 --- a/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/api/ContentProvider.java +++ /dev/null @@ -1,10 +0,0 @@ -package io.gitlab.jfronny.libjf.web.api; - -import io.gitlab.jfronny.libjf.web.impl.util.bluemapcore.HttpRequest; -import io.gitlab.jfronny.libjf.web.impl.util.bluemapcore.HttpResponse; - -import java.io.IOException; - -public interface ContentProvider { - HttpResponse handle(HttpRequest request) throws IOException; -} diff --git a/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/api/SubServer.java b/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/api/SubServer.java deleted file mode 100644 index 15c6d76..0000000 --- a/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/api/SubServer.java +++ /dev/null @@ -1,10 +0,0 @@ -package io.gitlab.jfronny.libjf.web.api; - -import io.gitlab.jfronny.libjf.web.impl.util.bluemapcore.HttpRequest; -import io.gitlab.jfronny.libjf.web.impl.util.bluemapcore.HttpResponse; - -import java.io.IOException; - -public interface SubServer { - HttpResponse handle(HttpRequest request, String[] segments) throws IOException; -} diff --git a/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/bluemapcore/HttpRequest.java b/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/bluemapcore/HttpRequest.java deleted file mode 100644 index 6e3a09d..0000000 --- a/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/bluemapcore/HttpRequest.java +++ /dev/null @@ -1,231 +0,0 @@ -/* - * This file is part of BlueMap, licensed under the MIT License (MIT). - * - * Copyright (c) Blue (Lukas Rieger) - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package io.gitlab.jfronny.libjf.web.impl.util.bluemapcore; - -import java.io.*; -import java.nio.charset.StandardCharsets; -import java.util.*; -import java.util.Map.Entry; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class HttpRequest { - - private static final Pattern REQUEST_PATTERN = Pattern.compile("^(\\w+) (\\S+) (.+)$"); - - private final String method; - private final String adress; - private final String version; - private final Map> header; - private final Map> headerLC; - private byte[] data; - - private String path = null; - private Map getParams = null; - private String getParamString = null; - - public HttpRequest(String method, String adress, String version, Map> header) { - this.method = method; - this.adress = adress; - this.version = version; - this.header = header; - this.headerLC = new HashMap<>(); - - for (Entry> e : header.entrySet()){ - Set values = new HashSet<>(); - for (String v : e.getValue()){ - values.add(v.toLowerCase()); - } - - headerLC.put(e.getKey().toLowerCase(), values); - } - - this.data = new byte[0]; - } - - public String getMethod() { - return method; - } - - public String getAdress(){ - return adress; - } - - public String getVersion() { - return version; - } - - public Map> getHeader() { - return header; - } - - public Map> getLowercaseHeader() { - return headerLC; - } - - public Set getHeader(String key){ - Set headerValues = header.get(key); - if (headerValues == null) return Collections.emptySet(); - return headerValues; - } - - public Set getLowercaseHeader(String key){ - Set headerValues = headerLC.get(key.toLowerCase()); - if (headerValues == null) return Collections.emptySet(); - return headerValues; - } - - public String getPath() { - if (path == null) parseAdress(); - return path; - } - - public Map getGETParams() { - if (getParams == null) parseAdress(); - return Collections.unmodifiableMap(getParams); - } - - public String getGETParamString() { - if (getParamString == null) parseAdress(); - return getParamString; - } - - private void parseAdress() { - String adress = this.adress; - if (adress.isEmpty()) adress = "/"; - String[] adressParts = adress.split("\\?", 2); - String path = adressParts[0]; - this.getParamString = adressParts.length > 1 ? adressParts[1] : ""; - - Map getParams = new HashMap<>(); - for (String getParam : this.getParamString.split("&")){ - if (getParam.isEmpty()) continue; - String[] kv = getParam.split("=", 2); - String key = kv[0]; - String value = kv.length > 1 ? kv[1] : ""; - getParams.put(key, value); - } - - this.path = path; - this.getParams = getParams; - } - - public InputStream getData(){ - return new ByteArrayInputStream(data); - } - - public static HttpRequest read(InputStream in) throws IOException { - BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8)); - List header = new ArrayList<>(20); - while(header.size() < 1000){ - String headerLine = readLine(reader); - if (headerLine.isEmpty()) break; - header.add(headerLine); - } - - if (header.isEmpty()) throw new HttpConnection.InvalidRequestException(); - - Matcher m = REQUEST_PATTERN.matcher(header.remove(0)); - if (!m.find()) throw new HttpConnection.InvalidRequestException(); - - String method = m.group(1); - if (method == null) throw new HttpConnection.InvalidRequestException(); - - String adress = m.group(2); - if (adress == null) throw new HttpConnection.InvalidRequestException(); - - String version = m.group(3); - if (version == null) throw new HttpConnection.InvalidRequestException(); - - Map> headerMap = new HashMap>(); - for (String line : header){ - if (line.trim().isEmpty()) continue; - - String[] kv = line.split(":", 2); - if (kv.length < 2) continue; - - Set values = new HashSet<>(); - if (kv[0].trim().equalsIgnoreCase("If-Modified-Since")){ - values.add(kv[1].trim()); - } else { - for(String v : kv[1].split(",")){ - values.add(v.trim()); - } - } - - headerMap.put(kv[0].trim(), values); - } - - HttpRequest request = new HttpRequest(method, adress, version, headerMap); - - if (request.getLowercaseHeader("Transfer-Encoding").contains("chunked")){ - try { - ByteArrayOutputStream dataStream = new ByteArrayOutputStream(); - while (dataStream.size() < 1000000){ - String hexSize = reader.readLine(); - int chunkSize = Integer.parseInt(hexSize, 16); - if (chunkSize <= 0) break; - byte[] data = new byte[chunkSize]; - in.read(data); - dataStream.write(data); - } - - if (dataStream.size() >= 1000000) { - throw new HttpConnection.InvalidRequestException(); - } - - request.data = dataStream.toByteArray(); - - return request; - } catch (NumberFormatException ex){ - return request; - } - } else { - Set clSet = request.getLowercaseHeader("Content-Length"); - if (clSet.isEmpty()){ - return request; - } else { - try { - int cl = Integer.parseInt(clSet.iterator().next()); - byte[] data = new byte[cl]; - in.read(data); - request.data = data; - return request; - } catch (NumberFormatException ex){ - return request; - } - } - } - } - - private static String readLine(BufferedReader in) throws IOException { - String line = in.readLine(); - if (line == null){ - throw new HttpConnection.ConnectionClosedException(); - } - return line; - } - -} diff --git a/libjf-web-v0/src/main/resources/assets/libjf-web-v0/lang/en_us.json b/libjf-web-v0/src/main/resources/assets/libjf-web-v0/lang/en_us.json deleted file mode 100644 index 38a4c7b..0000000 --- a/libjf-web-v0/src/main/resources/assets/libjf-web-v0/lang/en_us.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "libjf-web-v0.jfconfig.title": "LibJF Web v0", - "libjf-web-v0.jfconfig.serverIp": "Server IP", - "libjf-web-v0.jfconfig.serverIp.tooltip": "The public IP/host name to send to clients", - "libjf-web-v0.jfconfig.port": "Port", - "libjf-web-v0.jfconfig.port.tooltip": "The port to host content on", - "libjf-web-v0.jfconfig.portOverride": "Port Override", - "libjf-web-v0.jfconfig.portOverride.tooltip": "The port to send to clients (for reverse proxies, -1 to disable)", - "libjf-web-v0.jfconfig.maxConnections": "Max. Connections", - "libjf-web-v0.jfconfig.maxConnections.tooltip": "The maximum number of concurrent connections to this server", - "libjf-web-v0.jfconfig.enableFileHost": "Enable File Host", - "libjf-web-v0.jfconfig.enableFileHost.tooltip": "Whether files from config/wwwroot should be hosted as static resources" -} \ No newline at end of file diff --git a/libjf-web-v0/build.gradle.kts b/libjf-web-v1/build.gradle.kts similarity index 92% rename from libjf-web-v0/build.gradle.kts rename to libjf-web-v1/build.gradle.kts index c5e453a..b83d6a5 100644 --- a/libjf-web-v0/build.gradle.kts +++ b/libjf-web-v1/build.gradle.kts @@ -5,7 +5,7 @@ plugins { } base { - archivesName.set("libjf-web-v0") + archivesName.set("libjf-web-v1") } dependencies { diff --git a/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/api/AdvancedSubServer.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/AdvancedSubServer.java similarity index 68% rename from libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/api/AdvancedSubServer.java rename to libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/AdvancedSubServer.java index b570904..9748540 100644 --- a/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/api/AdvancedSubServer.java +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/AdvancedSubServer.java @@ -1,4 +1,4 @@ -package io.gitlab.jfronny.libjf.web.api; +package io.gitlab.jfronny.libjf.web.api.v1; public interface AdvancedSubServer extends SubServer { void onStop(); diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/ContentProvider.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/ContentProvider.java new file mode 100644 index 0000000..72d99e5 --- /dev/null +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/ContentProvider.java @@ -0,0 +1,7 @@ +package io.gitlab.jfronny.libjf.web.api.v1; + +import java.io.IOException; + +public interface ContentProvider { + HttpResponse handle(HttpRequest request) throws IOException; +} diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/HttpRequest.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/HttpRequest.java new file mode 100644 index 0000000..39f260c --- /dev/null +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/HttpRequest.java @@ -0,0 +1,30 @@ +package io.gitlab.jfronny.libjf.web.api.v1; + +import io.gitlab.jfronny.libjf.web.impl.util.HttpRequestImpl; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; +import java.util.Set; + +public interface HttpRequest { + static HttpRequest read(InputStream in) throws IOException { + return HttpRequestImpl.read(in); + } + + default HttpResponse createResponse(HttpStatusCode statusCode) { + return HttpResponse.create(statusCode); + } + + String getMethod(); + String getAddress(); + String getVersion(); + Map> getHeader(); + Map> getLowercaseHeader(); + Set getHeader(String key); + Set getLowercaseHeader(String key); + String getPath(); + Map getQuery(); + String getQueryString(); + InputStream getData(); +} diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/HttpResponse.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/HttpResponse.java new file mode 100644 index 0000000..7020775 --- /dev/null +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/HttpResponse.java @@ -0,0 +1,24 @@ +package io.gitlab.jfronny.libjf.web.api.v1; + +import io.gitlab.jfronny.libjf.web.impl.util.HttpResponseImpl; + +import java.io.*; +import java.util.Map; +import java.util.Set; + +public interface HttpResponse extends Closeable { + static HttpResponse create(HttpStatusCode statusCode) { + return new HttpResponseImpl(statusCode); + } + + HttpResponse addHeader(String key, String value); + HttpResponse removeHeader(String key, String value); + HttpResponse setData(InputStream data); + HttpResponse setData(String data); + void write(OutputStream out) throws IOException; + + HttpStatusCode getStatusCode(); + String getVersion(); + Map> getHeader(); + Set getHeader(String key); +} diff --git a/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/bluemapcore/HttpStatusCode.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/HttpStatusCode.java similarity index 97% rename from libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/bluemapcore/HttpStatusCode.java rename to libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/HttpStatusCode.java index d25f391..d72b634 100644 --- a/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/bluemapcore/HttpStatusCode.java +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/HttpStatusCode.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package io.gitlab.jfronny.libjf.web.impl.util.bluemapcore; +package io.gitlab.jfronny.libjf.web.api.v1; public enum HttpStatusCode { CONTINUE (100, "Continue"), diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/SubServer.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/SubServer.java new file mode 100644 index 0000000..816d035 --- /dev/null +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/SubServer.java @@ -0,0 +1,7 @@ +package io.gitlab.jfronny.libjf.web.api.v1; + +import java.io.IOException; + +public interface SubServer { + HttpResponse handle(HttpRequest request, String[] segments) throws IOException; +} diff --git a/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/api/WebInit.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/WebInit.java similarity index 59% rename from libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/api/WebInit.java rename to libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/WebInit.java index 4853388..6a15e23 100644 --- a/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/api/WebInit.java +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/WebInit.java @@ -1,4 +1,4 @@ -package io.gitlab.jfronny.libjf.web.api; +package io.gitlab.jfronny.libjf.web.api.v1; public interface WebInit { void register(WebServer api); diff --git a/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/api/WebServer.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/WebServer.java similarity index 73% rename from libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/api/WebServer.java rename to libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/WebServer.java index 3654962..7038ec6 100644 --- a/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/api/WebServer.java +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/WebServer.java @@ -1,4 +1,4 @@ -package io.gitlab.jfronny.libjf.web.api; +package io.gitlab.jfronny.libjf.web.api.v1; import io.gitlab.jfronny.libjf.web.impl.JfWeb; @@ -7,14 +7,14 @@ import java.nio.file.Path; public interface WebServer { String register(String webPath, ContentProvider provider); - String registerFile(String webPath, Path file, Boolean readOnSend) throws IOException; + String registerFile(String webPath, Path file, boolean readOnSend) throws IOException; String registerFile(String webPath, byte[] data, String contentType); - String registerDir(String webPath, Path dir, Boolean readOnSend) throws IOException; + String registerDir(String webPath, Path dir, boolean readOnSend) throws IOException; String registerSubServer(String webPath, SubServer subServer); String registerSubServer(String webPath, AdvancedSubServer subServer); String getServerRoot(); void stop(); - void restart(); + void queueRestart(Runnable callback); boolean isActive(); static WebServer getInstance() { diff --git a/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/DefaultFileHost.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/DefaultFileHost.java similarity index 88% rename from libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/DefaultFileHost.java rename to libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/DefaultFileHost.java index df20a97..17192a6 100644 --- a/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/DefaultFileHost.java +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/DefaultFileHost.java @@ -1,8 +1,8 @@ package io.gitlab.jfronny.libjf.web.impl; import io.gitlab.jfronny.libjf.LibJf; -import io.gitlab.jfronny.libjf.web.api.WebInit; -import io.gitlab.jfronny.libjf.web.api.WebServer; +import io.gitlab.jfronny.libjf.web.api.v1.WebInit; +import io.gitlab.jfronny.libjf.web.api.v1.WebServer; import net.fabricmc.loader.api.FabricLoader; import java.io.IOException; diff --git a/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/JfWeb.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/JfWeb.java similarity index 65% rename from libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/JfWeb.java rename to libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/JfWeb.java index 4ede783..9ecf1b8 100644 --- a/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/JfWeb.java +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/JfWeb.java @@ -1,31 +1,50 @@ package io.gitlab.jfronny.libjf.web.impl; import com.mojang.brigadier.Command; +import io.gitlab.jfronny.commons.ref.R; import io.gitlab.jfronny.libjf.Flags; import io.gitlab.jfronny.libjf.LibJf; import io.gitlab.jfronny.libjf.coprocess.CoProcess; -import io.gitlab.jfronny.libjf.web.api.WebServer; +import io.gitlab.jfronny.libjf.web.api.v1.WebServer; +import io.gitlab.jfronny.libjf.web.impl.variant.hosted.HostedWebServer; +import io.gitlab.jfronny.libjf.web.impl.variant.shared.SharedWebServer; +import net.fabricmc.api.EnvType; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; +import net.fabricmc.loader.api.FabricLoader; import net.minecraft.text.Text; +import org.jetbrains.annotations.ApiStatus; + +import java.time.chrono.IsoEra; import static net.minecraft.server.command.CommandManager.literal; public class JfWeb implements CoProcess, ModInitializer { + private static final RequestHandler handler; public static final WebServer SERVER; + static { JfWebConfig.ensureValidPort(); - SERVER = new JfWebServer(JfWebConfig.port, JfWebConfig.maxConnections); + handler = new RequestHandler(); + if (JfWebConfig.port != -1) SERVER = new HostedWebServer(handler, JfWebConfig.port, JfWebConfig.maxConnections); + else if (FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) + SERVER = new HostedWebServer(handler, 0, JfWebConfig.maxConnections); + else SERVER = new SharedWebServer(handler); + } + + @ApiStatus.Internal + public static RequestHandler getHandler() { + return handler; } @Override public void start() { - if (isEnabled()) SERVER.restart(); + if (isEnabled()) SERVER.queueRestart(R::nop); } @Override public void stop() { - if (isEnabled()) SERVER.stop(); + if (!(SERVER instanceof SharedWebServer)) SERVER.stop(); } @Override @@ -43,7 +62,9 @@ public class JfWeb implements CoProcess, ModInitializer { }).then(literal("restart").executes(context -> { try { context.getSource().sendFeedback(() -> Text.literal("Restarting LibWeb"), true); - SERVER.restart(); + SERVER.queueRestart(() -> { + context.getSource().sendFeedback(() -> Text.literal("LibWeb restarted"), true); + }); } catch (Exception e) { LibJf.LOGGER.error("Failed to run restart command", e); @@ -53,7 +74,6 @@ public class JfWeb implements CoProcess, ModInitializer { })))); }); } - Runtime.getRuntime().addShutdownHook(new Thread(SERVER::stop)); } private boolean isEnabled() { diff --git a/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/JfWebConfig.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/JfWebConfig.java similarity index 62% rename from libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/JfWebConfig.java rename to libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/JfWebConfig.java index 3d1e3b7..4a258ad 100644 --- a/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/JfWebConfig.java +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/JfWebConfig.java @@ -9,19 +9,24 @@ import java.net.ServerSocket; @JfConfig public class JfWebConfig { @Entry public static String serverIp = "http://127.0.0.1"; - @Entry(min = 0, max = 35535) public static int port = 0; + @Entry(min = -1, max = 35535) public static int port = 0; @Entry(min = -1, max = 35535) public static int portOverride = -1; @Entry(min = 8, max = 64) public static int maxConnections = 20; @Entry public static boolean enableFileHost = false; public static void ensureValidPort() { if (port == 0) { - try (ServerSocket socket = new ServerSocket(0)) { - port = socket.getLocalPort(); - } catch (IOException e) { - LibJf.LOGGER.error("Could not bind port to identify available", e); - } - ConfigHolder.getInstance().getRegistered().get("libjf-web-v0").write(); + port = findAvailablePort(); + ConfigHolder.getInstance().getRegistered().get("libjf-web-v1").write(); + } + } + + public static int findAvailablePort() { + try (ServerSocket socket = new ServerSocket(0)) { + return socket.getLocalPort(); + } catch (IOException e) { + LibJf.LOGGER.error("Could not bind port to identify available", e); + return 0; } } diff --git a/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/RequestHandler.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/RequestHandler.java similarity index 75% rename from libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/RequestHandler.java rename to libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/RequestHandler.java index 3c4953e..34b3d1e 100644 --- a/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/RequestHandler.java +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/RequestHandler.java @@ -1,10 +1,9 @@ package io.gitlab.jfronny.libjf.web.impl; import io.gitlab.jfronny.libjf.LibJf; -import io.gitlab.jfronny.libjf.web.api.AdvancedSubServer; -import io.gitlab.jfronny.libjf.web.api.ContentProvider; -import io.gitlab.jfronny.libjf.web.impl.util.WebPaths; -import io.gitlab.jfronny.libjf.web.impl.util.bluemapcore.*; +import io.gitlab.jfronny.libjf.web.api.v1.*; +import io.gitlab.jfronny.libjf.web.impl.util.*; +import io.gitlab.jfronny.libjf.web.impl.variant.hosted.HttpRequestHandler; import java.util.*; @@ -17,7 +16,7 @@ public class RequestHandler implements HttpRequestHandler { HttpResponse resp = null; try { String webPath = WebPaths.simplify(request.getPath()); - if (webPath.length() == 0) + if (webPath.isEmpty()) webPath = "index.html"; if (contentProviders.containsKey(webPath)) { resp = contentProviders.get(webPath).handle(request); @@ -32,16 +31,16 @@ public class RequestHandler implements HttpRequestHandler { } } if (resp == null) { - resp = new HttpResponse(HttpStatusCode.NOT_FOUND); + resp = new HttpResponseImpl(HttpStatusCode.NOT_FOUND); } } } catch (Throwable e) { LibJf.LOGGER.error("Caught error while sending", e); - resp = new HttpResponse(HttpStatusCode.INTERNAL_SERVER_ERROR); + resp = new HttpResponseImpl(HttpStatusCode.INTERNAL_SERVER_ERROR); } - if (resp.getHeader("Cache-Control").size() == 0) + if (resp.getHeader("Cache-Control").isEmpty()) resp.addHeader("Cache-Control", "no-cache"); - if (resp.getHeader("Server").size() == 0) + if (resp.getHeader("Server").isEmpty()) resp.addHeader("Server", "LibWeb using BlueMapCore"); return resp; } diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/mixin/JfWebMixinPlugin.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/mixin/JfWebMixinPlugin.java new file mode 100644 index 0000000..ef2f214 --- /dev/null +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/mixin/JfWebMixinPlugin.java @@ -0,0 +1,47 @@ +package io.gitlab.jfronny.libjf.web.impl.mixin; + +import io.gitlab.jfronny.libjf.web.impl.JfWebConfig; +import org.objectweb.asm.tree.ClassNode; +import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; +import org.spongepowered.asm.mixin.extensibility.IMixinInfo; + +import java.util.List; +import java.util.Set; + +public class JfWebMixinPlugin implements IMixinConfigPlugin { + private static final String MIXIN_PACKAGE = "io.gitlab.jfronny.libjf.web.impl.mixin."; + + @Override + public void onLoad(String mixinPackage) { + } + + @Override + public String getRefMapperConfig() { + return null; + } + + @Override + public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { + return switch (mixinClassName) { + case MIXIN_PACKAGE + "ServerNetworkIoMixin", MIXIN_PACKAGE + "ServerNetworkIo$1Mixin" -> JfWebConfig.port == -1; + default -> throw new IllegalArgumentException("Unexpected mixin: " + mixinClassName); + }; + } + + @Override + public void acceptTargets(Set myTargets, Set otherTargets) { + } + + @Override + public List getMixins() { + return null; + } + + @Override + public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { + } + + @Override + public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { + } +} diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/mixin/ServerNetworkIo$1Mixin.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/mixin/ServerNetworkIo$1Mixin.java new file mode 100644 index 0000000..a2a8e02 --- /dev/null +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/mixin/ServerNetworkIo$1Mixin.java @@ -0,0 +1,16 @@ +package io.gitlab.jfronny.libjf.web.impl.mixin; + +import io.gitlab.jfronny.libjf.web.impl.variant.shared.HttpDecoder; +import io.netty.channel.Channel; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(targets = "net.minecraft.server.ServerNetworkIo$1") +public class ServerNetworkIo$1Mixin { + @Inject(method = "initChannel(Lio/netty/channel/Channel;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/ClientConnection;addHandlers(Lio/netty/channel/ChannelPipeline;Lnet/minecraft/network/NetworkSide;Lnet/minecraft/network/handler/PacketSizeLogger;)V")) + private void inject(Channel channel, CallbackInfo ci) { + channel.pipeline().addAfter("legacy_query", "libjf_http", new HttpDecoder()); + } +} diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/mixin/ServerNetworkIoMixin.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/mixin/ServerNetworkIoMixin.java new file mode 100644 index 0000000..1a8da9b --- /dev/null +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/mixin/ServerNetworkIoMixin.java @@ -0,0 +1,30 @@ +package io.gitlab.jfronny.libjf.web.impl.mixin; + +import io.gitlab.jfronny.libjf.web.impl.util.ClaimPool; +import io.gitlab.jfronny.libjf.web.impl.variant.shared.SharedWebServer; +import net.minecraft.server.ServerNetworkIo; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.net.InetAddress; +import java.util.HashSet; +import java.util.Set; + +@Mixin(ServerNetworkIo.class) +public class ServerNetworkIoMixin { + @Unique private final Set.Claim> libjf$portClaim = new HashSet<>(); + + @Inject(method = "bind(Ljava/net/InetAddress;I)V", at = @At("HEAD")) + void onBind(InetAddress address, int port, CallbackInfo ci) { + libjf$portClaim.add(SharedWebServer.gamePort.claim(port)); + SharedWebServer.emitActive(); + } + + @Inject(method = "stop()V", at = @At("HEAD")) + void onStop(CallbackInfo ci) { + for (ClaimPool.Claim claim : libjf$portClaim) claim.release(); + } +} diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/ClaimPool.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/ClaimPool.java new file mode 100644 index 0000000..b6e0c03 --- /dev/null +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/ClaimPool.java @@ -0,0 +1,37 @@ +package io.gitlab.jfronny.libjf.web.impl.util; + +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; + +public class ClaimPool { + private final List content = new LinkedList<>(); + + public Claim claim(T value) { + return new Claim(value); + } + + public T getTopmost() { + return content.isEmpty() ? null : content.get(content.size() - 1).value; + } + + public boolean isEmpty() { + return content.isEmpty(); + } + + public class Claim { + private final T value; + private final AtomicBoolean active = new AtomicBoolean(true); + + private Claim(T value) { + this.value = value; + content.add(this); + } + + public void release() { + if (!active.getAndSet(false)) + throw new UnsupportedOperationException("Cannot release claim that is already released"); + content.remove(this); + } + } +} diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/HttpRequestImpl.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/HttpRequestImpl.java new file mode 100644 index 0000000..16f8aed --- /dev/null +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/HttpRequestImpl.java @@ -0,0 +1,249 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package io.gitlab.jfronny.libjf.web.impl.util; + +import io.gitlab.jfronny.libjf.web.api.v1.*; +import io.gitlab.jfronny.libjf.web.impl.variant.hosted.HttpConnection; + +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.Map.Entry; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class HttpRequestImpl implements HttpRequest { + private static final Pattern REQUEST_PATTERN = Pattern.compile("^(\\w+) (\\S+) (.+)$"); + + private final String method; + private final String address; + private final String version; + private final Map> header; + private final Map> headerLC; + private byte[] data; + + private String path = null; + private Map queryParameters = null; + private String queryString = null; + + public HttpRequestImpl(String method, String address, String version, Map> header) { + this.method = method; + this.address = address; + this.version = version; + this.header = header; + this.headerLC = new HashMap<>(); + + for (Entry> e : header.entrySet()){ + Set values = new HashSet<>(); + for (String v : e.getValue()){ + values.add(v.toLowerCase()); + } + + headerLC.put(e.getKey().toLowerCase(), values); + } + + this.data = new byte[0]; + } + + @Override + public String getMethod() { + return method; + } + + @Override + public String getAddress(){ + return address; + } + + @Override + public String getVersion() { + return version; + } + + @Override + public Map> getHeader() { + return header; + } + + @Override + public Map> getLowercaseHeader() { + return headerLC; + } + + @Override + public Set getHeader(String key){ + Set headerValues = header.get(key); + if (headerValues == null) return Collections.emptySet(); + return headerValues; + } + + @Override + public Set getLowercaseHeader(String key){ + Set headerValues = headerLC.get(key.toLowerCase()); + if (headerValues == null) return Collections.emptySet(); + return headerValues; + } + + @Override + public String getPath() { + if (path == null) parseAddress(); + return path; + } + + @Override + public Map getQuery() { + if (queryParameters == null) parseAddress(); + return Collections.unmodifiableMap(queryParameters); + } + + @Override + public String getQueryString() { + if (queryString == null) parseAddress(); + return queryString; + } + + private void parseAddress() { + String adress = this.address; + if (adress.isEmpty()) adress = "/"; + String[] addressParts = adress.split("\\?", 2); + String path = addressParts[0]; + this.queryString = addressParts.length > 1 ? addressParts[1] : ""; + + Map queryParams = new HashMap<>(); + for (String queryParam : this.queryString.split("&")){ + if (queryParam.isEmpty()) continue; + String[] kv = queryParam.split("=", 2); + String key = kv[0]; + String value = kv.length > 1 ? kv[1] : ""; + queryParams.put(key, value); + } + + this.path = path; + this.queryParameters = queryParams; + } + + @Override + public InputStream getData(){ + return new ByteArrayInputStream(data); + } + + public static HttpRequestImpl read(InputStream in) throws IOException { + BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8)); + HttpRequestImpl request = fromHeaders(extractHeaders(reader)); + readData(in, request, reader); + return request; + } + + private static void readData(InputStream in, HttpRequestImpl request, BufferedReader reader) throws IOException { + if (request.getLowercaseHeader("Transfer-Encoding").contains("chunked")) { + try { + ByteArrayOutputStream dataStream = new ByteArrayOutputStream(); + while (dataStream.size() < 1000000) { + String hexSize = reader.readLine(); + int chunkSize = Integer.parseInt(hexSize, 16); + if (chunkSize <= 0) break; + byte[] data = new byte[chunkSize]; + in.read(data); + dataStream.write(data); + } + + if (dataStream.size() >= 1000000) { + throw new HttpConnection.InvalidRequestException(); + } + + request.data = dataStream.toByteArray(); + } catch (NumberFormatException ex) { + } + } else { + Set clSet = request.getLowercaseHeader("Content-Length"); + if (clSet.isEmpty()) return; + try { + int cl = Integer.parseInt(clSet.iterator().next()); + byte[] data = new byte[cl]; + in.read(data); + request.data = data; + } catch (NumberFormatException ex) { + } + } + } + + private static List extractHeaders(BufferedReader reader) throws IOException { + List headers = new ArrayList<>(20); + while (headers.size() < 1000) { + String headerLine = readLine(reader); + if (headerLine.isEmpty()) break; + headers.add(headerLine); + } + return headers; + } + + private static HttpRequestImpl fromHeaders(List headers) throws HttpConnection.InvalidRequestException { + if (headers.isEmpty()) throw new HttpConnection.InvalidRequestException(); + + Matcher m = REQUEST_PATTERN.matcher(headers.remove(0)); + if (!m.find()) throw new HttpConnection.InvalidRequestException(); + + String method = m.group(1); + if (method == null) throw new HttpConnection.InvalidRequestException(); + + String adress = m.group(2); + if (adress == null) throw new HttpConnection.InvalidRequestException(); + + String version = m.group(3); + if (version == null) throw new HttpConnection.InvalidRequestException(); + + return new HttpRequestImpl(method, adress, version, parseExtraHeaders(headers)); + } + + private static Map> parseExtraHeaders(List header) { + Map> headerMap = new HashMap<>(); + for (String line : header) { + if (line.trim().isEmpty()) continue; + + String[] kv = line.split(":", 2); + if (kv.length < 2) continue; + + Set values = new HashSet<>(); + if (kv[0].trim().equalsIgnoreCase("If-Modified-Since")) { + values.add(kv[1].trim()); + } else { + for (String v : kv[1].split(",")) { + values.add(v.trim()); + } + } + + headerMap.put(kv[0].trim(), values); + } + return headerMap; + } + + private static String readLine(BufferedReader in) throws IOException { + String line = in.readLine(); + if (line == null) { + throw new HttpConnection.ConnectionClosedException(); + } + return line; + } +} diff --git a/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/bluemapcore/HttpResponse.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/HttpResponseImpl.java similarity index 73% rename from libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/bluemapcore/HttpResponse.java rename to libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/HttpResponseImpl.java index 5460420..7a4dcde 100644 --- a/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/bluemapcore/HttpResponse.java +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/HttpResponseImpl.java @@ -22,8 +22,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package io.gitlab.jfronny.libjf.web.impl.util.bluemapcore; +package io.gitlab.jfronny.libjf.web.impl.util; +import io.gitlab.jfronny.libjf.web.api.v1.HttpResponse; +import io.gitlab.jfronny.libjf.web.api.v1.HttpStatusCode; import org.apache.commons.lang3.StringUtils; import java.io.*; @@ -31,13 +33,14 @@ import java.nio.charset.StandardCharsets; import java.util.*; import java.util.Map.Entry; -public class HttpResponse implements Closeable { +public class HttpResponseImpl implements HttpResponse { private final String version; private final HttpStatusCode statusCode; private final Map> header; + private boolean closed = false; private InputStream data; - public HttpResponse(HttpStatusCode statusCode) { + public HttpResponseImpl(HttpStatusCode statusCode) { this.version = "HTTP/1.1"; this.statusCode = statusCode; @@ -46,24 +49,32 @@ public class HttpResponse implements Closeable { addHeader("Connection", "keep-alive"); } - public HttpResponse addHeader(String key, String value){ + @Override + public HttpResponseImpl addHeader(String key, String value) { + ensureOpen(); Set valueSet = header.computeIfAbsent(key, k -> new HashSet<>()); valueSet.add(value); return this; } - public HttpResponse removeHeader(String key, String value){ + @Override + public HttpResponseImpl removeHeader(String key, String value) { + ensureOpen(); Set valueSet = header.computeIfAbsent(key, k -> new HashSet<>()); valueSet.remove(value); return this; } - public HttpResponse setData(InputStream dataStream){ + @Override + public HttpResponseImpl setData(InputStream dataStream) { + ensureOpen(); this.data = dataStream; return this; } - public HttpResponse setData(String data){ + @Override + public HttpResponseImpl setData(String data) { + ensureOpen(); setData(new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8))); return this; } @@ -73,17 +84,18 @@ public class HttpResponse implements Closeable { *
* This method closes the data-Stream of this response so it can't be used again! */ - public HttpResponse write(OutputStream out) throws IOException { + @Override + public void write(OutputStream out) throws IOException { OutputStreamWriter writer = new OutputStreamWriter(out, StandardCharsets.UTF_8); - if (data != null){ + if (data != null) { addHeader("Transfer-Encoding", "chunked"); } else { addHeader("Content-Length", "0"); } writeLine(writer, version + " " + statusCode.getCode() + " " + statusCode.getMessage()); - for (Entry> e : header.entrySet()){ + for (Entry> e : header.entrySet()) { if (e.getValue().isEmpty()) continue; writeLine(writer, e.getKey() + ": " + StringUtils.join(e.getValue(), ", ")); } @@ -91,17 +103,20 @@ public class HttpResponse implements Closeable { writeLine(writer, ""); writer.flush(); - if(data != null){ + if (data != null) { + boolean markSupported = data.markSupported(); + if (markSupported) data.mark(Integer.MAX_VALUE); chunkedPipe(data, out); out.flush(); - data.close(); + if (markSupported) data.reset(); + else close(); } - return this; } @Override public void close() throws IOException { - data.close(); + if (data != null) data.close(); + this.closed = true; } private void writeLine(OutputStreamWriter writer, String line) throws IOException { @@ -119,18 +134,26 @@ public class HttpResponse implements Closeable { output.write("0\r\n\r\n".getBytes()); } + private void ensureOpen() { + if (closed) throw new UnsupportedOperationException("Response cannot be changed after being closed or written"); + } + + @Override public HttpStatusCode getStatusCode(){ return statusCode; } + @Override public String getVersion(){ return version; } + @Override public Map> getHeader() { return header; } + @Override public Set getHeader(String key){ Set headerValues = header.get(key); if (headerValues == null) return Collections.emptySet(); diff --git a/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/WebPaths.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/WebPaths.java similarity index 89% rename from libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/WebPaths.java rename to libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/WebPaths.java index 68051a2..1a30629 100644 --- a/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/WebPaths.java +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/WebPaths.java @@ -1,5 +1,7 @@ package io.gitlab.jfronny.libjf.web.impl.util; +import io.gitlab.jfronny.libjf.web.impl.JfWebConfig; + public class WebPaths { public static String concat(String s1, String s2) { return simplify(s1) + "/" + simplify(s2); @@ -13,6 +15,12 @@ public class WebPaths { return simplify(s.toString()); } + public static String getHttp(String ip) { + if (!ip.startsWith("http")) + ip = "http://" + ip; + return simplify(ip); + } + public static String simplify(String s) { boolean http = false; boolean https = false; diff --git a/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/JfWebServer.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/AbstractWebServer.java similarity index 66% rename from libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/JfWebServer.java rename to libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/AbstractWebServer.java index 3049646..4318440 100644 --- a/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/JfWebServer.java +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/AbstractWebServer.java @@ -1,10 +1,11 @@ -package io.gitlab.jfronny.libjf.web.impl; +package io.gitlab.jfronny.libjf.web.impl.variant; import io.gitlab.jfronny.libjf.LibJf; -import io.gitlab.jfronny.libjf.web.api.*; -import io.gitlab.jfronny.libjf.web.impl.util.WebPaths; -import io.gitlab.jfronny.libjf.web.impl.util.bluemapcore.*; +import io.gitlab.jfronny.libjf.web.api.v1.*; +import io.gitlab.jfronny.libjf.web.impl.*; +import io.gitlab.jfronny.libjf.web.impl.util.*; import net.fabricmc.loader.api.FabricLoader; +import org.jetbrains.annotations.ApiStatus; import javax.management.openmbean.KeyAlreadyExistsException; import java.io.*; @@ -13,15 +14,17 @@ import java.nio.file.Path; import java.util.Objects; import java.util.stream.Stream; -public class JfWebServer implements WebServer { - private HttpServer server = null; - private final RequestHandler handler = new RequestHandler(); - private final int port; - private final int maxConnections; +public abstract class AbstractWebServer implements WebServer { + protected final RequestHandler handler; private final DefaultFileHost dfh = new DefaultFileHost(); - public JfWebServer(int port, int maxConnections) { - this.port = port; - this.maxConnections = maxConnections; + + protected AbstractWebServer(RequestHandler handler) { + this.handler = handler; + } + + @ApiStatus.Internal + public RequestHandler getHandler() { + return handler; } @Override @@ -34,12 +37,12 @@ public class JfWebServer implements WebServer { } @Override - public String registerFile(String webPath, Path file, Boolean readOnSend) throws IOException { + public String registerFile(String webPath, Path file, boolean readOnSend) throws IOException { if (readOnSend) { if (!Files.exists(file)) throw new FileNotFoundException(); register(webPath, s -> { - HttpResponse resp = new HttpResponse(HttpStatusCode.OK); + HttpResponse resp = HttpResponse.create(HttpStatusCode.OK); resp.addHeader("Content-Type", Files.probeContentType(file)); resp.addHeader("Content-Length", String.valueOf(Files.size(file))); FileInputStream fs = new FileInputStream(file.toFile()); @@ -56,7 +59,7 @@ public class JfWebServer implements WebServer { @Override public String registerFile(String webPath, byte[] data, String contentType) { return register(webPath, s -> { - HttpResponse resp = new HttpResponse(HttpStatusCode.OK); + HttpResponse resp = HttpResponse.create(HttpStatusCode.OK); resp.addHeader("Content-Type", contentType); resp.addHeader("Content-Length", String.valueOf(data.length)); ByteArrayInputStream fs = new ByteArrayInputStream(data); @@ -66,7 +69,7 @@ public class JfWebServer implements WebServer { } @Override - public String registerDir(String webPath, Path dir, Boolean readOnSend) throws IOException { + public String registerDir(String webPath, Path dir, boolean readOnSend) throws IOException { try (Stream contentPath = Files.walk(dir)) { if (readOnSend) { return registerSubServer(webPath, (s, t) -> { @@ -89,13 +92,13 @@ public class JfWebServer implements WebServer { }); HttpResponse resp; if (c[0]) { - resp = new HttpResponse(HttpStatusCode.OK); + resp = HttpResponse.create(HttpStatusCode.OK); resp.addHeader("Content-Type", Files.probeContentType(p_f[0])); resp.addHeader("Content-Length", String.valueOf(Files.size(p_f[0]))); FileInputStream fs = new FileInputStream(p_f[0].toFile()); resp.setData(fs); } else { - resp = new HttpResponse(HttpStatusCode.NOT_FOUND); + resp = HttpResponse.create(HttpStatusCode.NOT_FOUND); } return resp; }); @@ -122,12 +125,10 @@ public class JfWebServer implements WebServer { return registerSubServer(webPath, new AdvancedSubServer() { @Override public void onStop() { - } @Override public void onStart() { - } @Override @@ -146,61 +147,16 @@ public class JfWebServer implements WebServer { return WebPaths.concat(getServerRoot(), webPath); } - @Override - public String getServerRoot() { - String ip = JfWebConfig.serverIp; - if (!ip.startsWith("http")) - ip = "http://" + ip; - if (JfWebConfig.portOverride != -1) { - return WebPaths.simplify(ip) + ":" + JfWebConfig.portOverride; - } - return WebPaths.simplify(ip) + ":" + JfWebConfig.port; - } - - @Override - public synchronized void stop() { - for (AdvancedSubServer subServer : handler.subServers.values()) subServer.onStop(); - if (server != null) { - try { - server.close(); - server.join(); - } - catch (InterruptedException e) { - //It is most likely already dead - } - } - } - - @Override - public synchronized void restart() { - JfWebConfig.ensureValidPort(); - int tmpPort = port; - if (server != null) { - tmpPort = server.getPort(); - stop(); - } - handler.clear(); - server = new HttpServer(null, tmpPort, maxConnections, handler, () -> { - if (JfWebConfig.enableFileHost) dfh.register(this); - FabricLoader.getInstance().getEntrypointContainers(LibJf.MOD_ID + ":web", WebInit.class).forEach(entrypoint -> { - WebInit init = entrypoint.getEntrypoint(); - init.register(this); - }); + protected void performRegistrations() { + if (JfWebConfig.enableFileHost) dfh.register(this); + FabricLoader.getInstance().getEntrypointContainers(LibJf.MOD_ID + ":web", WebInit.class).forEach(entrypoint -> { + WebInit init = entrypoint.getEntrypoint(); + init.register(this); }); - server.start(); - try { - server.waitUntilReady(); - } catch (InterruptedException e) { - stop(); - LibJf.LOGGER.error("Server could not be readied", e); - } - for (AdvancedSubServer subServer : handler.subServers.values()) { - subServer.onStart(); - } } - @Override - public boolean isActive() { - return server != null && server.isAlive(); + protected String getServerRoot(int hostedPort) { + return WebPaths.getHttp(JfWebConfig.serverIp) + ":" + + (JfWebConfig.portOverride != -1 ? JfWebConfig.portOverride : hostedPort); } } diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/hosted/HostedWebServer.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/hosted/HostedWebServer.java new file mode 100644 index 0000000..defb94a --- /dev/null +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/hosted/HostedWebServer.java @@ -0,0 +1,64 @@ +package io.gitlab.jfronny.libjf.web.impl.variant.hosted; + +import io.gitlab.jfronny.libjf.LibJf; +import io.gitlab.jfronny.libjf.web.api.v1.AdvancedSubServer; +import io.gitlab.jfronny.libjf.web.impl.*; +import io.gitlab.jfronny.libjf.web.impl.variant.AbstractWebServer; + +public class HostedWebServer extends AbstractWebServer { + private HttpServer server = null; + private final int port; + private final int maxConnections; + + public HostedWebServer(RequestHandler handler, int port, int maxConnections) { + super(handler); + this.port = port; + this.maxConnections = maxConnections; + } + + @Override + public String getServerRoot() { + return getServerRoot(server.getPort()); + } + + @Override + public synchronized void stop() { + for (AdvancedSubServer subServer : handler.subServers.values()) subServer.onStop(); + if (server != null) { + try { + server.close(); + server.join(); + } + catch (InterruptedException e) { + //It is most likely already dead + } + } + } + + @Override + public void queueRestart(Runnable callback) { + int tmpPort = port; + if (server != null) { + tmpPort = server.getPort(); + stop(); + } else if (tmpPort == 0) tmpPort = JfWebConfig.findAvailablePort(); + handler.clear(); + server = new HttpServer(null, tmpPort, maxConnections, handler, this::performRegistrations); + server.start(); + try { + server.waitUntilReady(); + } catch (InterruptedException e) { + stop(); + LibJf.LOGGER.error("Server could not be readied", e); + } + for (AdvancedSubServer subServer : handler.subServers.values()) { + subServer.onStart(); + } + callback.run(); + } + + @Override + public boolean isActive() { + return server != null && server.isAlive(); + } +} diff --git a/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/bluemapcore/HttpConnection.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/hosted/HttpConnection.java similarity index 90% rename from libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/bluemapcore/HttpConnection.java rename to libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/hosted/HttpConnection.java index aaab0d8..181533d 100644 --- a/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/bluemapcore/HttpConnection.java +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/hosted/HttpConnection.java @@ -22,9 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package io.gitlab.jfronny.libjf.web.impl.util.bluemapcore; +package io.gitlab.jfronny.libjf.web.impl.variant.hosted; import io.gitlab.jfronny.libjf.LibJf; +import io.gitlab.jfronny.libjf.web.api.v1.*; +import io.gitlab.jfronny.libjf.web.impl.util.HttpRequestImpl; +import io.gitlab.jfronny.libjf.web.impl.util.HttpResponseImpl; import java.io.*; import java.net.*; @@ -64,8 +67,9 @@ public class HttpConnection implements Runnable { sendResponse(response); } catch (InvalidRequestException e){ try { - sendResponse(new HttpResponse(HttpStatusCode.BAD_REQUEST)); - } catch (IOException e1) {} + sendResponse(HttpResponse.create(HttpStatusCode.BAD_REQUEST)); + } catch (IOException e1) { + } break; } catch (SocketTimeoutException | SocketException | ConnectionClosedException e) { break; @@ -82,7 +86,7 @@ public class HttpConnection implements Runnable { } } - private void log(HttpRequest request, HttpResponse response) { + private void log(HttpRequestImpl request, HttpResponseImpl response) { DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); Date date = new Date(); LibJf.LOGGER.info( diff --git a/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/bluemapcore/HttpRequestHandler.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/hosted/HttpRequestHandler.java similarity index 82% rename from libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/bluemapcore/HttpRequestHandler.java rename to libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/hosted/HttpRequestHandler.java index 7f5d490..8e2cd9f 100644 --- a/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/bluemapcore/HttpRequestHandler.java +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/hosted/HttpRequestHandler.java @@ -22,7 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package io.gitlab.jfronny.libjf.web.impl.util.bluemapcore; +package io.gitlab.jfronny.libjf.web.impl.variant.hosted; + +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.util.HttpRequestImpl; +import io.gitlab.jfronny.libjf.web.impl.util.HttpResponseImpl; @FunctionalInterface public interface HttpRequestHandler { diff --git a/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/bluemapcore/HttpServer.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/hosted/HttpServer.java similarity index 98% rename from libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/bluemapcore/HttpServer.java rename to libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/hosted/HttpServer.java index cc0e9ac..c01c4fe 100644 --- a/libjf-web-v0/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/bluemapcore/HttpServer.java +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/hosted/HttpServer.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package io.gitlab.jfronny.libjf.web.impl.util.bluemapcore; +package io.gitlab.jfronny.libjf.web.impl.variant.hosted; import io.gitlab.jfronny.libjf.LibJf; diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/shared/HttpDecoder.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/shared/HttpDecoder.java new file mode 100644 index 0000000..fb87c97 --- /dev/null +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/shared/HttpDecoder.java @@ -0,0 +1,68 @@ +package io.gitlab.jfronny.libjf.web.impl.variant.shared; + +import io.gitlab.jfronny.libjf.LibJf; +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.gitlab.jfronny.libjf.web.impl.RequestHandler; +import io.gitlab.jfronny.libjf.web.impl.util.HttpRequestImpl; +import io.gitlab.jfronny.libjf.web.impl.util.HttpResponseImpl; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.*; +import org.jetbrains.annotations.NotNull; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.util.List; + +public class HttpDecoder extends ChannelInboundHandlerAdapter { + private static final Trie METHOD = Trie.of(List.of( + "GET", + "HEAD", + "POST", + "PUT", + "PATCH", + "DELETE", + + "OPTIONS", "TRACE", "CONNECT" + )); + + @Override + public void channelRead(@NotNull ChannelHandlerContext ctx, @NotNull Object msg) throws Exception { + ByteBuf buf = (ByteBuf) msg; + buf.markReaderIndex(); + boolean passOn = true; + try { + Trie current = METHOD; + while (buf.isReadable() + && current != null + && current.content == null) + current = current.next.get((char) buf.readByte()); + if (current == null || current.content == null) return; + buf.resetReaderIndex(); + byte[] data = new byte[buf.readableBytes()]; + buf.readBytes(data); + try (ByteArrayInputStream is = new ByteArrayInputStream(data); + HttpResponse response = JfWeb.getHandler().handle(HttpRequest.read(is)); + ByteArrayOutputStream os = new ByteArrayOutputStream()) { + response.write(os); + os.flush(); + ctx.pipeline() + .firstContext() + .writeAndFlush(Unpooled.wrappedBuffer(os.toByteArray())) + .addListener(ChannelFutureListener.CLOSE); + } + buf.release(); + passOn = false; + } catch (RuntimeException re) { + LibJf.LOGGER.error("Could not process HTTP", re); + } finally { + if (passOn) { + buf.resetReaderIndex(); + ctx.channel().pipeline().remove(this); + ctx.fireChannelRead(msg); + } + } + } +} diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/shared/SharedWebServer.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/shared/SharedWebServer.java new file mode 100644 index 0000000..4892ba1 --- /dev/null +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/shared/SharedWebServer.java @@ -0,0 +1,51 @@ +package io.gitlab.jfronny.libjf.web.impl.variant.shared; + +import io.gitlab.jfronny.libjf.web.api.v1.AdvancedSubServer; +import io.gitlab.jfronny.libjf.web.impl.*; +import io.gitlab.jfronny.libjf.web.impl.util.ClaimPool; +import io.gitlab.jfronny.libjf.web.impl.variant.AbstractWebServer; + +import java.util.LinkedHashSet; +import java.util.Set; + +public class SharedWebServer extends AbstractWebServer { + public static final ClaimPool gamePort = new ClaimPool<>(); + public static final Set onActive = new LinkedHashSet<>(); + + public static void emitActive() { + for (Runnable runnable : onActive) runnable.run(); + } + + public SharedWebServer(RequestHandler handler) { + super(handler); + } + + @Override + public String getServerRoot() { + Integer gamePort = this.gamePort.getTopmost(); + if (gamePort == null) throw new UnsupportedOperationException("Attempted to get server root on unhosted server"); + else return getServerRoot(gamePort); + } + + @Override + public void stop() { + throw new UnsupportedOperationException("A shared server cannot be stopped"); + } + + @Override + public void queueRestart(Runnable callback) { + onActive.add(() -> { + for (AdvancedSubServer subServer : handler.subServers.values()) subServer.onStop(); + handler.clear(); + performRegistrations(); + for (AdvancedSubServer subServer : handler.subServers.values()) subServer.onStart(); + callback.run(); + }); + if (isActive()) emitActive(); + } + + @Override + public boolean isActive() { + return !gamePort.isEmpty(); + } +} diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/shared/Trie.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/shared/Trie.java new file mode 100644 index 0000000..7646c4e --- /dev/null +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/shared/Trie.java @@ -0,0 +1,38 @@ +package io.gitlab.jfronny.libjf.web.impl.variant.shared; + +import it.unimi.dsi.fastutil.chars.Char2ObjectArrayMap; +import it.unimi.dsi.fastutil.chars.Char2ObjectMap; + +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +public class Trie { + public final Char2ObjectMap> next; + public T content; + + public Trie() { + this.next = new Char2ObjectArrayMap<>(); + } + + public void add(Map next) { + next.forEach(this::add); + } + + public void add(String key, T value) { + if (key.isEmpty()) this.content = value; + else this.next.computeIfAbsent(key.charAt(0), k -> new Trie<>()) + .add(key.substring(1), value); + } + + public static Trie of(Map source) { + Trie root = new Trie<>(); + root.add(source); + return root; + } + + public static Trie of(List source) { + return of(source.stream().collect(Collectors.toMap(Function.identity(), Function.identity()))); + } +} diff --git a/libjf-web-v1/src/main/resources/assets/libjf-web-v1/lang/en_us.json b/libjf-web-v1/src/main/resources/assets/libjf-web-v1/lang/en_us.json new file mode 100644 index 0000000..b314596 --- /dev/null +++ b/libjf-web-v1/src/main/resources/assets/libjf-web-v1/lang/en_us.json @@ -0,0 +1,13 @@ +{ + "libjf-web-v1.jfconfig.title": "LibJF Web v0", + "libjf-web-v1.jfconfig.serverIp": "Server IP", + "libjf-web-v1.jfconfig.serverIp.tooltip": "The public IP/host name to send to clients", + "libjf-web-v1.jfconfig.port": "Port", + "libjf-web-v1.jfconfig.port.tooltip": "The port to host content on, 0 to choose a random one or -1 to reuse the minecraft port on servers (requires restart)", + "libjf-web-v1.jfconfig.portOverride": "Port Override", + "libjf-web-v1.jfconfig.portOverride.tooltip": "The port to send to clients (for reverse proxies, -1 to disable)", + "libjf-web-v1.jfconfig.maxConnections": "Max. Connections", + "libjf-web-v1.jfconfig.maxConnections.tooltip": "The maximum number of concurrent connections to this server", + "libjf-web-v1.jfconfig.enableFileHost": "Enable File Host", + "libjf-web-v1.jfconfig.enableFileHost.tooltip": "Whether files from config/wwwroot should be hosted as static resources" +} \ No newline at end of file diff --git a/libjf-web-v0/src/main/resources/fabric.mod.json b/libjf-web-v1/src/main/resources/fabric.mod.json similarity index 90% rename from libjf-web-v0/src/main/resources/fabric.mod.json rename to libjf-web-v1/src/main/resources/fabric.mod.json index d9bb8e4..7af09db 100644 --- a/libjf-web-v0/src/main/resources/fabric.mod.json +++ b/libjf-web-v1/src/main/resources/fabric.mod.json @@ -1,6 +1,7 @@ { "schemaVersion": 1, - "id": "libjf-web-v0", + "id": "libjf-web-v1", + "provides": ["libjf-web-v0"], "name": "LibJF Web", "version": "${version}", "authors": [ @@ -14,6 +15,7 @@ }, "license": "MIT", "environment": "*", + "mixins": ["libjf-web-v1.mixins.json"], "entrypoints": { "main": ["io.gitlab.jfronny.libjf.web.impl.JfWeb"], "libjf:coprocess": ["io.gitlab.jfronny.libjf.web.impl.JfWeb"], diff --git a/libjf-web-v1/src/main/resources/libjf-web-v1.mixins.json b/libjf-web-v1/src/main/resources/libjf-web-v1.mixins.json new file mode 100644 index 0000000..3bf60c3 --- /dev/null +++ b/libjf-web-v1/src/main/resources/libjf-web-v1.mixins.json @@ -0,0 +1,14 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "io.gitlab.jfronny.libjf.web.impl.mixin", + "compatibilityLevel": "JAVA_16", + "plugin": "io.gitlab.jfronny.libjf.web.impl.mixin.JfWebMixinPlugin", + "server": [ + "ServerNetworkIo$1Mixin", + "ServerNetworkIoMixin" + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/libjf-web-v0/src/testmod/java/io/gitlab/jfronny/libjf/web/test/WebTest.java b/libjf-web-v1/src/testmod/java/io/gitlab/jfronny/libjf/web/test/WebTest.java similarity index 60% rename from libjf-web-v0/src/testmod/java/io/gitlab/jfronny/libjf/web/test/WebTest.java rename to libjf-web-v1/src/testmod/java/io/gitlab/jfronny/libjf/web/test/WebTest.java index a92f49f..9901bdc 100644 --- a/libjf-web-v0/src/testmod/java/io/gitlab/jfronny/libjf/web/test/WebTest.java +++ b/libjf-web-v1/src/testmod/java/io/gitlab/jfronny/libjf/web/test/WebTest.java @@ -1,10 +1,8 @@ package io.gitlab.jfronny.libjf.web.test; import io.gitlab.jfronny.libjf.LibJf; -import io.gitlab.jfronny.libjf.web.api.WebInit; -import io.gitlab.jfronny.libjf.web.api.WebServer; -import io.gitlab.jfronny.libjf.web.impl.util.bluemapcore.HttpResponse; -import io.gitlab.jfronny.libjf.web.impl.util.bluemapcore.HttpStatusCode; +import io.gitlab.jfronny.libjf.web.api.v1.*; +import io.gitlab.jfronny.libjf.web.impl.util.HttpResponseImpl; import net.fabricmc.loader.api.FabricLoader; import java.io.IOException; @@ -14,8 +12,11 @@ import java.nio.file.Path; public class WebTest implements WebInit { @Override public void register(WebServer api) { - Path sourcePath = FabricLoader.getInstance().getModContainer("libjf-web-v0-testmod").get().findPath("test.html").get(); - LibJf.LOGGER.info(api.register("/test/0.html", request -> new HttpResponse(HttpStatusCode.OK).setData(Files.readString(sourcePath)))); + Path sourcePath = FabricLoader.getInstance() + .getModContainer("libjf-web-v1-testmod") + .flatMap(modContainer -> modContainer.findPath("test.html")) + .orElseThrow(); + LibJf.LOGGER.info(api.register("/test/0.html", request -> request.createResponse(HttpStatusCode.OK).setData(Files.readString(sourcePath)))); try { LibJf.LOGGER.info(api.registerFile("/test/1.html", sourcePath, false)); LibJf.LOGGER.info(api.registerFile("/test/2.html", sourcePath, true)); diff --git a/libjf-web-v0/src/testmod/resources/fabric.mod.json b/libjf-web-v1/src/testmod/resources/fabric.mod.json similarity index 90% rename from libjf-web-v0/src/testmod/resources/fabric.mod.json rename to libjf-web-v1/src/testmod/resources/fabric.mod.json index 01f70a7..bb77d58 100644 --- a/libjf-web-v0/src/testmod/resources/fabric.mod.json +++ b/libjf-web-v1/src/testmod/resources/fabric.mod.json @@ -1,6 +1,6 @@ { "schemaVersion": 1, - "id": "libjf-web-v0-testmod", + "id": "libjf-web-v1-testmod", "name": "LibJF Web", "version": "1.0", "environment": "*", diff --git a/libjf-web-v0/src/testmod/resources/test.html b/libjf-web-v1/src/testmod/resources/test.html similarity index 100% rename from libjf-web-v0/src/testmod/resources/test.html rename to libjf-web-v1/src/testmod/resources/test.html diff --git a/settings.gradle.kts b/settings.gradle.kts index db592b1..ee0e582 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -22,6 +22,6 @@ include("libjf-data-manipulation-v0") include("libjf-devutil") include("libjf-translate-v1") include("libjf-unsafe-v0") -include("libjf-web-v0") +include("libjf-web-v1") include("libjf-config-compiler-plugin-v2") From 3acc4b2420696ce508711e79c2f29a8d649f3da7 Mon Sep 17 00:00:00 2001 From: JFronny Date: Wed, 30 Aug 2023 22:18:34 +0200 Subject: [PATCH 6/7] feat(web): represent virtual hosts as tree and avoid collisions --- .../libjf/web/api/v1/AdvancedSubServer.java | 6 - .../libjf/web/api/v1/ContentProvider.java | 7 - .../hosted => api/v1}/HttpRequestHandler.java | 17 ++- .../jfronny/libjf/web/api/v1/PathSegment.java | 50 +++++++ .../jfronny/libjf/web/api/v1/SubServer.java | 7 - .../libjf/web/api/v1/VirtualHostNode.java | 10 ++ .../v1/{WebInit.java => WebEntrypoint.java} | 2 +- .../jfronny/libjf/web/api/v1/WebServer.java | 15 ++- .../gitlab/jfronny/libjf/web/impl/JfWeb.java | 3 +- .../libjf/web/impl/RequestHandler.java | 52 ------- .../web/impl/{ => host}/DefaultFileHost.java | 8 +- .../web/impl/host/ReadOnSendDirNode.java | 38 ++++++ .../libjf/web/impl/host/RequestHandler.java | 29 ++++ .../web/impl/host/VirtualHostBranch.java | 47 +++++++ .../libjf/web/impl/util/RunnableEvent.java | 12 ++ .../jfronny/libjf/web/impl/util/WebPaths.java | 13 +- .../web/impl/variant/AbstractWebServer.java | 127 ++++++------------ .../impl/variant/hosted/HostedWebServer.java | 8 +- .../web/impl/variant/hosted/HttpServer.java | 1 + .../web/impl/variant/shared/HttpDecoder.java | 12 +- .../impl/variant/shared/SharedWebServer.java | 15 ++- .../jfronny/libjf/web/test/WebTest.java | 9 +- 22 files changed, 280 insertions(+), 208 deletions(-) delete mode 100644 libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/AdvancedSubServer.java delete mode 100644 libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/ContentProvider.java rename libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/{impl/variant/hosted => api/v1}/HttpRequestHandler.java (78%) create mode 100644 libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/PathSegment.java delete mode 100644 libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/SubServer.java create mode 100644 libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/VirtualHostNode.java rename libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/{WebInit.java => WebEntrypoint.java} (71%) delete mode 100644 libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/RequestHandler.java rename libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/{ => host}/DefaultFileHost.java (76%) create mode 100644 libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/host/ReadOnSendDirNode.java create mode 100644 libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/host/RequestHandler.java create mode 100644 libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/host/VirtualHostBranch.java create mode 100644 libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/RunnableEvent.java diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/AdvancedSubServer.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/AdvancedSubServer.java deleted file mode 100644 index 9748540..0000000 --- a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/AdvancedSubServer.java +++ /dev/null @@ -1,6 +0,0 @@ -package io.gitlab.jfronny.libjf.web.api.v1; - -public interface AdvancedSubServer extends SubServer { - void onStop(); - void onStart(); -} diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/ContentProvider.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/ContentProvider.java deleted file mode 100644 index 72d99e5..0000000 --- a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/ContentProvider.java +++ /dev/null @@ -1,7 +0,0 @@ -package io.gitlab.jfronny.libjf.web.api.v1; - -import java.io.IOException; - -public interface ContentProvider { - HttpResponse handle(HttpRequest request) throws IOException; -} diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/hosted/HttpRequestHandler.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/HttpRequestHandler.java similarity index 78% rename from libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/hosted/HttpRequestHandler.java rename to libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/HttpRequestHandler.java index 8e2cd9f..2b8647e 100644 --- a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/hosted/HttpRequestHandler.java +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/HttpRequestHandler.java @@ -22,14 +22,19 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package io.gitlab.jfronny.libjf.web.impl.variant.hosted; +package io.gitlab.jfronny.libjf.web.api.v1; -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.util.HttpRequestImpl; -import io.gitlab.jfronny.libjf.web.impl.util.HttpResponseImpl; +import io.gitlab.jfronny.libjf.web.impl.host.VirtualHostBranch; + +import java.io.IOException; @FunctionalInterface public interface HttpRequestHandler { - HttpResponse handle(HttpRequest request); + HttpResponse handle(HttpRequest request) throws IOException; + + default VirtualHostNode asHostNode() { + VirtualHostBranch impl = new VirtualHostBranch(); + impl.setContent(this); + return impl; + } } diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/PathSegment.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/PathSegment.java new file mode 100644 index 0000000..0129d97 --- /dev/null +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/PathSegment.java @@ -0,0 +1,50 @@ +package io.gitlab.jfronny.libjf.web.api.v1; + +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +public record PathSegment(String segment, @Nullable PathSegment next) { + public PathSegment(String segment, @Nullable PathSegment next) { + if (segment.isEmpty() || segment.equals(".") || segment.contains("/")) { + PathSegment from = Objects.requireNonNull(of(segment, next)); + this.segment = from.segment; + this.next = from.next; + } else { + this.segment = segment; + this.next = next; + } + } + + public PathSegment(String path) { + this(path, null); + } + + @Override + public String toString() { + return next == null ? segment : segment + "/" + next; + } + + public PathSegment concat(@Nullable PathSegment seg) { + return seg == null ? this : new PathSegment(segment, next == null ? seg : next.concat(seg)); + } + + public static @Nullable PathSegment concat(@Nullable PathSegment seg1, @Nullable PathSegment seg2) { + return seg1 == null ? seg2 : seg1.concat(seg2); + } + + public static @Nullable PathSegment of(String path) { + return of(path, null); + } + + private static @Nullable PathSegment of(String path, PathSegment next) { + Deque segmentStack = new LinkedList<>(); + for (String s : path.split("/")) { + if (s.isEmpty() || s.equals(".")) continue; + if (s.equals("..")) segmentStack.pop(); + segmentStack.push(s); + } + for (String s : segmentStack) next = new PathSegment(s, next); + return next; + } +} diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/SubServer.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/SubServer.java deleted file mode 100644 index 816d035..0000000 --- a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/SubServer.java +++ /dev/null @@ -1,7 +0,0 @@ -package io.gitlab.jfronny.libjf.web.api.v1; - -import java.io.IOException; - -public interface SubServer { - HttpResponse handle(HttpRequest request, String[] segments) throws IOException; -} diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/VirtualHostNode.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/VirtualHostNode.java new file mode 100644 index 0000000..a26c456 --- /dev/null +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/VirtualHostNode.java @@ -0,0 +1,10 @@ +package io.gitlab.jfronny.libjf.web.api.v1; + +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; + +@FunctionalInterface +public interface VirtualHostNode { + HttpResponse handle(HttpRequest request, @Nullable PathSegment path) throws IOException; +} diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/WebInit.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/WebEntrypoint.java similarity index 71% rename from libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/WebInit.java rename to libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/WebEntrypoint.java index 6a15e23..3196e75 100644 --- a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/WebInit.java +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/WebEntrypoint.java @@ -1,5 +1,5 @@ package io.gitlab.jfronny.libjf.web.api.v1; -public interface WebInit { +public interface WebEntrypoint { void register(WebServer api); } diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/WebServer.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/WebServer.java index 7038ec6..ce3e085 100644 --- a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/WebServer.java +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/api/v1/WebServer.java @@ -6,13 +6,16 @@ import java.io.IOException; import java.nio.file.Path; public interface WebServer { - String register(String webPath, ContentProvider provider); - String registerFile(String webPath, Path file, boolean readOnSend) throws IOException; - String registerFile(String webPath, byte[] data, String contentType); - String registerDir(String webPath, Path dir, boolean readOnSend) throws IOException; - String registerSubServer(String webPath, SubServer subServer); - String registerSubServer(String webPath, AdvancedSubServer subServer); + String register(PathSegment path, VirtualHostNode provider); + default String register(PathSegment path, HttpRequestHandler provider) { + return register(path, provider.asHostNode()); + } + String registerFile(PathSegment path, Path file, boolean readOnSend) throws IOException; + String registerFile(PathSegment path, byte[] data, String contentType); + String registerDir(PathSegment path, Path dir, boolean readOnSend) throws IOException; String getServerRoot(); + void onStart(Runnable listener); + void onStop(Runnable listener); void stop(); void queueRestart(Runnable callback); boolean isActive(); diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/JfWeb.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/JfWeb.java index 9ecf1b8..d883aea 100644 --- a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/JfWeb.java +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/JfWeb.java @@ -6,6 +6,7 @@ import io.gitlab.jfronny.libjf.Flags; import io.gitlab.jfronny.libjf.LibJf; import io.gitlab.jfronny.libjf.coprocess.CoProcess; import io.gitlab.jfronny.libjf.web.api.v1.WebServer; +import io.gitlab.jfronny.libjf.web.impl.host.RequestHandler; import io.gitlab.jfronny.libjf.web.impl.variant.hosted.HostedWebServer; import io.gitlab.jfronny.libjf.web.impl.variant.shared.SharedWebServer; import net.fabricmc.api.EnvType; @@ -15,8 +16,6 @@ import net.fabricmc.loader.api.FabricLoader; import net.minecraft.text.Text; import org.jetbrains.annotations.ApiStatus; -import java.time.chrono.IsoEra; - import static net.minecraft.server.command.CommandManager.literal; public class JfWeb implements CoProcess, ModInitializer { diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/RequestHandler.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/RequestHandler.java deleted file mode 100644 index 34b3d1e..0000000 --- a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/RequestHandler.java +++ /dev/null @@ -1,52 +0,0 @@ -package io.gitlab.jfronny.libjf.web.impl; - -import io.gitlab.jfronny.libjf.LibJf; -import io.gitlab.jfronny.libjf.web.api.v1.*; -import io.gitlab.jfronny.libjf.web.impl.util.*; -import io.gitlab.jfronny.libjf.web.impl.variant.hosted.HttpRequestHandler; - -import java.util.*; - -public class RequestHandler implements HttpRequestHandler { - public Map subServers = new HashMap<>(); - public Map contentProviders = new HashMap<>(); - - @Override - public HttpResponse handle(HttpRequest request) { - HttpResponse resp = null; - try { - String webPath = WebPaths.simplify(request.getPath()); - if (webPath.isEmpty()) - webPath = "index.html"; - if (contentProviders.containsKey(webPath)) { - resp = contentProviders.get(webPath).handle(request); - } - else { - String[] segments = webPath.split("/"); - for (int i = segments.length - 1; i >= 0; i--) { - String wp = WebPaths.concat(Arrays.copyOfRange(segments, 0, i)); - if (subServers.containsKey(wp)) { - resp = subServers.get(wp).handle(request, Arrays.copyOfRange(segments, i, segments.length)); - break; - } - } - if (resp == null) { - resp = new HttpResponseImpl(HttpStatusCode.NOT_FOUND); - } - } - } catch (Throwable e) { - LibJf.LOGGER.error("Caught error while sending", e); - resp = new HttpResponseImpl(HttpStatusCode.INTERNAL_SERVER_ERROR); - } - if (resp.getHeader("Cache-Control").isEmpty()) - resp.addHeader("Cache-Control", "no-cache"); - if (resp.getHeader("Server").isEmpty()) - resp.addHeader("Server", "LibWeb using BlueMapCore"); - return resp; - } - - public void clear() { - subServers.clear(); - contentProviders.clear(); - } -} diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/DefaultFileHost.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/host/DefaultFileHost.java similarity index 76% rename from libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/DefaultFileHost.java rename to libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/host/DefaultFileHost.java index 17192a6..738e644 100644 --- a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/DefaultFileHost.java +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/host/DefaultFileHost.java @@ -1,7 +1,7 @@ -package io.gitlab.jfronny.libjf.web.impl; +package io.gitlab.jfronny.libjf.web.impl.host; import io.gitlab.jfronny.libjf.LibJf; -import io.gitlab.jfronny.libjf.web.api.v1.WebInit; +import io.gitlab.jfronny.libjf.web.api.v1.WebEntrypoint; import io.gitlab.jfronny.libjf.web.api.v1.WebServer; import net.fabricmc.loader.api.FabricLoader; @@ -9,7 +9,7 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -public class DefaultFileHost implements WebInit { +public class DefaultFileHost implements WebEntrypoint { @Override public void register(WebServer api) { Path p = FabricLoader.getInstance().getConfigDir().resolve("wwwroot"); @@ -21,7 +21,7 @@ public class DefaultFileHost implements WebInit { } } try { - LibJf.LOGGER.info(api.registerDir("/", p, false)); + LibJf.LOGGER.info(api.registerDir(null, p, false)); } catch (IOException e) { LibJf.LOGGER.error("Could not register wwwroot", e); } diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/host/ReadOnSendDirNode.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/host/ReadOnSendDirNode.java new file mode 100644 index 0000000..0496155 --- /dev/null +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/host/ReadOnSendDirNode.java @@ -0,0 +1,38 @@ +package io.gitlab.jfronny.libjf.web.impl.host; + +import io.gitlab.jfronny.libjf.web.api.v1.*; +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.stream.Stream; + +public record ReadOnSendDirNode(Path fsPath) implements VirtualHostNode { + @Override + public HttpResponse handle(HttpRequest request, @Nullable PathSegment path) throws IOException { + return handle(request, path, fsPath); + } + + private static HttpResponse handle(HttpRequest request, @Nullable PathSegment path, Path fsPath) throws IOException { + if (path == null) { + if (Files.isRegularFile(fsPath) && Files.isReadable(fsPath)) { + HttpResponse resp = request.createResponse(HttpStatusCode.OK); + resp.addHeader("Content-Type", Files.probeContentType(fsPath)); + resp.addHeader("Content-Length", String.valueOf(Files.size(fsPath))); + resp.setData(Files.newInputStream(fsPath)); + return resp; + } else return request.createResponse(HttpStatusCode.NOT_FOUND); + } else { + if (!Files.isDirectory(fsPath)) return request.createResponse(HttpStatusCode.NOT_FOUND); + try (Stream s = Files.list(fsPath)) { + for (Path sub : s.toList()) { + if (path.segment().equals(sub.getFileName().toString())) { + return handle(request, path.next(), sub); + } + } + } + return request.createResponse(HttpStatusCode.NOT_FOUND); + } + } +} diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/host/RequestHandler.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/host/RequestHandler.java new file mode 100644 index 0000000..1f480ac --- /dev/null +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/host/RequestHandler.java @@ -0,0 +1,29 @@ +package io.gitlab.jfronny.libjf.web.impl.host; + +import io.gitlab.jfronny.libjf.LibJf; +import io.gitlab.jfronny.libjf.web.api.v1.*; +import io.gitlab.jfronny.libjf.web.api.v1.HttpRequestHandler; + +public class RequestHandler extends VirtualHostBranch implements HttpRequestHandler { + @Override + public HttpResponse handle(HttpRequest request) { + HttpResponse resp; + try { + PathSegment path = PathSegment.of(request.getPath()); + if (path == null) path = new PathSegment("index.html"); + resp = handle(request, path); + } catch (Throwable e) { + LibJf.LOGGER.error("Caught error while sending", e); + resp = request.createResponse(HttpStatusCode.INTERNAL_SERVER_ERROR); + } + if (resp.getHeader("Cache-Control").isEmpty()) + resp.addHeader("Cache-Control", "no-cache"); + if (resp.getHeader("Server").isEmpty()) + resp.addHeader("Server", "LibWeb using BlueMapCore"); + return resp; + } + + public void clear() { + children.clear(); + } +} diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/host/VirtualHostBranch.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/host/VirtualHostBranch.java new file mode 100644 index 0000000..c66333b --- /dev/null +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/host/VirtualHostBranch.java @@ -0,0 +1,47 @@ +package io.gitlab.jfronny.libjf.web.impl.host; + +import io.gitlab.jfronny.libjf.web.api.v1.*; +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; +import java.util.*; + +public class VirtualHostBranch implements VirtualHostNode { + protected final Map children = new HashMap<>(); + protected HttpRequestHandler content; + + @Override + public HttpResponse handle(HttpRequest request, @Nullable PathSegment path) throws IOException { + if (path == null) { + if (content != null) return content.handle(request); + else return request.createResponse(HttpStatusCode.NOT_FOUND); + } else { + VirtualHostNode child = children.get(path.segment()); + if (child == null) return request.createResponse(HttpStatusCode.NOT_FOUND); + else return child.handle(request, path.next()); + } + } + + public void register(PathSegment path, VirtualHostNode node) { + Objects.requireNonNull(path); + if (path.next() == null) { + if (children.containsKey(path.segment())) { + VirtualHostNode childNode = children.get(path.segment()); + if (node instanceof VirtualHostBranch next + && childNode instanceof VirtualHostBranch source) { + if (next.content != null) source.setContent(next.content); + next.children.forEach((k, v) -> source.register(PathSegment.of(k), v)); + } else throw new UnsupportedOperationException("VirtualHostNode already exists for path and merging is unsupported for " + childNode.getClass() + " and " + node.getClass()); + } else children.put(path.segment(), node); + } else { + VirtualHostNode child = children.computeIfAbsent(path.segment(), s -> new VirtualHostBranch()); + if (child instanceof VirtualHostBranch source) source.register(path.next(), node); + else throw new UnsupportedOperationException("Cannot register VirtualHostNode to non-branch VirtualHostNode " + child.getClass()); + } + } + + public void setContent(HttpRequestHandler content) { + if (this.content != null) throw new UnsupportedOperationException("Content already set for virtual host node"); + this.content = Objects.requireNonNull(content); + } +} diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/RunnableEvent.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/RunnableEvent.java new file mode 100644 index 0000000..9deb8af --- /dev/null +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/RunnableEvent.java @@ -0,0 +1,12 @@ +package io.gitlab.jfronny.libjf.web.impl.util; + +import net.fabricmc.fabric.api.event.Event; +import net.fabricmc.fabric.api.event.EventFactory; + +public class RunnableEvent { + public static Event create() { + return EventFactory.createArrayBacked(Runnable.class, listeners -> () -> { + for (Runnable listener : listeners) listener.run(); + }); + } +} diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/WebPaths.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/WebPaths.java index 1a30629..df57a5c 100644 --- a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/WebPaths.java +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/WebPaths.java @@ -1,20 +1,10 @@ package io.gitlab.jfronny.libjf.web.impl.util; -import io.gitlab.jfronny.libjf.web.impl.JfWebConfig; - public class WebPaths { public static String concat(String s1, String s2) { return simplify(s1) + "/" + simplify(s2); } - public static String concat(String[] elements) { - StringBuilder s = new StringBuilder(); - for (String element : elements) { - s.append("/").append(element); - } - return simplify(s.toString()); - } - public static String getHttp(String ip) { if (!ip.startsWith("http")) ip = "http://" + ip; @@ -36,8 +26,7 @@ public class WebPaths { StringBuilder q = new StringBuilder(); for (String s1 : simplifyPart(s, false).split("/")) { String w = simplifyPart(s1, true); - if (w != null && w.length() != 0) - q.append("/").append(w); + if (w != null && !w.isEmpty()) q.append("/").append(w); } String result = simplifyPart(q.toString(), false); if (http) result = "http://" + result; diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/AbstractWebServer.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/AbstractWebServer.java index 4318440..9d3402a 100644 --- a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/AbstractWebServer.java +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/AbstractWebServer.java @@ -2,16 +2,17 @@ package io.gitlab.jfronny.libjf.web.impl.variant; import io.gitlab.jfronny.libjf.LibJf; import io.gitlab.jfronny.libjf.web.api.v1.*; -import io.gitlab.jfronny.libjf.web.impl.*; -import io.gitlab.jfronny.libjf.web.impl.util.*; +import io.gitlab.jfronny.libjf.web.impl.JfWebConfig; +import io.gitlab.jfronny.libjf.web.impl.host.*; +import io.gitlab.jfronny.libjf.web.impl.util.RunnableEvent; +import io.gitlab.jfronny.libjf.web.impl.util.WebPaths; +import net.fabricmc.fabric.api.event.Event; import net.fabricmc.loader.api.FabricLoader; import org.jetbrains.annotations.ApiStatus; -import javax.management.openmbean.KeyAlreadyExistsException; import java.io.*; import java.nio.file.Files; import java.nio.file.Path; -import java.util.Objects; import java.util.stream.Stream; public abstract class AbstractWebServer implements WebServer { @@ -28,20 +29,16 @@ public abstract class AbstractWebServer implements WebServer { } @Override - public String register(String webPath, ContentProvider provider) { - webPath = WebPaths.simplify(webPath); - if (handler.contentProviders.containsKey(webPath)) - throw new KeyAlreadyExistsException("A ContentProvider already exists at that address (" + handler.contentProviders.get(webPath).getClass() + ")"); - handler.contentProviders.put(webPath, provider); - return WebPaths.concat(getServerRoot(), webPath); + public String register(PathSegment path, VirtualHostNode provider) { + handler.register(path, provider); + return toUrl(path); } @Override - public String registerFile(String webPath, Path file, boolean readOnSend) throws IOException { + public String registerFile(PathSegment path, Path file, boolean readOnSend) throws IOException { if (readOnSend) { - if (!Files.exists(file)) - throw new FileNotFoundException(); - register(webPath, s -> { + if (!Files.exists(file)) throw new FileNotFoundException(); + return register(path, s -> { HttpResponse resp = HttpResponse.create(HttpStatusCode.OK); resp.addHeader("Content-Type", Files.probeContentType(file)); resp.addHeader("Content-Length", String.valueOf(Files.size(file))); @@ -49,16 +46,14 @@ public abstract class AbstractWebServer implements WebServer { resp.setData(fs); return resp; }); - return WebPaths.concat(getServerRoot(), webPath); - } - else { - return registerFile(webPath, Files.readAllBytes(file), Files.probeContentType(file)); + } else { + return registerFile(path, Files.readAllBytes(file), Files.probeContentType(file)); } } @Override - public String registerFile(String webPath, byte[] data, String contentType) { - return register(webPath, s -> { + public String registerFile(PathSegment path, byte[] data, String contentType) { + return register(path, s -> { HttpResponse resp = HttpResponse.create(HttpStatusCode.OK); resp.addHeader("Content-Type", contentType); resp.addHeader("Content-Length", String.valueOf(data.length)); @@ -69,88 +64,54 @@ public abstract class AbstractWebServer implements WebServer { } @Override - public String registerDir(String webPath, Path dir, boolean readOnSend) throws IOException { - try (Stream contentPath = Files.walk(dir)) { - if (readOnSend) { - return registerSubServer(webPath, (s, t) -> { - final boolean[] c = {false}; - final Path[] p_f = new Path[1]; - contentPath.filter(Files::isRegularFile) - .filter(Files::isReadable) - .forEach(q -> { - if (c[0]) - return; - Path p = dir.toAbsolutePath().relativize(q.toAbsolutePath()); - String wp = webPath; - for (Path path : p) { - wp = WebPaths.concat(wp, path.toString()); - } - if (Objects.equals(WebPaths.simplify(wp), WebPaths.simplify(WebPaths.concat(t)))) { - p_f[0] = q; - c[0] = true; - } - }); - HttpResponse resp; - if (c[0]) { - resp = HttpResponse.create(HttpStatusCode.OK); - resp.addHeader("Content-Type", Files.probeContentType(p_f[0])); - resp.addHeader("Content-Length", String.valueOf(Files.size(p_f[0]))); - FileInputStream fs = new FileInputStream(p_f[0].toFile()); - resp.setData(fs); - } else { - resp = HttpResponse.create(HttpStatusCode.NOT_FOUND); - } - return resp; - }); - } else { + public String registerDir(PathSegment path, Path dir, boolean readOnSend) throws IOException { + if (readOnSend) return register(path, new ReadOnSendDirNode(dir)); + else { + try (Stream contentPath = Files.walk(dir)) { contentPath.filter(Files::isRegularFile) .filter(Files::isReadable) .forEach(s -> { - Path p = dir.toAbsolutePath().relativize(s.toAbsolutePath()); - String wp = webPath; - for (Path path : p) wp = WebPaths.concat(wp, path.toString()); + Path p = dir.toAbsolutePath().normalize().relativize(s.toAbsolutePath().normalize()); + PathSegment subPath = path.concat(PathSegment.of(p.toString())); try { - registerFile(wp, s, false); + registerFile(subPath, s, false); } catch (IOException e) { LibJf.LOGGER.error("Could not register static file", e); } }); } - return WebPaths.concat(getServerRoot(), webPath); + return toUrl(path); } } - @Override - public String registerSubServer(String webPath, SubServer subServer) { - return registerSubServer(webPath, new AdvancedSubServer() { - @Override - public void onStop() { - } - - @Override - public void onStart() { - } - - @Override - public HttpResponse handle(HttpRequest request, String[] segments) throws IOException { - return subServer.handle(request, segments); - } - }); + private String toUrl(PathSegment path) { + return WebPaths.concat(getServerRoot(), path.toString()); } + private final Event onStart = RunnableEvent.create(); @Override - public String registerSubServer(String webPath, AdvancedSubServer subServer) { - webPath = WebPaths.simplify(webPath); - if (handler.subServers.containsKey(webPath)) - throw new KeyAlreadyExistsException("A Subserver already exists at that address (" + handler.subServers.get(webPath).getClass() + ")"); - handler.subServers.put(webPath, subServer); - return WebPaths.concat(getServerRoot(), webPath); + public void onStart(Runnable listener) { + onStart.register(listener); + } + + protected void emitStart() { + onStart.invoker().run(); + } + + private final Event onStop = RunnableEvent.create(); + @Override + public void onStop(Runnable listener) { + onStop.register(listener); + } + + protected void emitStop() { + onStop.invoker().run(); } protected void performRegistrations() { if (JfWebConfig.enableFileHost) dfh.register(this); - FabricLoader.getInstance().getEntrypointContainers(LibJf.MOD_ID + ":web", WebInit.class).forEach(entrypoint -> { - WebInit init = entrypoint.getEntrypoint(); + FabricLoader.getInstance().getEntrypointContainers(LibJf.MOD_ID + ":web", WebEntrypoint.class).forEach(entrypoint -> { + WebEntrypoint init = entrypoint.getEntrypoint(); init.register(this); }); } diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/hosted/HostedWebServer.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/hosted/HostedWebServer.java index defb94a..99974b6 100644 --- a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/hosted/HostedWebServer.java +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/hosted/HostedWebServer.java @@ -1,8 +1,8 @@ package io.gitlab.jfronny.libjf.web.impl.variant.hosted; import io.gitlab.jfronny.libjf.LibJf; -import io.gitlab.jfronny.libjf.web.api.v1.AdvancedSubServer; import io.gitlab.jfronny.libjf.web.impl.*; +import io.gitlab.jfronny.libjf.web.impl.host.RequestHandler; import io.gitlab.jfronny.libjf.web.impl.variant.AbstractWebServer; public class HostedWebServer extends AbstractWebServer { @@ -23,7 +23,7 @@ public class HostedWebServer extends AbstractWebServer { @Override public synchronized void stop() { - for (AdvancedSubServer subServer : handler.subServers.values()) subServer.onStop(); + emitStop(); if (server != null) { try { server.close(); @@ -51,9 +51,7 @@ public class HostedWebServer extends AbstractWebServer { stop(); LibJf.LOGGER.error("Server could not be readied", e); } - for (AdvancedSubServer subServer : handler.subServers.values()) { - subServer.onStart(); - } + emitStart(); callback.run(); } diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/hosted/HttpServer.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/hosted/HttpServer.java index c01c4fe..91a6ace 100644 --- a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/hosted/HttpServer.java +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/hosted/HttpServer.java @@ -25,6 +25,7 @@ package io.gitlab.jfronny.libjf.web.impl.variant.hosted; import io.gitlab.jfronny.libjf.LibJf; +import io.gitlab.jfronny.libjf.web.api.v1.HttpRequestHandler; import java.io.IOException; import java.net.*; diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/shared/HttpDecoder.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/shared/HttpDecoder.java index fb87c97..dc041bf 100644 --- a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/shared/HttpDecoder.java +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/shared/HttpDecoder.java @@ -4,9 +4,6 @@ import io.gitlab.jfronny.libjf.LibJf; 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.gitlab.jfronny.libjf.web.impl.RequestHandler; -import io.gitlab.jfronny.libjf.web.impl.util.HttpRequestImpl; -import io.gitlab.jfronny.libjf.web.impl.util.HttpResponseImpl; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.*; @@ -34,18 +31,25 @@ public class HttpDecoder extends ChannelInboundHandlerAdapter { buf.markReaderIndex(); boolean passOn = true; try { + // Check whether buf starts with an HTTP method, as a request would Trie current = METHOD; while (buf.isReadable() && current != null && current.content == null) current = current.next.get((char) buf.readByte()); if (current == null || current.content == null) return; + // Method identified, this is HTTP! + passOn = false; + // Read all data from buffer buf.resetReaderIndex(); byte[] data = new byte[buf.readableBytes()]; buf.readBytes(data); + buf.release(); + // Parse and process request try (ByteArrayInputStream is = new ByteArrayInputStream(data); HttpResponse response = JfWeb.getHandler().handle(HttpRequest.read(is)); ByteArrayOutputStream os = new ByteArrayOutputStream()) { + // Write and send response response.write(os); os.flush(); ctx.pipeline() @@ -53,8 +57,6 @@ public class HttpDecoder extends ChannelInboundHandlerAdapter { .writeAndFlush(Unpooled.wrappedBuffer(os.toByteArray())) .addListener(ChannelFutureListener.CLOSE); } - buf.release(); - passOn = false; } catch (RuntimeException re) { LibJf.LOGGER.error("Could not process HTTP", re); } finally { diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/shared/SharedWebServer.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/shared/SharedWebServer.java index 4892ba1..6db7d76 100644 --- a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/shared/SharedWebServer.java +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/shared/SharedWebServer.java @@ -1,19 +1,20 @@ package io.gitlab.jfronny.libjf.web.impl.variant.shared; -import io.gitlab.jfronny.libjf.web.api.v1.AdvancedSubServer; -import io.gitlab.jfronny.libjf.web.impl.*; +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 java.util.LinkedHashSet; -import java.util.Set; +import java.util.*; public class SharedWebServer extends AbstractWebServer { public static final ClaimPool gamePort = new ClaimPool<>(); public static final Set onActive = new LinkedHashSet<>(); public static void emitActive() { - for (Runnable runnable : onActive) runnable.run(); + for (Iterator iterator = onActive.iterator(); iterator.hasNext(); iterator.remove()) { + Runnable runnable = iterator.next(); + runnable.run(); + } } public SharedWebServer(RequestHandler handler) { @@ -35,10 +36,10 @@ public class SharedWebServer extends AbstractWebServer { @Override public void queueRestart(Runnable callback) { onActive.add(() -> { - for (AdvancedSubServer subServer : handler.subServers.values()) subServer.onStop(); + emitStop(); handler.clear(); performRegistrations(); - for (AdvancedSubServer subServer : handler.subServers.values()) subServer.onStart(); + emitStart(); callback.run(); }); if (isActive()) emitActive(); diff --git a/libjf-web-v1/src/testmod/java/io/gitlab/jfronny/libjf/web/test/WebTest.java b/libjf-web-v1/src/testmod/java/io/gitlab/jfronny/libjf/web/test/WebTest.java index 9901bdc..65e8237 100644 --- a/libjf-web-v1/src/testmod/java/io/gitlab/jfronny/libjf/web/test/WebTest.java +++ b/libjf-web-v1/src/testmod/java/io/gitlab/jfronny/libjf/web/test/WebTest.java @@ -2,24 +2,23 @@ package io.gitlab.jfronny.libjf.web.test; import io.gitlab.jfronny.libjf.LibJf; import io.gitlab.jfronny.libjf.web.api.v1.*; -import io.gitlab.jfronny.libjf.web.impl.util.HttpResponseImpl; import net.fabricmc.loader.api.FabricLoader; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -public class WebTest implements WebInit { +public class WebTest implements WebEntrypoint { @Override public void register(WebServer api) { Path sourcePath = FabricLoader.getInstance() .getModContainer("libjf-web-v1-testmod") .flatMap(modContainer -> modContainer.findPath("test.html")) .orElseThrow(); - LibJf.LOGGER.info(api.register("/test/0.html", request -> request.createResponse(HttpStatusCode.OK).setData(Files.readString(sourcePath)))); + LibJf.LOGGER.info(api.register(PathSegment.of("test/0.html"), request -> request.createResponse(HttpStatusCode.OK).setData(Files.readString(sourcePath)))); try { - LibJf.LOGGER.info(api.registerFile("/test/1.html", sourcePath, false)); - LibJf.LOGGER.info(api.registerFile("/test/2.html", sourcePath, true)); + LibJf.LOGGER.info(api.registerFile(PathSegment.of("test/1.html"), sourcePath, false)); + LibJf.LOGGER.info(api.registerFile(PathSegment.of("test/2.html"), sourcePath, true)); } catch (IOException e) { throw new RuntimeException("Could not register hosted files", e); } From 915f60b6b4a6f81d28049fabc5928059d848e02e Mon Sep 17 00:00:00 2001 From: JFronny Date: Wed, 30 Aug 2023 23:15:43 +0200 Subject: [PATCH 7/7] feat(web): move main port hooking to lightweight separate library for interoperability --- libjf-mainhttp-v0/build.gradle.kts | 12 ++++++ .../mainhttp/api/v0/MainHttpHandler.java | 11 +++++ .../libjf/mainhttp/api/v0/ServerState.java | 17 ++++++++ .../libjf/mainhttp/impl}/HttpDecoder.java | 28 ++++--------- .../jfronny/libjf/mainhttp/impl/MainHttp.java | 42 +++++++++++++++++++ .../impl/mixin/JfMainHTTPMixinPlugin.java | 10 ++--- .../impl/mixin/ServerNetworkIo$1Mixin.java | 4 +- .../impl/mixin/ServerNetworkIoMixin.java | 13 +++--- .../libjf/mainhttp}/impl/util/ClaimPool.java | 2 +- .../libjf/mainhttp/impl/util}/Trie.java | 2 +- .../src/main/resources/fabric.mod.json | 28 +++++++++++++ .../resources/libjf-mainhttp-v0.mixins.json | 4 +- libjf-web-v1/build.gradle.kts | 1 + .../libjf/web/impl/util/HttpResponseImpl.java | 13 +++--- .../variant/shared/MainHttpHandlerImpl.java | 38 +++++++++++++++++ .../impl/variant/shared/SharedWebServer.java | 10 ++--- .../src/main/resources/fabric.mod.json | 5 ++- settings.gradle.kts | 15 ++++--- 18 files changed, 199 insertions(+), 56 deletions(-) create mode 100644 libjf-mainhttp-v0/build.gradle.kts create mode 100644 libjf-mainhttp-v0/src/main/java/io/gitlab/jfronny/libjf/mainhttp/api/v0/MainHttpHandler.java create mode 100644 libjf-mainhttp-v0/src/main/java/io/gitlab/jfronny/libjf/mainhttp/api/v0/ServerState.java rename {libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/shared => libjf-mainhttp-v0/src/main/java/io/gitlab/jfronny/libjf/mainhttp/impl}/HttpDecoder.java (61%) create mode 100644 libjf-mainhttp-v0/src/main/java/io/gitlab/jfronny/libjf/mainhttp/impl/MainHttp.java rename libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/mixin/JfWebMixinPlugin.java => libjf-mainhttp-v0/src/main/java/io/gitlab/jfronny/libjf/mainhttp/impl/mixin/JfMainHTTPMixinPlugin.java (82%) rename {libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web => libjf-mainhttp-v0/src/main/java/io/gitlab/jfronny/libjf/mainhttp}/impl/mixin/ServerNetworkIo$1Mixin.java (86%) rename {libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web => libjf-mainhttp-v0/src/main/java/io/gitlab/jfronny/libjf/mainhttp}/impl/mixin/ServerNetworkIoMixin.java (67%) rename {libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web => libjf-mainhttp-v0/src/main/java/io/gitlab/jfronny/libjf/mainhttp}/impl/util/ClaimPool.java (94%) rename {libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/shared => libjf-mainhttp-v0/src/main/java/io/gitlab/jfronny/libjf/mainhttp/impl/util}/Trie.java (94%) create mode 100644 libjf-mainhttp-v0/src/main/resources/fabric.mod.json rename libjf-web-v1/src/main/resources/libjf-web-v1.mixins.json => libjf-mainhttp-v0/src/main/resources/libjf-mainhttp-v0.mixins.json (59%) create mode 100644 libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/shared/MainHttpHandlerImpl.java diff --git a/libjf-mainhttp-v0/build.gradle.kts b/libjf-mainhttp-v0/build.gradle.kts new file mode 100644 index 0000000..fd0c61f --- /dev/null +++ b/libjf-mainhttp-v0/build.gradle.kts @@ -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)) +} diff --git a/libjf-mainhttp-v0/src/main/java/io/gitlab/jfronny/libjf/mainhttp/api/v0/MainHttpHandler.java b/libjf-mainhttp-v0/src/main/java/io/gitlab/jfronny/libjf/mainhttp/api/v0/MainHttpHandler.java new file mode 100644 index 0000000..e1af3e2 --- /dev/null +++ b/libjf-mainhttp-v0/src/main/java/io/gitlab/jfronny/libjf/mainhttp/api/v0/MainHttpHandler.java @@ -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); +} diff --git a/libjf-mainhttp-v0/src/main/java/io/gitlab/jfronny/libjf/mainhttp/api/v0/ServerState.java b/libjf-mainhttp-v0/src/main/java/io/gitlab/jfronny/libjf/mainhttp/api/v0/ServerState.java new file mode 100644 index 0000000..15d9132 --- /dev/null +++ b/libjf-mainhttp-v0/src/main/java/io/gitlab/jfronny/libjf/mainhttp/api/v0/ServerState.java @@ -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(); + } +} diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/shared/HttpDecoder.java b/libjf-mainhttp-v0/src/main/java/io/gitlab/jfronny/libjf/mainhttp/impl/HttpDecoder.java similarity index 61% rename from libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/shared/HttpDecoder.java rename to libjf-mainhttp-v0/src/main/java/io/gitlab/jfronny/libjf/mainhttp/impl/HttpDecoder.java index dc041bf..28897eb 100644 --- a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/shared/HttpDecoder.java +++ b/libjf-mainhttp-v0/src/main/java/io/gitlab/jfronny/libjf/mainhttp/impl/HttpDecoder.java @@ -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.web.api.v1.HttpRequest; -import io.gitlab.jfronny.libjf.web.api.v1.HttpResponse; -import io.gitlab.jfronny.libjf.web.impl.JfWeb; +import io.gitlab.jfronny.libjf.mainhttp.impl.util.Trie; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.*; import org.jetbrains.annotations.NotNull; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; import java.util.List; public class HttpDecoder extends ChannelInboundHandlerAdapter { @@ -45,20 +40,13 @@ public class HttpDecoder extends ChannelInboundHandlerAdapter { byte[] data = new byte[buf.readableBytes()]; buf.readBytes(data); buf.release(); - // Parse and process request - try (ByteArrayInputStream is = new ByteArrayInputStream(data); - HttpResponse response = JfWeb.getHandler().handle(HttpRequest.read(is)); - ByteArrayOutputStream os = new ByteArrayOutputStream()) { - // Write and send response - response.write(os); - os.flush(); - ctx.pipeline() - .firstContext() - .writeAndFlush(Unpooled.wrappedBuffer(os.toByteArray())) - .addListener(ChannelFutureListener.CLOSE); - } + // Process request + ctx.pipeline() + .firstContext() + .writeAndFlush(Unpooled.wrappedBuffer(MainHttp.handle(data))) + .addListener(ChannelFutureListener.CLOSE); } catch (RuntimeException re) { - LibJf.LOGGER.error("Could not process HTTP", re); + MainHttp.LOGGER.error("Could not process HTTP", re); } finally { if (passOn) { buf.resetReaderIndex(); diff --git a/libjf-mainhttp-v0/src/main/java/io/gitlab/jfronny/libjf/mainhttp/impl/MainHttp.java b/libjf-mainhttp-v0/src/main/java/io/gitlab/jfronny/libjf/mainhttp/impl/MainHttp.java new file mode 100644 index 0000000..f820821 --- /dev/null +++ b/libjf-mainhttp-v0/src/main/java/io/gitlab/jfronny/libjf/mainhttp/impl/MainHttp.java @@ -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 ON_ACTIVATE = EventFactory.createArrayBacked(Runnable.class, listeners -> () -> { + for (Runnable listener : listeners) listener.run(); + }); + public static final ClaimPool 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 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; + } +} diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/mixin/JfWebMixinPlugin.java b/libjf-mainhttp-v0/src/main/java/io/gitlab/jfronny/libjf/mainhttp/impl/mixin/JfMainHTTPMixinPlugin.java similarity index 82% rename from libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/mixin/JfWebMixinPlugin.java rename to libjf-mainhttp-v0/src/main/java/io/gitlab/jfronny/libjf/mainhttp/impl/mixin/JfMainHTTPMixinPlugin.java index ef2f214..deb7953 100644 --- a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/mixin/JfWebMixinPlugin.java +++ b/libjf-mainhttp-v0/src/main/java/io/gitlab/jfronny/libjf/mainhttp/impl/mixin/JfMainHTTPMixinPlugin.java @@ -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.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; 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.Set; -public class JfWebMixinPlugin implements IMixinConfigPlugin { - private static final String MIXIN_PACKAGE = "io.gitlab.jfronny.libjf.web.impl.mixin."; +public class JfMainHTTPMixinPlugin implements IMixinConfigPlugin { + private static final String MIXIN_PACKAGE = "io.gitlab.jfronny.libjf.mainhttp.impl.mixin."; @Override public void onLoad(String mixinPackage) { @@ -23,7 +23,7 @@ public class JfWebMixinPlugin implements IMixinConfigPlugin { @Override public boolean shouldApplyMixin(String targetClassName, String 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); }; } diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/mixin/ServerNetworkIo$1Mixin.java b/libjf-mainhttp-v0/src/main/java/io/gitlab/jfronny/libjf/mainhttp/impl/mixin/ServerNetworkIo$1Mixin.java similarity index 86% rename from libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/mixin/ServerNetworkIo$1Mixin.java rename to libjf-mainhttp-v0/src/main/java/io/gitlab/jfronny/libjf/mainhttp/impl/mixin/ServerNetworkIo$1Mixin.java index a2a8e02..38c164c 100644 --- a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/mixin/ServerNetworkIo$1Mixin.java +++ b/libjf-mainhttp-v0/src/main/java/io/gitlab/jfronny/libjf/mainhttp/impl/mixin/ServerNetworkIo$1Mixin.java @@ -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 org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/mixin/ServerNetworkIoMixin.java b/libjf-mainhttp-v0/src/main/java/io/gitlab/jfronny/libjf/mainhttp/impl/mixin/ServerNetworkIoMixin.java similarity index 67% rename from libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/mixin/ServerNetworkIoMixin.java rename to libjf-mainhttp-v0/src/main/java/io/gitlab/jfronny/libjf/mainhttp/impl/mixin/ServerNetworkIoMixin.java index 1a8da9b..308fd31 100644 --- a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/mixin/ServerNetworkIoMixin.java +++ b/libjf-mainhttp-v0/src/main/java/io/gitlab/jfronny/libjf/mainhttp/impl/mixin/ServerNetworkIoMixin.java @@ -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.web.impl.variant.shared.SharedWebServer; +import io.gitlab.jfronny.libjf.mainhttp.impl.MainHttp; +import io.gitlab.jfronny.libjf.mainhttp.impl.util.ClaimPool; import net.minecraft.server.ServerNetworkIo; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -15,12 +15,13 @@ import java.util.Set; @Mixin(ServerNetworkIo.class) public class ServerNetworkIoMixin { - @Unique private final Set.Claim> libjf$portClaim = new HashSet<>(); + @Unique + private final Set.Claim> libjf$portClaim = new HashSet<>(); @Inject(method = "bind(Ljava/net/InetAddress;I)V", at = @At("HEAD")) void onBind(InetAddress address, int port, CallbackInfo ci) { - libjf$portClaim.add(SharedWebServer.gamePort.claim(port)); - SharedWebServer.emitActive(); + libjf$portClaim.add(MainHttp.GAME_PORT.claim(port)); + MainHttp.ON_ACTIVATE.invoker().run(); } @Inject(method = "stop()V", at = @At("HEAD")) diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/ClaimPool.java b/libjf-mainhttp-v0/src/main/java/io/gitlab/jfronny/libjf/mainhttp/impl/util/ClaimPool.java similarity index 94% rename from libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/ClaimPool.java rename to libjf-mainhttp-v0/src/main/java/io/gitlab/jfronny/libjf/mainhttp/impl/util/ClaimPool.java index b6e0c03..935ed15 100644 --- a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/ClaimPool.java +++ b/libjf-mainhttp-v0/src/main/java/io/gitlab/jfronny/libjf/mainhttp/impl/util/ClaimPool.java @@ -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.List; diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/shared/Trie.java b/libjf-mainhttp-v0/src/main/java/io/gitlab/jfronny/libjf/mainhttp/impl/util/Trie.java similarity index 94% rename from libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/shared/Trie.java rename to libjf-mainhttp-v0/src/main/java/io/gitlab/jfronny/libjf/mainhttp/impl/util/Trie.java index 7646c4e..553c5c8 100644 --- a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/shared/Trie.java +++ b/libjf-mainhttp-v0/src/main/java/io/gitlab/jfronny/libjf/mainhttp/impl/util/Trie.java @@ -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.Char2ObjectMap; diff --git a/libjf-mainhttp-v0/src/main/resources/fabric.mod.json b/libjf-mainhttp-v0/src/main/resources/fabric.mod.json new file mode 100644 index 0000000..f76bbb8 --- /dev/null +++ b/libjf-mainhttp-v0/src/main/resources/fabric.mod.json @@ -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"] + } + } +} diff --git a/libjf-web-v1/src/main/resources/libjf-web-v1.mixins.json b/libjf-mainhttp-v0/src/main/resources/libjf-mainhttp-v0.mixins.json similarity index 59% rename from libjf-web-v1/src/main/resources/libjf-web-v1.mixins.json rename to libjf-mainhttp-v0/src/main/resources/libjf-mainhttp-v0.mixins.json index 3bf60c3..ec0a860 100644 --- a/libjf-web-v1/src/main/resources/libjf-web-v1.mixins.json +++ b/libjf-mainhttp-v0/src/main/resources/libjf-mainhttp-v0.mixins.json @@ -1,9 +1,9 @@ { "required": true, "minVersion": "0.8", - "package": "io.gitlab.jfronny.libjf.web.impl.mixin", + "package": "io.gitlab.jfronny.libjf.mainhttp.impl.mixin", "compatibilityLevel": "JAVA_16", - "plugin": "io.gitlab.jfronny.libjf.web.impl.mixin.JfWebMixinPlugin", + "plugin": "io.gitlab.jfronny.libjf.mainhttp.impl.mixin.JfMainHTTPMixinPlugin", "server": [ "ServerNetworkIo$1Mixin", "ServerNetworkIoMixin" diff --git a/libjf-web-v1/build.gradle.kts b/libjf-web-v1/build.gradle.kts index b83d6a5..9b27cd7 100644 --- a/libjf-web-v1/build.gradle.kts +++ b/libjf-web-v1/build.gradle.kts @@ -12,6 +12,7 @@ dependencies { val fabricVersion: String by rootProject.extra api(devProject(":libjf-base")) api(devProject(":libjf-config-core-v2")) + api(devProject(":libjf-mainhttp-v0")) include(modImplementation(fabricApi.module("fabric-command-api-v2", fabricVersion))!!) annotationProcessor(project(":libjf-config-compiler-plugin-v2")) diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/HttpResponseImpl.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/HttpResponseImpl.java index 7a4dcde..16512d5 100644 --- a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/HttpResponseImpl.java +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/util/HttpResponseImpl.java @@ -44,7 +44,7 @@ public class HttpResponseImpl implements HttpResponse { this.version = "HTTP/1.1"; this.statusCode = statusCode; - this.header = new HashMap<>(); + this.header = new LinkedHashMap<>(); addHeader("Connection", "keep-alive"); } @@ -52,7 +52,7 @@ public class HttpResponseImpl implements HttpResponse { @Override public HttpResponseImpl addHeader(String key, String value) { ensureOpen(); - Set valueSet = header.computeIfAbsent(key, k -> new HashSet<>()); + Set valueSet = header.computeIfAbsent(key, k -> new LinkedHashSet<>()); valueSet.add(value); return this; } @@ -60,7 +60,7 @@ public class HttpResponseImpl implements HttpResponse { @Override public HttpResponseImpl removeHeader(String key, String value) { ensureOpen(); - Set valueSet = header.computeIfAbsent(key, k -> new HashSet<>()); + Set valueSet = header.computeIfAbsent(key, k -> new LinkedHashSet<>()); valueSet.remove(value); return this; } @@ -88,14 +88,15 @@ public class HttpResponseImpl implements HttpResponse { public void write(OutputStream out) throws IOException { OutputStreamWriter writer = new OutputStreamWriter(out, StandardCharsets.UTF_8); + Map> finalHeaders = new LinkedHashMap<>(header); if (data != null) { - addHeader("Transfer-Encoding", "chunked"); + finalHeaders.computeIfAbsent("Transfer-Encoding", k -> new LinkedHashSet<>()).add("chunked"); } else { - addHeader("Content-Length", "0"); + finalHeaders.computeIfAbsent("Content-Length", k -> new LinkedHashSet<>()).add("0"); } writeLine(writer, version + " " + statusCode.getCode() + " " + statusCode.getMessage()); - for (Entry> e : header.entrySet()) { + for (Entry> e : finalHeaders.entrySet()) { if (e.getValue().isEmpty()) continue; writeLine(writer, e.getKey() + ": " + StringUtils.join(e.getValue(), ", ")); } diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/shared/MainHttpHandlerImpl.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/shared/MainHttpHandlerImpl.java new file mode 100644 index 0000000..c4f3b6a --- /dev/null +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/shared/MainHttpHandlerImpl.java @@ -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; + } + } +} diff --git a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/shared/SharedWebServer.java b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/shared/SharedWebServer.java index 6db7d76..4579e60 100644 --- a/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/shared/SharedWebServer.java +++ b/libjf-web-v1/src/main/java/io/gitlab/jfronny/libjf/web/impl/variant/shared/SharedWebServer.java @@ -1,13 +1,12 @@ 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.util.ClaimPool; import io.gitlab.jfronny.libjf.web.impl.variant.AbstractWebServer; import java.util.*; public class SharedWebServer extends AbstractWebServer { - public static final ClaimPool gamePort = new ClaimPool<>(); public static final Set onActive = new LinkedHashSet<>(); public static void emitActive() { @@ -23,9 +22,8 @@ public class SharedWebServer extends AbstractWebServer { @Override public String getServerRoot() { - Integer gamePort = this.gamePort.getTopmost(); - if (gamePort == null) throw new UnsupportedOperationException("Attempted to get server root on unhosted server"); - else return getServerRoot(gamePort); + if (!ServerState.isActive()) throw new UnsupportedOperationException("Attempted to get server root on unhosted server"); + else return getServerRoot(ServerState.getPort()); } @Override @@ -47,6 +45,6 @@ public class SharedWebServer extends AbstractWebServer { @Override public boolean isActive() { - return !gamePort.isEmpty(); + return ServerState.isActive(); } } diff --git a/libjf-web-v1/src/main/resources/fabric.mod.json b/libjf-web-v1/src/main/resources/fabric.mod.json index 7af09db..813cedb 100644 --- a/libjf-web-v1/src/main/resources/fabric.mod.json +++ b/libjf-web-v1/src/main/resources/fabric.mod.json @@ -15,17 +15,18 @@ }, "license": "MIT", "environment": "*", - "mixins": ["libjf-web-v1.mixins.json"], "entrypoints": { "main": ["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": { "fabricloader": ">=0.12.0", "minecraft": "*", "libjf-base": ">=${version}", "libjf-config-core-v2": ">=${version}", + "libjf-mainhttp-v0": ">=${version}", "fabric-command-api-v2": "*" }, "custom": { diff --git a/settings.gradle.kts b/settings.gradle.kts index ee0e582..83731fb 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -17,11 +17,16 @@ include("libjf-base") include("libjf-config-core-v2") include("libjf-config-commands") include("libjf-config-ui-tiny") +include("libjf-config-compiler-plugin-v2") + include("libjf-data-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")