From db32a41e2b7a5c608512c6bbdb230b3d0078d7ba Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Thu, 29 Aug 2024 13:38:38 +0200 Subject: [PATCH] Enable commands in all environments - Many command-related fixes and improvements - Added test environment for easier development --- .../eu/midnightdust/core/MidnightLib.java | 5 +- .../screen/MidnightConfigOverviewScreen.java | 18 +++-- .../midnightdust/lib/config/AutoCommand.java | 37 ++++------ .../lib/config/MidnightConfig.java | 14 ++-- .../fabric/core/MidnightLibFabric.java | 8 +-- fabric/src/main/resources/fabric.mod.json | 4 +- .../util/neoforge/PlatformFunctionsImpl.java | 4 +- .../neoforge/MidnightLibNeoForge.java | 11 +-- settings.gradle | 4 +- test-fabric/build.gradle | 32 +++++++++ .../fabric/example/MLExampleFabric.java | 11 +++ .../example/config/MidnightConfigExample.java | 71 +++++++++++++++++++ .../main/resources/assets/modid/en_US.json | 23 ++++++ .../src/main/resources/fabric.mod.json | 23 ++++++ 14 files changed, 215 insertions(+), 50 deletions(-) create mode 100644 test-fabric/build.gradle create mode 100644 test-fabric/src/main/java/eu/midnightdust/fabric/example/MLExampleFabric.java create mode 100644 test-fabric/src/main/java/eu/midnightdust/fabric/example/config/MidnightConfigExample.java create mode 100644 test-fabric/src/main/resources/assets/modid/en_US.json create mode 100644 test-fabric/src/main/resources/fabric.mod.json diff --git a/common/src/main/java/eu/midnightdust/core/MidnightLib.java b/common/src/main/java/eu/midnightdust/core/MidnightLib.java index dd3561f..c338573 100755 --- a/common/src/main/java/eu/midnightdust/core/MidnightLib.java +++ b/common/src/main/java/eu/midnightdust/core/MidnightLib.java @@ -8,7 +8,7 @@ import net.fabricmc.api.Environment; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.swing.*; +import javax.swing.UIManager; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; @@ -25,8 +25,7 @@ public class MidnightLib { } catch (Exception e) { LOGGER.error("Error setting system look and feel", e); } MidnightLibConfig.init(MOD_ID, MidnightLibConfig.class); } - @Environment(EnvType.SERVER) - public static void onInitializeServer() { + public static void onInitialize() { MidnightConfig.configClass.forEach((modid, config) -> { for (Field field : config.getFields()) { if (field.isAnnotationPresent(MidnightConfig.Entry.class) && !field.isAnnotationPresent(MidnightConfig.Client.class) && !field.isAnnotationPresent(MidnightConfig.Hidden.class)) diff --git a/common/src/main/java/eu/midnightdust/core/screen/MidnightConfigOverviewScreen.java b/common/src/main/java/eu/midnightdust/core/screen/MidnightConfigOverviewScreen.java index dab1926..7a1df8a 100755 --- a/common/src/main/java/eu/midnightdust/core/screen/MidnightConfigOverviewScreen.java +++ b/common/src/main/java/eu/midnightdust/core/screen/MidnightConfigOverviewScreen.java @@ -6,11 +6,16 @@ import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.widget.*; +import net.minecraft.client.gui.widget.ButtonWidget; import net.minecraft.screen.ScreenTexts; -import net.minecraft.text.*; +import net.minecraft.text.Text; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +import static eu.midnightdust.lib.config.MidnightConfig.MidnightConfigListWidget; @Environment(EnvType.CLIENT) public class MidnightConfigOverviewScreen extends Screen { @@ -20,19 +25,19 @@ public class MidnightConfigOverviewScreen extends Screen { this.parent = parent; } private final Screen parent; - private MidnightConfig.MidnightConfigListWidget list; + private MidnightConfigListWidget list; @Override protected void init() { this.addDrawableChild(ButtonWidget.builder(ScreenTexts.DONE, (button) -> Objects.requireNonNull(client).setScreen(parent)).dimensions(this.width / 2 - 100, this.height - 26, 200, 20).build()); - this.addSelectableChild(this.list = new MidnightConfig.MidnightConfigListWidget(this.client, this.width, this.height - 57, 24, 25)); + this.addSelectableChild(this.list = new MidnightConfigListWidget(this.client, this.width, this.height - 57, 24, 25)); List sortedMods = new ArrayList<>(MidnightConfig.configClass.keySet()); Collections.sort(sortedMods); sortedMods.forEach((modid) -> { if (!MidnightLib.hiddenMods.contains(modid)) { list.addButton(List.of(ButtonWidget.builder(Text.translatable(modid +".midnightconfig.title"), (button) -> - Objects.requireNonNull(client).setScreen(MidnightConfig.getScreen(this,modid))).dimensions(this.width / 2 - 125, this.height - 28, 250, 20).build()), null, null); + Objects.requireNonNull(client).setScreen(MidnightConfig.getScreen(this, modid))).dimensions(this.width / 2 - 125, this.height - 28, 250, 20).build()), null, null); }}); super.init(); } @@ -40,7 +45,6 @@ public class MidnightConfigOverviewScreen extends Screen { public void render(DrawContext context, int mouseX, int mouseY, float delta) { super.render(context, mouseX, mouseY, delta); this.list.render(context, mouseX, mouseY, delta); - context.drawCenteredTextWithShadow(textRenderer, title, width / 2, 10, 0xFFFFFF); } } \ No newline at end of file diff --git a/common/src/main/java/eu/midnightdust/lib/config/AutoCommand.java b/common/src/main/java/eu/midnightdust/lib/config/AutoCommand.java index 45c8d4f..95571c8 100644 --- a/common/src/main/java/eu/midnightdust/lib/config/AutoCommand.java +++ b/common/src/main/java/eu/midnightdust/lib/config/AutoCommand.java @@ -1,7 +1,6 @@ package eu.midnightdust.lib.config; import com.mojang.brigadier.arguments.*; -import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.context.CommandContext; import eu.midnightdust.lib.util.PlatformFunctions; import net.minecraft.server.command.CommandManager; @@ -9,47 +8,41 @@ import net.minecraft.server.command.ServerCommandSource; import net.minecraft.text.Text; import java.lang.reflect.Field; -import java.util.ArrayList; import java.util.List; import java.util.Objects; +import static eu.midnightdust.lib.config.MidnightConfig.Entry; + public class AutoCommand { - public static List> commands = new ArrayList<>(); - final static String BASE = "midnightconfig"; final static String VALUE = "value"; final Field field; final Class type; final String modid; - final boolean isList; + final boolean isList, isNumber; public AutoCommand(Field field, String modid) { - this.field = field; - this.modid = modid; - this.type = field.getType(); + this.field = field; this.modid = modid; + this.type = MidnightConfig.getUnderlyingType(field); this.isList = field.getType() == List.class; + this.isNumber = type == int.class || type == double.class || type == float.class; - LiteralArgumentBuilder command = CommandManager.literal(BASE).requires(source -> source.hasPermissionLevel(2)).then( - CommandManager.literal(modid).then(CommandManager.literal(field.getName()).executes(this::getValue))); + var command = CommandManager.literal(field.getName()).executes(this::getValue); if (type.isEnum()) { - for (Object enumValue : field.getType().getEnumConstants()) { + for (Object enumValue : field.getType().getEnumConstants()) command = command.then(CommandManager.literal(enumValue.toString()).executes(ctx -> this.setValue(ctx.getSource(), enumValue, ""))); - } - } - else if (isList) { - for (String action : List.of("add", "remove")) { + } else if (isList) { + for (String action : List.of("add", "remove")) command = command.then(CommandManager.literal(action).then( CommandManager.argument(VALUE, getArgType()).executes(ctx -> setValueFromArg(ctx, action)))); - } - } - else command = command.then(CommandManager.argument(VALUE, getArgType()).executes(ctx -> setValueFromArg(ctx, ""))); + } else command = command.then(CommandManager.argument(VALUE, getArgType()).executes(ctx -> setValueFromArg(ctx, ""))); - PlatformFunctions.registerCommand(command); commands.add(command); + PlatformFunctions.registerCommand(CommandManager.literal("midnightconfig").requires(source -> source.hasPermissionLevel(2)).then(CommandManager.literal(modid).then(command))); } public ArgumentType getArgType() { - MidnightConfig.Entry entry = type.getAnnotation(MidnightConfig.Entry.class); - if (type.isInstance(Number.class)) { + if (isNumber) { + Entry entry = field.getAnnotation(Entry.class); if (type == int.class) return IntegerArgumentType.integer((int) entry.min(), (int) entry.max()); else if (type == double.class) return DoubleArgumentType.doubleArg(entry.min(), entry.max()); else if (type == float.class) return FloatArgumentType.floatArg((float) entry.min(), (float) entry.max()); @@ -58,7 +51,7 @@ public class AutoCommand { return StringArgumentType.string(); } public int setValueFromArg(CommandContext context, String action) { - if (type.isInstance(Number.class)) { + if (isNumber) { if (type == int.class) return setValue(context.getSource(), IntegerArgumentType.getInteger(context, VALUE), action); else if (type == double.class) return setValue(context.getSource(), DoubleArgumentType.getDouble(context, VALUE), action); else if (type == float.class) return setValue(context.getSource(), FloatArgumentType.getFloat(context, VALUE), action); diff --git a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java index 76a18f8..0144f41 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -107,15 +107,10 @@ public abstract class MidnightConfig { } @Environment(EnvType.CLIENT) private static void initClient(String modid, Field field, EntryInfo info) { - info.dataType = field.getType(); + info.dataType = getUnderlyingType(field); Entry e = field.getAnnotation(Entry.class); info.width = e != null ? e.width() : 0; info.field = field; info.modid = modid; - if (info.dataType == List.class) { - Class listType = (Class) ((ParameterizedType) info.field.getGenericType()).getActualTypeArguments()[0]; - try { info.dataType = (Class) listType.getField("TYPE").get(null); - } catch (NoSuchFieldException | IllegalAccessException ignored) { info.dataType = listType; } - } if (e != null) { if (!e.name().isEmpty()) info.name = Text.translatable(e.name()); @@ -138,6 +133,13 @@ public abstract class MidnightConfig { }} entries.add(info); } + public static Class getUnderlyingType(Field field) { + if (field.getType() == List.class) { + Class listType = (Class) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0]; + try { return (Class) listType.getField("TYPE").get(null); + } catch (NoSuchFieldException | IllegalAccessException ignored) { return listType; } + } else return field.getType(); + } public static Tooltip getTooltip(EntryInfo info) { String key = info.modid + ".midnightconfig."+info.field.getName()+".tooltip"; return Tooltip.of(info.error != null ? info.error : I18n.hasTranslation(key) ? Text.translatable(key) : Text.empty()); diff --git a/fabric/src/main/java/eu/midnightdust/fabric/core/MidnightLibFabric.java b/fabric/src/main/java/eu/midnightdust/fabric/core/MidnightLibFabric.java index 2919334..272a107 100644 --- a/fabric/src/main/java/eu/midnightdust/fabric/core/MidnightLibFabric.java +++ b/fabric/src/main/java/eu/midnightdust/fabric/core/MidnightLibFabric.java @@ -2,13 +2,13 @@ package eu.midnightdust.fabric.core; import eu.midnightdust.core.MidnightLib; import net.fabricmc.api.ClientModInitializer; -import net.fabricmc.api.DedicatedServerModInitializer; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; +import net.fabricmc.api.ModInitializer; -public class MidnightLibFabric implements ClientModInitializer, DedicatedServerModInitializer { +public class MidnightLibFabric implements ModInitializer, ClientModInitializer { @Override @Environment(EnvType.CLIENT) public void onInitializeClient() {MidnightLib.onInitializeClient();} - @Override @Environment(EnvType.SERVER) - public void onInitializeServer() {MidnightLib.onInitializeServer();} + @Override + public void onInitialize() {MidnightLib.onInitialize();} } diff --git a/fabric/src/main/resources/fabric.mod.json b/fabric/src/main/resources/fabric.mod.json index 5395b55..3b33107 100644 --- a/fabric/src/main/resources/fabric.mod.json +++ b/fabric/src/main/resources/fabric.mod.json @@ -29,10 +29,10 @@ "environment": "*", "entrypoints": { - "client": [ + "main": [ "eu.midnightdust.fabric.core.MidnightLibFabric" ], - "server": [ + "client": [ "eu.midnightdust.fabric.core.MidnightLibFabric" ], "modmenu": [ diff --git a/neoforge/src/main/java/eu/midnightdust/lib/util/neoforge/PlatformFunctionsImpl.java b/neoforge/src/main/java/eu/midnightdust/lib/util/neoforge/PlatformFunctionsImpl.java index 878264a..5e92f60 100644 --- a/neoforge/src/main/java/eu/midnightdust/lib/util/neoforge/PlatformFunctionsImpl.java +++ b/neoforge/src/main/java/eu/midnightdust/lib/util/neoforge/PlatformFunctionsImpl.java @@ -9,6 +9,8 @@ import net.neoforged.fml.loading.FMLPaths; import java.nio.file.Path; +import static eu.midnightdust.neoforge.MidnightLibNeoForge.commands; + public class PlatformFunctionsImpl { public static String getPlatformName() { return "neoforge"; @@ -26,6 +28,6 @@ public class PlatformFunctionsImpl { return ModList.get().isLoaded(modid); } public static void registerCommand(LiteralArgumentBuilder command) { - // Ignored here, see MidnightLibNeoForge#registerCommands + commands.add(command); } } diff --git a/neoforge/src/main/java/eu/midnightdust/neoforge/MidnightLibNeoForge.java b/neoforge/src/main/java/eu/midnightdust/neoforge/MidnightLibNeoForge.java index ce2deec..26d7e4b 100644 --- a/neoforge/src/main/java/eu/midnightdust/neoforge/MidnightLibNeoForge.java +++ b/neoforge/src/main/java/eu/midnightdust/neoforge/MidnightLibNeoForge.java @@ -15,11 +15,16 @@ import net.neoforged.fml.loading.FMLEnvironment; import net.neoforged.neoforge.client.gui.IConfigScreenFactory; import net.neoforged.neoforge.event.RegisterCommandsEvent; +import java.util.ArrayList; +import java.util.List; + @Mod("midnightlib") public class MidnightLibNeoForge { + public static List> commands = new ArrayList<>(); + public MidnightLibNeoForge() { if (FMLEnvironment.dist == Dist.CLIENT) MidnightLib.onInitializeClient(); - else MidnightLib.onInitializeServer(); + MidnightLib.onInitialize(); } @EventBusSubscriber(modid = "midnightlib", bus = EventBusSubscriber.Bus.MOD, value = Dist.CLIENT) @@ -38,9 +43,7 @@ public class MidnightLibNeoForge { public static class MidnightLibServerEvents { @SubscribeEvent public static void registerCommands(RegisterCommandsEvent event) { - for (LiteralArgumentBuilder command : AutoCommand.commands) { - event.getDispatcher().register(command); - } + commands.forEach(command -> event.getDispatcher().register(command)); } } } diff --git a/settings.gradle b/settings.gradle index d1592c9..6f5c32b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -9,7 +9,9 @@ pluginManagement { include("common") include("fabric") -//include("quilt") +include("test-fabric") include("neoforge") +include("test-neoforge") +//include("quilt") rootProject.name = "midnightlib" diff --git a/test-fabric/build.gradle b/test-fabric/build.gradle new file mode 100644 index 0000000..1d35a52 --- /dev/null +++ b/test-fabric/build.gradle @@ -0,0 +1,32 @@ +plugins { + id 'com.github.johnrengelman.shadow' + id "me.shedaniel.unified-publishing" +} +repositories { + maven { url "https://maven.terraformersmc.com/releases" } +} + +architectury { + platformSetupLoomIde() + fabric() +} + +loom { +} + +configurations { + common + shadowCommon // Don't use shadow from the shadow plugin since it *excludes* files. + compileClasspath.extendsFrom common + runtimeClasspath.extendsFrom common + developmentFabric.extendsFrom common + archivesBaseName = rootProject.archives_base_name + "-fabric" +} + +dependencies { + modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" + modApi "net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_api_version}" + + implementation project(path: ":fabric", configuration: "namedElements") + common(project(path: ":common", configuration: "namedElements")) { transitive false } +} \ No newline at end of file diff --git a/test-fabric/src/main/java/eu/midnightdust/fabric/example/MLExampleFabric.java b/test-fabric/src/main/java/eu/midnightdust/fabric/example/MLExampleFabric.java new file mode 100644 index 0000000..e873330 --- /dev/null +++ b/test-fabric/src/main/java/eu/midnightdust/fabric/example/MLExampleFabric.java @@ -0,0 +1,11 @@ +package eu.midnightdust.fabric.example; + +import eu.midnightdust.fabric.example.config.MidnightConfigExample; +import net.fabricmc.api.ModInitializer; + +public class MLExampleFabric implements ModInitializer { + @Override + public void onInitialize() { + MidnightConfigExample.init("modid", MidnightConfigExample.class); + } +} diff --git a/test-fabric/src/main/java/eu/midnightdust/fabric/example/config/MidnightConfigExample.java b/test-fabric/src/main/java/eu/midnightdust/fabric/example/config/MidnightConfigExample.java new file mode 100644 index 0000000..f16c370 --- /dev/null +++ b/test-fabric/src/main/java/eu/midnightdust/fabric/example/config/MidnightConfigExample.java @@ -0,0 +1,71 @@ +package eu.midnightdust.fabric.example.config; + +import com.google.common.collect.Lists; +import eu.midnightdust.lib.config.MidnightConfig; +import net.minecraft.util.Identifier; + +import javax.swing.*; +import java.util.ArrayList; +import java.util.List; + +/** Every option in a MidnightConfig class has to be public and static, so we can access it from other classes. + * The config class also has to extend MidnightConfig*/ + +public class MidnightConfigExample extends MidnightConfig { + public static final String TEXT = "text"; + public static final String NUMBERS = "numbers"; + public static final String SLIDERS = "sliders"; + public static final String LISTS = "lists"; + public static final String FILES = "files"; + + @Comment(category = TEXT) public static Comment text1; // Comments are rendered like an option without a button and are excluded from the config file + @Comment(category = TEXT, centered = true) public static Comment text2; // Centered comments are the same as normal ones - just centered! + @Comment(category = TEXT) public static Comment spacer1; // Comments containing the word "spacer" will just appear as a blank line + @Entry(category = TEXT) public static boolean showInfo = true; // Example for a boolean option + @Entry(category = TEXT) public static String name = "Hello World!"; // Example for a string option, which is in a category! + @Entry(category = TEXT, width = 7, min = 7, isColor = true, name = "I am a color!") public static String titleColor = "#ffffff"; // The isColor property adds a color chooser for a hexadecimal color + @Entry(category = TEXT, idMode = 0) public static Identifier id = Identifier.ofVanilla("diamond"); // Example for an identifier with matching items displayed next to it! + @Entry(category = TEXT) public static TestEnum testEnum = TestEnum.FABRIC; // Example for an enum option + public enum TestEnum { // Enums allow the user to cycle through predefined options + QUILT, FABRIC, FORGE + } + @Entry(category = NUMBERS) public static int fabric = 16777215; // Example for an int option + @Entry(category = NUMBERS) public static double world = 1.4D; // Example for a double option + @Entry(category = NUMBERS, min=69,max=420) public static int hello = 420; // - The entered number has to be larger than 69 and smaller than 420 + @Entry(category = SLIDERS, name = "I am an int slider.",isSlider = true, min = 0, max = 100) public static int intSlider = 35; // Int fields can also be displayed as a Slider + @Entry(category = SLIDERS, name = "I am a float slider!", isSlider = true, min = 0f, max = 1f, precision = 1000) public static float floatSlider = 0.24f; // And so can floats! Precision defines the amount of decimal places + // The name field can be used to specify a custom translation string or plain text + @Entry(category = LISTS, name = "I am a string list!") public static List stringList = Lists.newArrayList("String1", "String2"); // Array String Lists are also supported + @Entry(category = LISTS, isColor = true, name = "I am a color list!") public static List colorList = Lists.newArrayList("#ac5f99", "#11aa44"); // Lists also support colors + @Entry(category = LISTS, name = "I am an identifier list!", idMode = 1) public static List idList = Lists.newArrayList(Identifier.ofVanilla("dirt")); // A list of block identifiers + @Entry(category = LISTS, name = "I am an integer list!") public static List intList = Lists.newArrayList(69, 420); + @Entry(category = LISTS, name = "I am a float list!") public static List floatList = Lists.newArrayList(4.1f, -1.3f, -1f); + + @Entry(category = FILES, + selectionMode = JFileChooser.FILES_ONLY, + fileExtensions = {"json", "txt", "log"}, // Define valid file extensions + fileChooserType = JFileChooser.SAVE_DIALOG, + name = "I am a file!") + public static String myFile = ""; // The isFile property adds a file picker button + + @Entry(category = FILES, + selectionMode = JFileChooser.DIRECTORIES_ONLY, + fileChooserType = JFileChooser.OPEN_DIALOG, + name = "I am a directory!") + public static String myDirectory = ""; // The isDirectory property adds a directory picker button + + @Entry(category = FILES, + selectionMode = JFileChooser.FILES_AND_DIRECTORIES, + fileExtensions = {"png", "jpg", "jpeg"}, + fileChooserType = JFileChooser.OPEN_DIALOG, + name = "I can choose both files & directories!") + public static String myFileOrDirectory = ""; // The isFileOrDirectory property adds a file or directory picker button + @Entry(category = FILES, + selectionMode = JFileChooser.FILES_AND_DIRECTORIES, + fileExtensions = {"png", "jpg", "jpeg"}, + fileChooserType = JFileChooser.OPEN_DIALOG, + name = "I am a mf file/directory list!") + public static List fileOrDirectoryList = new ArrayList<>(); // Yes, that's right – you can even have lists of files/directories + + public static int imposter = 16777215; // - Entries without an @Entry or @Comment annotation are ignored +} \ No newline at end of file diff --git a/test-fabric/src/main/resources/assets/modid/en_US.json b/test-fabric/src/main/resources/assets/modid/en_US.json new file mode 100644 index 0000000..993eca1 --- /dev/null +++ b/test-fabric/src/main/resources/assets/modid/en_US.json @@ -0,0 +1,23 @@ +{ + "modid.midnightconfig.title":"I am a title", + "modid.midnightconfig.text1":"I am a comment *u*", + "modid.midnightconfig.text2":"I am a centered comment (╯°□°)╯︵ ┻━┻", + "modid.midnightconfig.name":"I am a string!", + "modid.midnightconfig.name.tooltip":"I am a tooltip uwu \nI am a new line", + "modid.midnightconfig.fabric":"I am an int", + "modid.midnightconfig.world":"I am a double", + "modid.midnightconfig.showInfo":"I am a boolean", + "modid.midnightconfig.hello":"I am a limited int!", + "modid.midnightconfig.id":"I am an Item Identifier!", + "modid.midnightconfig.testEnum":"I am an enum!", + "modid.midnightconfig.enum.TestEnum.FORGE":"Slow", + "modid.midnightconfig.enum.TestEnum.FABRIC":"Fancy", + "modid.midnightconfig.enum.TestEnum.QUILT":"Fabulous", + "modid.midnightconfig.myFileOrDirectory.fileChooser": "Select an image or directory", + "modid.midnightconfig.myFileOrDirectory.fileFilter": "Supported Images (.png, .jpg, .jpeg)", + "modid.midnightconfig.category.numbers": "Numbers", + "modid.midnightconfig.category.text": "Text", + "modid.midnightconfig.category.sliders": "Sliders", + "modid.midnightconfig.category.lists": "Lists", + "modid.midnightconfig.category.files": "Files" +} \ No newline at end of file diff --git a/test-fabric/src/main/resources/fabric.mod.json b/test-fabric/src/main/resources/fabric.mod.json new file mode 100644 index 0000000..f82ee29 --- /dev/null +++ b/test-fabric/src/main/resources/fabric.mod.json @@ -0,0 +1,23 @@ +{ + "schemaVersion": 1, + "id": "midnightlib-example", + "version": "${version}", + + "name": "MidnightLib Example", + "description": "Wow, you can do so much.", + "authors": [ "MidnightDust" ], + + "license": "CC0", + "icon": "assets/midnightlib/icon.png", + + "environment": "*", + "entrypoints": { + "main": [ + "eu.midnightdust.fabric.example.MLExampleFabric" + ] + }, + "depends": { + "fabric-resource-loader-v0": "*", + "midnightlib": ">=1.6.0" + } +}