From cbfaeb3c6f99d35d1b75b0c0b20c37ac3745f8ed Mon Sep 17 00:00:00 2001 From: Motschen Date: Sat, 16 Sep 2023 21:52:14 +0200 Subject: [PATCH 001/100] MidnightLib 1.5.0 - 1.20.2, slight redesign & cleanup - Port to 1.20.2 - "Reset" button now uses a custom icon (closes #25) - Config instances can now specify custom config change behavior (implement "writeChanges" method in your class; closes #33) - Remove TexturedOverlayButtonWidget (replaced by vanilla's TextIconButtonWidget) - Removed radialRainbow (used very rarely) - Updated AutoCommand to support editing list and float config values via commands on serverside installs - Reworded description - Forge & Quilt temporarily disabled until they release, as always --- .../midnightdust/core/MidnightLibClient.java | 3 +- .../core/mixin/MixinOptionsScreen.java | 12 ++- .../screen/MidnightConfigOverviewScreen.java | 14 +--- .../midnightdust/lib/config/AutoCommand.java | 73 +++++++++++------- .../lib/config/MidnightConfig.java | 31 +++++--- .../lib/util/MidnightColorUtil.java | 10 --- .../screen/TexturedOverlayButtonWidget.java | 40 ---------- .../assets/midnightlib/lang/de_de.json | 5 +- .../assets/midnightlib/lang/en_us.json | 5 +- .../assets/midnightlib/lang/fr_fr.json | 3 +- .../assets/midnightlib/lang/pt_br.json | 3 +- .../assets/midnightlib/lang/tt_ru.json | 1 - .../assets/midnightlib/lang/uk_ua.json | 1 - .../assets/midnightlib/lang/zh_tw.json | 3 - .../textures/gui/midnightlib_button.png | Bin 293 -> 0 bytes .../textures/gui/sprites/icon/midnightlib.png | Bin 0 -> 189 bytes .../textures/gui/sprites/icon/reset.png | Bin 0 -> 178 bytes .../main/resources/midnightlib.mixins.json | 13 +--- .../fabric/core/MidnightLibClientFabric.java | 3 - .../forge/MidnightLibClientEvents.java | 5 -- gradle.properties | 12 +-- .../quilt/core/MidnightLibClientQuilt.java | 3 - settings.gradle | 4 +- 23 files changed, 93 insertions(+), 151 deletions(-) delete mode 100644 common/src/main/java/eu/midnightdust/lib/util/screen/TexturedOverlayButtonWidget.java delete mode 100644 common/src/main/resources/assets/midnightlib/textures/gui/midnightlib_button.png create mode 100644 common/src/main/resources/assets/midnightlib/textures/gui/sprites/icon/midnightlib.png create mode 100644 common/src/main/resources/assets/midnightlib/textures/gui/sprites/icon/reset.png diff --git a/common/src/main/java/eu/midnightdust/core/MidnightLibClient.java b/common/src/main/java/eu/midnightdust/core/MidnightLibClient.java index 8d6df02..2cfdd0d 100755 --- a/common/src/main/java/eu/midnightdust/core/MidnightLibClient.java +++ b/common/src/main/java/eu/midnightdust/core/MidnightLibClient.java @@ -1,7 +1,6 @@ package eu.midnightdust.core; import eu.midnightdust.core.config.MidnightLibConfig; -import eu.midnightdust.lib.config.MidnightConfig; import java.util.ArrayList; import java.util.List; @@ -10,6 +9,6 @@ public class MidnightLibClient { public static List hiddenMods = new ArrayList<>(); public static void onInitializeClient() { - MidnightConfig.init("midnightlib", MidnightLibConfig.class); + MidnightLibConfig.init("midnightlib", MidnightLibConfig.class); } } diff --git a/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java b/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java index 1f3da97..f6af033 100755 --- a/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java +++ b/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java @@ -3,9 +3,9 @@ package eu.midnightdust.core.mixin; import eu.midnightdust.core.config.MidnightLibConfig; import eu.midnightdust.core.screen.MidnightConfigOverviewScreen; import eu.midnightdust.lib.util.PlatformFunctions; -import eu.midnightdust.lib.util.screen.TexturedOverlayButtonWidget; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.option.OptionsScreen; +import net.minecraft.client.gui.widget.TextIconButtonWidget; import net.minecraft.text.Text; import net.minecraft.util.Identifier; import org.spongepowered.asm.mixin.Mixin; @@ -17,14 +17,18 @@ import java.util.Objects; @Mixin(OptionsScreen.class) public class MixinOptionsScreen extends Screen { - private static final Identifier MIDNIGHTLIB_ICON_TEXTURE = new Identifier("midnightlib","textures/gui/midnightlib_button.png"); protected MixinOptionsScreen(Text title) { super(title); } @Inject(at = @At("HEAD"),method = "init") private void midnightlib$init(CallbackInfo ci) { - if (MidnightLibConfig.config_screen_list.equals(MidnightLibConfig.ConfigButton.TRUE) || (MidnightLibConfig.config_screen_list.equals(MidnightLibConfig.ConfigButton.MODMENU) && !PlatformFunctions.isModLoaded("modmenu"))) - this.addDrawableChild(new TexturedOverlayButtonWidget(this.width / 2 + 158, this.height / 6 - 12, 20, 20, 0, 0, 20, MIDNIGHTLIB_ICON_TEXTURE, 32, 64, (buttonWidget) -> Objects.requireNonNull(client).setScreen(new MidnightConfigOverviewScreen(this)), Text.translatable("midnightlib.overview.title"))); + if (MidnightLibConfig.config_screen_list.equals(MidnightLibConfig.ConfigButton.TRUE) || (MidnightLibConfig.config_screen_list.equals(MidnightLibConfig.ConfigButton.MODMENU) && !PlatformFunctions.isModLoaded("modmenu"))) { + TextIconButtonWidget button = TextIconButtonWidget.builder(Text.translatable("midnightlib.overview.title"), ( + buttonWidget) -> Objects.requireNonNull(client).setScreen(new MidnightConfigOverviewScreen(this)), true) + .texture(new Identifier("midnightlib","icon/midnightlib"), 16, 16).dimension(20, 20).build(); + button.setPosition(this.width / 2 + 158, this.height / 6 - 12); + this.addDrawableChild(button); + } } } 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 c115063..9ec56c7 100755 --- a/common/src/main/java/eu/midnightdust/core/screen/MidnightConfigOverviewScreen.java +++ b/common/src/main/java/eu/midnightdust/core/screen/MidnightConfigOverviewScreen.java @@ -5,13 +5,11 @@ import eu.midnightdust.lib.config.MidnightConfig; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.Element; import net.minecraft.client.gui.Selectable; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.widget.*; -import net.minecraft.client.util.math.MatrixStack; import net.minecraft.screen.ScreenTexts; import net.minecraft.text.*; import java.util.*; @@ -45,19 +43,15 @@ public class MidnightConfigOverviewScreen extends Screen { } @Override public void render(DrawContext context, int mouseX, int mouseY, float delta) { - this.renderBackground(context); + super.render(context, mouseX, mouseY, delta); this.list.render(context, mouseX, mouseY, delta); context.drawCenteredTextWithShadow(textRenderer, title, width / 2, 15, 0xFFFFFF); - super.render(context, mouseX, mouseY, delta); } @Environment(EnvType.CLIENT) public static class MidnightOverviewListWidget extends ElementListWidget { - TextRenderer textRenderer; - public MidnightOverviewListWidget(MinecraftClient minecraftClient, int i, int j, int k, int l, int m) { super(minecraftClient, i, j, k, l, m); this.centerListVertically = false; - textRenderer = minecraftClient.textRenderer; } @Override public int getScrollbarPositionX() {return this.width-7;} @@ -70,18 +64,16 @@ public class MidnightConfigOverviewScreen extends Screen { } public static class OverviewButtonEntry extends ElementListWidget.Entry { private final ClickableWidget button; - private final List buttonList = new ArrayList<>(); private OverviewButtonEntry(ClickableWidget button) { this.button = button; - this.buttonList.add(button); } public static OverviewButtonEntry create(ClickableWidget button) {return new OverviewButtonEntry(button);} public void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { button.setY(y); button.render(context, mouseX, mouseY, tickDelta); } - public List children() {return buttonList;} - public List selectableChildren() {return buttonList;} + public List children() {return List.of(button);} + public List selectableChildren() {return List.of(button);} } } \ 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 c948a69..5598308 100644 --- a/common/src/main/java/eu/midnightdust/lib/config/AutoCommand.java +++ b/common/src/main/java/eu/midnightdust/lib/config/AutoCommand.java @@ -1,6 +1,7 @@ package eu.midnightdust.lib.config; import com.mojang.brigadier.arguments.DoubleArgumentType; +import com.mojang.brigadier.arguments.FloatArgumentType; import com.mojang.brigadier.arguments.IntegerArgumentType; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.builder.LiteralArgumentBuilder; @@ -14,9 +15,9 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +@SuppressWarnings("unchecked") public class AutoCommand { public static List> commands = new ArrayList<>(); - private LiteralArgumentBuilder command; final Field entry; final String modid; @@ -26,14 +27,7 @@ public class AutoCommand { } public void register() { - command = CommandManager.literal(modid); - command(); - LiteralArgumentBuilder finalized = CommandManager.literal("midnightconfig").requires(source -> source.hasPermissionLevel(2)).then(command); - - PlatformFunctions.registerCommand(finalized); commands.add(finalized); - } - - private void command() { + LiteralArgumentBuilder command = CommandManager.literal(modid); if (entry.getType() == int.class) command = command.then(CommandManager.literal(this.entry.getName()).executes(ctx -> getValue(ctx.getSource())).then( CommandManager.argument("value", IntegerArgumentType.integer((int) entry.getAnnotation(MidnightConfig.Entry.class).min(),(int) entry.getAnnotation(MidnightConfig.Entry.class).max())) @@ -44,15 +38,18 @@ public class AutoCommand { CommandManager.argument("value", DoubleArgumentType.doubleArg(entry.getAnnotation(MidnightConfig.Entry.class).min(),entry.getAnnotation(MidnightConfig.Entry.class).max())) .executes(ctx -> this.setValue(ctx.getSource(), DoubleArgumentType.getDouble(ctx, "value"))) )); + else if (entry.getType() == float.class) + command = command.then(CommandManager.literal(this.entry.getName()).executes(ctx -> getValue(ctx.getSource())).then( + CommandManager.argument("value", FloatArgumentType.floatArg((float) entry.getAnnotation(MidnightConfig.Entry.class).min(), (float) entry.getAnnotation(MidnightConfig.Entry.class).max())) + .executes(ctx -> this.setValue(ctx.getSource(), FloatArgumentType.getFloat(ctx, "value"))) + )); else if (entry.getType() == boolean.class) { - command = command.then(CommandManager.literal(this.entry.getName()).executes(ctx -> getValue(ctx.getSource())).then( - CommandManager.literal("true") - .executes(ctx -> this.setValue(ctx.getSource(), true)) - )); - command = command.then(CommandManager.literal(this.entry.getName()).executes(ctx -> getValue(ctx.getSource())).then( - CommandManager.literal("false") - .executes(ctx -> this.setValue(ctx.getSource(), false)) - )); + for (int i = 0; i < 2; i++) { + command = command.then(CommandManager.literal(this.entry.getName()).executes(ctx -> getValue(ctx.getSource())).then( + CommandManager.literal(i==0 ? "true":"false") + .executes(ctx -> this.setValue(ctx.getSource(), ctx.getInput().endsWith("true"))) + )); + } } else if (entry.getType().isEnum()) { for (int i = 0; i < entry.getType().getEnumConstants().length; ++i) { @@ -63,16 +60,28 @@ public class AutoCommand { )); } } - else + else if (entry.getType() == List.class) { + for (int i = 0; i < 2; i++) { + int finalI = i; + command = command.then(CommandManager.literal(this.entry.getName()).executes(ctx -> getValue(ctx.getSource())).then(CommandManager.literal(i==0 ? "add":"remove").then( + CommandManager.argument("value", StringArgumentType.string()) + .executes(ctx -> this.setList(ctx.getSource(), StringArgumentType.getString(ctx, "value"), finalI==0)) + ))); + } + } + else { command = command.then(CommandManager.literal(this.entry.getName()).executes(ctx -> getValue(ctx.getSource())).then( CommandManager.argument("value", StringArgumentType.string()) .executes(ctx -> this.setValue(ctx.getSource(), StringArgumentType.getString(ctx, "value"))) )); - } + } + LiteralArgumentBuilder finalized = CommandManager.literal("midnightconfig").requires(source -> source.hasPermissionLevel(2)).then(command); + PlatformFunctions.registerCommand(finalized); commands.add(finalized); + } private int setValue(ServerCommandSource source, Object value) { try { - entry.set(null,value); + if (entry.getType() != List.class) entry.set(null,value); MidnightConfig.write(modid); } catch (Exception e) { @@ -83,14 +92,26 @@ public class AutoCommand { source.sendFeedback(() -> Text.literal("Successfully set " + entry.getName()+" to "+value), true); return 1; } + private int setList(ServerCommandSource source, String value, boolean add) { + try { + List e = (List)entry.get(null); + if (add) e.add(value); + else if (!e.contains(value)) throw new IllegalArgumentException("List does not contain this string!"); + else e.remove(value); + MidnightConfig.write(modid); + } + catch (Exception e) { + source.sendError(Text.literal((add ? "Could not add "+value+" to " : "Could not remove "+value+" from ")+entry.getName() +": " + e)); + return 0; + } + source.sendFeedback(() -> Text.literal((add ? "Successfully added " +value+" to " : "Successfully removed " +value+" from ") +entry.getName()), true); + return 1; + } private int getValue(ServerCommandSource source) { source.sendFeedback(() -> { - try { - return Text.literal("The value of "+entry.getName()+" is "+entry.get(null)); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - }, false); + try {return Text.literal("The value of "+entry.getName()+" is "+entry.get(null)); + } catch (IllegalAccessException e) {throw new RuntimeException(e);} + }, true); return 0; } } 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 e62e529..d842ddd 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -24,6 +24,7 @@ import net.minecraft.text.OrderedText; import net.minecraft.text.Style; import net.minecraft.text.Text; import net.minecraft.util.Formatting; +import net.minecraft.util.Identifier; import java.awt.Color; import java.lang.annotation.ElementType; @@ -41,7 +42,7 @@ import java.util.function.Function; import java.util.function.Predicate; import java.util.regex.Pattern; -/** MidnightConfig v2.4.1 by TeamMidnightDust & Motschen +/** MidnightConfig v2.5.0 by TeamMidnightDust & Motschen * Single class config library - feel free to copy! * Based on ... * Credits to Minenash */ @@ -49,7 +50,7 @@ import java.util.regex.Pattern; @SuppressWarnings("unchecked") public abstract class MidnightConfig { private static final Pattern INTEGER_ONLY = Pattern.compile("(-?[0-9]*)"); - private static final Pattern DECIMAL_ONLY = Pattern.compile("-?([\\d]+\\.?[\\d]*|[\\d]*\\.?[\\d]+|\\.)"); + private static final Pattern DECIMAL_ONLY = Pattern.compile("-?(\\d+\\.?\\d*|\\d*\\.?\\d+|\\.)"); private static final Pattern HEXADECIMAL_ONLY = Pattern.compile("(-?[#0-9a-fA-F]*)"); private static final List entries = new ArrayList<>(); @@ -71,12 +72,12 @@ public abstract class MidnightConfig { Tab tab; } - public static final Map> configClass = new HashMap<>(); + public static final Map> configClass = new HashMap<>(); private static Path path; private static final Gson gson = new GsonBuilder().excludeFieldsWithModifiers(Modifier.TRANSIENT).excludeFieldsWithModifiers(Modifier.PRIVATE).addSerializationExclusionStrategy(new HiddenAnnotationExclusionStrategy()).setPrettyPrinting().create(); - public static void init(String modid, Class config) { + public static void init(String modid, Class config) { path = PlatformFunctions.getConfigDirectory().resolve(modid + ".json"); configClass.put(modid, config); @@ -177,12 +178,18 @@ public abstract class MidnightConfig { return true; }; } - + public static MidnightConfig getClass(String modid) { + try { return configClass.get(modid).getDeclaredConstructor().newInstance(); } catch (Exception e) {throw new RuntimeException(e);} + } public static void write(String modid) { + getClass(modid).writeChanges(modid); + } + + public void writeChanges(String modid) { path = PlatformFunctions.getConfigDirectory().resolve(modid + ".json"); try { if (!Files.exists(path)) Files.createFile(path); - Files.write(path, gson.toJson(configClass.get(modid).getDeclaredConstructor().newInstance()).getBytes()); + Files.write(path, gson.toJson(getClass(modid)).getBytes()); } catch (Exception e) { e.printStackTrace(); } @@ -251,6 +258,8 @@ public abstract class MidnightConfig { for (ButtonEntry entry : this.list.children()) { if (entry.buttons != null && entry.buttons.size() > 1 && entry.buttons.get(1) instanceof ButtonWidget button) { button.active = !Objects.equals(entry.info.value.toString(), entry.info.defaultValue.toString()); + if (button.active) button.setTooltip(Tooltip.of(Text.translatable("controls.reset").formatted(Formatting.RED))); + else button.setTooltip(Tooltip.of(Text.empty())); } } } @@ -305,13 +314,14 @@ public abstract class MidnightConfig { for (EntryInfo info : entries) { if (info.id.equals(modid) && (info.tab == null || info.tab == tabManager.getCurrentTab())) { Text name = Objects.requireNonNullElseGet(info.name, () -> Text.translatable(translationPrefix + info.field.getName())); - ButtonWidget resetButton = ButtonWidget.builder(Text.literal("Reset").formatted(Formatting.RED), (button -> { + TextIconButtonWidget resetButton = TextIconButtonWidget.builder(Text.translatable("controls.reset"), (button -> { info.value = info.defaultValue; info.tempValue = info.defaultValue.toString(); info.index = 0; list.clear(); fillList(); - })).dimensions(width - 205, 0, 40, 20).build(); + }), true).texture(new Identifier("midnightlib","icon/reset"), 12, 12).dimension(40, 20).build(); + resetButton.setPosition(width - 205, 0); if (info.widget instanceof Map.Entry) { Map.Entry> widget = (Map.Entry>) info.widget; @@ -327,7 +337,6 @@ public abstract class MidnightConfig { Predicate processor = ((BiFunction>) info.widget).apply(widget, done); widget.setTextPredicate(processor); resetButton.setWidth(20); - resetButton.setMessage(Text.literal("R").formatted(Formatting.RED)); ButtonWidget cycleButton = ButtonWidget.builder(Text.literal(String.valueOf(info.index)).formatted(Formatting.GOLD), (button -> { if (((List) info.value).contains("")) ((List) info.value).remove(""); info.index = info.index + 1; @@ -353,7 +362,6 @@ public abstract class MidnightConfig { widget.setTooltip(getTooltip(info)); if (e.isColor()) { resetButton.setWidth(20); - resetButton.setMessage(Text.literal("R").formatted(Formatting.RED)); ButtonWidget colorButton = ButtonWidget.builder(Text.literal("⬛"), (button -> { })).dimensions(width - 185, 0, 20, 20).build(); try { @@ -374,11 +382,10 @@ public abstract class MidnightConfig { } @Override public void render(DrawContext context, int mouseX, int mouseY, float delta) { - this.renderBackground(context); + super.render(context,mouseX,mouseY,delta); this.list.render(context, mouseX, mouseY, delta); if (tabs.size() < 2) context.drawCenteredTextWithShadow(textRenderer, title, width / 2, 15, 0xFFFFFF); - super.render(context,mouseX,mouseY,delta); } } @Environment(EnvType.CLIENT) diff --git a/common/src/main/java/eu/midnightdust/lib/util/MidnightColorUtil.java b/common/src/main/java/eu/midnightdust/lib/util/MidnightColorUtil.java index f46f972..f858bc7 100755 --- a/common/src/main/java/eu/midnightdust/lib/util/MidnightColorUtil.java +++ b/common/src/main/java/eu/midnightdust/lib/util/MidnightColorUtil.java @@ -3,12 +3,6 @@ package eu.midnightdust.lib.util; import java.awt.Color; public class MidnightColorUtil { - public static float hue; - public static void tick() { - if (hue > 1) hue = 0f; - hue = hue + 0.01f; - } - /** * @param colorStr e.g. "FFFFFF" or "#FFFFFF" * @return Color as RGB @@ -19,8 +13,4 @@ public class MidnightColorUtil { } catch (Exception ignored) {} return Color.BLACK; } - - public static Color radialRainbow(float saturation, float brightness) { - return Color.getHSBColor(hue, saturation, brightness); - } } diff --git a/common/src/main/java/eu/midnightdust/lib/util/screen/TexturedOverlayButtonWidget.java b/common/src/main/java/eu/midnightdust/lib/util/screen/TexturedOverlayButtonWidget.java deleted file mode 100644 index e5f1f38..0000000 --- a/common/src/main/java/eu/midnightdust/lib/util/screen/TexturedOverlayButtonWidget.java +++ /dev/null @@ -1,40 +0,0 @@ -package eu.midnightdust.lib.util.screen; - -import com.mojang.blaze3d.systems.RenderSystem; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.widget.TexturedButtonWidget; -import net.minecraft.client.render.GameRenderer; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.text.Text; -import net.minecraft.util.Identifier; - -public class TexturedOverlayButtonWidget extends TexturedButtonWidget { - - public TexturedOverlayButtonWidget(int x, int y, int width, int height, int u, int v, Identifier texture, PressAction pressAction) { - super(x, y, width, height, u, v, texture, pressAction); - } - - public TexturedOverlayButtonWidget(int x, int y, int width, int height, int u, int v, int hoveredVOffset, Identifier texture, PressAction pressAction) { - super(x, y, width, height, u, v, hoveredVOffset, texture, pressAction); - } - - public TexturedOverlayButtonWidget(int x, int y, int width, int height, int u, int v, int hoveredVOffset, Identifier texture, int textureWidth, int textureHeight, PressAction pressAction) { - super(x, y, width, height, u, v, hoveredVOffset, texture, textureWidth, textureHeight, pressAction); - } - - public TexturedOverlayButtonWidget(int x, int y, int width, int height, int u, int v, int hoveredVOffset, Identifier texture, int textureWidth, int textureHeight, PressAction pressAction, Text text) { - super(x, y, width, height, u, v, hoveredVOffset, texture, textureWidth, textureHeight, pressAction, text); - } - - @Override - public void renderButton(DrawContext context, int mouseX, int mouseY, float delta) { - int i = 66; - if (!this.isNarratable()) { - i += hoveredVOffset * 2; - } else if (this.isSelected()) { - i += hoveredVOffset; - } - context.drawNineSlicedTexture(WIDGETS_TEXTURE, this.getX(), this.getY(), this.width, this.height, 4, 200, 20, 0, i); - super.renderButton(context, mouseX, mouseY, delta); - } -} diff --git a/common/src/main/resources/assets/midnightlib/lang/de_de.json b/common/src/main/resources/assets/midnightlib/lang/de_de.json index b425e31..6d5212d 100755 --- a/common/src/main/resources/assets/midnightlib/lang/de_de.json +++ b/common/src/main/resources/assets/midnightlib/lang/de_de.json @@ -2,7 +2,6 @@ "midnightlib.overview.title":"MidnightConfig Übersicht", "midnightlib.midnightconfig.title":"MidnightLib Konfiguration", "midnightlib.midnightconfig.config_screen_list":"Konfigurationsübersicht", - "midnightlib.midnightconfig.background_texture":"Textur der Konfigurationsbildschirme", - "modmenu.descriptionTranslation.midnightlib": "Code-Bibliothek für Mods von MidnightDust.\nStellt eine Konfigurationsschnittstelle, automatische Kompatibilität, oft genutzten Code und Hüte für Unterstützer bereit.", - "modmenu.summaryTranslation.midnightlib": "Code-Bibliothek für Mods von MidnightDust." + "modmenu.descriptionTranslation.midnightlib": "Code-Bibliothek für einfache Konfiguration.\nStellt eine Konfigurationsschnittstelle, automatische Kompatibilität und oft genutzten Code bereit.", + "modmenu.summaryTranslation.midnightlib": "Code-Bibliothek für einfache Konfiguration." } \ No newline at end of file diff --git a/common/src/main/resources/assets/midnightlib/lang/en_us.json b/common/src/main/resources/assets/midnightlib/lang/en_us.json index 326564a..871eb57 100755 --- a/common/src/main/resources/assets/midnightlib/lang/en_us.json +++ b/common/src/main/resources/assets/midnightlib/lang/en_us.json @@ -5,10 +5,9 @@ "midnightlib.midnightconfig.enum.ConfigButton.TRUE":"§aYes", "midnightlib.midnightconfig.enum.ConfigButton.FALSE":"§cNo", "midnightlib.midnightconfig.enum.ConfigButton.MODMENU":"§bModMenu", - "midnightlib.midnightconfig.background_texture":"Texture of config screen backgrounds", "midnightlib.modrinth":"Modrinth", "midnightlib.curseforge":"CurseForge", "midnightlib.wiki":"Wiki", - "modmenu.descriptionTranslation.midnightlib": "Common Library for Team MidnightDust's mods.\nProvides a config api, automatic integration with other mods, common utils, and cosmetics.", - "modmenu.summaryTranslation.midnightlib": "Common Library for Team MidnightDust's mods." + "modmenu.descriptionTranslation.midnightlib": "Common Library for easy configuration.\nProvides a config api, automatic integration with other mods and common utils.", + "modmenu.summaryTranslation.midnightlib": "Common Library for easy configuration." } \ No newline at end of file diff --git a/common/src/main/resources/assets/midnightlib/lang/fr_fr.json b/common/src/main/resources/assets/midnightlib/lang/fr_fr.json index 143b2eb..49e7a92 100644 --- a/common/src/main/resources/assets/midnightlib/lang/fr_fr.json +++ b/common/src/main/resources/assets/midnightlib/lang/fr_fr.json @@ -4,7 +4,6 @@ "midnightlib.midnightconfig.config_screen_list":"Activer la liste de l'écran de configuration", "midnightlib.midnightconfig.enum.ConfigButton.TRUE":"§aOui", "midnightlib.midnightconfig.enum.ConfigButton.FALSE":"§cNon", - "midnightlib.midnightconfig.background_texture":"Texture d'arrière-plan de l'écran de configuration", - "modmenu.descriptionTranslation.midnightlib": "Bibliothèque commune pour les mods de la Team MidnightDust.\nFournit une API de configuration, une intégration automatique avec d'autres mods, des utilitaires courants et des cosmétiques.", + "modmenu.descriptionTranslation.midnightlib": "Bibliothèque commune pour les mods de la Team MidnightDust.\nFournit une API de configuration, une intégration automatique avec d'autres mods et des utilitaires courants.", "modmenu.summaryTranslation.midnightlib": "Bibliothèque commune pour les mods de la Team MidnightDust." } diff --git a/common/src/main/resources/assets/midnightlib/lang/pt_br.json b/common/src/main/resources/assets/midnightlib/lang/pt_br.json index 79cd680..3a47a49 100644 --- a/common/src/main/resources/assets/midnightlib/lang/pt_br.json +++ b/common/src/main/resources/assets/midnightlib/lang/pt_br.json @@ -4,7 +4,6 @@ "midnightlib.midnightconfig.config_screen_list":"Ativar lista de telas de configuração", "midnightlib.midnightconfig.enum.ConfigButton.TRUE":"§aVerdadeiro", "midnightlib.midnightconfig.enum.ConfigButton.FALSE":"§cFalso", - "midnightlib.midnightconfig.background_texture":"Textura dos fundos da tela de configuração", - "modmenu.descriptionTranslation.midnightlib": "Biblioteca comum para mods do Team MidnightDust.\nFornece uma API de configuração, integração automática com outros mods, utilitários comuns e cosméticos.", + "modmenu.descriptionTranslation.midnightlib": "Biblioteca comum para mods do Team MidnightDust.\nFornece uma API de configuração, integração automática com outros mods e utilitários comuns.", "modmenu.summaryTranslation.midnightlib": "Biblioteca comum para mods do Team MidnightDust." } \ No newline at end of file diff --git a/common/src/main/resources/assets/midnightlib/lang/tt_ru.json b/common/src/main/resources/assets/midnightlib/lang/tt_ru.json index ce648ee..9118e46 100644 --- a/common/src/main/resources/assets/midnightlib/lang/tt_ru.json +++ b/common/src/main/resources/assets/midnightlib/lang/tt_ru.json @@ -4,7 +4,6 @@ "midnightlib.midnightconfig.config_screen_list":"Көйләүләр экранының исемлеген кушу", "midnightlib.midnightconfig.enum.ConfigButton.TRUE":"§aӘйе", "midnightlib.midnightconfig.enum.ConfigButton.FALSE":"§cЮк", - "midnightlib.midnightconfig.background_texture":"Көйләүләр экранының фонының текстурасы", "midnightlib.wiki":"Вики", "modmenu.descriptionTranslation.midnightlib": "MidnightDust төркеменең модлары өчен гомуми китапханә.\nКөйләүләр API-ын, башка модлар белән автоматик интеграцияне, гомуми хезмәти программаларны һәм бизәнүләрне тәэмин ителә.", "modmenu.summaryTranslation.midnightlib": "MidnightDust төркеменең модлары өчен гомуми китапханә." diff --git a/common/src/main/resources/assets/midnightlib/lang/uk_ua.json b/common/src/main/resources/assets/midnightlib/lang/uk_ua.json index 6aee0e9..41e542f 100644 --- a/common/src/main/resources/assets/midnightlib/lang/uk_ua.json +++ b/common/src/main/resources/assets/midnightlib/lang/uk_ua.json @@ -2,7 +2,6 @@ "midnightlib.overview.title":"Огляд MidnightConfig", "midnightlib.midnightconfig.title":"Конфігурація MidnightLib", "midnightlib.midnightconfig.config_screen_list":"Увімкнути список екрана конфігурації", - "midnightlib.midnightconfig.background_texture":"Текстура фону екрана конфігурації", "midnightlib.wiki":"Вікі", "modmenu.descriptionTranslation.midnightlib": "Загальна бібліотека для модів команди MidnightDust.\nНадає конфігураційний API, автоматичну інтеграцію з іншими модами, загальні утиліти та косметику.", "modmenu.summaryTranslation.midnightlib": "Загальна бібліотека для модів команди MidnightDust." diff --git a/common/src/main/resources/assets/midnightlib/lang/zh_tw.json b/common/src/main/resources/assets/midnightlib/lang/zh_tw.json index 4b8207c..9b689cb 100644 --- a/common/src/main/resources/assets/midnightlib/lang/zh_tw.json +++ b/common/src/main/resources/assets/midnightlib/lang/zh_tw.json @@ -5,9 +5,6 @@ "midnightlib.midnightconfig.enum.ConfigButton.TRUE":"§a是", "midnightlib.midnightconfig.enum.ConfigButton.FALSE":"§c否", "midnightlib.midnightconfig.enum.ConfigButton.MODMENU":"§b模組選單", - "midnightlib.midnightconfig.background_texture":"設定背景畫面的材質", - "midnightlib.modrinth":"Modrinth", - "midnightlib.curseforge":"CurseForge", "midnightlib.wiki":"維基", "modmenu.descriptionTranslation.midnightlib": "MidnightDust 團隊的常用程式庫模組。\n提供設定 API、與其他模組自動整合、常用工具和美觀。", "modmenu.summaryTranslation.midnightlib": "MidnightDust 團隊的常用程式庫模組。" diff --git a/common/src/main/resources/assets/midnightlib/textures/gui/midnightlib_button.png b/common/src/main/resources/assets/midnightlib/textures/gui/midnightlib_button.png deleted file mode 100644 index 08282660c7ad3b161cd6bf4cb6779e8536cabfdf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 293 zcmeAS@N?(olHy`uVBq!ia0vp^3P9|@!3-pQ0$S$)sqg@w5LX}#1nvbs|Ns97GV=2B zfDANHT3Q+t6H{4P86F(-q(aiXZGC?_XJOG_&xB*f0nZq1rCiHV6XUcB)4 z_g}w$y+q4=U!ZY}B|(0{3=Yq3q=7g|-tI089jvk*Kn`btM`SSr1Gg{;GcwGYBLNg- zFY)wsWq-yb#wjWpUsB@^6ms`;aSZV|o}3_I(jdvDan*mDD2h1racX=D zVv$i)^*b>05sQsd-{sYd1P&PNIrzYTa)@8xnZ=n!B0Wuk4k`=`HEC?CWrH2I0F7ku MboFyt=akR{01PH(#sB~S diff --git a/common/src/main/resources/assets/midnightlib/textures/gui/sprites/icon/midnightlib.png b/common/src/main/resources/assets/midnightlib/textures/gui/sprites/icon/midnightlib.png new file mode 100644 index 0000000000000000000000000000000000000000..49977137720088246037d738752d990f9c1ae8fa GIT binary patch literal 189 zcmeAS@N?(olHy`uVBq!ia0vp^0w65F1|Vh_GL zHs82u^{nlt8}A;dwD0KX_;caF#$6kC@2*bz9GaY#CU)@5nK=frwhmT1swPAhR0#?Q j3fkr`Shecb4~f{4Qe%~jbsJfMRx^0I`njxgN@xNAby`2{ literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/midnightlib/textures/gui/sprites/icon/reset.png b/common/src/main/resources/assets/midnightlib/textures/gui/sprites/icon/reset.png new file mode 100644 index 0000000000000000000000000000000000000000..7678297efb7ce36e78de1c21dee5e01098d13c5a GIT binary patch literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^JRmH<1|->@HY@>Bm7Xq+Ar_~v25sa$V8G$MD(Gb0)$Z=`DoID8cr-L|2lgJYfne@Ijm!9t=s0 MidnightColorUtil.tick() - ); } } diff --git a/forge/src/main/java/eu/midnightdust/forge/MidnightLibClientEvents.java b/forge/src/main/java/eu/midnightdust/forge/MidnightLibClientEvents.java index c21b2c7..af1ff6e 100644 --- a/forge/src/main/java/eu/midnightdust/forge/MidnightLibClientEvents.java +++ b/forge/src/main/java/eu/midnightdust/forge/MidnightLibClientEvents.java @@ -13,13 +13,8 @@ import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; @Mod.EventBusSubscriber(modid = "midnightlib", bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT) public class MidnightLibClientEvents { - public static void registerClientTick(TickEvent.ClientTickEvent event) { - MidnightColorUtil.tick(); - } - @SubscribeEvent public static void onPostInit(FMLClientSetupEvent event) { - MinecraftForge.EVENT_BUS.addListener(MidnightLibClientEvents::registerClientTick); ModList.get().forEachModContainer((modid, modContainer) -> { if (MidnightConfig.configClass.containsKey(modid)) { modContainer.registerExtensionPoint(ConfigScreenHandler.ConfigScreenFactory.class, () -> diff --git a/gradle.properties b/gradle.properties index 3afe1a9..a9f37e3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,15 +1,15 @@ org.gradle.jvmargs=-Xmx4096M -minecraft_version=1.20 -yarn_mappings=1.20+build.1 -enabled_platforms=quilt,fabric,forge +minecraft_version=1.20.2-rc1 +yarn_mappings=1.20.2-rc1+build.2 +enabled_platforms=fabric archives_base_name=midnightlib -mod_version=1.4.1 +mod_version=1.5.0 maven_group=eu.midnightdust -fabric_loader_version=0.14.21 -fabric_api_version=0.83.0+1.20 +fabric_loader_version=0.14.22 +fabric_api_version=0.88.5+1.20.2 forge_version=1.20-46.0.2 diff --git a/quilt/src/main/java/eu/midnightdust/quilt/core/MidnightLibClientQuilt.java b/quilt/src/main/java/eu/midnightdust/quilt/core/MidnightLibClientQuilt.java index fe7491a..6899896 100644 --- a/quilt/src/main/java/eu/midnightdust/quilt/core/MidnightLibClientQuilt.java +++ b/quilt/src/main/java/eu/midnightdust/quilt/core/MidnightLibClientQuilt.java @@ -10,8 +10,5 @@ public class MidnightLibClientQuilt implements ClientModInitializer { @Override public void onInitializeClient(ModContainer mod) { MidnightLibClient.onInitializeClient(); - ClientTickEvents.END.register( - client -> MidnightColorUtil.tick() - ); } } diff --git a/settings.gradle b/settings.gradle index c86c020..f83aad5 100644 --- a/settings.gradle +++ b/settings.gradle @@ -10,7 +10,7 @@ pluginManagement { include("common") include("fabric-like") include("fabric") -include("quilt") -include("forge") +//include("quilt") +//include("forge") rootProject.name = "midnightlib" From 38e2e55a074c8233ebba8f4853938170dc20dae6 Mon Sep 17 00:00:00 2001 From: Motschen Date: Sat, 30 Sep 2023 10:55:25 +0200 Subject: [PATCH 002/100] Re-enable Forge support - QSL is still not released for whatever reason, so Quilt support will come later --- fabric/src/main/resources/fabric.mod.json | 2 +- .../main/java/eu/midnightdust/forge/MidnightLibForge.java | 5 +++-- gradle.properties | 8 ++++---- settings.gradle | 2 +- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/fabric/src/main/resources/fabric.mod.json b/fabric/src/main/resources/fabric.mod.json index 6a57513..54aa44c 100644 --- a/fabric/src/main/resources/fabric.mod.json +++ b/fabric/src/main/resources/fabric.mod.json @@ -32,7 +32,7 @@ }, "depends": { "fabric-resource-loader-v0": "*", - "minecraft": ">=1.20-beta.2" + "minecraft": ">=1.20.2" }, "mixins": [ diff --git a/forge/src/main/java/eu/midnightdust/forge/MidnightLibForge.java b/forge/src/main/java/eu/midnightdust/forge/MidnightLibForge.java index 122d6ec..7ecbeee 100644 --- a/forge/src/main/java/eu/midnightdust/forge/MidnightLibForge.java +++ b/forge/src/main/java/eu/midnightdust/forge/MidnightLibForge.java @@ -7,12 +7,13 @@ import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.fml.IExtensionPoint; import net.minecraftforge.fml.ModLoadingContext; import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.network.NetworkConstants; + +import static net.minecraftforge.fml.IExtensionPoint.DisplayTest.IGNORESERVERONLY; @Mod("midnightlib") public class MidnightLibForge { public MidnightLibForge() { - ModLoadingContext.get().registerExtensionPoint(IExtensionPoint.DisplayTest.class, () -> new IExtensionPoint.DisplayTest(() -> NetworkConstants.IGNORESERVERONLY, (remote, server) -> true)); + ModLoadingContext.get().registerExtensionPoint(IExtensionPoint.DisplayTest.class, () -> new IExtensionPoint.DisplayTest(() -> IGNORESERVERONLY, (remote, server) -> true)); DistExecutor.safeRunWhenOn(Dist.CLIENT, () -> MidnightLibClient::onInitializeClient); DistExecutor.safeRunWhenOn(Dist.DEDICATED_SERVER, () -> MidnightLibServer::onInitializeServer); } diff --git a/gradle.properties b/gradle.properties index a9f37e3..759c29d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,8 +1,8 @@ org.gradle.jvmargs=-Xmx4096M -minecraft_version=1.20.2-rc1 -yarn_mappings=1.20.2-rc1+build.2 -enabled_platforms=fabric +minecraft_version=1.20.2 +yarn_mappings=1.20.2+build.2 +enabled_platforms=fabric,forge archives_base_name=midnightlib mod_version=1.5.0 @@ -11,7 +11,7 @@ maven_group=eu.midnightdust fabric_loader_version=0.14.22 fabric_api_version=0.88.5+1.20.2 -forge_version=1.20-46.0.2 +forge_version=1.20.2-48.0.13 quilt_loader_version=0.19.0-beta.18 quilt_fabric_api_version=7.0.1+0.83.0-1.20 diff --git a/settings.gradle b/settings.gradle index f83aad5..0b4cc13 100644 --- a/settings.gradle +++ b/settings.gradle @@ -11,6 +11,6 @@ include("common") include("fabric-like") include("fabric") //include("quilt") -//include("forge") +include("forge") rootProject.name = "midnightlib" From 29c8a9ccfebfdd263e3fd3be10923d933ffd6df4 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Thu, 7 Dec 2023 18:07:09 +0100 Subject: [PATCH 003/100] MidnightLib 1.5.1 for 1.20.4 - Port to 1.20.4 - Add back fancy list background - File size optimizations - Update tooling --- build.gradle | 4 +- .../core/config/MidnightLibConfig.java | 2 +- .../screen/MidnightConfigOverviewScreen.java | 45 +++-------------- .../lib/config/MidnightConfig.java | 50 ++++++++++--------- fabric-like/build.gradle | 4 +- fabric/build.gradle | 16 ++---- .../fabric/core/MidnightLibClientFabric.java | 13 ----- .../fabric/core/MidnightLibFabric.java | 19 +++++++ .../fabric/core/MidnightLibServerFabric.java | 11 ---- fabric/src/main/resources/fabric.mod.json | 4 +- forge/build.gradle | 7 +-- gradle.properties | 14 +++--- gradle/wrapper/gradle-wrapper.properties | 2 +- settings.gradle | 2 +- 14 files changed, 75 insertions(+), 118 deletions(-) delete mode 100644 fabric/src/main/java/eu/midnightdust/fabric/core/MidnightLibClientFabric.java create mode 100644 fabric/src/main/java/eu/midnightdust/fabric/core/MidnightLibFabric.java delete mode 100644 fabric/src/main/java/eu/midnightdust/fabric/core/MidnightLibServerFabric.java diff --git a/build.gradle b/build.gradle index a2da9cc..7d1c5e5 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ plugins { id "architectury-plugin" version "3.4-SNAPSHOT" - id "dev.architectury.loom" version "1.1-SNAPSHOT" apply false + id "dev.architectury.loom" version "1.4-SNAPSHOT" apply false } architectury { @@ -12,8 +12,6 @@ subprojects { dependencies { minecraft "com.mojang:minecraft:${rootProject.minecraft_version}" - // The following line declares the mojmap mappings, you may use other mappings as well - //mappings loom.officialMojangMappings() // The following line declares the yarn mappings you may select this one as well. mappings "net.fabricmc:yarn:${rootProject.yarn_mappings}:v2" } diff --git a/common/src/main/java/eu/midnightdust/core/config/MidnightLibConfig.java b/common/src/main/java/eu/midnightdust/core/config/MidnightLibConfig.java index 41ac616..41c8e4d 100644 --- a/common/src/main/java/eu/midnightdust/core/config/MidnightLibConfig.java +++ b/common/src/main/java/eu/midnightdust/core/config/MidnightLibConfig.java @@ -4,7 +4,7 @@ import eu.midnightdust.lib.config.MidnightConfig; import eu.midnightdust.lib.util.PlatformFunctions; public class MidnightLibConfig extends MidnightConfig { - @Entry // Enable or disable the MidnightConfig overview screen button + @Entry public static ConfigButton config_screen_list = PlatformFunctions.isModLoaded("modmenu") ? ConfigButton.MODMENU : ConfigButton.TRUE; public enum ConfigButton { 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 9ec56c7..82b1e69 100755 --- a/common/src/main/java/eu/midnightdust/core/screen/MidnightConfigOverviewScreen.java +++ b/common/src/main/java/eu/midnightdust/core/screen/MidnightConfigOverviewScreen.java @@ -4,10 +4,7 @@ import eu.midnightdust.core.MidnightLibClient; import eu.midnightdust.lib.config.MidnightConfig; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; -import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.Element; -import net.minecraft.client.gui.Selectable; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.widget.*; import net.minecraft.screen.ScreenTexts; @@ -22,58 +19,32 @@ public class MidnightConfigOverviewScreen extends Screen { this.parent = parent; } private final Screen parent; - private MidnightOverviewListWidget list; + private MidnightConfig.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 - 28, 200, 20).build()); - this.list = new MidnightOverviewListWidget(this.client, this.width, this.height, 32, this.height - 32, 25); + this.list = new MidnightConfig.MidnightConfigListWidget(this.client, this.width, this.height - 64, 32, 25); if (this.client != null && this.client.world != null) this.list.setRenderBackground(false); this.addSelectableChild(this.list); List sortedMods = new ArrayList<>(MidnightConfig.configClass.keySet()); Collections.sort(sortedMods); sortedMods.forEach((modid) -> { if (!MidnightLibClient.hiddenMods.contains(modid)) { - list.addButton(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()); + 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); } }); super.init(); } @Override public void render(DrawContext context, int mouseX, int mouseY, float delta) { - super.render(context, mouseX, mouseY, delta); + if (client != null && client.world != null) super.renderInGameBackground(context); this.list.render(context, mouseX, mouseY, delta); + super.render(context, mouseX, mouseY, delta); + context.drawCenteredTextWithShadow(textRenderer, title, width / 2, 15, 0xFFFFFF); } - @Environment(EnvType.CLIENT) - public static class MidnightOverviewListWidget extends ElementListWidget { - public MidnightOverviewListWidget(MinecraftClient minecraftClient, int i, int j, int k, int l, int m) { - super(minecraftClient, i, j, k, l, m); - this.centerListVertically = false; - } - @Override - public int getScrollbarPositionX() {return this.width-7;} - - public void addButton(ClickableWidget button) { - this.addEntry(OverviewButtonEntry.create(button)); - } - @Override - public int getRowWidth() { return 400; } - } - public static class OverviewButtonEntry extends ElementListWidget.Entry { - private final ClickableWidget button; - - private OverviewButtonEntry(ClickableWidget button) { - this.button = button; - } - public static OverviewButtonEntry create(ClickableWidget button) {return new OverviewButtonEntry(button);} - public void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { - button.setY(y); - button.render(context, mouseX, mouseY, tickDelta); - } - public List children() {return List.of(button);} - public List selectableChildren() {return List.of(button);} - } + @Override public void renderBackground(DrawContext c, int x, int y, float d) {} } \ No newline at end of file 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 d842ddd..4245352 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -1,5 +1,6 @@ package eu.midnightdust.lib.config; +import com.google.common.collect.Lists; import com.google.gson.ExclusionStrategy; import com.google.gson.FieldAttributes; import com.google.gson.Gson; @@ -18,6 +19,7 @@ import net.minecraft.client.gui.tab.Tab; import net.minecraft.client.gui.tab.TabManager; import net.minecraft.client.gui.tooltip.Tooltip; import net.minecraft.client.gui.widget.*; +import net.minecraft.client.render.RenderLayer; import net.minecraft.client.resource.language.I18n; import net.minecraft.screen.ScreenTexts; import net.minecraft.text.OrderedText; @@ -42,7 +44,7 @@ import java.util.function.Function; import java.util.function.Predicate; import java.util.regex.Pattern; -/** MidnightConfig v2.5.0 by TeamMidnightDust & Motschen +/** MidnightConfig v2.5.1 by TeamMidnightDust & Motschen * Single class config library - feel free to copy! * Based on ... * Credits to Minenash */ @@ -55,7 +57,7 @@ public abstract class MidnightConfig { private static final List entries = new ArrayList<>(); - protected static class EntryInfo { + public static class EntryInfo { Field field; Object widget; int width; @@ -111,7 +113,7 @@ public abstract class MidnightConfig { info.id = modid; if (e != null) { - if (!e.name().equals("")) info.name = Text.translatable(e.name()); + if (!e.name().isEmpty()) info.name = Text.translatable(e.name()); if (type == int.class) textField(info, Integer::parseInt, INTEGER_ONLY, (int) e.min(), (int) e.max(), true); else if (type == float.class) textField(info, Float::parseFloat, DECIMAL_ONLY, (float) e.min(), (float) e.max(), false); else if (type == double.class) textField(info, Double::parseDouble, DECIMAL_ONLY, e.min(), e.max(), false); @@ -135,7 +137,8 @@ public abstract class MidnightConfig { entries.add(info); } public static Tooltip getTooltip(EntryInfo info) { - return Tooltip.of(info.error != null ? info.error : I18n.hasTranslation(info.id + ".midnightconfig."+info.field.getName()+".tooltip") ? Text.translatable(info.id + ".midnightconfig."+info.field.getName()+".tooltip") : Text.empty()); + String key = info.id + ".midnightconfig."+info.field.getName()+".tooltip"; + return Tooltip.of(info.error != null ? info.error : I18n.hasTranslation(key) ? Text.translatable(key) : Text.empty()); } private static void textField(EntryInfo info, Function f, Pattern pattern, double min, double max, boolean cast) { @@ -258,8 +261,6 @@ public abstract class MidnightConfig { for (ButtonEntry entry : this.list.children()) { if (entry.buttons != null && entry.buttons.size() > 1 && entry.buttons.get(1) instanceof ButtonWidget button) { button.active = !Objects.equals(entry.info.value.toString(), entry.info.defaultValue.toString()); - if (button.active) button.setTooltip(Tooltip.of(Text.translatable("controls.reset").formatted(Formatting.RED))); - else button.setTooltip(Tooltip.of(Text.empty())); } } } @@ -303,7 +304,7 @@ public abstract class MidnightConfig { Objects.requireNonNull(client).setScreen(parent); }).dimensions(this.width / 2 + 4, this.height - 28, 150, 20).build()); - this.list = new MidnightConfigListWidget(this.client, this.width, this.height, 32, this.height - 32, 25); + this.list = new MidnightConfigListWidget(this.client, this.width, this.height - 64, 32, 25); if (this.client != null && this.client.world != null) this.list.setRenderBackground(false); this.addSelectableChild(this.list); @@ -366,8 +367,7 @@ public abstract class MidnightConfig { })).dimensions(width - 185, 0, 20, 20).build(); try { colorButton.setMessage(Text.literal("⬛").setStyle(Style.EMPTY.withColor(Color.decode(info.tempValue).getRGB()))); - } catch (Exception ignored) { - } + } catch (Exception ignored) {} info.colorButton = colorButton; colorButton.active = false; this.list.addButton(List.of(widget, resetButton, colorButton), name, info); @@ -382,20 +382,18 @@ public abstract class MidnightConfig { } @Override public void render(DrawContext context, int mouseX, int mouseY, float delta) { - super.render(context,mouseX,mouseY,delta); + if (client != null && client.world != null) super.renderInGameBackground(context); this.list.render(context, mouseX, mouseY, delta); + super.render(context,mouseX,mouseY,delta); if (tabs.size() < 2) context.drawCenteredTextWithShadow(textRenderer, title, width / 2, 15, 0xFFFFFF); } + @Override public void renderBackground(DrawContext c, int x, int y, float d) {} } @Environment(EnvType.CLIENT) public static class MidnightConfigListWidget extends ElementListWidget { - TextRenderer textRenderer; - - public MidnightConfigListWidget(MinecraftClient minecraftClient, int i, int j, int k, int l, int m) { - super(minecraftClient, i, j, k, l, m); - this.centerListVertically = false; - textRenderer = minecraftClient.textRenderer; + public MidnightConfigListWidget(MinecraftClient client, int width, int height, int y, int itemHeight) { + super(client, width, height, y, itemHeight); } @Override public int getScrollbarPositionX() { return this.width -7; } @@ -403,18 +401,25 @@ public abstract class MidnightConfig { public void addButton(List buttons, Text text, EntryInfo info) { this.addEntry(new ButtonEntry(buttons, text, info)); } - public void clear() { - this.clearEntries(); - } + public void clear() { this.clearEntries(); } @Override public int getRowWidth() { return 10000; } + @Override + protected void renderDecorations(DrawContext c, int mouseX, int mouseY) { + c.setShaderColor(0.25F, 0.25F, 0.25F, 1.0F); + c.drawTexture(Screen.OPTIONS_BACKGROUND_TEXTURE, this.getX(), 0, 0.0F, 0.0F, this.width, this.getY(), 32, 32); + c.drawTexture(Screen.OPTIONS_BACKGROUND_TEXTURE, this.getX(), this.getBottom(), 0.0F, 0.0F, this.width, this.height, 32, 32); + c.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + if (client == null || client.world == null) return; + c.fillGradient(RenderLayer.getGuiOverlay(), this.getX(), this.getY(), this.getRight(), this.getY() + 4, -16777216, 0, 0); + c.fillGradient(RenderLayer.getGuiOverlay(), this.getX(), this.getBottom() - 4, this.getRight(), this.getBottom(), 0, -16777216, 0); + } } public static class ButtonEntry extends ElementListWidget.Entry { private static final TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; public final List buttons; private final Text text; public final EntryInfo info; - private final List children = new ArrayList<>(); public static final Map buttonsWithText = new HashMap<>(); private ButtonEntry(List buttons, Text text, EntryInfo info) { @@ -422,7 +427,6 @@ public abstract class MidnightConfig { this.buttons = buttons; this.text = text; this.info = info; - children.addAll(buttons); } public void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { buttons.forEach(b -> { b.setY(y); b.render(context, mouseX, mouseY, tickDelta); }); @@ -437,8 +441,8 @@ public abstract class MidnightConfig { } } } - public List children() {return children;} - public List selectableChildren() {return children;} + public List children() {return Lists.newArrayList(buttons);} + public List selectableChildren() {return Lists.newArrayList(buttons);} } public static class MidnightSliderWidget extends SliderWidget { private final EntryInfo info; private final Entry e; diff --git a/fabric-like/build.gradle b/fabric-like/build.gradle index 1b87612..eb27af5 100644 --- a/fabric-like/build.gradle +++ b/fabric-like/build.gradle @@ -13,5 +13,5 @@ dependencies { modApi "net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_api_version}" modImplementation ("com.terraformersmc:modmenu:${rootProject.mod_menu_version}") - compileClasspath(project(path: ":common", configuration: "namedElements")) { transitive false } -} + compileOnly(project(path: ":common", configuration: "namedElements")) { transitive false } +} \ No newline at end of file diff --git a/fabric/build.gradle b/fabric/build.gradle index 3cc4036..a5356cf 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -12,7 +12,7 @@ loom { configurations { common - shadowCommon // Don't use shadow from the shadow plugin because we don't want IDEA to index this. + shadowCommon // Don't use shadow from the shadow plugin since it *excludes* files. compileClasspath.extendsFrom common runtimeClasspath.extendsFrom common developmentFabric.extendsFrom common @@ -25,8 +25,6 @@ dependencies { common(project(path: ":common", configuration: "namedElements")) { transitive false } shadowCommon(project(path: ":common", configuration: "transformProductionFabric")) { transitive false } - common(project(path: ":fabric-like", configuration: "namedElements")) { transitive false } - shadowCommon(project(path: ":fabric-like", configuration: "transformProductionFabric")) { transitive false } } processResources { @@ -41,17 +39,13 @@ shadowJar { exclude "architectury.common.json" configurations = [project.configurations.shadowCommon] - classifier "dev-shadow" + archiveClassifier = "dev-shadow" } remapJar { + injectAccessWidener = true input.set shadowJar.archiveFile dependsOn shadowJar - classifier null -} - -jar { - classifier "dev" } sourcesJar { @@ -69,7 +63,7 @@ components.java { publishing { publications { mavenFabric(MavenPublication) { - artifactId = rootProject.archives_base_name + "-" + project.name + artifactId = archives_base_name + "-" + project.name from components.java } } @@ -78,4 +72,4 @@ publishing { repositories { // Add repositories to publish to here. } -} +} \ No newline at end of file diff --git a/fabric/src/main/java/eu/midnightdust/fabric/core/MidnightLibClientFabric.java b/fabric/src/main/java/eu/midnightdust/fabric/core/MidnightLibClientFabric.java deleted file mode 100644 index 5a01dbc..0000000 --- a/fabric/src/main/java/eu/midnightdust/fabric/core/MidnightLibClientFabric.java +++ /dev/null @@ -1,13 +0,0 @@ -package eu.midnightdust.fabric.core; - -import eu.midnightdust.core.MidnightLibClient; -import eu.midnightdust.lib.util.MidnightColorUtil; -import net.fabricmc.api.ClientModInitializer; -import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; - -public class MidnightLibClientFabric implements ClientModInitializer { - @Override - public void onInitializeClient() { - MidnightLibClient.onInitializeClient(); - } -} diff --git a/fabric/src/main/java/eu/midnightdust/fabric/core/MidnightLibFabric.java b/fabric/src/main/java/eu/midnightdust/fabric/core/MidnightLibFabric.java new file mode 100644 index 0000000..c1e08ee --- /dev/null +++ b/fabric/src/main/java/eu/midnightdust/fabric/core/MidnightLibFabric.java @@ -0,0 +1,19 @@ +package eu.midnightdust.fabric.core; + +import eu.midnightdust.core.MidnightLibClient; +import eu.midnightdust.core.MidnightLibServer; +import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.api.DedicatedServerModInitializer; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +public class MidnightLibFabric implements ClientModInitializer, DedicatedServerModInitializer { + @Override @Environment(EnvType.CLIENT) + public void onInitializeClient() { + MidnightLibClient.onInitializeClient(); + } + @Override @Environment(EnvType.SERVER) + public void onInitializeServer() { + MidnightLibServer.onInitializeServer(); + } +} diff --git a/fabric/src/main/java/eu/midnightdust/fabric/core/MidnightLibServerFabric.java b/fabric/src/main/java/eu/midnightdust/fabric/core/MidnightLibServerFabric.java deleted file mode 100644 index 90fb7bb..0000000 --- a/fabric/src/main/java/eu/midnightdust/fabric/core/MidnightLibServerFabric.java +++ /dev/null @@ -1,11 +0,0 @@ -package eu.midnightdust.fabric.core; - -import eu.midnightdust.core.MidnightLibServer; -import net.fabricmc.api.DedicatedServerModInitializer; - -public class MidnightLibServerFabric implements DedicatedServerModInitializer { - @Override - public void onInitializeServer() { - MidnightLibServer.onInitializeServer(); - } -} diff --git a/fabric/src/main/resources/fabric.mod.json b/fabric/src/main/resources/fabric.mod.json index 54aa44c..4304f35 100644 --- a/fabric/src/main/resources/fabric.mod.json +++ b/fabric/src/main/resources/fabric.mod.json @@ -21,10 +21,10 @@ "environment": "*", "entrypoints": { "client": [ - "eu.midnightdust.fabric.core.MidnightLibClientFabric" + "eu.midnightdust.fabric.core.MidnightLibFabric" ], "server": [ - "eu.midnightdust.fabric.core.MidnightLibServerFabric" + "eu.midnightdust.fabric.core.MidnightLibFabric" ], "modmenu": [ "eu.midnightdust.lib.config.AutoModMenu" diff --git a/forge/build.gradle b/forge/build.gradle index f80b84f..e4cd273 100644 --- a/forge/build.gradle +++ b/forge/build.gradle @@ -42,17 +42,12 @@ shadowJar { exclude "architectury.common.json" configurations = [project.configurations.shadowCommon] - classifier "dev-shadow" + archiveClassifier = "dev-shadow" } remapJar { input.set shadowJar.archiveFile dependsOn shadowJar - classifier null -} - -jar { - classifier "dev" } sourcesJar { diff --git a/gradle.properties b/gradle.properties index 759c29d..92122bc 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,17 +1,17 @@ org.gradle.jvmargs=-Xmx4096M -minecraft_version=1.20.2 -yarn_mappings=1.20.2+build.2 -enabled_platforms=fabric,forge +minecraft_version=1.20.4 +yarn_mappings=1.20.4+build.1 +enabled_platforms=fabric archives_base_name=midnightlib -mod_version=1.5.0 +mod_version=1.5.1 maven_group=eu.midnightdust -fabric_loader_version=0.14.22 -fabric_api_version=0.88.5+1.20.2 +fabric_loader_version=0.15.0 +fabric_api_version=0.91.1+1.20.4 -forge_version=1.20.2-48.0.13 +forge_version=1.20.3-49.0.2 quilt_loader_version=0.19.0-beta.18 quilt_fabric_api_version=7.0.1+0.83.0-1.20 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ae04661..a595206 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/settings.gradle b/settings.gradle index 0b4cc13..f83aad5 100644 --- a/settings.gradle +++ b/settings.gradle @@ -11,6 +11,6 @@ include("common") include("fabric-like") include("fabric") //include("quilt") -include("forge") +//include("forge") rootProject.name = "midnightlib" From fb1c4c1158c2728c77a12416c69336a46ff18f05 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Mon, 11 Dec 2023 19:28:04 +0100 Subject: [PATCH 004/100] MidnightLib 1.5.2 - NeoForge & more cleanness - Native support for NeoForge (& dropped support for regular Forge) - Cleanup of some code -> Overview button is now added via callbacks instead of a mixin - Unify client & server classes - Minor breaking change only affecting mods using the hiding functionality --- common/build.gradle | 1 + ...idnightLibServer.java => MidnightLib.java} | 13 +++- .../midnightdust/core/MidnightLibClient.java | 14 ----- .../core/mixin/MixinOptionsScreen.java | 34 ---------- .../screen/MidnightConfigOverviewScreen.java | 21 ++++++- .../lib/config/MidnightConfig.java | 2 +- .../main/resources/architectury.common.json | 4 +- .../main/resources/midnightlib.accesswidener | 3 + .../main/resources/midnightlib.mixins.json | 1 - .../midnightdust/lib/config/AutoModMenu.java | 4 +- .../fabric/core/MidnightLibFabric.java | 14 +++-- fabric/src/main/resources/fabric.mod.json | 9 +-- forge/gradle.properties | 1 - .../forge/MidnightLibClientEvents.java | 25 -------- .../midnightdust/forge/MidnightLibForge.java | 20 ------ .../forge/MidnightLibServerEvents.java | 19 ------ gradle.properties | 8 +-- {forge => neoforge}/build.gradle | 16 ++--- neoforge/gradle.properties | 1 + .../util/neoforge}/PlatformFunctionsImpl.java | 8 +-- .../neoforge/MidnightLibNeoForge.java | 58 ++++++++++++++++++ .../src/main/resources/META-INF/mods.toml | 8 +-- .../src/main/resources/midnightlib.png | Bin .../src/main/resources/pack.mcmeta | 2 +- settings.gradle | 4 +- 25 files changed, 135 insertions(+), 155 deletions(-) rename common/src/main/java/eu/midnightdust/core/{MidnightLibServer.java => MidnightLib.java} (57%) delete mode 100755 common/src/main/java/eu/midnightdust/core/MidnightLibClient.java delete mode 100755 common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java create mode 100644 common/src/main/resources/midnightlib.accesswidener delete mode 100644 common/src/main/resources/midnightlib.mixins.json delete mode 100644 forge/gradle.properties delete mode 100644 forge/src/main/java/eu/midnightdust/forge/MidnightLibClientEvents.java delete mode 100644 forge/src/main/java/eu/midnightdust/forge/MidnightLibForge.java delete mode 100644 forge/src/main/java/eu/midnightdust/forge/MidnightLibServerEvents.java rename {forge => neoforge}/build.gradle (80%) create mode 100644 neoforge/gradle.properties rename {forge/src/main/java/eu/midnightdust/lib/util/forge => neoforge/src/main/java/eu/midnightdust/lib/util/neoforge}/PlatformFunctionsImpl.java (81%) create mode 100644 neoforge/src/main/java/eu/midnightdust/neoforge/MidnightLibNeoForge.java rename {forge => neoforge}/src/main/resources/META-INF/mods.toml (81%) rename {forge => neoforge}/src/main/resources/midnightlib.png (100%) rename {forge => neoforge}/src/main/resources/pack.mcmeta (71%) diff --git a/common/build.gradle b/common/build.gradle index 4b57e84..21d4a73 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -3,6 +3,7 @@ architectury { } loom { + accessWidenerPath = file("src/main/resources/midnightlib.accesswidener") } dependencies { diff --git a/common/src/main/java/eu/midnightdust/core/MidnightLibServer.java b/common/src/main/java/eu/midnightdust/core/MidnightLib.java similarity index 57% rename from common/src/main/java/eu/midnightdust/core/MidnightLibServer.java rename to common/src/main/java/eu/midnightdust/core/MidnightLib.java index a092123..b729dc1 100755 --- a/common/src/main/java/eu/midnightdust/core/MidnightLibServer.java +++ b/common/src/main/java/eu/midnightdust/core/MidnightLib.java @@ -1,12 +1,23 @@ package eu.midnightdust.core; +import eu.midnightdust.core.config.MidnightLibConfig; import eu.midnightdust.lib.config.AutoCommand; import eu.midnightdust.lib.config.MidnightConfig; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; -public class MidnightLibServer { +public class MidnightLib { + public static List hiddenMods = new ArrayList<>(); + @Environment(EnvType.CLIENT) + public static void onInitializeClient() { + MidnightLibConfig.init("midnightlib", MidnightLibConfig.class); + } + @Environment(EnvType.SERVER) public static void onInitializeServer() { MidnightConfig.configClass.forEach((modid, config) -> { for (Field field : config.getFields()) { diff --git a/common/src/main/java/eu/midnightdust/core/MidnightLibClient.java b/common/src/main/java/eu/midnightdust/core/MidnightLibClient.java deleted file mode 100755 index 2cfdd0d..0000000 --- a/common/src/main/java/eu/midnightdust/core/MidnightLibClient.java +++ /dev/null @@ -1,14 +0,0 @@ -package eu.midnightdust.core; - -import eu.midnightdust.core.config.MidnightLibConfig; - -import java.util.ArrayList; -import java.util.List; - -public class MidnightLibClient { - public static List hiddenMods = new ArrayList<>(); - - public static void onInitializeClient() { - MidnightLibConfig.init("midnightlib", MidnightLibConfig.class); - } -} diff --git a/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java b/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java deleted file mode 100755 index f6af033..0000000 --- a/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java +++ /dev/null @@ -1,34 +0,0 @@ -package eu.midnightdust.core.mixin; - -import eu.midnightdust.core.config.MidnightLibConfig; -import eu.midnightdust.core.screen.MidnightConfigOverviewScreen; -import eu.midnightdust.lib.util.PlatformFunctions; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.screen.option.OptionsScreen; -import net.minecraft.client.gui.widget.TextIconButtonWidget; -import net.minecraft.text.Text; -import net.minecraft.util.Identifier; -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; - -import java.util.Objects; - -@Mixin(OptionsScreen.class) -public class MixinOptionsScreen extends Screen { - protected MixinOptionsScreen(Text title) { - super(title); - } - - @Inject(at = @At("HEAD"),method = "init") - private void midnightlib$init(CallbackInfo ci) { - if (MidnightLibConfig.config_screen_list.equals(MidnightLibConfig.ConfigButton.TRUE) || (MidnightLibConfig.config_screen_list.equals(MidnightLibConfig.ConfigButton.MODMENU) && !PlatformFunctions.isModLoaded("modmenu"))) { - TextIconButtonWidget button = TextIconButtonWidget.builder(Text.translatable("midnightlib.overview.title"), ( - buttonWidget) -> Objects.requireNonNull(client).setScreen(new MidnightConfigOverviewScreen(this)), true) - .texture(new Identifier("midnightlib","icon/midnightlib"), 16, 16).dimension(20, 20).build(); - button.setPosition(this.width / 2 + 158, this.height / 6 - 12); - this.addDrawableChild(button); - } - } -} 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 82b1e69..12e5da9 100755 --- a/common/src/main/java/eu/midnightdust/core/screen/MidnightConfigOverviewScreen.java +++ b/common/src/main/java/eu/midnightdust/core/screen/MidnightConfigOverviewScreen.java @@ -1,14 +1,20 @@ package eu.midnightdust.core.screen; -import eu.midnightdust.core.MidnightLibClient; +import eu.midnightdust.core.MidnightLib; +import eu.midnightdust.core.config.MidnightLibConfig; import eu.midnightdust.lib.config.MidnightConfig; +import eu.midnightdust.lib.util.PlatformFunctions; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.option.OptionsScreen; import net.minecraft.client.gui.widget.*; import net.minecraft.screen.ScreenTexts; import net.minecraft.text.*; +import net.minecraft.util.Identifier; + import java.util.*; @Environment(EnvType.CLIENT) @@ -31,7 +37,7 @@ public class MidnightConfigOverviewScreen extends Screen { List sortedMods = new ArrayList<>(MidnightConfig.configClass.keySet()); Collections.sort(sortedMods); sortedMods.forEach((modid) -> { - if (!MidnightLibClient.hiddenMods.contains(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); } @@ -47,4 +53,15 @@ public class MidnightConfigOverviewScreen extends Screen { context.drawCenteredTextWithShadow(textRenderer, title, width / 2, 15, 0xFFFFFF); } @Override public void renderBackground(DrawContext c, int x, int y, float d) {} + + public static void addButtonToOptionsScreen(Screen screen, MinecraftClient client) { + if (screen.getClass() == OptionsScreen.class && MidnightLibConfig.config_screen_list.equals(MidnightLibConfig.ConfigButton.TRUE) + || (MidnightLibConfig.config_screen_list.equals(MidnightLibConfig.ConfigButton.MODMENU) && !PlatformFunctions.isModLoaded("modmenu"))) { + TextIconButtonWidget button = TextIconButtonWidget.builder(Text.translatable("midnightlib.overview.title"), ( + buttonWidget) -> Objects.requireNonNull(client).setScreen(new MidnightConfigOverviewScreen(screen)), true) + .texture(new Identifier("midnightlib","icon/midnightlib"), 16, 16).dimension(20, 20).build(); + button.setPosition(screen.width / 2 + 158, screen.height / 6 - 12); + screen.addDrawableChild(button); + } + } } \ No newline at end of file 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 4245352..1e2e939 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -194,7 +194,7 @@ public abstract class MidnightConfig { if (!Files.exists(path)) Files.createFile(path); Files.write(path, gson.toJson(getClass(modid)).getBytes()); } catch (Exception e) { - e.printStackTrace(); + e.fillInStackTrace(); } } @Environment(EnvType.CLIENT) diff --git a/common/src/main/resources/architectury.common.json b/common/src/main/resources/architectury.common.json index 9e26dfe..093c5d3 100644 --- a/common/src/main/resources/architectury.common.json +++ b/common/src/main/resources/architectury.common.json @@ -1 +1,3 @@ -{} \ No newline at end of file +{ + "accessWidener": "midnightlib.accesswidener" +} \ No newline at end of file diff --git a/common/src/main/resources/midnightlib.accesswidener b/common/src/main/resources/midnightlib.accesswidener new file mode 100644 index 0000000..561ebaa --- /dev/null +++ b/common/src/main/resources/midnightlib.accesswidener @@ -0,0 +1,3 @@ +accessWidener v2 named + +accessible method net/minecraft/client/gui/screen/Screen addDrawableChild (Lnet/minecraft/client/gui/Element;)Lnet/minecraft/client/gui/Element; \ No newline at end of file diff --git a/common/src/main/resources/midnightlib.mixins.json b/common/src/main/resources/midnightlib.mixins.json deleted file mode 100644 index 20c4305..0000000 --- a/common/src/main/resources/midnightlib.mixins.json +++ /dev/null @@ -1 +0,0 @@ -{"required": true,"minVersion": "0.8","package": "eu.midnightdust.core.mixin","compatibilityLevel": "JAVA_17","client": ["MixinOptionsScreen"],"injectors": {"defaultRequire": 1}} \ No newline at end of file diff --git a/fabric-like/src/main/java/eu/midnightdust/lib/config/AutoModMenu.java b/fabric-like/src/main/java/eu/midnightdust/lib/config/AutoModMenu.java index 4a16c68..72bcc21 100755 --- a/fabric-like/src/main/java/eu/midnightdust/lib/config/AutoModMenu.java +++ b/fabric-like/src/main/java/eu/midnightdust/lib/config/AutoModMenu.java @@ -2,7 +2,7 @@ package eu.midnightdust.lib.config; import com.terraformersmc.modmenu.api.ConfigScreenFactory; import com.terraformersmc.modmenu.api.ModMenuApi; -import eu.midnightdust.core.MidnightLibClient; +import eu.midnightdust.core.MidnightLib; import eu.midnightdust.core.config.MidnightLibConfig; import java.util.HashMap; @@ -19,7 +19,7 @@ public class AutoModMenu implements ModMenuApi { public Map> getProvidedConfigScreenFactories() { HashMap> map = new HashMap<>(); MidnightConfig.configClass.forEach((modid, cClass) -> { - if (!MidnightLibClient.hiddenMods.contains(modid)) + if (!MidnightLib.hiddenMods.contains(modid)) map.put(modid, parent -> MidnightConfig.getScreen(parent, modid)); } ); 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 c1e08ee..f1cffed 100644 --- a/fabric/src/main/java/eu/midnightdust/fabric/core/MidnightLibFabric.java +++ b/fabric/src/main/java/eu/midnightdust/fabric/core/MidnightLibFabric.java @@ -1,19 +1,21 @@ package eu.midnightdust.fabric.core; -import eu.midnightdust.core.MidnightLibClient; -import eu.midnightdust.core.MidnightLibServer; +import eu.midnightdust.core.MidnightLib; +import eu.midnightdust.core.screen.MidnightConfigOverviewScreen; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.api.DedicatedServerModInitializer; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents; public class MidnightLibFabric implements ClientModInitializer, DedicatedServerModInitializer { @Override @Environment(EnvType.CLIENT) public void onInitializeClient() { - MidnightLibClient.onInitializeClient(); + MidnightLib.onInitializeClient(); + ScreenEvents.AFTER_INIT.register((client, screen, scaledWidth, scaledHeight) -> { + MidnightConfigOverviewScreen.addButtonToOptionsScreen(screen, client); + }); } @Override @Environment(EnvType.SERVER) - public void onInitializeServer() { - MidnightLibServer.onInitializeServer(); - } + public void onInitializeServer() {MidnightLib.onInitializeServer();} } diff --git a/fabric/src/main/resources/fabric.mod.json b/fabric/src/main/resources/fabric.mod.json index 4304f35..3944bac 100644 --- a/fabric/src/main/resources/fabric.mod.json +++ b/fabric/src/main/resources/fabric.mod.json @@ -32,13 +32,9 @@ }, "depends": { "fabric-resource-loader-v0": "*", - "minecraft": ">=1.20.2" + "minecraft": ">=1.20.3" }, - "mixins": [ - "midnightlib.mixins.json" - ], - "custom": { "modmenu": { "links": { @@ -50,5 +46,6 @@ }, "badges": [ "library" ] } - } + }, + "accessWidener": "midnightlib.accesswidener" } diff --git a/forge/gradle.properties b/forge/gradle.properties deleted file mode 100644 index 32f842a..0000000 --- a/forge/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -loom.platform=forge \ No newline at end of file diff --git a/forge/src/main/java/eu/midnightdust/forge/MidnightLibClientEvents.java b/forge/src/main/java/eu/midnightdust/forge/MidnightLibClientEvents.java deleted file mode 100644 index af1ff6e..0000000 --- a/forge/src/main/java/eu/midnightdust/forge/MidnightLibClientEvents.java +++ /dev/null @@ -1,25 +0,0 @@ -package eu.midnightdust.forge; - -import eu.midnightdust.lib.config.MidnightConfig; -import eu.midnightdust.lib.util.MidnightColorUtil; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.client.ConfigScreenHandler; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.event.TickEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.ModList; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; - -@Mod.EventBusSubscriber(modid = "midnightlib", bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT) -public class MidnightLibClientEvents { - @SubscribeEvent - public static void onPostInit(FMLClientSetupEvent event) { - ModList.get().forEachModContainer((modid, modContainer) -> { - if (MidnightConfig.configClass.containsKey(modid)) { - modContainer.registerExtensionPoint(ConfigScreenHandler.ConfigScreenFactory.class, () -> - new ConfigScreenHandler.ConfigScreenFactory((client, parent) -> MidnightConfig.getScreen(parent, modid))); - } - }); - } -} diff --git a/forge/src/main/java/eu/midnightdust/forge/MidnightLibForge.java b/forge/src/main/java/eu/midnightdust/forge/MidnightLibForge.java deleted file mode 100644 index 7ecbeee..0000000 --- a/forge/src/main/java/eu/midnightdust/forge/MidnightLibForge.java +++ /dev/null @@ -1,20 +0,0 @@ -package eu.midnightdust.forge; - -import eu.midnightdust.core.MidnightLibClient; -import eu.midnightdust.core.MidnightLibServer; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.fml.DistExecutor; -import net.minecraftforge.fml.IExtensionPoint; -import net.minecraftforge.fml.ModLoadingContext; -import net.minecraftforge.fml.common.Mod; - -import static net.minecraftforge.fml.IExtensionPoint.DisplayTest.IGNORESERVERONLY; - -@Mod("midnightlib") -public class MidnightLibForge { - public MidnightLibForge() { - ModLoadingContext.get().registerExtensionPoint(IExtensionPoint.DisplayTest.class, () -> new IExtensionPoint.DisplayTest(() -> IGNORESERVERONLY, (remote, server) -> true)); - DistExecutor.safeRunWhenOn(Dist.CLIENT, () -> MidnightLibClient::onInitializeClient); - DistExecutor.safeRunWhenOn(Dist.DEDICATED_SERVER, () -> MidnightLibServer::onInitializeServer); - } -} diff --git a/forge/src/main/java/eu/midnightdust/forge/MidnightLibServerEvents.java b/forge/src/main/java/eu/midnightdust/forge/MidnightLibServerEvents.java deleted file mode 100644 index faa63b0..0000000 --- a/forge/src/main/java/eu/midnightdust/forge/MidnightLibServerEvents.java +++ /dev/null @@ -1,19 +0,0 @@ -package eu.midnightdust.forge; - -import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import eu.midnightdust.lib.config.AutoCommand; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.event.RegisterCommandsEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; - -@Mod.EventBusSubscriber(modid = "midnightlib", value = Dist.DEDICATED_SERVER) -public class MidnightLibServerEvents { - @SubscribeEvent - public static void registerCommands(RegisterCommandsEvent event) { - for (LiteralArgumentBuilder command : AutoCommand.commands){ - event.getDispatcher().register(command); - } - } -} diff --git a/gradle.properties b/gradle.properties index 92122bc..be0ee04 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,16 +2,16 @@ org.gradle.jvmargs=-Xmx4096M minecraft_version=1.20.4 yarn_mappings=1.20.4+build.1 -enabled_platforms=fabric +enabled_platforms=fabric,neoforge archives_base_name=midnightlib -mod_version=1.5.1 +mod_version=1.5.2 maven_group=eu.midnightdust -fabric_loader_version=0.15.0 +fabric_loader_version=0.15.1 fabric_api_version=0.91.1+1.20.4 -forge_version=1.20.3-49.0.2 +neoforge_version=20.4.12-beta quilt_loader_version=0.19.0-beta.18 quilt_fabric_api_version=7.0.1+0.83.0-1.20 diff --git a/forge/build.gradle b/neoforge/build.gradle similarity index 80% rename from forge/build.gradle rename to neoforge/build.gradle index e4cd273..d7870e2 100644 --- a/forge/build.gradle +++ b/neoforge/build.gradle @@ -1,16 +1,17 @@ plugins { id "com.github.johnrengelman.shadow" version "7.1.2" } +repositories{ + maven {url "https://maven.neoforged.net/releases"} +} architectury { platformSetupLoomIde() - forge() + neoForge() } loom { - forge { - mixinConfig "midnightlib.mixins.json" - } + accessWidenerPath = project(":common").loom.accessWidenerPath } configurations { @@ -19,14 +20,14 @@ configurations { compileClasspath.extendsFrom common runtimeClasspath.extendsFrom common developmentForge.extendsFrom common - archivesBaseName = rootProject.archives_base_name + "-forge" + archivesBaseName = rootProject.archives_base_name + "-neoforge" } dependencies { - forge "net.minecraftforge:forge:${rootProject.forge_version}" + neoForge "net.neoforged:neoforge:${rootProject.neoforge_version}" common(project(path: ":common", configuration: "namedElements")) { transitive false } - shadowCommon(project(path: ":common", configuration: "transformProductionForge")) { transitive = false } + shadowCommon(project(path: ":common", configuration: "transformProductionNeoForge")) { transitive = false } } processResources { @@ -46,6 +47,7 @@ shadowJar { } remapJar { + atAccessWideners.add('midnightlib.accesswidener') input.set shadowJar.archiveFile dependsOn shadowJar } diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties new file mode 100644 index 0000000..2914393 --- /dev/null +++ b/neoforge/gradle.properties @@ -0,0 +1 @@ +loom.platform=neoforge \ No newline at end of file diff --git a/forge/src/main/java/eu/midnightdust/lib/util/forge/PlatformFunctionsImpl.java b/neoforge/src/main/java/eu/midnightdust/lib/util/neoforge/PlatformFunctionsImpl.java similarity index 81% rename from forge/src/main/java/eu/midnightdust/lib/util/forge/PlatformFunctionsImpl.java rename to neoforge/src/main/java/eu/midnightdust/lib/util/neoforge/PlatformFunctionsImpl.java index 84471c8..16ee0a0 100644 --- a/forge/src/main/java/eu/midnightdust/lib/util/forge/PlatformFunctionsImpl.java +++ b/neoforge/src/main/java/eu/midnightdust/lib/util/neoforge/PlatformFunctionsImpl.java @@ -1,11 +1,11 @@ -package eu.midnightdust.lib.util.forge; +package eu.midnightdust.lib.util.neoforge; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import eu.midnightdust.lib.util.PlatformFunctions; import net.minecraft.server.command.ServerCommandSource; -import net.minecraftforge.fml.ModList; -import net.minecraftforge.fml.loading.FMLEnvironment; -import net.minecraftforge.fml.loading.FMLPaths; +import net.neoforged.fml.ModList; +import net.neoforged.fml.loading.FMLEnvironment; +import net.neoforged.fml.loading.FMLPaths; import java.nio.file.Path; diff --git a/neoforge/src/main/java/eu/midnightdust/neoforge/MidnightLibNeoForge.java b/neoforge/src/main/java/eu/midnightdust/neoforge/MidnightLibNeoForge.java new file mode 100644 index 0000000..31b0124 --- /dev/null +++ b/neoforge/src/main/java/eu/midnightdust/neoforge/MidnightLibNeoForge.java @@ -0,0 +1,58 @@ +package eu.midnightdust.neoforge; + +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import eu.midnightdust.core.MidnightLib; +import eu.midnightdust.core.screen.MidnightConfigOverviewScreen; +import eu.midnightdust.lib.config.AutoCommand; +import eu.midnightdust.lib.config.MidnightConfig; +import net.minecraft.server.command.ServerCommandSource; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.IExtensionPoint; +import net.neoforged.fml.ModList; +import net.neoforged.fml.ModLoadingContext; +import net.neoforged.fml.common.Mod; +import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent; +import net.neoforged.fml.loading.FMLEnvironment; +import net.neoforged.neoforge.client.ConfigScreenHandler; +import net.neoforged.neoforge.client.event.ScreenEvent; +import net.neoforged.neoforge.event.RegisterCommandsEvent; + +import static net.neoforged.fml.IExtensionPoint.DisplayTest.IGNORESERVERONLY; + +@Mod("midnightlib") +public class MidnightLibNeoForge { + public MidnightLibNeoForge() { + ModLoadingContext.get().registerExtensionPoint(IExtensionPoint.DisplayTest.class, () -> new IExtensionPoint.DisplayTest(() -> IGNORESERVERONLY, (remote, server) -> true)); + if (FMLEnvironment.dist == Dist.CLIENT) MidnightLib.onInitializeClient(); else MidnightLib.onInitializeServer(); + } + @Mod.EventBusSubscriber(modid = "midnightlib", bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT) + public static class MidnightLibBusEvents { + @SubscribeEvent + public static void onPostInit(FMLClientSetupEvent event) { + ModList.get().forEachModContainer((modid, modContainer) -> { + if (MidnightConfig.configClass.containsKey(modid)) { + modContainer.registerExtensionPoint(ConfigScreenHandler.ConfigScreenFactory.class, () -> + new ConfigScreenHandler.ConfigScreenFactory((client, parent) -> MidnightConfig.getScreen(parent, modid))); + } + }); + } + } + @Mod.EventBusSubscriber(modid = "midnightlib", value = Dist.CLIENT) + public static class MidnightLibClientEvents { + @SubscribeEvent + public static void afterInitScreen(ScreenEvent.Init.Post event) { + MidnightConfigOverviewScreen.addButtonToOptionsScreen(event.getScreen(), event.getScreen().getMinecraft()); + } + } + + @Mod.EventBusSubscriber(modid = "midnightlib", value = Dist.DEDICATED_SERVER) + public static class MidnightLibServerEvents { + @SubscribeEvent + public static void registerCommands(RegisterCommandsEvent event) { + for (LiteralArgumentBuilder command : AutoCommand.commands){ + event.getDispatcher().register(command); + } + } + } +} diff --git a/forge/src/main/resources/META-INF/mods.toml b/neoforge/src/main/resources/META-INF/mods.toml similarity index 81% rename from forge/src/main/resources/META-INF/mods.toml rename to neoforge/src/main/resources/META-INF/mods.toml index 2cde8d9..466a580 100644 --- a/forge/src/main/resources/META-INF/mods.toml +++ b/neoforge/src/main/resources/META-INF/mods.toml @@ -1,5 +1,5 @@ modLoader = "javafml" -loaderVersion = "[43,)" +loaderVersion = "[1,)" #issueTrackerURL = "" license = "MIT License" @@ -15,15 +15,15 @@ Common Library for Team MidnightDust's mods. #logoFile = "" [[dependencies.midnightlib]] -modId = "forge" +modId = "neoforge" mandatory = true -versionRange = "[43,)" +versionRange = "[20.3,)" ordering = "NONE" side = "BOTH" [[dependencies.midnightlib]] modId = "minecraft" mandatory = true -versionRange = "[1.19.4,)" +versionRange = "[1.20.3,)" ordering = "NONE" side = "BOTH" \ No newline at end of file diff --git a/forge/src/main/resources/midnightlib.png b/neoforge/src/main/resources/midnightlib.png similarity index 100% rename from forge/src/main/resources/midnightlib.png rename to neoforge/src/main/resources/midnightlib.png diff --git a/forge/src/main/resources/pack.mcmeta b/neoforge/src/main/resources/pack.mcmeta similarity index 71% rename from forge/src/main/resources/pack.mcmeta rename to neoforge/src/main/resources/pack.mcmeta index 0a839a6..e4499d4 100644 --- a/forge/src/main/resources/pack.mcmeta +++ b/neoforge/src/main/resources/pack.mcmeta @@ -1,6 +1,6 @@ { "pack": { "description": "MidnightLib", - "pack_format": 9 + "pack_format": 22 } } diff --git a/settings.gradle b/settings.gradle index f83aad5..d64842c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -2,7 +2,7 @@ pluginManagement { repositories { maven { url "https://maven.fabricmc.net/" } maven { url "https://maven.architectury.dev/" } - maven { url "https://maven.minecraftforge.net/" } + maven { url "https://maven.neoforged.net/releases" } gradlePluginPortal() } } @@ -11,6 +11,6 @@ include("common") include("fabric-like") include("fabric") //include("quilt") -//include("forge") +include("neoforge") rootProject.name = "midnightlib" From 2ff92526ba4be513a0a535e7ffb4171a9837568e Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Tue, 19 Dec 2023 14:59:47 +0100 Subject: [PATCH 005/100] Fix ModMenu integration --- fabric/build.gradle | 4 +++ .../midnightdust/lib/config/AutoModMenu.java | 28 +++++++++++++++++++ gradle.properties | 4 +-- 3 files changed, 34 insertions(+), 2 deletions(-) create mode 100755 fabric/src/main/java/eu/midnightdust/lib/config/AutoModMenu.java diff --git a/fabric/build.gradle b/fabric/build.gradle index a5356cf..4cfbb4b 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -1,6 +1,9 @@ plugins { id "com.github.johnrengelman.shadow" version "7.1.2" } +repositories { + maven { url "https://maven.terraformersmc.com/releases" } +} architectury { platformSetupLoomIde() @@ -22,6 +25,7 @@ configurations { dependencies { modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" modApi "net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_api_version}" + modImplementation ("com.terraformersmc:modmenu:${rootProject.mod_menu_version}") common(project(path: ":common", configuration: "namedElements")) { transitive false } shadowCommon(project(path: ":common", configuration: "transformProductionFabric")) { transitive false } diff --git a/fabric/src/main/java/eu/midnightdust/lib/config/AutoModMenu.java b/fabric/src/main/java/eu/midnightdust/lib/config/AutoModMenu.java new file mode 100755 index 0000000..72bcc21 --- /dev/null +++ b/fabric/src/main/java/eu/midnightdust/lib/config/AutoModMenu.java @@ -0,0 +1,28 @@ +package eu.midnightdust.lib.config; + +import com.terraformersmc.modmenu.api.ConfigScreenFactory; +import com.terraformersmc.modmenu.api.ModMenuApi; +import eu.midnightdust.core.MidnightLib; +import eu.midnightdust.core.config.MidnightLibConfig; + +import java.util.HashMap; +import java.util.Map; + +public class AutoModMenu implements ModMenuApi { + + @Override + public ConfigScreenFactory getModConfigScreenFactory() { + return parent -> MidnightLibConfig.getScreen(parent,"midnightlib"); + } + + @Override + public Map> getProvidedConfigScreenFactories() { + HashMap> map = new HashMap<>(); + MidnightConfig.configClass.forEach((modid, cClass) -> { + if (!MidnightLib.hiddenMods.contains(modid)) + map.put(modid, parent -> MidnightConfig.getScreen(parent, modid)); + } + ); + return map; + } +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index be0ee04..16e2ba3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,7 +5,7 @@ yarn_mappings=1.20.4+build.1 enabled_platforms=fabric,neoforge archives_base_name=midnightlib -mod_version=1.5.2 +mod_version=1.5.3 maven_group=eu.midnightdust fabric_loader_version=0.15.1 @@ -15,4 +15,4 @@ neoforge_version=20.4.12-beta quilt_loader_version=0.19.0-beta.18 quilt_fabric_api_version=7.0.1+0.83.0-1.20 -mod_menu_version = 7.0.1 \ No newline at end of file +mod_menu_version = 9.0.0 \ No newline at end of file From 2f1bfbf44e78ed512313750cde771636894fb199 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Tue, 5 Mar 2024 12:58:59 +0100 Subject: [PATCH 006/100] Experimental 24w09a port - Only the overview button position in the Options Screen is not quite right --- build.gradle | 2 +- common/build.gradle | 4 --- .../core/config/MidnightConfigExample.java | 28 ++++++++-------- .../core/mixin/MixinOptionsScreen.java | 33 +++++++++++++++++++ .../screen/MidnightConfigOverviewScreen.java | 27 +++------------ .../lib/config/MidnightConfig.java | 23 +++---------- .../main/resources/architectury.common.json | 4 +-- .../main/resources/midnightlib.accesswidener | 3 -- .../main/resources/midnightlib.mixins.json | 1 + fabric/build.gradle | 3 +- .../fabric/core/MidnightLibFabric.java | 9 +---- fabric/src/main/resources/fabric.mod.json | 9 +++-- gradle.properties | 10 +++--- settings.gradle | 2 +- 14 files changed, 73 insertions(+), 85 deletions(-) rename MidnightConfigExample.java => common/src/main/java/eu/midnightdust/core/config/MidnightConfigExample.java (68%) create mode 100644 common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java delete mode 100644 common/src/main/resources/midnightlib.accesswidener create mode 100644 common/src/main/resources/midnightlib.mixins.json diff --git a/build.gradle b/build.gradle index 7d1c5e5..d7dad13 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ plugins { id "architectury-plugin" version "3.4-SNAPSHOT" - id "dev.architectury.loom" version "1.4-SNAPSHOT" apply false + id "dev.architectury.loom" version "1.5-SNAPSHOT" apply false } architectury { diff --git a/common/build.gradle b/common/build.gradle index 21d4a73..ceedbf7 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -2,10 +2,6 @@ architectury { common(rootProject.enabled_platforms.split(",")) } -loom { - accessWidenerPath = file("src/main/resources/midnightlib.accesswidener") -} - dependencies { // We depend on fabric loader here to use the fabric @Environment annotations and get the mixin dependencies // Do NOT use other classes from fabric loader diff --git a/MidnightConfigExample.java b/common/src/main/java/eu/midnightdust/core/config/MidnightConfigExample.java similarity index 68% rename from MidnightConfigExample.java rename to common/src/main/java/eu/midnightdust/core/config/MidnightConfigExample.java index 2975aea..83954e5 100644 --- a/MidnightConfigExample.java +++ b/common/src/main/java/eu/midnightdust/core/config/MidnightConfigExample.java @@ -13,22 +13,22 @@ import java.util.List; public class MidnightConfigExample extends MidnightConfig { - @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") public static TestEnum testEnum = TestEnum.FABRIC; // Example for an enum option - public enum TestEnum { // Enums allow the user to cycle through predefined options + @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") 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 = "text", width = 7, min = 7, isColor = true, name = "I am a color!") public static String titleColor = "#ffffff"; // The isColor property adds a preview box for a hexadecimal color - @Entry(category = "text", name = "I am an array list!") public static List arrayList = Lists.newArrayList("String1", "String2"); // Array String Lists are also supported - @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 + @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 = "text", isColor = true) public static String titleColor = "#ffffff"; // The isColor property adds a preview box for a hexadecimal color + @Entry(category = "text") public static List arrayList = Lists.newArrayList(); // Array String Lists are also supported + @Entry(isSlider = true, min = 0, max = 100) public static int intSlider = 35; // Int fields can also be displayed as a Slider + @Entry(isSlider = true, min = 0f, max = 1f) 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 public static int imposter = 16777215; // - Entries without an @Entry or @Comment annotation are ignored diff --git a/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java b/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java new file mode 100644 index 0000000..1e37bf1 --- /dev/null +++ b/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java @@ -0,0 +1,33 @@ +package eu.midnightdust.core.mixin; + +import eu.midnightdust.core.config.MidnightLibConfig; +import eu.midnightdust.core.screen.MidnightConfigOverviewScreen; +import eu.midnightdust.lib.util.PlatformFunctions; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.option.OptionsScreen; +import net.minecraft.client.gui.widget.TextIconButtonWidget; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; +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; + +import java.util.Objects; + +@Mixin(OptionsScreen.class) +public class MixinOptionsScreen extends Screen { + protected MixinOptionsScreen(Text title) {super(title);} + + @Inject(at = @At("HEAD"),method = "init") + private void midnightlib$init(CallbackInfo ci) { + if (MidnightLibConfig.config_screen_list.equals(MidnightLibConfig.ConfigButton.TRUE) || (MidnightLibConfig.config_screen_list.equals(MidnightLibConfig.ConfigButton.MODMENU) && !PlatformFunctions.isModLoaded("modmenu"))) { + TextIconButtonWidget button = TextIconButtonWidget.builder(Text.translatable("midnightlib.overview.title"), ( + buttonWidget) -> Objects.requireNonNull(client).setScreen(new MidnightConfigOverviewScreen(this)), true) + .texture(new Identifier("midnightlib","icon/midnightlib"), 16, 16).dimension(20, 20).build(); + //button.setPosition(this.width / 2 + 158, this.height / 6 - 17); + button.setPosition(this.width / 2 + 158, this.height / 2 - 105); + this.addDrawableChild(button); + } + } +} \ No newline at end of file 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 12e5da9..9c0d520 100755 --- a/common/src/main/java/eu/midnightdust/core/screen/MidnightConfigOverviewScreen.java +++ b/common/src/main/java/eu/midnightdust/core/screen/MidnightConfigOverviewScreen.java @@ -1,19 +1,14 @@ package eu.midnightdust.core.screen; import eu.midnightdust.core.MidnightLib; -import eu.midnightdust.core.config.MidnightLibConfig; import eu.midnightdust.lib.config.MidnightConfig; -import eu.midnightdust.lib.util.PlatformFunctions; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; -import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.screen.option.OptionsScreen; import net.minecraft.client.gui.widget.*; import net.minecraft.screen.ScreenTexts; import net.minecraft.text.*; -import net.minecraft.util.Identifier; import java.util.*; @@ -29,10 +24,9 @@ public class MidnightConfigOverviewScreen extends Screen { @Override protected void init() { - this.addDrawableChild(ButtonWidget.builder(ScreenTexts.DONE, (button) -> Objects.requireNonNull(client).setScreen(parent)).dimensions(this.width / 2 - 100, this.height - 28, 200, 20).build()); + this.addDrawableChild(ButtonWidget.builder(ScreenTexts.DONE, (button) -> Objects.requireNonNull(client).setScreen(parent)).dimensions(this.width / 2 - 100, this.height - 26, 200, 20).build()); - this.list = new MidnightConfig.MidnightConfigListWidget(this.client, this.width, this.height - 64, 32, 25); - if (this.client != null && this.client.world != null) this.list.setRenderBackground(false); + this.list = new MidnightConfig.MidnightConfigListWidget(this.client, this.width, this.height - 64, 24, 25); this.addSelectableChild(this.list); List sortedMods = new ArrayList<>(MidnightConfig.configClass.keySet()); Collections.sort(sortedMods); @@ -46,22 +40,9 @@ public class MidnightConfigOverviewScreen extends Screen { } @Override public void render(DrawContext context, int mouseX, int mouseY, float delta) { - if (client != null && client.world != null) super.renderInGameBackground(context); - this.list.render(context, mouseX, mouseY, delta); super.render(context, mouseX, mouseY, delta); + this.list.render(context, mouseX, mouseY, delta); - context.drawCenteredTextWithShadow(textRenderer, title, width / 2, 15, 0xFFFFFF); - } - @Override public void renderBackground(DrawContext c, int x, int y, float d) {} - - public static void addButtonToOptionsScreen(Screen screen, MinecraftClient client) { - if (screen.getClass() == OptionsScreen.class && MidnightLibConfig.config_screen_list.equals(MidnightLibConfig.ConfigButton.TRUE) - || (MidnightLibConfig.config_screen_list.equals(MidnightLibConfig.ConfigButton.MODMENU) && !PlatformFunctions.isModLoaded("modmenu"))) { - TextIconButtonWidget button = TextIconButtonWidget.builder(Text.translatable("midnightlib.overview.title"), ( - buttonWidget) -> Objects.requireNonNull(client).setScreen(new MidnightConfigOverviewScreen(screen)), true) - .texture(new Identifier("midnightlib","icon/midnightlib"), 16, 16).dimension(20, 20).build(); - button.setPosition(screen.width / 2 + 158, screen.height / 6 - 12); - screen.addDrawableChild(button); - } + 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/MidnightConfig.java b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java index 1e2e939..68392bb 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -292,7 +292,7 @@ public abstract class MidnightConfig { this.addDrawableChild(ButtonWidget.builder(ScreenTexts.CANCEL, button -> { loadValues(); Objects.requireNonNull(client).setScreen(parent); - }).dimensions(this.width / 2 - 154, this.height - 28, 150, 20).build()); + }).dimensions(this.width / 2 - 154, this.height - 26, 150, 20).build()); done = this.addDrawableChild(ButtonWidget.builder(ScreenTexts.DONE, (button) -> { for (EntryInfo info : entries) if (info.id.equals(modid)) { @@ -302,10 +302,9 @@ public abstract class MidnightConfig { } write(modid); Objects.requireNonNull(client).setScreen(parent); - }).dimensions(this.width / 2 + 4, this.height - 28, 150, 20).build()); + }).dimensions(this.width / 2 + 4, this.height - 26, 150, 20).build()); - this.list = new MidnightConfigListWidget(this.client, this.width, this.height - 64, 32, 25); - if (this.client != null && this.client.world != null) this.list.setRenderBackground(false); + this.list = new MidnightConfigListWidget(this.client, this.width, this.height - 64, 24, 25); this.addSelectableChild(this.list); fillList(); @@ -382,13 +381,11 @@ public abstract class MidnightConfig { } @Override public void render(DrawContext context, int mouseX, int mouseY, float delta) { - if (client != null && client.world != null) super.renderInGameBackground(context); - this.list.render(context, mouseX, mouseY, delta); super.render(context,mouseX,mouseY,delta); + this.list.render(context, mouseX, mouseY, delta); - if (tabs.size() < 2) context.drawCenteredTextWithShadow(textRenderer, title, width / 2, 15, 0xFFFFFF); + if (tabs.size() < 2) context.drawCenteredTextWithShadow(textRenderer, title, width / 2, 10, 0xFFFFFF); } - @Override public void renderBackground(DrawContext c, int x, int y, float d) {} } @Environment(EnvType.CLIENT) public static class MidnightConfigListWidget extends ElementListWidget { @@ -404,16 +401,6 @@ public abstract class MidnightConfig { public void clear() { this.clearEntries(); } @Override public int getRowWidth() { return 10000; } - @Override - protected void renderDecorations(DrawContext c, int mouseX, int mouseY) { - c.setShaderColor(0.25F, 0.25F, 0.25F, 1.0F); - c.drawTexture(Screen.OPTIONS_BACKGROUND_TEXTURE, this.getX(), 0, 0.0F, 0.0F, this.width, this.getY(), 32, 32); - c.drawTexture(Screen.OPTIONS_BACKGROUND_TEXTURE, this.getX(), this.getBottom(), 0.0F, 0.0F, this.width, this.height, 32, 32); - c.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - if (client == null || client.world == null) return; - c.fillGradient(RenderLayer.getGuiOverlay(), this.getX(), this.getY(), this.getRight(), this.getY() + 4, -16777216, 0, 0); - c.fillGradient(RenderLayer.getGuiOverlay(), this.getX(), this.getBottom() - 4, this.getRight(), this.getBottom(), 0, -16777216, 0); - } } public static class ButtonEntry extends ElementListWidget.Entry { private static final TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; diff --git a/common/src/main/resources/architectury.common.json b/common/src/main/resources/architectury.common.json index 093c5d3..9e26dfe 100644 --- a/common/src/main/resources/architectury.common.json +++ b/common/src/main/resources/architectury.common.json @@ -1,3 +1 @@ -{ - "accessWidener": "midnightlib.accesswidener" -} \ No newline at end of file +{} \ No newline at end of file diff --git a/common/src/main/resources/midnightlib.accesswidener b/common/src/main/resources/midnightlib.accesswidener deleted file mode 100644 index 561ebaa..0000000 --- a/common/src/main/resources/midnightlib.accesswidener +++ /dev/null @@ -1,3 +0,0 @@ -accessWidener v2 named - -accessible method net/minecraft/client/gui/screen/Screen addDrawableChild (Lnet/minecraft/client/gui/Element;)Lnet/minecraft/client/gui/Element; \ No newline at end of file diff --git a/common/src/main/resources/midnightlib.mixins.json b/common/src/main/resources/midnightlib.mixins.json new file mode 100644 index 0000000..20c4305 --- /dev/null +++ b/common/src/main/resources/midnightlib.mixins.json @@ -0,0 +1 @@ +{"required": true,"minVersion": "0.8","package": "eu.midnightdust.core.mixin","compatibilityLevel": "JAVA_17","client": ["MixinOptionsScreen"],"injectors": {"defaultRequire": 1}} \ No newline at end of file diff --git a/fabric/build.gradle b/fabric/build.gradle index 4cfbb4b..7b64ae2 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -25,7 +25,7 @@ configurations { dependencies { modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" modApi "net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_api_version}" - modImplementation ("com.terraformersmc:modmenu:${rootProject.mod_menu_version}") + modCompileOnly ("com.terraformersmc:modmenu:${rootProject.mod_menu_version}") common(project(path: ":common", configuration: "namedElements")) { transitive false } shadowCommon(project(path: ":common", configuration: "transformProductionFabric")) { transitive false } @@ -47,7 +47,6 @@ shadowJar { } remapJar { - injectAccessWidener = true input.set shadowJar.archiveFile dependsOn shadowJar } 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 f1cffed..2919334 100644 --- a/fabric/src/main/java/eu/midnightdust/fabric/core/MidnightLibFabric.java +++ b/fabric/src/main/java/eu/midnightdust/fabric/core/MidnightLibFabric.java @@ -1,21 +1,14 @@ package eu.midnightdust.fabric.core; import eu.midnightdust.core.MidnightLib; -import eu.midnightdust.core.screen.MidnightConfigOverviewScreen; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.api.DedicatedServerModInitializer; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents; public class MidnightLibFabric implements ClientModInitializer, DedicatedServerModInitializer { @Override @Environment(EnvType.CLIENT) - public void onInitializeClient() { - MidnightLib.onInitializeClient(); - ScreenEvents.AFTER_INIT.register((client, screen, scaledWidth, scaledHeight) -> { - MidnightConfigOverviewScreen.addButtonToOptionsScreen(screen, client); - }); - } + public void onInitializeClient() {MidnightLib.onInitializeClient();} @Override @Environment(EnvType.SERVER) public void onInitializeServer() {MidnightLib.onInitializeServer();} } diff --git a/fabric/src/main/resources/fabric.mod.json b/fabric/src/main/resources/fabric.mod.json index 3944bac..8bc8a5e 100644 --- a/fabric/src/main/resources/fabric.mod.json +++ b/fabric/src/main/resources/fabric.mod.json @@ -32,9 +32,13 @@ }, "depends": { "fabric-resource-loader-v0": "*", - "minecraft": ">=1.20.3" + "minecraft": ">=1.20.4" }, + "mixins": [ + "midnightlib.mixins.json" + ], + "custom": { "modmenu": { "links": { @@ -46,6 +50,5 @@ }, "badges": [ "library" ] } - }, - "accessWidener": "midnightlib.accesswidener" + } } diff --git a/gradle.properties b/gradle.properties index 16e2ba3..0bd450e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,15 +1,15 @@ org.gradle.jvmargs=-Xmx4096M -minecraft_version=1.20.4 -yarn_mappings=1.20.4+build.1 -enabled_platforms=fabric,neoforge +minecraft_version=24w09a +yarn_mappings=24w09a+build.11 +enabled_platforms=fabric archives_base_name=midnightlib mod_version=1.5.3 maven_group=eu.midnightdust -fabric_loader_version=0.15.1 -fabric_api_version=0.91.1+1.20.4 +fabric_loader_version=0.15.7 +fabric_api_version=0.96.7+1.20.5 neoforge_version=20.4.12-beta diff --git a/settings.gradle b/settings.gradle index d64842c..f865b79 100644 --- a/settings.gradle +++ b/settings.gradle @@ -11,6 +11,6 @@ include("common") include("fabric-like") include("fabric") //include("quilt") -include("neoforge") +//include("neoforge") rootProject.name = "midnightlib" From 0241f81235e3aca11691c9ca56c5eecfadc75d91 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Thu, 4 Apr 2024 17:03:41 +0200 Subject: [PATCH 007/100] Fix button positioning - Overview button is now positioned correctly again - Updated to 24w13a (also works on 24w14a) --- .../core/mixin/MixinOptionsScreen.java | 33 ++++++++++++++----- .../lib/config/MidnightConfig.java | 3 +- gradle.properties | 10 +++--- 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java b/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java index 1e37bf1..90eedf3 100644 --- a/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java +++ b/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java @@ -3,12 +3,17 @@ package eu.midnightdust.core.mixin; import eu.midnightdust.core.config.MidnightLibConfig; import eu.midnightdust.core.screen.MidnightConfigOverviewScreen; import eu.midnightdust.lib.util.PlatformFunctions; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.option.OptionsScreen; import net.minecraft.client.gui.widget.TextIconButtonWidget; +import net.minecraft.client.gui.widget.ThreePartsLayoutWidget; import net.minecraft.text.Text; import net.minecraft.util.Identifier; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +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; @@ -17,17 +22,27 @@ import java.util.Objects; @Mixin(OptionsScreen.class) public class MixinOptionsScreen extends Screen { - protected MixinOptionsScreen(Text title) {super(title);} + @Shadow @Final private ThreePartsLayoutWidget layout; + @Unique TextIconButtonWidget button = TextIconButtonWidget.builder(Text.translatable("midnightlib.overview.title"), ( + buttonWidget) -> Objects.requireNonNull(client).setScreen(new MidnightConfigOverviewScreen(this)), true) + .texture(new Identifier("midnightlib","icon/midnightlib"), 16, 16).dimension(20, 20).build(); - @Inject(at = @At("HEAD"),method = "init") - private void midnightlib$init(CallbackInfo ci) { + protected MixinOptionsScreen(Text title) {super(title);} + @Inject(at = @At("HEAD"), method = "init") + public void midnightlib$onInit(CallbackInfo ci) { + this.midnightlib$setupButton(); + this.addDrawableChild(button); + } + + @Override + public void resize(MinecraftClient client, int width, int height) { + super.resize(client, width, height); + this.midnightlib$setupButton(); + } + @Unique + public void midnightlib$setupButton() { if (MidnightLibConfig.config_screen_list.equals(MidnightLibConfig.ConfigButton.TRUE) || (MidnightLibConfig.config_screen_list.equals(MidnightLibConfig.ConfigButton.MODMENU) && !PlatformFunctions.isModLoaded("modmenu"))) { - TextIconButtonWidget button = TextIconButtonWidget.builder(Text.translatable("midnightlib.overview.title"), ( - buttonWidget) -> Objects.requireNonNull(client).setScreen(new MidnightConfigOverviewScreen(this)), true) - .texture(new Identifier("midnightlib","icon/midnightlib"), 16, 16).dimension(20, 20).build(); - //button.setPosition(this.width / 2 + 158, this.height / 6 - 17); - button.setPosition(this.width / 2 + 158, this.height / 2 - 105); - this.addDrawableChild(button); + button.setPosition(layout.getWidth() / 2 + 158, layout.getY() + layout.getFooterHeight() - 4); } } } \ No newline at end of file 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 68392bb..3ff5d76 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -19,7 +19,6 @@ import net.minecraft.client.gui.tab.Tab; import net.minecraft.client.gui.tab.TabManager; import net.minecraft.client.gui.tooltip.Tooltip; import net.minecraft.client.gui.widget.*; -import net.minecraft.client.render.RenderLayer; import net.minecraft.client.resource.language.I18n; import net.minecraft.screen.ScreenTexts; import net.minecraft.text.OrderedText; @@ -393,7 +392,7 @@ public abstract class MidnightConfig { super(client, width, height, y, itemHeight); } @Override - public int getScrollbarPositionX() { return this.width -7; } + public int getScrollbarX() { return this.width -7; } public void addButton(List buttons, Text text, EntryInfo info) { this.addEntry(new ButtonEntry(buttons, text, info)); diff --git a/gradle.properties b/gradle.properties index 0bd450e..020a147 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,15 +1,15 @@ org.gradle.jvmargs=-Xmx4096M -minecraft_version=24w09a -yarn_mappings=24w09a+build.11 +minecraft_version=24w13a +yarn_mappings=24w13a+build.5 enabled_platforms=fabric archives_base_name=midnightlib -mod_version=1.5.3 +mod_version=1.5.4 maven_group=eu.midnightdust -fabric_loader_version=0.15.7 -fabric_api_version=0.96.7+1.20.5 +fabric_loader_version=0.15.9 +fabric_api_version=0.96.13+1.20.5 neoforge_version=20.4.12-beta From afc3c091485cb2f6246f57d5af443d6e00db41cd Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Thu, 4 Apr 2024 17:25:53 +0200 Subject: [PATCH 008/100] Fixed #48 Also reduced code complexity, nice :) --- .../eu/midnightdust/lib/config/MidnightConfig.java | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) 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 1e2e939..a9ee4ae 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -431,13 +431,9 @@ public abstract class MidnightConfig { public void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { buttons.forEach(b -> { b.setY(y); b.render(context, mouseX, mouseY, tickDelta); }); if (text != null && (!text.getString().contains("spacer") || !buttons.isEmpty())) { - if (info.centered) context.drawTextWithShadow(textRenderer, text, MinecraftClient.getInstance().getWindow().getScaledWidth() / 2 - (textRenderer.getWidth(text) / 2), y + 5, 0xFFFFFF); - else { - int wrappedY = y; - for(Iterator iterator = textRenderer.wrapLines(text, (buttons.size() > 1 ? buttons.get(1).getX()-24 : MinecraftClient.getInstance().getWindow().getScaledWidth() - 24)).iterator(); iterator.hasNext(); wrappedY += 9) { - OrderedText orderedText = iterator.next(); - context.drawTextWithShadow(textRenderer, orderedText, 12, wrappedY + 5, 0xFFFFFF); - } + int wrappedY = y; + for(Iterator textIterator = textRenderer.wrapLines(text, (buttons.size() > 1 ? buttons.get(1).getX()-24 : MinecraftClient.getInstance().getWindow().getScaledWidth() - 24)).iterator(); textIterator.hasNext(); wrappedY += 9) { + context.drawTextWithShadow(textRenderer, textIterator.next(), (info.centered) ? (MinecraftClient.getInstance().getWindow().getScaledWidth() / 2 - (textRenderer.getWidth(text) / 2)) : 12, wrappedY + 5, 0xFFFFFF); } } } From a43820c9041a788246c83e0075c9d1a0aeb5b4c1 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Sun, 21 Apr 2024 14:46:09 +0200 Subject: [PATCH 009/100] Update to 1.20.5-rc2 --- build.gradle | 2 +- gradle.properties | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index d7dad13..b1669a4 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ plugins { id "architectury-plugin" version "3.4-SNAPSHOT" - id "dev.architectury.loom" version "1.5-SNAPSHOT" apply false + id "dev.architectury.loom" version "1.6-SNAPSHOT" apply false } architectury { diff --git a/gradle.properties b/gradle.properties index 020a147..3eb3655 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,15 +1,15 @@ org.gradle.jvmargs=-Xmx4096M -minecraft_version=24w13a -yarn_mappings=24w13a+build.5 +minecraft_version=1.20.5-rc2 +yarn_mappings=1.20.5-rc2+build.2 enabled_platforms=fabric archives_base_name=midnightlib mod_version=1.5.4 maven_group=eu.midnightdust -fabric_loader_version=0.15.9 -fabric_api_version=0.96.13+1.20.5 +fabric_loader_version=0.15.10 +fabric_api_version=0.97.4+1.20.5 neoforge_version=20.4.12-beta From d75d34d67512c8fb57ad2b12b599d7e0ea539cba Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Sat, 4 May 2024 17:59:06 +0200 Subject: [PATCH 010/100] MidnightLib 1.5.5 - Fixed button always being visible - Various visual improvements --- build.gradle | 18 +++++++- .../core/mixin/MixinOptionsScreen.java | 13 +++--- .../screen/MidnightConfigOverviewScreen.java | 2 +- .../lib/config/MidnightConfig.java | 28 +++++++++--- fabric/build.gradle | 43 ++++++++++++++----- gradle.properties | 15 ++++--- gradle/wrapper/gradle-wrapper.properties | 2 +- .../util/neoforge/PlatformFunctionsImpl.java | 2 +- .../neoforge/MidnightLibNeoForge.java | 7 --- 9 files changed, 91 insertions(+), 39 deletions(-) diff --git a/build.gradle b/build.gradle index b1669a4..4071417 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,7 @@ plugins { id "architectury-plugin" version "3.4-SNAPSHOT" id "dev.architectury.loom" version "1.6-SNAPSHOT" apply false + id "me.shedaniel.unified-publishing" version "0.1.+" apply false } architectury { @@ -36,7 +37,22 @@ allprojects { tasks.withType(JavaCompile) { options.encoding = "UTF-8" - options.release = 17 + options.release = 21 + } + ext { + releaseChangelog = { + def changes = new StringBuilder() + changes << "## MidnightLib v$project.version for $project.minecraft_version\n[View the changelog](https://www.github.com/TeamMidnightDust/MidnightLib/commits/)" + def proc = "git log --max-count=1 --pretty=format:%s".execute() + proc.in.eachLine { line -> + def processedLine = line.toString() + if (!processedLine.contains("New translations") && !processedLine.contains("Merge") && !processedLine.contains("branch")) { + changes << "\n- ${processedLine.capitalize()}" + } + } + proc.waitFor() + return changes.toString() + } } java { diff --git a/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java b/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java index 90eedf3..6ce5b88 100644 --- a/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java +++ b/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java @@ -26,23 +26,24 @@ public class MixinOptionsScreen extends Screen { @Unique TextIconButtonWidget button = TextIconButtonWidget.builder(Text.translatable("midnightlib.overview.title"), ( buttonWidget) -> Objects.requireNonNull(client).setScreen(new MidnightConfigOverviewScreen(this)), true) .texture(new Identifier("midnightlib","icon/midnightlib"), 16, 16).dimension(20, 20).build(); + @Unique boolean shouldShowButton = MidnightLibConfig.config_screen_list.equals(MidnightLibConfig.ConfigButton.TRUE) || (MidnightLibConfig.config_screen_list.equals(MidnightLibConfig.ConfigButton.MODMENU) && !PlatformFunctions.isModLoaded("modmenu")); protected MixinOptionsScreen(Text title) {super(title);} @Inject(at = @At("HEAD"), method = "init") public void midnightlib$onInit(CallbackInfo ci) { - this.midnightlib$setupButton(); - this.addDrawableChild(button); + if (shouldShowButton) { + this.midnightlib$setupButton(); + this.addDrawableChild(button); + } } @Override public void resize(MinecraftClient client, int width, int height) { super.resize(client, width, height); - this.midnightlib$setupButton(); + if (shouldShowButton) this.midnightlib$setupButton(); } @Unique public void midnightlib$setupButton() { - if (MidnightLibConfig.config_screen_list.equals(MidnightLibConfig.ConfigButton.TRUE) || (MidnightLibConfig.config_screen_list.equals(MidnightLibConfig.ConfigButton.MODMENU) && !PlatformFunctions.isModLoaded("modmenu"))) { - button.setPosition(layout.getWidth() / 2 + 158, layout.getY() + layout.getFooterHeight() - 4); - } + button.setPosition(layout.getWidth() / 2 + 158, layout.getY() + layout.getFooterHeight() - 4); } } \ No newline at end of file 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 9c0d520..85cdd93 100755 --- a/common/src/main/java/eu/midnightdust/core/screen/MidnightConfigOverviewScreen.java +++ b/common/src/main/java/eu/midnightdust/core/screen/MidnightConfigOverviewScreen.java @@ -26,7 +26,7 @@ public class MidnightConfigOverviewScreen extends Screen { 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.list = new MidnightConfig.MidnightConfigListWidget(this.client, this.width, this.height - 64, 24, 25); + this.list = new MidnightConfig.MidnightConfigListWidget(this.client, this.width, this.height - 57, 24, 25); this.addSelectableChild(this.list); List sortedMods = new ArrayList<>(MidnightConfig.configClass.keySet()); Collections.sort(sortedMods); 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 52212b0..048ca30 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -5,6 +5,7 @@ import com.google.gson.ExclusionStrategy; import com.google.gson.FieldAttributes; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import com.mojang.blaze3d.systems.RenderSystem; import eu.midnightdust.lib.util.PlatformFunctions; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; @@ -167,7 +168,7 @@ public abstract class MidnightConfig { info.value = isNumber? value : s; else if (inLimits) { if (((List) info.value).size() == info.index) ((List) info.value).add(""); - ((List) info.value).set(info.index, Arrays.stream(info.tempValue.replace("[", "").replace("]", "").split(", ")).toList().get(0)); + ((List) info.value).set(info.index, Arrays.stream(info.tempValue.replace("[", "").replace("]", "").split(", ")).toList().getFirst()); } if (info.field.getAnnotation(Entry.class).isColor()) { @@ -303,7 +304,7 @@ public abstract class MidnightConfig { Objects.requireNonNull(client).setScreen(parent); }).dimensions(this.width / 2 + 4, this.height - 26, 150, 20).build()); - this.list = new MidnightConfigListWidget(this.client, this.width, this.height - 64, 24, 25); + this.list = new MidnightConfigListWidget(this.client, this.width, this.height - 57, 24, 25); this.addSelectableChild(this.list); fillList(); @@ -383,17 +384,30 @@ public abstract class MidnightConfig { super.render(context,mouseX,mouseY,delta); this.list.render(context, mouseX, mouseY, delta); - if (tabs.size() < 2) context.drawCenteredTextWithShadow(textRenderer, title, width / 2, 10, 0xFFFFFF); + if (tabs.size() < 2) + context.drawCenteredTextWithShadow(textRenderer, title, width / 2, 10, 0xFFFFFF); + list.renderHeaderSeperator = tabs.size() < 2; } } @Environment(EnvType.CLIENT) public static class MidnightConfigListWidget extends ElementListWidget { + boolean renderHeaderSeperator = true; public MidnightConfigListWidget(MinecraftClient client, int width, int height, int y, int itemHeight) { super(client, width, height, y, itemHeight); } @Override public int getScrollbarX() { return this.width -7; } + @Override + protected void drawHeaderAndFooterSeparators(DrawContext context) { + if (renderHeaderSeperator) super.drawHeaderAndFooterSeparators(context); + else { + RenderSystem.enableBlend(); + context.drawTexture(this.client.world == null ? Screen.FOOTER_SEPARATOR_TEXTURE : Screen.INWORLD_FOOTER_SEPARATOR_TEXTURE, this.getX(), this.getBottom(), 0.0F, 0.0F, this.getWidth(), 2, 32, 2); + RenderSystem.disableBlend(); + } + } + public void addButton(List buttons, Text text, EntryInfo info) { this.addEntry(new ButtonEntry(buttons, text, info)); } @@ -406,20 +420,22 @@ public abstract class MidnightConfig { public final List buttons; private final Text text; public final EntryInfo info; + public boolean centered = false; public static final Map buttonsWithText = new HashMap<>(); - private ButtonEntry(List buttons, Text text, EntryInfo info) { - if (!buttons.isEmpty()) buttonsWithText.put(buttons.get(0),text); + public ButtonEntry(List buttons, Text text, EntryInfo info) { + if (!buttons.isEmpty()) buttonsWithText.put(buttons.getFirst(),text); this.buttons = buttons; this.text = text; this.info = info; + if (info != null) this.centered = info.centered; } public void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { buttons.forEach(b -> { b.setY(y); b.render(context, mouseX, mouseY, tickDelta); }); if (text != null && (!text.getString().contains("spacer") || !buttons.isEmpty())) { int wrappedY = y; for(Iterator textIterator = textRenderer.wrapLines(text, (buttons.size() > 1 ? buttons.get(1).getX()-24 : MinecraftClient.getInstance().getWindow().getScaledWidth() - 24)).iterator(); textIterator.hasNext(); wrappedY += 9) { - context.drawTextWithShadow(textRenderer, textIterator.next(), (info.centered) ? (MinecraftClient.getInstance().getWindow().getScaledWidth() / 2 - (textRenderer.getWidth(text) / 2)) : 12, wrappedY + 5, 0xFFFFFF); + context.drawTextWithShadow(textRenderer, textIterator.next(), (centered) ? (MinecraftClient.getInstance().getWindow().getScaledWidth() / 2 - (textRenderer.getWidth(text) / 2)) : 12, wrappedY + 5, 0xFFFFFF); } } } diff --git a/fabric/build.gradle b/fabric/build.gradle index 7b64ae2..bcc3e13 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -1,5 +1,6 @@ plugins { id "com.github.johnrengelman.shadow" version "7.1.2" + id "me.shedaniel.unified-publishing" } repositories { maven { url "https://maven.terraformersmc.com/releases" } @@ -63,16 +64,38 @@ components.java { } } -publishing { - publications { - mavenFabric(MavenPublication) { - artifactId = archives_base_name + "-" + project.name - from components.java +unifiedPublishing { + project { + displayName = "MidnightLib v$project.version - Fabric $project.minecraft_version" + releaseType = "$project.release_type" + changelog = releaseChangelog() + gameVersions = [] + gameLoaders = ["fabric","quilt"] + mainPublication remapJar + relations { + depends { + curseforge = "fabric-api" + modrinth = "fabric-api" + } + } + + var CURSEFORGE_TOKEN = project.findProperty("CURSEFORGE_TOKEN") ?: System.getenv("CURSEFORGE_TOKEN") + if (CURSEFORGE_TOKEN != null) { + curseforge { + token = CURSEFORGE_TOKEN + id = rootProject.curseforge_id + gameVersions.addAll "Java 21", project.minecraft_version + } + } + + var MODRINTH_TOKEN = project.findProperty("MODRINTH_TOKEN") ?: System.getenv("MODRINTH_TOKEN") + if (MODRINTH_TOKEN != null) { + modrinth { + token = MODRINTH_TOKEN + id = rootProject.modrinth_id + version = "$project.version-$project.name" + gameVersions.addAll project.minecraft_version + } } } - - // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. - repositories { - // Add repositories to publish to here. - } } \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 3eb3655..7cc82cb 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,17 +1,20 @@ org.gradle.jvmargs=-Xmx4096M -minecraft_version=1.20.5-rc2 -yarn_mappings=1.20.5-rc2+build.2 +minecraft_version=1.20.6 +yarn_mappings=1.20.6+build.1 enabled_platforms=fabric archives_base_name=midnightlib -mod_version=1.5.4 +mod_version=1.5.5 maven_group=eu.midnightdust +release_type=release +curseforge_id=488090 +modrinth_id=codAaoxh -fabric_loader_version=0.15.10 -fabric_api_version=0.97.4+1.20.5 +fabric_loader_version=0.15.11 +fabric_api_version=0.97.8+1.20.6 -neoforge_version=20.4.12-beta +neoforge_version=20.6.30-beta quilt_loader_version=0.19.0-beta.18 quilt_fabric_api_version=7.0.1+0.83.0-1.20 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a595206..48c0a02 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists 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 16ee0a0..d2d5a19 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 @@ -23,6 +23,6 @@ public class PlatformFunctionsImpl { return ModList.get().isLoaded(modid); } public static void registerCommand(LiteralArgumentBuilder command) { - // Ignored here, see MidnightLibServerEvents#registerCommands + // Ignored here, see MidnightLibNeoForge#registerCommands } } diff --git a/neoforge/src/main/java/eu/midnightdust/neoforge/MidnightLibNeoForge.java b/neoforge/src/main/java/eu/midnightdust/neoforge/MidnightLibNeoForge.java index 31b0124..bdf4df0 100644 --- a/neoforge/src/main/java/eu/midnightdust/neoforge/MidnightLibNeoForge.java +++ b/neoforge/src/main/java/eu/midnightdust/neoforge/MidnightLibNeoForge.java @@ -38,13 +38,6 @@ public class MidnightLibNeoForge { }); } } - @Mod.EventBusSubscriber(modid = "midnightlib", value = Dist.CLIENT) - public static class MidnightLibClientEvents { - @SubscribeEvent - public static void afterInitScreen(ScreenEvent.Init.Post event) { - MidnightConfigOverviewScreen.addButtonToOptionsScreen(event.getScreen(), event.getScreen().getMinecraft()); - } - } @Mod.EventBusSubscriber(modid = "midnightlib", value = Dist.DEDICATED_SERVER) public static class MidnightLibServerEvents { From d1df2e4d9b93a8d5544b2e65f08f65e72c9550d5 Mon Sep 17 00:00:00 2001 From: 12emin34 Date: Wed, 15 May 2024 12:06:07 +0200 Subject: [PATCH 011/100] fix NeoForge for 1.20.5/6 --- build.gradle | 6 ++- fabric/build.gradle | 2 +- gradle.properties | 5 +- neoforge/build.gradle | 48 +++++++++++-------- .../neoforge/MidnightLibNeoForge.java | 23 ++++----- .../{mods.toml => neoforge.mods.toml} | 6 +-- settings.gradle | 2 +- 7 files changed, 50 insertions(+), 42 deletions(-) rename neoforge/src/main/resources/META-INF/{mods.toml => neoforge.mods.toml} (84%) diff --git a/build.gradle b/build.gradle index 4071417..c2dac89 100644 --- a/build.gradle +++ b/build.gradle @@ -2,6 +2,7 @@ plugins { id "architectury-plugin" version "3.4-SNAPSHOT" id "dev.architectury.loom" version "1.6-SNAPSHOT" apply false id "me.shedaniel.unified-publishing" version "0.1.+" apply false + id 'com.github.johnrengelman.shadow' version '8.1.1' apply false } architectury { @@ -14,7 +15,10 @@ subprojects { dependencies { minecraft "com.mojang:minecraft:${rootProject.minecraft_version}" // The following line declares the yarn mappings you may select this one as well. - mappings "net.fabricmc:yarn:${rootProject.yarn_mappings}:v2" + mappings loom.layered { + it.mappings("net.fabricmc:yarn:$rootProject.yarn_mappings:v2") + it.mappings("dev.architectury:yarn-mappings-patch-neoforge:$rootProject.yarn_mappings_patch_neoforge_version") + } } } diff --git a/fabric/build.gradle b/fabric/build.gradle index bcc3e13..d301610 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -1,5 +1,5 @@ plugins { - id "com.github.johnrengelman.shadow" version "7.1.2" + id 'com.github.johnrengelman.shadow' id "me.shedaniel.unified-publishing" } repositories { diff --git a/gradle.properties b/gradle.properties index 7cc82cb..742f48b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ org.gradle.jvmargs=-Xmx4096M minecraft_version=1.20.6 yarn_mappings=1.20.6+build.1 -enabled_platforms=fabric +enabled_platforms=fabric,neoforge archives_base_name=midnightlib mod_version=1.5.5 @@ -14,7 +14,8 @@ modrinth_id=codAaoxh fabric_loader_version=0.15.11 fabric_api_version=0.97.8+1.20.6 -neoforge_version=20.6.30-beta +neoforge_version=20.6.63-beta +yarn_mappings_patch_neoforge_version = 1.20.5+build.3 quilt_loader_version=0.19.0-beta.18 quilt_fabric_api_version=7.0.1+0.83.0-1.20 diff --git a/neoforge/build.gradle b/neoforge/build.gradle index d7870e2..ceb4dc4 100644 --- a/neoforge/build.gradle +++ b/neoforge/build.gradle @@ -1,10 +1,15 @@ plugins { - id "com.github.johnrengelman.shadow" version "7.1.2" + id 'com.github.johnrengelman.shadow' } -repositories{ - maven {url "https://maven.neoforged.net/releases"} + +repositories { + maven { + name = 'NeoForged' + url = 'https://maven.neoforged.net/releases' + } } + architectury { platformSetupLoomIde() neoForge() @@ -15,41 +20,44 @@ loom { } configurations { - common - shadowCommon // Don't use shadow from the shadow plugin because we don't want IDEA to index this. + common { + canBeResolved = true + canBeConsumed = false + } compileClasspath.extendsFrom common runtimeClasspath.extendsFrom common - developmentForge.extendsFrom common - archivesBaseName = rootProject.archives_base_name + "-neoforge" + developmentNeoForge.extendsFrom common + + // Files in this configuration will be bundled into your mod using the Shadow plugin. + // Don't use the `shadow` configuration from the plugin itself as it's meant for excluding files. + shadowBundle { + canBeResolved = true + canBeConsumed = false + } } dependencies { - neoForge "net.neoforged:neoforge:${rootProject.neoforge_version}" + neoForge "net.neoforged:neoforge:$rootProject.neoforge_version" - common(project(path: ":common", configuration: "namedElements")) { transitive false } - shadowCommon(project(path: ":common", configuration: "transformProductionNeoForge")) { transitive = false } + common(project(path: ':common', configuration: 'namedElements')) { transitive false } + shadowBundle project(path: ':common', configuration: 'transformProductionNeoForge') } processResources { - inputs.property "version", project.version + inputs.property 'version', project.version - filesMatching("META-INF/mods.toml") { - expand "version": project.version + filesMatching('META-INF/neoforge.mods.toml') { + expand version: project.version } } shadowJar { - exclude "fabric.mod.json" - exclude "architectury.common.json" - - configurations = [project.configurations.shadowCommon] - archiveClassifier = "dev-shadow" + configurations = [project.configurations.shadowBundle] + archiveClassifier = 'dev-shadow' } remapJar { - atAccessWideners.add('midnightlib.accesswidener') input.set shadowJar.archiveFile - dependsOn shadowJar } sourcesJar { diff --git a/neoforge/src/main/java/eu/midnightdust/neoforge/MidnightLibNeoForge.java b/neoforge/src/main/java/eu/midnightdust/neoforge/MidnightLibNeoForge.java index bdf4df0..ce2deec 100644 --- a/neoforge/src/main/java/eu/midnightdust/neoforge/MidnightLibNeoForge.java +++ b/neoforge/src/main/java/eu/midnightdust/neoforge/MidnightLibNeoForge.java @@ -2,48 +2,43 @@ package eu.midnightdust.neoforge; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import eu.midnightdust.core.MidnightLib; -import eu.midnightdust.core.screen.MidnightConfigOverviewScreen; import eu.midnightdust.lib.config.AutoCommand; import eu.midnightdust.lib.config.MidnightConfig; import net.minecraft.server.command.ServerCommandSource; import net.neoforged.api.distmarker.Dist; import net.neoforged.bus.api.SubscribeEvent; -import net.neoforged.fml.IExtensionPoint; import net.neoforged.fml.ModList; -import net.neoforged.fml.ModLoadingContext; +import net.neoforged.fml.common.EventBusSubscriber; import net.neoforged.fml.common.Mod; import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent; import net.neoforged.fml.loading.FMLEnvironment; -import net.neoforged.neoforge.client.ConfigScreenHandler; -import net.neoforged.neoforge.client.event.ScreenEvent; +import net.neoforged.neoforge.client.gui.IConfigScreenFactory; import net.neoforged.neoforge.event.RegisterCommandsEvent; -import static net.neoforged.fml.IExtensionPoint.DisplayTest.IGNORESERVERONLY; - @Mod("midnightlib") public class MidnightLibNeoForge { public MidnightLibNeoForge() { - ModLoadingContext.get().registerExtensionPoint(IExtensionPoint.DisplayTest.class, () -> new IExtensionPoint.DisplayTest(() -> IGNORESERVERONLY, (remote, server) -> true)); - if (FMLEnvironment.dist == Dist.CLIENT) MidnightLib.onInitializeClient(); else MidnightLib.onInitializeServer(); + if (FMLEnvironment.dist == Dist.CLIENT) MidnightLib.onInitializeClient(); + else MidnightLib.onInitializeServer(); } - @Mod.EventBusSubscriber(modid = "midnightlib", bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT) + + @EventBusSubscriber(modid = "midnightlib", bus = EventBusSubscriber.Bus.MOD, value = Dist.CLIENT) public static class MidnightLibBusEvents { @SubscribeEvent public static void onPostInit(FMLClientSetupEvent event) { ModList.get().forEachModContainer((modid, modContainer) -> { if (MidnightConfig.configClass.containsKey(modid)) { - modContainer.registerExtensionPoint(ConfigScreenHandler.ConfigScreenFactory.class, () -> - new ConfigScreenHandler.ConfigScreenFactory((client, parent) -> MidnightConfig.getScreen(parent, modid))); + modContainer.registerExtensionPoint(IConfigScreenFactory.class, (minecraftClient, screen) -> MidnightConfig.getScreen(screen, modid)); } }); } } - @Mod.EventBusSubscriber(modid = "midnightlib", value = Dist.DEDICATED_SERVER) + @EventBusSubscriber(modid = "midnightlib", value = Dist.DEDICATED_SERVER) public static class MidnightLibServerEvents { @SubscribeEvent public static void registerCommands(RegisterCommandsEvent event) { - for (LiteralArgumentBuilder command : AutoCommand.commands){ + for (LiteralArgumentBuilder command : AutoCommand.commands) { event.getDispatcher().register(command); } } diff --git a/neoforge/src/main/resources/META-INF/mods.toml b/neoforge/src/main/resources/META-INF/neoforge.mods.toml similarity index 84% rename from neoforge/src/main/resources/META-INF/mods.toml rename to neoforge/src/main/resources/META-INF/neoforge.mods.toml index 466a580..8b38520 100644 --- a/neoforge/src/main/resources/META-INF/mods.toml +++ b/neoforge/src/main/resources/META-INF/neoforge.mods.toml @@ -1,5 +1,5 @@ modLoader = "javafml" -loaderVersion = "[1,)" +loaderVersion = "[2,)" #issueTrackerURL = "" license = "MIT License" @@ -17,13 +17,13 @@ Common Library for Team MidnightDust's mods. [[dependencies.midnightlib]] modId = "neoforge" mandatory = true -versionRange = "[20.3,)" +versionRange = "[20.5,)" ordering = "NONE" side = "BOTH" [[dependencies.midnightlib]] modId = "minecraft" mandatory = true -versionRange = "[1.20.3,)" +versionRange = "[1.20.5,)" ordering = "NONE" side = "BOTH" \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index f865b79..d64842c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -11,6 +11,6 @@ include("common") include("fabric-like") include("fabric") //include("quilt") -//include("neoforge") +include("neoforge") rootProject.name = "midnightlib" From 9c02d399b78c36f52cfa7cf23f1af1e3a1f5f2ad Mon Sep 17 00:00:00 2001 From: 12emin34 Date: Wed, 15 May 2024 13:06:23 +0200 Subject: [PATCH 012/100] oops, forgot to remove unneeded pack.mcmeta file --- neoforge/src/main/resources/pack.mcmeta | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 neoforge/src/main/resources/pack.mcmeta diff --git a/neoforge/src/main/resources/pack.mcmeta b/neoforge/src/main/resources/pack.mcmeta deleted file mode 100644 index e4499d4..0000000 --- a/neoforge/src/main/resources/pack.mcmeta +++ /dev/null @@ -1,6 +0,0 @@ -{ - "pack": { - "description": "MidnightLib", - "pack_format": 22 - } -} From aeeed9922ae84f62c35d46a4be8d413febcd4188 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Sat, 8 Jun 2024 20:35:30 +0200 Subject: [PATCH 013/100] Add unified publishing for NeoForge --- neoforge/build.gradle | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/neoforge/build.gradle b/neoforge/build.gradle index ceb4dc4..ccbd89c 100644 --- a/neoforge/build.gradle +++ b/neoforge/build.gradle @@ -1,5 +1,6 @@ plugins { id 'com.github.johnrengelman.shadow' + id "me.shedaniel.unified-publishing" } repositories { @@ -72,16 +73,32 @@ components.java { } } -publishing { - publications { - mavenForge(MavenPublication) { - artifactId = rootProject.archives_base_name + "-" + project.name - from components.java +unifiedPublishing { + project { + displayName = "MidnightLib v$project.version - NeoForge $project.minecraft_version" + releaseType = "$project.release_type" + changelog = releaseChangelog() + gameVersions = [] + gameLoaders = ["neoforge"] + mainPublication remapJar + + var CURSEFORGE_TOKEN = project.findProperty("CURSEFORGE_TOKEN") ?: System.getenv("CURSEFORGE_TOKEN") + if (CURSEFORGE_TOKEN != null) { + curseforge { + token = CURSEFORGE_TOKEN + id = rootProject.curseforge_id + gameVersions.addAll "Java 21", project.minecraft_version + } + } + + var MODRINTH_TOKEN = project.findProperty("MODRINTH_TOKEN") ?: System.getenv("MODRINTH_TOKEN") + if (MODRINTH_TOKEN != null) { + modrinth { + token = MODRINTH_TOKEN + id = rootProject.modrinth_id + version = "$project.version-$project.name" + gameVersions.addAll project.minecraft_version + } } } - - // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. - repositories { - // Add repositories to publish to here. - } } From f0c8895d74f95a128bcf7afc8851995b2cdd8f99 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Sat, 8 Jun 2024 20:42:16 +0200 Subject: [PATCH 014/100] Port to 1.21-pre4 --- .../midnightdust/core/mixin/MixinOptionsScreen.java | 2 +- .../eu/midnightdust/lib/config/MidnightConfig.java | 12 +++++++----- fabric/build.gradle | 2 +- gradle.properties | 10 +++++----- neoforge/build.gradle | 2 +- settings.gradle | 2 +- 6 files changed, 16 insertions(+), 14 deletions(-) diff --git a/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java b/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java index 6ce5b88..5080819 100644 --- a/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java +++ b/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java @@ -25,7 +25,7 @@ public class MixinOptionsScreen extends Screen { @Shadow @Final private ThreePartsLayoutWidget layout; @Unique TextIconButtonWidget button = TextIconButtonWidget.builder(Text.translatable("midnightlib.overview.title"), ( buttonWidget) -> Objects.requireNonNull(client).setScreen(new MidnightConfigOverviewScreen(this)), true) - .texture(new Identifier("midnightlib","icon/midnightlib"), 16, 16).dimension(20, 20).build(); + .texture(Identifier.of("midnightlib","icon/midnightlib"), 16, 16).dimension(20, 20).build(); @Unique boolean shouldShowButton = MidnightLibConfig.config_screen_list.equals(MidnightLibConfig.ConfigButton.TRUE) || (MidnightLibConfig.config_screen_list.equals(MidnightLibConfig.ConfigButton.MODMENU) && !PlatformFunctions.isModLoaded("modmenu")); protected MixinOptionsScreen(Text title) {super(title);} 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 048ca30..38c2bac 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -287,7 +287,10 @@ public abstract class MidnightConfig { super.init(); tabNavigation.setWidth(this.width); tabNavigation.init(); - if (tabs.size() > 1) this.addDrawableChild(tabNavigation); + if (tabs.size() > 1) { + this.addDrawableChild(tabNavigation); + list.renderHeaderSeparator = false; + } this.addDrawableChild(ButtonWidget.builder(ScreenTexts.CANCEL, button -> { loadValues(); @@ -320,7 +323,7 @@ public abstract class MidnightConfig { info.index = 0; list.clear(); fillList(); - }), true).texture(new Identifier("midnightlib","icon/reset"), 12, 12).dimension(40, 20).build(); + }), true).texture(Identifier.of("midnightlib","icon/reset"), 12, 12).dimension(40, 20).build(); resetButton.setPosition(width - 205, 0); if (info.widget instanceof Map.Entry) { @@ -386,12 +389,11 @@ public abstract class MidnightConfig { if (tabs.size() < 2) context.drawCenteredTextWithShadow(textRenderer, title, width / 2, 10, 0xFFFFFF); - list.renderHeaderSeperator = tabs.size() < 2; } } @Environment(EnvType.CLIENT) public static class MidnightConfigListWidget extends ElementListWidget { - boolean renderHeaderSeperator = true; + boolean renderHeaderSeparator = true; public MidnightConfigListWidget(MinecraftClient client, int width, int height, int y, int itemHeight) { super(client, width, height, y, itemHeight); } @@ -400,7 +402,7 @@ public abstract class MidnightConfig { @Override protected void drawHeaderAndFooterSeparators(DrawContext context) { - if (renderHeaderSeperator) super.drawHeaderAndFooterSeparators(context); + if (renderHeaderSeparator) super.drawHeaderAndFooterSeparators(context); else { RenderSystem.enableBlend(); context.drawTexture(this.client.world == null ? Screen.FOOTER_SEPARATOR_TEXTURE : Screen.INWORLD_FOOTER_SEPARATOR_TEXTURE, this.getX(), this.getBottom(), 0.0F, 0.0F, this.getWidth(), 2, 32, 2); diff --git a/fabric/build.gradle b/fabric/build.gradle index d301610..932970e 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -66,7 +66,7 @@ components.java { unifiedPublishing { project { - displayName = "MidnightLib v$project.version - Fabric $project.minecraft_version" + displayName = "MidnightLib $project.version - Fabric $project.minecraft_version" releaseType = "$project.release_type" changelog = releaseChangelog() gameVersions = [] diff --git a/gradle.properties b/gradle.properties index 742f48b..5c5ec71 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,18 +1,18 @@ org.gradle.jvmargs=-Xmx4096M -minecraft_version=1.20.6 -yarn_mappings=1.20.6+build.1 -enabled_platforms=fabric,neoforge +minecraft_version=1.21-pre4 +yarn_mappings=1.21-pre4+build.3 +enabled_platforms=fabric archives_base_name=midnightlib -mod_version=1.5.5 +mod_version=1.5.6 maven_group=eu.midnightdust release_type=release curseforge_id=488090 modrinth_id=codAaoxh fabric_loader_version=0.15.11 -fabric_api_version=0.97.8+1.20.6 +fabric_api_version=0.100.0+1.21 neoforge_version=20.6.63-beta yarn_mappings_patch_neoforge_version = 1.20.5+build.3 diff --git a/neoforge/build.gradle b/neoforge/build.gradle index ccbd89c..ebedf83 100644 --- a/neoforge/build.gradle +++ b/neoforge/build.gradle @@ -75,7 +75,7 @@ components.java { unifiedPublishing { project { - displayName = "MidnightLib v$project.version - NeoForge $project.minecraft_version" + displayName = "MidnightLib $project.version - NeoForge $project.minecraft_version" releaseType = "$project.release_type" changelog = releaseChangelog() gameVersions = [] diff --git a/settings.gradle b/settings.gradle index d64842c..f865b79 100644 --- a/settings.gradle +++ b/settings.gradle @@ -11,6 +11,6 @@ include("common") include("fabric-like") include("fabric") //include("quilt") -include("neoforge") +//include("neoforge") rootProject.name = "midnightlib" From 03d70cf9a0484c975057db65f15eeb237fa96595 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Wed, 12 Jun 2024 08:05:23 +0200 Subject: [PATCH 015/100] Update to rc1 --- gradle.properties | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index 5c5ec71..92f9de2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ org.gradle.jvmargs=-Xmx4096M -minecraft_version=1.21-pre4 -yarn_mappings=1.21-pre4+build.3 +minecraft_version=1.21-rc1 +yarn_mappings=1.21-rc1+build.1 enabled_platforms=fabric archives_base_name=midnightlib @@ -12,7 +12,7 @@ curseforge_id=488090 modrinth_id=codAaoxh fabric_loader_version=0.15.11 -fabric_api_version=0.100.0+1.21 +fabric_api_version=0.100.1+1.21 neoforge_version=20.6.63-beta yarn_mappings_patch_neoforge_version = 1.20.5+build.3 From 86a665c41a18ba9ae9d7cf6c6a2979af09939ff5 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Thu, 13 Jun 2024 20:23:53 +0200 Subject: [PATCH 016/100] Fix crash with multiple visible tabs --- .../eu/midnightdust/lib/config/MidnightConfig.java | 6 ++---- gradle.properties | 10 +++++----- 2 files changed, 7 insertions(+), 9 deletions(-) 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 38c2bac..1f6d0a6 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -287,10 +287,7 @@ public abstract class MidnightConfig { super.init(); tabNavigation.setWidth(this.width); tabNavigation.init(); - if (tabs.size() > 1) { - this.addDrawableChild(tabNavigation); - list.renderHeaderSeparator = false; - } + if (tabs.size() > 1) this.addDrawableChild(tabNavigation); this.addDrawableChild(ButtonWidget.builder(ScreenTexts.CANCEL, button -> { loadValues(); @@ -311,6 +308,7 @@ public abstract class MidnightConfig { this.addSelectableChild(this.list); fillList(); + if (tabs.size() > 1) list.renderHeaderSeparator = false; reload = true; } public void fillList() { diff --git a/gradle.properties b/gradle.properties index 92f9de2..2768f80 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,11 +1,11 @@ org.gradle.jvmargs=-Xmx4096M -minecraft_version=1.21-rc1 -yarn_mappings=1.21-rc1+build.1 -enabled_platforms=fabric +minecraft_version=1.21 +yarn_mappings=1.21+build.1 +enabled_platforms=fabric,neoforge archives_base_name=midnightlib -mod_version=1.5.6 +mod_version=1.5.7 maven_group=eu.midnightdust release_type=release curseforge_id=488090 @@ -14,7 +14,7 @@ modrinth_id=codAaoxh fabric_loader_version=0.15.11 fabric_api_version=0.100.1+1.21 -neoforge_version=20.6.63-beta +neoforge_version=21.0.0-beta yarn_mappings_patch_neoforge_version = 1.20.5+build.3 quilt_loader_version=0.19.0-beta.18 From dfb53f391d28c0b8be833a066298ad535f4cb19b Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Mon, 17 Jun 2024 15:17:07 +0200 Subject: [PATCH 017/100] NeoForge 1.21 - Added new method to get Modloader/Platform name in common classes --- .../core/config/MidnightConfigExample.java | 67 ------------------- .../core/config/MidnightLibConfig.java | 4 +- .../core/mixin/MixinOptionsScreen.java | 2 +- .../lib/util/PlatformFunctions.java | 5 ++ .../util/fabric/PlatformFunctionsImpl.java | 3 + gradle.properties | 4 +- .../util/neoforge/PlatformFunctionsImpl.java | 3 + .../resources/META-INF/neoforge.mods.toml | 4 +- settings.gradle | 2 +- 9 files changed, 21 insertions(+), 73 deletions(-) delete mode 100644 common/src/main/java/eu/midnightdust/core/config/MidnightConfigExample.java diff --git a/common/src/main/java/eu/midnightdust/core/config/MidnightConfigExample.java b/common/src/main/java/eu/midnightdust/core/config/MidnightConfigExample.java deleted file mode 100644 index 83954e5..0000000 --- a/common/src/main/java/eu/midnightdust/core/config/MidnightConfigExample.java +++ /dev/null @@ -1,67 +0,0 @@ -package eu.midnightdust.core.config; - -import com.google.common.collect.Lists; -import eu.midnightdust.lib.config.MidnightConfig; - -import java.util.List; - -/** MidnightConfig documentation & examples: - * Thanks for choosing MidnightConfig - the fancy, tiny and lightweight config library. - * If you want to use the lib in your mod, here are some examples and hints: - * 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 { - - @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") 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 = "text", isColor = true) public static String titleColor = "#ffffff"; // The isColor property adds a preview box for a hexadecimal color - @Entry(category = "text") public static List arrayList = Lists.newArrayList(); // Array String Lists are also supported - @Entry(isSlider = true, min = 0, max = 100) public static int intSlider = 35; // Int fields can also be displayed as a Slider - @Entry(isSlider = true, min = 0f, max = 1f) 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 - - public static int imposter = 16777215; // - Entries without an @Entry or @Comment annotation are ignored - - /* - The .json language file for your config class could look similar to this: - { - "modid.midnightconfig.title":"I am a title", // "*.midnightconfig.title" defines the title of the screen - "modid.midnightconfig.text1":"I am a comment *u*", // Translation for the comment "text1" defined in the example config - "modid.midnightconfig.text2":"I am a centered comment (╯°□°)╯︵ ┻━┻", - "modid.midnightconfig.name":"I am a string!", // Translation for the field "name" defined in the example config - "modid.midnightconfig.name.tooltip":"I am a tooltip uwu \nI am a new line", - // When hovering over the option "showInfo", - // this text will appear as a tooltip. - // "\n" inserts a line break. - "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.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.category.numbers": "Numbers", - "modid.midnightconfig.category.text": "Text", - "modid.midnightconfig.category.sliders": "Sliders" - } - To initialize the config you have to call "MidnightConfig.init("modid", MidnightConfigExample.class)" in your ModInitializer - To get an instance of the config screen you have to call "MidnightConfig.getScreen(parent, "modid");" - If you don't use the whole library and therefore not the automatic ModMenu integration, the code in your ModMenu integration class would look something like this: - @Override - public ConfigScreenFactory getModConfigScreenFactory() { - return parent -> MidnightConfig.getScreen(parent, "modid"); - } - */ -} \ No newline at end of file diff --git a/common/src/main/java/eu/midnightdust/core/config/MidnightLibConfig.java b/common/src/main/java/eu/midnightdust/core/config/MidnightLibConfig.java index 41c8e4d..8f7af15 100644 --- a/common/src/main/java/eu/midnightdust/core/config/MidnightLibConfig.java +++ b/common/src/main/java/eu/midnightdust/core/config/MidnightLibConfig.java @@ -3,9 +3,11 @@ package eu.midnightdust.core.config; import eu.midnightdust.lib.config.MidnightConfig; import eu.midnightdust.lib.util.PlatformFunctions; +import java.util.Objects; + public class MidnightLibConfig extends MidnightConfig { @Entry - public static ConfigButton config_screen_list = PlatformFunctions.isModLoaded("modmenu") ? ConfigButton.MODMENU : ConfigButton.TRUE; + public static ConfigButton config_screen_list = (PlatformFunctions.isModLoaded("modmenu") || Objects.equals(PlatformFunctions.getPlatformName(), "neoforge")) ? ConfigButton.MODMENU : ConfigButton.TRUE; public enum ConfigButton { TRUE,FALSE,MODMENU diff --git a/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java b/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java index 5080819..5fa9be6 100644 --- a/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java +++ b/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java @@ -26,7 +26,7 @@ public class MixinOptionsScreen extends Screen { @Unique TextIconButtonWidget button = TextIconButtonWidget.builder(Text.translatable("midnightlib.overview.title"), ( buttonWidget) -> Objects.requireNonNull(client).setScreen(new MidnightConfigOverviewScreen(this)), true) .texture(Identifier.of("midnightlib","icon/midnightlib"), 16, 16).dimension(20, 20).build(); - @Unique boolean shouldShowButton = MidnightLibConfig.config_screen_list.equals(MidnightLibConfig.ConfigButton.TRUE) || (MidnightLibConfig.config_screen_list.equals(MidnightLibConfig.ConfigButton.MODMENU) && !PlatformFunctions.isModLoaded("modmenu")); + @Unique boolean shouldShowButton = MidnightLibConfig.config_screen_list.equals(MidnightLibConfig.ConfigButton.TRUE) || (MidnightLibConfig.config_screen_list.equals(MidnightLibConfig.ConfigButton.MODMENU) && !PlatformFunctions.isModLoaded("modmenu") && PlatformFunctions.getPlatformName() != "neoforge"); protected MixinOptionsScreen(Text title) {super(title);} @Inject(at = @At("HEAD"), method = "init") diff --git a/common/src/main/java/eu/midnightdust/lib/util/PlatformFunctions.java b/common/src/main/java/eu/midnightdust/lib/util/PlatformFunctions.java index 7cc3b5b..aabefb3 100644 --- a/common/src/main/java/eu/midnightdust/lib/util/PlatformFunctions.java +++ b/common/src/main/java/eu/midnightdust/lib/util/PlatformFunctions.java @@ -7,6 +7,11 @@ import net.minecraft.server.command.ServerCommandSource; import java.nio.file.Path; public class PlatformFunctions { + @ExpectPlatform + public static String getPlatformName() { + // Just throw an error, the content should get replaced at runtime. + throw new AssertionError(); + } @ExpectPlatform public static Path getConfigDirectory() { // Just throw an error, the content should get replaced at runtime. diff --git a/fabric/src/main/java/eu/midnightdust/lib/util/fabric/PlatformFunctionsImpl.java b/fabric/src/main/java/eu/midnightdust/lib/util/fabric/PlatformFunctionsImpl.java index 2ade0c4..5615bd8 100644 --- a/fabric/src/main/java/eu/midnightdust/lib/util/fabric/PlatformFunctionsImpl.java +++ b/fabric/src/main/java/eu/midnightdust/lib/util/fabric/PlatformFunctionsImpl.java @@ -10,6 +10,9 @@ import net.minecraft.server.command.ServerCommandSource; import java.nio.file.Path; public class PlatformFunctionsImpl { + public static String getPlatformName() { + return "fabric"; + } /** * This is our actual method to {@link PlatformFunctions#getConfigDirectory()}. */ diff --git a/gradle.properties b/gradle.properties index 2768f80..7d03f5f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,8 +14,8 @@ modrinth_id=codAaoxh fabric_loader_version=0.15.11 fabric_api_version=0.100.1+1.21 -neoforge_version=21.0.0-beta -yarn_mappings_patch_neoforge_version = 1.20.5+build.3 +neoforge_version=21.0.14-beta +yarn_mappings_patch_neoforge_version = 1.21+build.4 quilt_loader_version=0.19.0-beta.18 quilt_fabric_api_version=7.0.1+0.83.0-1.20 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 d2d5a19..878264a 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 @@ -10,6 +10,9 @@ import net.neoforged.fml.loading.FMLPaths; import java.nio.file.Path; public class PlatformFunctionsImpl { + public static String getPlatformName() { + return "neoforge"; + } /** * This is our actual method to {@link PlatformFunctions#getConfigDirectory()}. */ diff --git a/neoforge/src/main/resources/META-INF/neoforge.mods.toml b/neoforge/src/main/resources/META-INF/neoforge.mods.toml index 8b38520..0887a3c 100644 --- a/neoforge/src/main/resources/META-INF/neoforge.mods.toml +++ b/neoforge/src/main/resources/META-INF/neoforge.mods.toml @@ -12,7 +12,9 @@ authors = "TeamMidnightDust, Motschen" description = ''' Common Library for Team MidnightDust's mods. ''' -#logoFile = "" + +[[mixins]] +config = "midnightlib.mixins.json" [[dependencies.midnightlib]] modId = "neoforge" diff --git a/settings.gradle b/settings.gradle index f865b79..d64842c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -11,6 +11,6 @@ include("common") include("fabric-like") include("fabric") //include("quilt") -//include("neoforge") +include("neoforge") rootProject.name = "midnightlib" From c16b9be9b23df23bbf2d9d086351d2e633b6f84b Mon Sep 17 00:00:00 2001 From: Mc_candycube6623 <110833307+Mccandycube6623@users.noreply.github.com> Date: Sat, 22 Jun 2024 00:10:52 +0800 Subject: [PATCH 018/100] Create zh_cn.json --- .../main/resources/assets/midnightlib/lang/zh_cn.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 common/src/main/resources/assets/midnightlib/lang/zh_cn.json diff --git a/common/src/main/resources/assets/midnightlib/lang/zh_cn.json b/common/src/main/resources/assets/midnightlib/lang/zh_cn.json new file mode 100644 index 0000000..8ca70b6 --- /dev/null +++ b/common/src/main/resources/assets/midnightlib/lang/zh_cn.json @@ -0,0 +1,11 @@ +{ + "midnightlib.overview.title":"MidnightConfig 概述", + "midnightlib.midnightconfig.title":"MidnightLib 设定", + "midnightlib.midnightconfig.config_screen_list":"启用设定画面列表", + "midnightlib.midnightconfig.enum.ConfigButton.TRUE":"§a是", + "midnightlib.midnightconfig.enum.ConfigButton.FALSE":"§c否", + "midnightlib.midnightconfig.enum.ConfigButton.MODMENU":"§b模組菜单", + "midnightlib.wiki":"维基", + "modmenu.descriptionTranslation.midnightlib": "MidnightDust 团队的常用库模组。 n提供设定 API、与其他模块自动整合、常用工具和美观。", + "modmenu.summaryTranslation.midnightlib": "MidnightDust 团队的常用库模组。" +} From 91e264cbb55fdaf285f9c7269d3685c686060b9f Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Sat, 10 Aug 2024 09:48:39 +0200 Subject: [PATCH 019/100] Update Neoforge to fix #60 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 7d03f5f..931011d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,7 +14,7 @@ modrinth_id=codAaoxh fabric_loader_version=0.15.11 fabric_api_version=0.100.1+1.21 -neoforge_version=21.0.14-beta +neoforge_version=21.0.143 yarn_mappings_patch_neoforge_version = 1.21+build.4 quilt_loader_version=0.19.0-beta.18 From 9cce0ff10a4a7e377924e3e9921c4df8c1306338 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Sat, 10 Aug 2024 09:53:11 +0200 Subject: [PATCH 020/100] Bump version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 931011d..f1222b5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,7 +5,7 @@ yarn_mappings=1.21+build.1 enabled_platforms=fabric,neoforge archives_base_name=midnightlib -mod_version=1.5.7 +mod_version=1.5.8 maven_group=eu.midnightdust release_type=release curseforge_id=488090 From fbde598420ae51ed7b4f22b290fa834ab2eda359 Mon Sep 17 00:00:00 2001 From: Jaffe2718 Date: Thu, 22 Aug 2024 15:44:22 +0800 Subject: [PATCH 021/100] - add file chooser for String field in 1.6.0 --- .../eu/midnightdust/core/MidnightLib.java | 10 ++ .../core/config/MidnightLibConfig.java | 2 +- .../lib/config/MidnightConfig.java | 78 ++++++++++++-- .../textures/gui/sprites/icon/explorer.png | Bin 0 -> 197 bytes fabric/src/main/resources/fabric.mod.json | 101 ++++++++++-------- gradle.properties | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 7 files changed, 137 insertions(+), 58 deletions(-) create mode 100644 common/src/main/resources/assets/midnightlib/textures/gui/sprites/icon/explorer.png diff --git a/common/src/main/java/eu/midnightdust/core/MidnightLib.java b/common/src/main/java/eu/midnightdust/core/MidnightLib.java index b729dc1..68287e0 100755 --- a/common/src/main/java/eu/midnightdust/core/MidnightLib.java +++ b/common/src/main/java/eu/midnightdust/core/MidnightLib.java @@ -5,16 +5,26 @@ import eu.midnightdust.lib.config.AutoCommand; import eu.midnightdust.lib.config.MidnightConfig; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import javax.swing.*; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; public class MidnightLib { public static List hiddenMods = new ArrayList<>(); + public static final Logger LOGGER = LoggerFactory.getLogger("midnightlib"); @Environment(EnvType.CLIENT) public static void onInitializeClient() { + System.setProperty("java.awt.headless", "false"); + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (Exception e) { + LOGGER.error("Error setting system look and feel", e); + } MidnightLibConfig.init("midnightlib", MidnightLibConfig.class); } @Environment(EnvType.SERVER) diff --git a/common/src/main/java/eu/midnightdust/core/config/MidnightLibConfig.java b/common/src/main/java/eu/midnightdust/core/config/MidnightLibConfig.java index 8f7af15..393c1e3 100644 --- a/common/src/main/java/eu/midnightdust/core/config/MidnightLibConfig.java +++ b/common/src/main/java/eu/midnightdust/core/config/MidnightLibConfig.java @@ -10,6 +10,6 @@ public class MidnightLibConfig extends MidnightConfig { public static ConfigButton config_screen_list = (PlatformFunctions.isModLoaded("modmenu") || Objects.equals(PlatformFunctions.getPlatformName(), "neoforge")) ? ConfigButton.MODMENU : ConfigButton.TRUE; public enum ConfigButton { - TRUE,FALSE,MODMENU + TRUE, FALSE, MODMENU } } 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 1f6d0a6..b70c349 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -28,6 +28,8 @@ import net.minecraft.text.Text; import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; +import javax.swing.JFileChooser; +import javax.swing.filechooser.FileNameExtensionFilter; import java.awt.Color; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -70,7 +72,7 @@ public abstract class MidnightConfig { String id; Text name; int index; - ClickableWidget colorButton; + ClickableWidget functionButton; // color picker button / explorer button Tab tab; } @@ -175,7 +177,7 @@ public abstract class MidnightConfig { if (!s.contains("#")) s = '#' + s; if (!HEXADECIMAL_ONLY.matcher(s).matches()) return false; try { - info.colorButton.setMessage(Text.literal("⬛").setStyle(Style.EMPTY.withColor(Color.decode(info.tempValue).getRGB()))); + info.functionButton.setMessage(Text.literal("⬛").setStyle(Style.EMPTY.withColor(Color.decode(info.tempValue).getRGB()))); } catch (Exception ignored) {} } return true; @@ -353,7 +355,9 @@ public abstract class MidnightConfig { if (e.isSlider()) widget = new MidnightSliderWidget(width - 160, 0, 150, 20, Text.of(info.tempValue), (Double.parseDouble(info.tempValue) - e.min()) / (e.max() - e.min()), info); else - widget = new TextFieldWidget(textRenderer, width - 160, 0, 150, 20, null, Text.of(info.tempValue)); + widget = new TextFieldWidget(textRenderer, + width - (160 + (e.selectionMode() > -1 ? 20 : 0)), + 0, 150, 20, null, Text.of(info.tempValue)); if (widget instanceof TextFieldWidget textField) { textField.setMaxLength(info.width); textField.setText(info.tempValue); @@ -363,15 +367,43 @@ public abstract class MidnightConfig { widget.setTooltip(getTooltip(info)); if (e.isColor()) { resetButton.setWidth(20); - ButtonWidget colorButton = ButtonWidget.builder(Text.literal("⬛"), (button -> { - })).dimensions(width - 185, 0, 20, 20).build(); + ButtonWidget colorButton = ButtonWidget.builder(Text.literal("⬛"), (button -> {})).dimensions(width - 185, 0, 20, 20).build(); try { colorButton.setMessage(Text.literal("⬛").setStyle(Style.EMPTY.withColor(Color.decode(info.tempValue).getRGB()))); } catch (Exception ignored) {} - info.colorButton = colorButton; + info.functionButton = colorButton; colorButton.active = false; this.list.addButton(List.of(widget, resetButton, colorButton), name, info); - } else this.list.addButton(List.of(widget, resetButton), name, info); + } else if (e.selectionMode() > -1) { + ButtonWidget explorerButton = TextIconButtonWidget.builder( + Text.of(""), + button -> { + JFileChooser fileChooser = new JFileChooser(); + fileChooser.setFileSelectionMode(e.selectionMode()); + fileChooser.setDialogType(e.fileChooserType()); + fileChooser.setDialogTitle(Text.translatable(translationPrefix + info.field.getName() + ".fileChooser.title").getString()); + if ((e.selectionMode() == JFileChooser.FILES_ONLY || e.selectionMode() == JFileChooser.FILES_AND_DIRECTORIES) && + Arrays.stream(e.fileExtensions()).noneMatch("*"::equals)) { + fileChooser.setFileFilter(new FileNameExtensionFilter( + Text.translatable(translationPrefix + info.field.getName() + ".fileFilter.description").getString(), + e.fileExtensions())); + } + if (fileChooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) { + info.value = fileChooser.getSelectedFile().getAbsolutePath(); + info.tempValue = info.value.toString(); + list.clear(); + fillList(); + } + }, + true + ).texture(Identifier.of("midnightlib","icon/explorer"), 12, 12).dimension(20, 20).build(); + explorerButton.setPosition(width - 25, 0); + resetButton.setWidth(20); + info.functionButton = explorerButton; + this.list.addButton(List.of(widget, resetButton, explorerButton), name, info); + } else { + this.list.addButton(List.of(widget, resetButton), name, info); + } } else { this.list.addButton(List.of(), name, info); } @@ -463,16 +495,44 @@ public abstract class MidnightConfig { info.tempValue = String.valueOf(info.value); } } - @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Entry { - int width() default 100; + + /** + * Entry Annotation
+ * - width: The maximum character length of the {@link String} or {@link List} field
+ * - min: The minimum value of the int, float or double field
+ * - max: The maximum value of the int, float or double field
+ * - name: The name of the field in the config screen
+ * - selectionMode: The selection mode of the file picker button for {@link String} fields, + * -1 for none, {@link JFileChooser#FILES_ONLY} for files, {@link JFileChooser#DIRECTORIES_ONLY} for directories, + * {@link JFileChooser#FILES_AND_DIRECTORIES} for both (default: -1). Remember to set the translation key + * [modid].midnightconfig.[fieldName].fileChooser.title for the file picker dialog title
+ * - fileChooserType: The type of the file picker button for {@link String} fields, + * can be {@link JFileChooser#OPEN_DIALOG} or {@link JFileChooser#SAVE_DIALOG} (default: {@link JFileChooser#OPEN_DIALOG}). + * Remember to set the translation key [modid].midnightconfig.[fieldName].fileFilter.description for the file filter description + * if "*" is not used as file extension
+ * - fileExtensions: The file extensions for the file picker button for {@link String} fields (default: {"*"}), + * only works if selectionMode is {@link JFileChooser#FILES_ONLY} or {@link JFileChooser#FILES_AND_DIRECTORIES}
+ * - isColor: If the field is a hexadecimal color code (default: false)
+ * - isSlider: If the field is a slider (default: false)
+ * - precision: The precision of the float or double field (default: 100)
+ * - category: The category of the field in the config screen (default: "default")
+ * */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + public @interface Entry { + int width() default 400; double min() default Double.MIN_NORMAL; double max() default Double.MAX_VALUE; String name() default ""; + int selectionMode() default -1; // -1 for none, 0 for file, 1 for firectory, 2 for both + int fileChooserType() default JFileChooser.OPEN_DIALOG; + String[] fileExtensions() default {"*"}; boolean isColor() default false; boolean isSlider() default false; int precision() default 100; String category() default "default"; } + @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Client {} @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Server {} @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Hidden {} diff --git a/common/src/main/resources/assets/midnightlib/textures/gui/sprites/icon/explorer.png b/common/src/main/resources/assets/midnightlib/textures/gui/sprites/icon/explorer.png new file mode 100644 index 0000000000000000000000000000000000000000..cf925b8e141574687f401251dc5aafab3fd3fa1f GIT binary patch literal 197 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=$1|-8uW1a&k#^NA%Cx&(BWL^R}Ea{HEjtmSN z`?>!lvI6;>1s;*b3=CqbAk63)r1AkM80G2W7@`rpwLg&WfC7i}#pZ)IA12LKJ>WAf z=1.20.4" - }, + "contact": { + "homepage": "https://www.midnightdust.eu/", + "sources": "https://github.com/TeamMidnightDust/MidnightLib", + "issues": "https://github.com/TeamMidnightDust/MidnightLib/issues" + }, - "mixins": [ - "midnightlib.mixins.json" - ], + "license": "MIT", + "icon": "assets/midnightlib/icon.png", - "custom": { - "modmenu": { - "links": { - "modmenu.discord": "https://discord.midnightdust.eu/", - "modmenu.website": "https://www.midnightdust.eu/", - "midnightlib.curseforge": "https://www.curseforge.com/minecraft/mc-mods/midnightlib", - "midnightlib.modrinth": "https://modrinth.com/mod/midnightlib", - "midnightlib.wiki": "https://github.com/TeamMidnightDust/MidnightLib/wiki" - }, - "badges": [ "library" ] + "environment": "*", + "entrypoints": { + "client": [ + "eu.midnightdust.fabric.core.MidnightLibFabric" + ], + "server": [ + "eu.midnightdust.fabric.core.MidnightLibFabric" + ], + "modmenu": [ + "eu.midnightdust.lib.config.AutoModMenu" + ] + }, + "depends": { + "fabric-resource-loader-v0": "*", + "minecraft": ">=1.20.4" + }, + + "mixins": [ + "midnightlib.mixins.json" + ], + + "custom": { + "modmenu": { + "links": { + "modmenu.discord": "https://discord.midnightdust.eu/", + "modmenu.website": "https://www.midnightdust.eu/", + "midnightlib.curseforge": "https://www.curseforge.com/minecraft/mc-mods/midnightlib", + "midnightlib.modrinth": "https://modrinth.com/mod/midnightlib", + "midnightlib.wiki": "https://github.com/TeamMidnightDust/MidnightLib/wiki" + }, + "badges": [ "library" ] + } } - } } diff --git a/gradle.properties b/gradle.properties index f1222b5..3b3a7b5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,7 +5,7 @@ yarn_mappings=1.21+build.1 enabled_platforms=fabric,neoforge archives_base_name=midnightlib -mod_version=1.5.8 +mod_version=1.6.0 maven_group=eu.midnightdust release_type=release curseforge_id=488090 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 48c0a02..0d18421 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 7deccf4199a16651839e40b091ce198d08960999 Mon Sep 17 00:00:00 2001 From: Jaffe2718 Date: Thu, 22 Aug 2024 18:09:43 +0800 Subject: [PATCH 022/100] - use `fileChooser.showDialog(null, null)` instead of `fileChooser.showOpenDialog(null)` --- .../main/java/eu/midnightdust/lib/config/MidnightConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 b70c349..f51e319 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -388,7 +388,7 @@ public abstract class MidnightConfig { Text.translatable(translationPrefix + info.field.getName() + ".fileFilter.description").getString(), e.fileExtensions())); } - if (fileChooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) { + if (fileChooser.showDialog(null, null) == JFileChooser.APPROVE_OPTION) { info.value = fileChooser.getSelectedFile().getAbsolutePath(); info.tempValue = info.value.toString(); list.clear(); From 3e20b904b76f7a343b655b0605028e1b317a89f7 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Fri, 23 Aug 2024 21:08:16 +0200 Subject: [PATCH 023/100] Improved layout and lists - Moved reset buttons right - Added support for Identifiers - Added isItem property to visually show items associated with Identifiers - Lists can now also contain Identifiers and numbers - Added method to get default values - Added color chooser for color options --- .../lib/config/MidnightConfig.java | 233 ++++++++++++------ .../assets/midnightlib/lang/de_de.json | 4 +- .../assets/midnightlib/lang/en_us.json | 4 +- 3 files changed, 160 insertions(+), 81 deletions(-) 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 f51e319..17d4f80 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -21,14 +21,16 @@ import net.minecraft.client.gui.tab.TabManager; import net.minecraft.client.gui.tooltip.Tooltip; import net.minecraft.client.gui.widget.*; import net.minecraft.client.resource.language.I18n; +import net.minecraft.registry.Registries; import net.minecraft.screen.ScreenTexts; import net.minecraft.text.OrderedText; import net.minecraft.text.Style; import net.minecraft.text.Text; import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; +import org.jetbrains.annotations.Nullable; -import javax.swing.JFileChooser; +import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; import java.awt.Color; import java.lang.annotation.ElementType; @@ -37,16 +39,16 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Field; import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; import java.nio.file.Files; import java.nio.file.Path; import java.util.*; -import java.util.List; import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.Predicate; import java.util.regex.Pattern; -/** MidnightConfig v2.5.1 by TeamMidnightDust & Motschen +/** MidnightConfig v2.6.0 by TeamMidnightDust & Motschen * Single class config library - feel free to copy! * Based on ... * Credits to Minenash */ @@ -61,25 +63,62 @@ public abstract class MidnightConfig { public static class EntryInfo { Field field; + Class dataType; Object widget; int width; boolean centered; Text error; Object defaultValue; Object value; - String tempValue; + String tempValue; // The value visible in the config screen boolean inLimits = true; - String id; + String modid; Text name; int index; - ClickableWidget functionButton; // color picker button / explorer button + ClickableWidget functionButton; // color picker button / explorer button Tab tab; + + public void setValue(Object value) { + if (this.field.getType() != List.class) { + this.value = value; + this.tempValue = value.toString(); + } else { + writeList(this.index, value); + this.tempValue = toTemporaryValue(); + } + } + public String toTemporaryValue() { + if (this.field.getType() != List.class) return this.value.toString(); + else { + try { return ((List) this.value).get(this.index).toString(); + } catch (Exception ignored) {return "";} + } + } + public void writeList(int index, T value) { + var list = (List) this.value; + if (index >= list.size()) list.add(value); + else list.set(index, value); + } } public static final Map> configClass = new HashMap<>(); private static Path path; - private static final Gson gson = new GsonBuilder().excludeFieldsWithModifiers(Modifier.TRANSIENT).excludeFieldsWithModifiers(Modifier.PRIVATE).addSerializationExclusionStrategy(new HiddenAnnotationExclusionStrategy()).setPrettyPrinting().create(); + private static final Gson gson = new GsonBuilder() + .excludeFieldsWithModifiers(Modifier.TRANSIENT) + .excludeFieldsWithModifiers(Modifier.PRIVATE) + .addSerializationExclusionStrategy(new HiddenAnnotationExclusionStrategy()) + .registerTypeAdapter(Identifier.class, new Identifier.Serializer()) + .setPrettyPrinting().create(); + + public static @Nullable Object getDefaultValue(String modid, String entry) { + for (EntryInfo e : entries) { + if (modid.equals(e.modid) && entry.equals(e.field.getName())) { + return e.defaultValue; + } + } + return null; + } public static void init(String modid, Class config) { path = PlatformFunctions.getConfigDirectory().resolve(modid + ".json"); @@ -102,33 +141,41 @@ public abstract class MidnightConfig { if (info.field.isAnnotationPresent(Entry.class)) try { info.value = info.field.get(null); - info.tempValue = info.value.toString(); + info.tempValue = info.toTemporaryValue(); } catch (IllegalAccessException ignored) {} } } @Environment(EnvType.CLIENT) private static void initClient(String modid, Field field, EntryInfo info) { - Class type = field.getType(); + info.dataType = field.getType(); Entry e = field.getAnnotation(Entry.class); info.width = e != null ? e.width() : 0; info.field = field; - info.id = modid; + 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()); - if (type == int.class) textField(info, Integer::parseInt, INTEGER_ONLY, (int) e.min(), (int) e.max(), true); - else if (type == float.class) textField(info, Float::parseFloat, DECIMAL_ONLY, (float) e.min(), (float) e.max(), false); - else if (type == double.class) textField(info, Double::parseDouble, DECIMAL_ONLY, e.min(), e.max(), false); - else if (type == String.class || type == List.class) textField(info, String::length, null, Math.min(e.min(), 0), Math.max(e.max(), 1), true); - else if (type == boolean.class) { + if (info.dataType == int.class) textField(info, Integer::parseInt, INTEGER_ONLY, (int) e.min(), (int) e.max(), true); + else if (info.dataType == float.class) textField(info, Float::parseFloat, DECIMAL_ONLY, (float) e.min(), (float) e.max(), false); + else if (info.dataType == double.class) textField(info, Double::parseDouble, DECIMAL_ONLY, e.min(), e.max(), false); + else if (info.dataType == String.class || info.dataType == Identifier.class) + textField(info, String::length, null, Math.min(e.min(), 0), Math.max(e.max(), 1), true); + else if (info.dataType == boolean.class) { Function func = value -> Text.translatable((Boolean) value ? "gui.yes" : "gui.no").formatted((Boolean) value ? Formatting.GREEN : Formatting.RED); info.widget = new AbstractMap.SimpleEntry>(button -> { - info.value = !(Boolean) info.value; + info.setValue(!(Boolean) info.value); button.setMessage(func.apply(info.value)); }, func); - } else if (type.isEnum()) { + } else if (info.dataType.isEnum()) { List values = Arrays.asList(field.getType().getEnumConstants()); - Function func = value -> Text.translatable(modid + ".midnightconfig." + "enum." + type.getSimpleName() + "." + info.value.toString()); + Function func = value -> Text.translatable(modid + ".midnightconfig." + "enum." + info.dataType.getSimpleName() + "." + info.toTemporaryValue()); info.widget = new AbstractMap.SimpleEntry>(button -> { int index = values.indexOf(info.value) + 1; info.value = values.get(index >= values.size() ? 0 : index); @@ -139,10 +186,11 @@ public abstract class MidnightConfig { entries.add(info); } public static Tooltip getTooltip(EntryInfo info) { - String key = info.id + ".midnightconfig."+info.field.getName()+".tooltip"; + 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()); } + // TODO: Maybe move this into the screen class itself to free up some RAM? private static void textField(EntryInfo info, Function f, Pattern pattern, double min, double max, boolean cast) { boolean isNumber = pattern != null; info.widget = (BiFunction>) (t, b) -> s -> { @@ -166,11 +214,10 @@ public abstract class MidnightConfig { info.inLimits = inLimits; b.active = entries.stream().allMatch(e -> e.inLimits); - if (inLimits && info.field.getType() != List.class) - info.value = isNumber? value : s; - else if (inLimits) { - if (((List) info.value).size() == info.index) ((List) info.value).add(""); - ((List) info.value).set(info.index, Arrays.stream(info.tempValue.replace("[", "").replace("]", "").split(", ")).toList().getFirst()); + if (inLimits) { + if (info.dataType == Identifier.class) { + info.setValue(Identifier.tryParse(s)); + } else info.setValue(isNumber ? value : s); } if (info.field.getAnnotation(Entry.class).isColor()) { @@ -213,7 +260,7 @@ public abstract class MidnightConfig { loadValues(); for (EntryInfo e : entries) { - if (e.id.equals(modid)) { + if (e.modid.equals(modid)) { String tabId = e.field.isAnnotationPresent(Entry.class) ? e.field.getAnnotation(Entry.class).category() : e.field.getAnnotation(Comment.class).category(); String name = translationPrefix + "category." + tabId; if (!I18n.hasTranslation(name) && tabId.equals("default")) @@ -275,7 +322,7 @@ public abstract class MidnightConfig { if (info.field.isAnnotationPresent(Entry.class)) try { info.value = info.field.get(null); - info.tempValue = info.value.toString(); + info.tempValue = info.toTemporaryValue(); } catch (IllegalAccessException ignored) {} } } @@ -297,7 +344,7 @@ public abstract class MidnightConfig { }).dimensions(this.width / 2 - 154, this.height - 26, 150, 20).build()); done = this.addDrawableChild(ButtonWidget.builder(ScreenTexts.DONE, (button) -> { for (EntryInfo info : entries) - if (info.id.equals(modid)) { + if (info.modid.equals(modid)) { try { info.field.set(null, info.value); } catch (IllegalAccessException ignored) {} @@ -315,49 +362,33 @@ public abstract class MidnightConfig { } public void fillList() { for (EntryInfo info : entries) { - if (info.id.equals(modid) && (info.tab == null || info.tab == tabManager.getCurrentTab())) { + if (info.modid.equals(modid) && (info.tab == null || info.tab == tabManager.getCurrentTab())) { Text name = Objects.requireNonNullElseGet(info.name, () -> Text.translatable(translationPrefix + info.field.getName())); TextIconButtonWidget resetButton = TextIconButtonWidget.builder(Text.translatable("controls.reset"), (button -> { info.value = info.defaultValue; - info.tempValue = info.defaultValue.toString(); + info.tempValue = info.toTemporaryValue(); info.index = 0; list.clear(); fillList(); - }), true).texture(Identifier.of("midnightlib","icon/reset"), 12, 12).dimension(40, 20).build(); - resetButton.setPosition(width - 205, 0); + }), true).texture(Identifier.of("midnightlib","icon/reset"), 12, 12).dimension(20, 20).build(); + resetButton.setPosition(width - 205 + 150 + 25, 0); - if (info.widget instanceof Map.Entry) { - Map.Entry> widget = (Map.Entry>) info.widget; - if (info.field.getType().isEnum()) - widget.setValue(value -> Text.translatable(translationPrefix + "enum." + info.field.getType().getSimpleName() + "." + info.value.toString())); - this.list.addButton(List.of(ButtonWidget.builder(widget.getValue().apply(info.value), widget.getKey()).dimensions(width - 160, 0, 150, 20).tooltip(getTooltip(info)).build(), resetButton), name, info); - } else if (info.field.getType() == List.class) { + if (info.widget != null) { if (!reload) info.index = 0; - TextFieldWidget widget = new TextFieldWidget(textRenderer, width - 160, 0, 150, 20, Text.empty()); - widget.setMaxLength(info.width); - if (info.index < ((List) info.value).size()) - widget.setText((String.valueOf(((List) info.value).get(info.index)))); - Predicate processor = ((BiFunction>) info.widget).apply(widget, done); - widget.setTextPredicate(processor); - resetButton.setWidth(20); - ButtonWidget cycleButton = ButtonWidget.builder(Text.literal(String.valueOf(info.index)).formatted(Formatting.GOLD), (button -> { - if (((List) info.value).contains("")) ((List) info.value).remove(""); - info.index = info.index + 1; - if (info.index > ((List) info.value).size()) info.index = 0; - list.clear(); - fillList(); - })).dimensions(width - 185, 0, 20, 20).build(); - widget.setTooltip(getTooltip(info)); - this.list.addButton(List.of(widget, resetButton, cycleButton), name, info); - } else if (info.widget != null) { ClickableWidget widget; Entry e = info.field.getAnnotation(Entry.class); - if (e.isSlider()) - widget = new MidnightSliderWidget(width - 160, 0, 150, 20, Text.of(info.tempValue), (Double.parseDouble(info.tempValue) - e.min()) / (e.max() - e.min()), info); + + if (info.widget instanceof Map.Entry) { // Enums & booleans + var values = (Map.Entry>) info.widget; + if (info.dataType.isEnum()) + values.setValue(value -> Text.translatable(translationPrefix + "enum." + info.field.getType().getSimpleName() + "." + info.value.toString())); + widget = ButtonWidget.builder(values.getValue().apply(info.value), values.getKey()).dimensions(width - 185, 0, 150, 20).tooltip(getTooltip(info)).build(); + } + else if (e.isSlider()) + widget = new MidnightSliderWidget(width - 185, 0, 150, 20, Text.of(info.tempValue), (Double.parseDouble(info.tempValue) - e.min()) / (e.max() - e.min()), info); else - widget = new TextFieldWidget(textRenderer, - width - (160 + (e.selectionMode() > -1 ? 20 : 0)), - 0, 150, 20, null, Text.of(info.tempValue)); + widget = new MidnightTextFieldWidget(textRenderer, width - 185, 0, 150, 20, info); + if (widget instanceof TextFieldWidget textField) { textField.setMaxLength(info.width); textField.setText(info.tempValue); @@ -365,19 +396,40 @@ public abstract class MidnightConfig { textField.setTextPredicate(processor); } widget.setTooltip(getTooltip(info)); + + ButtonWidget cycleButton = null; + if (info.field.getType() == List.class) { + cycleButton = ButtonWidget.builder(Text.literal(String.valueOf(info.index)).formatted(Formatting.GOLD), (button -> { + var values = (List) info.value; + values.remove(""); + info.index = info.index + 1; + if (info.index > values.size()) info.index = 0; + info.tempValue = info.toTemporaryValue(); + if (info.index == values.size()) info.tempValue = ""; + list.clear(); + fillList(); + })).dimensions(width - 185, 0, 20, 20).build(); + } if (e.isColor()) { - resetButton.setWidth(20); - ButtonWidget colorButton = ButtonWidget.builder(Text.literal("⬛"), (button -> {})).dimensions(width - 185, 0, 20, 20).build(); + ButtonWidget colorButton = ButtonWidget.builder( + Text.literal("⬛"), + button -> new Thread(()-> { + Color newColor = JColorChooser.showDialog(null, Text.translatable("midnightconfig.colorChooser.title").getString(), Color.decode(!Objects.equals(info.tempValue, "") ? info.tempValue : "#FFFFFF")); + if (newColor != null) { + info.setValue("#" + Integer.toHexString(newColor.getRGB()).substring(2)); + list.clear(); + fillList(); + } + }).start() + ).dimensions(width - 185, 0, 20, 20).build(); try { colorButton.setMessage(Text.literal("⬛").setStyle(Style.EMPTY.withColor(Color.decode(info.tempValue).getRGB()))); } catch (Exception ignored) {} info.functionButton = colorButton; - colorButton.active = false; - this.list.addButton(List.of(widget, resetButton, colorButton), name, info); } else if (e.selectionMode() > -1) { ButtonWidget explorerButton = TextIconButtonWidget.builder( Text.of(""), - button -> { + button -> new Thread(()-> { JFileChooser fileChooser = new JFileChooser(); fileChooser.setFileSelectionMode(e.selectionMode()); fileChooser.setDialogType(e.fileChooserType()); @@ -389,21 +441,28 @@ public abstract class MidnightConfig { e.fileExtensions())); } if (fileChooser.showDialog(null, null) == JFileChooser.APPROVE_OPTION) { - info.value = fileChooser.getSelectedFile().getAbsolutePath(); - info.tempValue = info.value.toString(); + info.setValue(fileChooser.getSelectedFile().getAbsolutePath()); list.clear(); fillList(); } - }, + }).start(), true - ).texture(Identifier.of("midnightlib","icon/explorer"), 12, 12).dimension(20, 20).build(); - explorerButton.setPosition(width - 25, 0); - resetButton.setWidth(20); + ).texture(Identifier.of("midnightlib", "icon/explorer"), 12, 12).dimension(20, 20).build(); + explorerButton.setPosition(width - 185, 0); info.functionButton = explorerButton; - this.list.addButton(List.of(widget, resetButton, explorerButton), name, info); - } else { - this.list.addButton(List.of(widget, resetButton), name, info); } + List widgets = Lists.newArrayList(widget, resetButton); + if (info.functionButton != null) { + widget.setWidth(widget.getWidth() - 22); + widget.setX(widget.getX() + 22); + widgets.add(info.functionButton); + } if (cycleButton != null) { + if (info.functionButton != null) info.functionButton.setX(info.functionButton.getX() + 22); + widget.setWidth(widget.getWidth() - 22); + widget.setX(widget.getX() + 22); + widgets.add(cycleButton); + } + this.list.addButton(widgets, name, info); } else { this.list.addButton(List.of(), name, info); } @@ -489,10 +548,25 @@ public abstract class MidnightConfig { @Override protected void applyValue() { - if (info.field.getType() == int.class) info.value = ((Number) (e.min() + value * (e.max() - e.min()))).intValue(); - else if (info.field.getType() == double.class) info.value = Math.round((e.min() + value * (e.max() - e.min())) * (double) e.precision()) / (double) e.precision(); - else if (info.field.getType() == float.class) info.value = Math.round((e.min() + value * (e.max() - e.min())) * (float) e.precision()) / (float) e.precision(); - info.tempValue = String.valueOf(info.value); + if (info.dataType == int.class) info.setValue(((Number) (e.min() + value * (e.max() - e.min()))).intValue()); + else if (info.field.getType() == double.class) info.setValue(Math.round((e.min() + value * (e.max() - e.min())) * (double) e.precision()) / (double) e.precision()); + else if (info.field.getType() == float.class) info.setValue(Math.round((e.min() + value * (e.max() - e.min())) * (float) e.precision()) / (float) e.precision()); + } + } + public static class MidnightTextFieldWidget extends TextFieldWidget { + private final EntryInfo info; + private final boolean isItem; + + public MidnightTextFieldWidget(TextRenderer textRenderer, int x, int y, int width, int height, EntryInfo info) { + super(textRenderer, x, y, width, height, Text.of(info.tempValue)); + this.info = info; + this.isItem = info.field.getAnnotation(Entry.class).isItem(); + } + + public void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) { + super.renderWidget(context, mouseX, mouseY, delta); + if (isItem) + context.drawItem(Registries.ITEM.get(Identifier.tryParse(info.tempValue)).getDefaultStack(), this.getX()+this.getWidth()-18, this.getY()+2); } } @@ -524,9 +598,10 @@ public abstract class MidnightConfig { double min() default Double.MIN_NORMAL; double max() default Double.MAX_VALUE; String name() default ""; - int selectionMode() default -1; // -1 for none, 0 for file, 1 for firectory, 2 for both + int selectionMode() default -1; // -1 for none, 0 for file, 1 for directory, 2 for both int fileChooserType() default JFileChooser.OPEN_DIALOG; String[] fileExtensions() default {"*"}; + boolean isItem() default false; boolean isColor() default false; boolean isSlider() default false; int precision() default 100; @@ -547,4 +622,4 @@ public abstract class MidnightConfig { return fieldAttributes.getAnnotation(Entry.class) == null; } } -} +} \ No newline at end of file diff --git a/common/src/main/resources/assets/midnightlib/lang/de_de.json b/common/src/main/resources/assets/midnightlib/lang/de_de.json index 6d5212d..cd0da97 100755 --- a/common/src/main/resources/assets/midnightlib/lang/de_de.json +++ b/common/src/main/resources/assets/midnightlib/lang/de_de.json @@ -3,5 +3,7 @@ "midnightlib.midnightconfig.title":"MidnightLib Konfiguration", "midnightlib.midnightconfig.config_screen_list":"Konfigurationsübersicht", "modmenu.descriptionTranslation.midnightlib": "Code-Bibliothek für einfache Konfiguration.\nStellt eine Konfigurationsschnittstelle, automatische Kompatibilität und oft genutzten Code bereit.", - "modmenu.summaryTranslation.midnightlib": "Code-Bibliothek für einfache Konfiguration." + "modmenu.summaryTranslation.midnightlib": "Code-Bibliothek für einfache Konfiguration.", + + "midnightconfig.colorChooser.title": "Wähle eine Farbe" } \ No newline at end of file diff --git a/common/src/main/resources/assets/midnightlib/lang/en_us.json b/common/src/main/resources/assets/midnightlib/lang/en_us.json index 871eb57..8579b86 100755 --- a/common/src/main/resources/assets/midnightlib/lang/en_us.json +++ b/common/src/main/resources/assets/midnightlib/lang/en_us.json @@ -9,5 +9,7 @@ "midnightlib.curseforge":"CurseForge", "midnightlib.wiki":"Wiki", "modmenu.descriptionTranslation.midnightlib": "Common Library for easy configuration.\nProvides a config api, automatic integration with other mods and common utils.", - "modmenu.summaryTranslation.midnightlib": "Common Library for easy configuration." + "modmenu.summaryTranslation.midnightlib": "Common Library for easy configuration.", + + "midnightconfig.colorChooser.title": "Choose a color" } \ No newline at end of file From 5fa635911f2c2441a19c5ec8e141a907da90c763 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Fri, 23 Aug 2024 21:35:29 +0200 Subject: [PATCH 024/100] Show errors again and correctly handle closing --- .../lib/config/MidnightConfig.java | 71 ++++++++++++------- 1 file changed, 44 insertions(+), 27 deletions(-) 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 17d4f80..74f2fe5 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -64,7 +64,7 @@ public abstract class MidnightConfig { public static class EntryInfo { Field field; Class dataType; - Object widget; + Object function; int width; boolean centered; Text error; @@ -75,7 +75,7 @@ public abstract class MidnightConfig { String modid; Text name; int index; - ClickableWidget functionButton; // color picker button / explorer button + ClickableWidget actionButton; // color picker button / explorer button Tab tab; public void setValue(Object value) { @@ -169,14 +169,14 @@ public abstract class MidnightConfig { textField(info, String::length, null, Math.min(e.min(), 0), Math.max(e.max(), 1), true); else if (info.dataType == boolean.class) { Function func = value -> Text.translatable((Boolean) value ? "gui.yes" : "gui.no").formatted((Boolean) value ? Formatting.GREEN : Formatting.RED); - info.widget = new AbstractMap.SimpleEntry>(button -> { + info.function = new AbstractMap.SimpleEntry>(button -> { info.setValue(!(Boolean) info.value); button.setMessage(func.apply(info.value)); }, func); } else if (info.dataType.isEnum()) { List values = Arrays.asList(field.getType().getEnumConstants()); Function func = value -> Text.translatable(modid + ".midnightconfig." + "enum." + info.dataType.getSimpleName() + "." + info.toTemporaryValue()); - info.widget = new AbstractMap.SimpleEntry>(button -> { + info.function = new AbstractMap.SimpleEntry>(button -> { int index = values.indexOf(info.value) + 1; info.value = values.get(index >= values.size() ? 0 : index); button.setMessage(func.apply(info.value)); @@ -193,7 +193,7 @@ public abstract class MidnightConfig { // TODO: Maybe move this into the screen class itself to free up some RAM? private static void textField(EntryInfo info, Function f, Pattern pattern, double min, double max, boolean cast) { boolean isNumber = pattern != null; - info.widget = (BiFunction>) (t, b) -> s -> { + info.function = (BiFunction>) (t, b) -> s -> { s = s.trim(); if (!(s.isEmpty() || !isNumber || pattern.matcher(s).matches())) return false; @@ -224,7 +224,7 @@ public abstract class MidnightConfig { if (!s.contains("#")) s = '#' + s; if (!HEXADECIMAL_ONLY.matcher(s).matches()) return false; try { - info.functionButton.setMessage(Text.literal("⬛").setStyle(Style.EMPTY.withColor(Color.decode(info.tempValue).getRGB()))); + info.actionButton.setMessage(Text.literal("⬛").setStyle(Style.EMPTY.withColor(Color.decode(info.tempValue).getRGB()))); } catch (Exception ignored) {} } return true; @@ -281,7 +281,6 @@ public abstract class MidnightConfig { public final Screen parent; public final String modid; public MidnightConfigListWidget list; - public boolean reload = false; public TabManager tabManager = new TabManager(a -> {}, a -> {}); public Map tabs = new HashMap<>(); public Tab prevTab; @@ -303,13 +302,18 @@ public abstract class MidnightConfig { for (EntryInfo info : entries) { try {info.field.set(null, info.value);} catch (IllegalAccessException ignored) {} } - updateResetButtons(); + updateButtons(); } - public void updateResetButtons() { + public void updateButtons() { if (this.list != null) { for (ButtonEntry entry : this.list.children()) { - if (entry.buttons != null && entry.buttons.size() > 1 && entry.buttons.get(1) instanceof ButtonWidget button) { - button.active = !Objects.equals(entry.info.value.toString(), entry.info.defaultValue.toString()); + if (entry.buttons != null) { + if (entry.buttons.size() > 1 && entry.buttons.get(0) instanceof ClickableWidget widget && (widget.isFocused() || widget.isHovered())) { + widget.setTooltip(getTooltip(entry.info)); + } + if (entry.buttons.size() > 1 && entry.buttons.get(1) instanceof ButtonWidget button) { + button.active = !Objects.equals(entry.info.value.toString(), entry.info.defaultValue.toString()); + } } } } @@ -332,16 +336,30 @@ public abstract class MidnightConfig { return super.keyPressed(keyCode, scanCode, modifiers); } @Override + public void close() { + loadValues(); + cleanup(); + Objects.requireNonNull(client).setScreen(parent); + } + private void cleanup() { + entries.forEach(info -> { + info.error = null; + info.value = null; + info.tempValue = null; + info.actionButton = null; + info.index = 0; + info.tab = null; + info.inLimits = true; + }); + } + @Override public void init() { super.init(); tabNavigation.setWidth(this.width); tabNavigation.init(); if (tabs.size() > 1) this.addDrawableChild(tabNavigation); - this.addDrawableChild(ButtonWidget.builder(ScreenTexts.CANCEL, button -> { - loadValues(); - Objects.requireNonNull(client).setScreen(parent); - }).dimensions(this.width / 2 - 154, this.height - 26, 150, 20).build()); + this.addDrawableChild(ButtonWidget.builder(ScreenTexts.CANCEL, button -> this.close()).dimensions(this.width / 2 - 154, this.height - 26, 150, 20).build()); done = this.addDrawableChild(ButtonWidget.builder(ScreenTexts.DONE, (button) -> { for (EntryInfo info : entries) if (info.modid.equals(modid)) { @@ -350,6 +368,7 @@ public abstract class MidnightConfig { } catch (IllegalAccessException ignored) {} } write(modid); + cleanup(); Objects.requireNonNull(client).setScreen(parent); }).dimensions(this.width / 2 + 4, this.height - 26, 150, 20).build()); @@ -358,7 +377,6 @@ public abstract class MidnightConfig { fillList(); if (tabs.size() > 1) list.renderHeaderSeparator = false; - reload = true; } public void fillList() { for (EntryInfo info : entries) { @@ -373,13 +391,12 @@ public abstract class MidnightConfig { }), true).texture(Identifier.of("midnightlib","icon/reset"), 12, 12).dimension(20, 20).build(); resetButton.setPosition(width - 205 + 150 + 25, 0); - if (info.widget != null) { - if (!reload) info.index = 0; + if (info.function != null) { ClickableWidget widget; Entry e = info.field.getAnnotation(Entry.class); - if (info.widget instanceof Map.Entry) { // Enums & booleans - var values = (Map.Entry>) info.widget; + if (info.function instanceof Map.Entry) { // Enums & booleans + var values = (Map.Entry>) info.function; if (info.dataType.isEnum()) values.setValue(value -> Text.translatable(translationPrefix + "enum." + info.field.getType().getSimpleName() + "." + info.value.toString())); widget = ButtonWidget.builder(values.getValue().apply(info.value), values.getKey()).dimensions(width - 185, 0, 150, 20).tooltip(getTooltip(info)).build(); @@ -392,7 +409,7 @@ public abstract class MidnightConfig { if (widget instanceof TextFieldWidget textField) { textField.setMaxLength(info.width); textField.setText(info.tempValue); - Predicate processor = ((BiFunction>) info.widget).apply(textField, done); + Predicate processor = ((BiFunction>) info.function).apply(textField, done); textField.setTextPredicate(processor); } widget.setTooltip(getTooltip(info)); @@ -425,7 +442,7 @@ public abstract class MidnightConfig { try { colorButton.setMessage(Text.literal("⬛").setStyle(Style.EMPTY.withColor(Color.decode(info.tempValue).getRGB()))); } catch (Exception ignored) {} - info.functionButton = colorButton; + info.actionButton = colorButton; } else if (e.selectionMode() > -1) { ButtonWidget explorerButton = TextIconButtonWidget.builder( Text.of(""), @@ -449,15 +466,15 @@ public abstract class MidnightConfig { true ).texture(Identifier.of("midnightlib", "icon/explorer"), 12, 12).dimension(20, 20).build(); explorerButton.setPosition(width - 185, 0); - info.functionButton = explorerButton; + info.actionButton = explorerButton; } List widgets = Lists.newArrayList(widget, resetButton); - if (info.functionButton != null) { + if (info.actionButton != null) { widget.setWidth(widget.getWidth() - 22); widget.setX(widget.getX() + 22); - widgets.add(info.functionButton); + widgets.add(info.actionButton); } if (cycleButton != null) { - if (info.functionButton != null) info.functionButton.setX(info.functionButton.getX() + 22); + if (info.actionButton != null) info.actionButton.setX(info.actionButton.getX() + 22); widget.setWidth(widget.getWidth() - 22); widget.setX(widget.getX() + 22); widgets.add(cycleButton); @@ -468,7 +485,7 @@ public abstract class MidnightConfig { } } list.setScrollAmount(scrollProgress); - updateResetButtons(); + updateButtons(); } } @Override From 8aab796530df426fc68e26274886fdbcfb8d7847 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Sun, 25 Aug 2024 12:17:04 +0200 Subject: [PATCH 025/100] More compact code & finishing touches --- .../eu/midnightdust/core/MidnightLib.java | 7 +- .../screen/MidnightConfigOverviewScreen.java | 6 +- .../lib/config/MidnightConfig.java | 350 ++++++------------ .../lib/util/MidnightColorUtil.java | 6 +- fabric-like/build.gradle | 17 - .../midnightdust/lib/config/AutoModMenu.java | 28 -- .../midnightdust/lib/config/AutoModMenu.java | 4 +- settings.gradle | 1 - 8 files changed, 115 insertions(+), 304 deletions(-) delete mode 100644 fabric-like/build.gradle delete mode 100755 fabric-like/src/main/java/eu/midnightdust/lib/config/AutoModMenu.java diff --git a/common/src/main/java/eu/midnightdust/core/MidnightLib.java b/common/src/main/java/eu/midnightdust/core/MidnightLib.java index 68287e0..2999bc2 100755 --- a/common/src/main/java/eu/midnightdust/core/MidnightLib.java +++ b/common/src/main/java/eu/midnightdust/core/MidnightLib.java @@ -20,11 +20,8 @@ public class MidnightLib { @Environment(EnvType.CLIENT) public static void onInitializeClient() { System.setProperty("java.awt.headless", "false"); - try { - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - } catch (Exception e) { - LOGGER.error("Error setting system look and feel", e); - } + try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (Exception e) { LOGGER.error("Error setting system look and feel", e); } MidnightLibConfig.init("midnightlib", MidnightLibConfig.class); } @Environment(EnvType.SERVER) 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 85cdd93..dab1926 100755 --- a/common/src/main/java/eu/midnightdust/core/screen/MidnightConfigOverviewScreen.java +++ b/common/src/main/java/eu/midnightdust/core/screen/MidnightConfigOverviewScreen.java @@ -26,16 +26,14 @@ public class MidnightConfigOverviewScreen extends Screen { 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.list = new MidnightConfig.MidnightConfigListWidget(this.client, this.width, this.height - 57, 24, 25); - this.addSelectableChild(this.list); + this.addSelectableChild(this.list = new MidnightConfig.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); - } - }); + }}); super.init(); } @Override 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 74f2fe5..da35c4c 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -1,54 +1,31 @@ package eu.midnightdust.lib.config; import com.google.common.collect.Lists; -import com.google.gson.ExclusionStrategy; -import com.google.gson.FieldAttributes; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; +import com.google.gson.ExclusionStrategy; import com.google.gson.FieldAttributes; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.mojang.blaze3d.systems.RenderSystem; import eu.midnightdust.lib.util.PlatformFunctions; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.Element; -import net.minecraft.client.gui.Selectable; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.tab.GridScreenTab; -import net.minecraft.client.gui.tab.Tab; -import net.minecraft.client.gui.tab.TabManager; -import net.minecraft.client.gui.tooltip.Tooltip; -import net.minecraft.client.gui.widget.*; +import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.Element; import net.minecraft.client.gui.Selectable; import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.tab.GridScreenTab; import net.minecraft.client.gui.tab.Tab; import net.minecraft.client.gui.tab.TabManager; +import net.minecraft.client.gui.tooltip.Tooltip; import net.minecraft.client.gui.widget.*; import net.minecraft.client.resource.language.I18n; import net.minecraft.registry.Registries; import net.minecraft.screen.ScreenTexts; -import net.minecraft.text.OrderedText; -import net.minecraft.text.Style; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; -import net.minecraft.util.Identifier; +import net.minecraft.text.OrderedText; import net.minecraft.text.Style; import net.minecraft.text.Text; +import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; import org.jetbrains.annotations.Nullable; -import javax.swing.*; -import javax.swing.filechooser.FileNameExtensionFilter; +import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; import java.awt.Color; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.lang.reflect.ParameterizedType; -import java.nio.file.Files; -import java.nio.file.Path; +import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; +import java.nio.file.Files; import java.nio.file.Path; import java.util.*; -import java.util.function.BiFunction; -import java.util.function.Function; -import java.util.function.Predicate; +import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.Predicate; import java.util.regex.Pattern; -/** MidnightConfig v2.6.0 by TeamMidnightDust & Motschen +/** MidnightConfig v2.6.0 by Martin "Motschen" Prokoph * Single class config library - feel free to copy! * Based on ... * Credits to Minenash */ @@ -64,35 +41,24 @@ public abstract class MidnightConfig { public static class EntryInfo { Field field; Class dataType; - Object function; - int width; + int width, listIndex; boolean centered; - Text error; - Object defaultValue; - Object value; - String tempValue; // The value visible in the config screen + Object defaultValue, value, function; + String modid, tempValue; // The value visible in the config screen boolean inLimits = true; - String modid; - Text name; - int index; + Text name, error; ClickableWidget actionButton; // color picker button / explorer button Tab tab; public void setValue(Object value) { - if (this.field.getType() != List.class) { - this.value = value; + if (this.field.getType() != List.class) { this.value = value; this.tempValue = value.toString(); - } else { - writeList(this.index, value); - this.tempValue = toTemporaryValue(); - } + } else { writeList(this.listIndex, value); + this.tempValue = toTemporaryValue(); } } public String toTemporaryValue() { if (this.field.getType() != List.class) return this.value.toString(); - else { - try { return ((List) this.value).get(this.index).toString(); - } catch (Exception ignored) {return "";} - } + else try { return ((List) this.value).get(this.listIndex).toString(); } catch (Exception ignored) {return "";} } public void writeList(int index, T value) { var list = (List) this.value; @@ -105,19 +71,15 @@ public abstract class MidnightConfig { private static Path path; private static final Gson gson = new GsonBuilder() - .excludeFieldsWithModifiers(Modifier.TRANSIENT) - .excludeFieldsWithModifiers(Modifier.PRIVATE) + .excludeFieldsWithModifiers(Modifier.TRANSIENT).excludeFieldsWithModifiers(Modifier.PRIVATE) .addSerializationExclusionStrategy(new HiddenAnnotationExclusionStrategy()) .registerTypeAdapter(Identifier.class, new Identifier.Serializer()) .setPrettyPrinting().create(); public static @Nullable Object getDefaultValue(String modid, String entry) { for (EntryInfo e : entries) { - if (modid.equals(e.modid) && entry.equals(e.field.getName())) { - return e.defaultValue; - } - } - return null; + if (modid.equals(e.modid) && entry.equals(e.field.getName())) return e.defaultValue; + } return null; } public static void init(String modid, Class config) { @@ -130,19 +92,17 @@ public abstract class MidnightConfig { initClient(modid, field, info); if (field.isAnnotationPresent(Comment.class)) info.centered = field.getAnnotation(Comment.class).centered(); if (field.isAnnotationPresent(Entry.class)) - try { - info.defaultValue = field.get(null); + try { info.defaultValue = field.get(null); } catch (IllegalAccessException ignored) {} } try { gson.fromJson(Files.newBufferedReader(path), config); } catch (Exception e) { write(modid); } for (EntryInfo info : entries) { - if (info.field.isAnnotationPresent(Entry.class)) - try { - info.value = info.field.get(null); - info.tempValue = info.toTemporaryValue(); - } catch (IllegalAccessException ignored) {} + if (info.field.isAnnotationPresent(Entry.class)) try { + info.value = info.field.get(null); + info.tempValue = info.toTemporaryValue(); + } catch (IllegalAccessException ignored) {} } } @Environment(EnvType.CLIENT) @@ -150,14 +110,11 @@ public abstract class MidnightConfig { info.dataType = field.getType(); Entry e = field.getAnnotation(Entry.class); info.width = e != null ? e.width() : 0; - info.field = field; - info.modid = modid; + 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; - } + } catch (NoSuchFieldException | IllegalAccessException ignored) { info.dataType = listType; } } if (e != null) { @@ -165,24 +122,20 @@ public abstract class MidnightConfig { if (info.dataType == int.class) textField(info, Integer::parseInt, INTEGER_ONLY, (int) e.min(), (int) e.max(), true); else if (info.dataType == float.class) textField(info, Float::parseFloat, DECIMAL_ONLY, (float) e.min(), (float) e.max(), false); else if (info.dataType == double.class) textField(info, Double::parseDouble, DECIMAL_ONLY, e.min(), e.max(), false); - else if (info.dataType == String.class || info.dataType == Identifier.class) - textField(info, String::length, null, Math.min(e.min(), 0), Math.max(e.max(), 1), true); + else if (info.dataType == String.class || info.dataType == Identifier.class) textField(info, String::length, null, Math.min(e.min(), 0), Math.max(e.max(), 1), true); else if (info.dataType == boolean.class) { Function func = value -> Text.translatable((Boolean) value ? "gui.yes" : "gui.no").formatted((Boolean) value ? Formatting.GREEN : Formatting.RED); info.function = new AbstractMap.SimpleEntry>(button -> { - info.setValue(!(Boolean) info.value); - button.setMessage(func.apply(info.value)); + info.setValue(!(Boolean) info.value); button.setMessage(func.apply(info.value)); }, func); } else if (info.dataType.isEnum()) { List values = Arrays.asList(field.getType().getEnumConstants()); Function func = value -> Text.translatable(modid + ".midnightconfig." + "enum." + info.dataType.getSimpleName() + "." + info.toTemporaryValue()); info.function = new AbstractMap.SimpleEntry>(button -> { int index = values.indexOf(info.value) + 1; - info.value = values.get(index >= values.size() ? 0 : index); - button.setMessage(func.apply(info.value)); + info.value = values.get(index >= values.size() ? 0 : index); button.setMessage(func.apply(info.value)); }, func); - } - } + }} entries.add(info); } public static Tooltip getTooltip(EntryInfo info) { @@ -197,9 +150,7 @@ public abstract class MidnightConfig { s = s.trim(); if (!(s.isEmpty() || !isNumber || pattern.matcher(s).matches())) return false; - Number value = 0; - boolean inLimits = false; - info.error = null; + Number value = 0; boolean inLimits = false; info.error = null; if (!(isNumber && s.isEmpty()) && !s.equals("-") && !s.equals(".")) { try { value = f.apply(s); } catch(NumberFormatException e){ return false; } inLimits = value.doubleValue() >= min && value.doubleValue() <= max; @@ -215,16 +166,14 @@ public abstract class MidnightConfig { b.active = entries.stream().allMatch(e -> e.inLimits); if (inLimits) { - if (info.dataType == Identifier.class) { - info.setValue(Identifier.tryParse(s)); - } else info.setValue(isNumber ? value : s); + if (info.dataType == Identifier.class) info.setValue(Identifier.tryParse(s)); + else info.setValue(isNumber ? value : s); } if (info.field.getAnnotation(Entry.class).isColor()) { if (!s.contains("#")) s = '#' + s; if (!HEXADECIMAL_ONLY.matcher(s).matches()) return false; - try { - info.actionButton.setMessage(Text.literal("⬛").setStyle(Style.EMPTY.withColor(Color.decode(info.tempValue).getRGB()))); + try { info.actionButton.setMessage(Text.literal("⬛").setStyle(Style.EMPTY.withColor(Color.decode(info.tempValue).getRGB()))); } catch (Exception ignored) {} } return true; @@ -233,18 +182,12 @@ public abstract class MidnightConfig { public static MidnightConfig getClass(String modid) { try { return configClass.get(modid).getDeclaredConstructor().newInstance(); } catch (Exception e) {throw new RuntimeException(e);} } - public static void write(String modid) { - getClass(modid).writeChanges(modid); - } + public static void write(String modid) { getClass(modid).writeChanges(modid); } public void writeChanges(String modid) { - path = PlatformFunctions.getConfigDirectory().resolve(modid + ".json"); - try { - if (!Files.exists(path)) Files.createFile(path); - Files.write(path, gson.toJson(getClass(modid)).getBytes()); - } catch (Exception e) { - e.fillInStackTrace(); - } + try { if (!Files.exists(path = PlatformFunctions.getConfigDirectory().resolve(modid + ".json"))) Files.createFile(path); + Files.write(path, gson.toJson(getClass(modid)).getBytes()); + } catch (Exception e) { e.fillInStackTrace(); } } @Environment(EnvType.CLIENT) public static Screen getScreen(Screen parent, String modid) { @@ -254,8 +197,7 @@ public abstract class MidnightConfig { public static class MidnightConfigScreen extends Screen { protected MidnightConfigScreen(Screen parent, String modid) { super(Text.translatable(modid + ".midnightconfig." + "title")); - this.parent = parent; - this.modid = modid; + this.parent = parent; this.modid = modid; this.translationPrefix = modid + ".midnightconfig."; loadValues(); @@ -277,9 +219,8 @@ public abstract class MidnightConfig { tabNavigation.init(); prevTab = tabManager.getCurrentTab(); } - public final String translationPrefix; + public final String translationPrefix, modid; public final Screen parent; - public final String modid; public MidnightConfigListWidget list; public TabManager tabManager = new TabManager(a -> {}, a -> {}); public Map tabs = new HashMap<>(); @@ -294,39 +235,29 @@ public abstract class MidnightConfig { super.tick(); if (prevTab != null && prevTab != tabManager.getCurrentTab()) { prevTab = tabManager.getCurrentTab(); - this.list.clear(); - fillList(); + this.list.clear(); fillList(); list.setScrollAmount(0); } scrollProgress = list.getScrollAmount(); - for (EntryInfo info : entries) { - try {info.field.set(null, info.value);} catch (IllegalAccessException ignored) {} - } + for (EntryInfo info : entries) try {info.field.set(null, info.value);} catch (IllegalAccessException ignored) {} updateButtons(); } public void updateButtons() { if (this.list != null) { for (ButtonEntry entry : this.list.children()) { - if (entry.buttons != null) { - if (entry.buttons.size() > 1 && entry.buttons.get(0) instanceof ClickableWidget widget && (widget.isFocused() || widget.isHovered())) { - widget.setTooltip(getTooltip(entry.info)); - } - if (entry.buttons.size() > 1 && entry.buttons.get(1) instanceof ButtonWidget button) { + if (entry.buttons != null && entry.buttons.size() > 1) { + if (entry.buttons.get(0) instanceof ClickableWidget widget) + if (widget.isFocused() || widget.isHovered()) widget.setTooltip(getTooltip(entry.info)); + if (entry.buttons.get(1) instanceof ButtonWidget button) button.active = !Objects.equals(entry.info.value.toString(), entry.info.defaultValue.toString()); - } - } - } - } - } + }}}} public void loadValues() { try { gson.fromJson(Files.newBufferedReader(path), configClass.get(modid)); } catch (Exception e) { write(modid); } for (EntryInfo info : entries) { if (info.field.isAnnotationPresent(Entry.class)) - try { - info.value = info.field.get(null); - info.tempValue = info.toTemporaryValue(); + try { info.value = info.field.get(null); info.tempValue = info.toTemporaryValue(); } catch (IllegalAccessException ignored) {} } } @@ -337,45 +268,29 @@ public abstract class MidnightConfig { } @Override public void close() { - loadValues(); - cleanup(); + loadValues(); cleanup(); Objects.requireNonNull(client).setScreen(parent); } private void cleanup() { entries.forEach(info -> { - info.error = null; - info.value = null; - info.tempValue = null; - info.actionButton = null; - info.index = 0; - info.tab = null; - info.inLimits = true; + info.error = null; info.value = null; info.tempValue = null; info.actionButton = null; info.listIndex = 0; info.tab = null; info.inLimits = true; }); } @Override public void init() { super.init(); - tabNavigation.setWidth(this.width); - tabNavigation.init(); + tabNavigation.setWidth(this.width); tabNavigation.init(); if (tabs.size() > 1) this.addDrawableChild(tabNavigation); this.addDrawableChild(ButtonWidget.builder(ScreenTexts.CANCEL, button -> this.close()).dimensions(this.width / 2 - 154, this.height - 26, 150, 20).build()); done = this.addDrawableChild(ButtonWidget.builder(ScreenTexts.DONE, (button) -> { - for (EntryInfo info : entries) - if (info.modid.equals(modid)) { - try { - info.field.set(null, info.value); - } catch (IllegalAccessException ignored) {} - } - write(modid); - cleanup(); + for (EntryInfo info : entries) if (info.modid.equals(modid)) try { info.field.set(null, info.value); } catch (IllegalAccessException ignored) {} + write(modid); cleanup(); Objects.requireNonNull(client).setScreen(parent); }).dimensions(this.width / 2 + 4, this.height - 26, 150, 20).build()); this.list = new MidnightConfigListWidget(this.client, this.width, this.height - 57, 24, 25); - this.addSelectableChild(this.list); - - fillList(); + this.addSelectableChild(this.list); fillList(); if (tabs.size() > 1) list.renderHeaderSeparator = false; } public void fillList() { @@ -383,11 +298,9 @@ public abstract class MidnightConfig { if (info.modid.equals(modid) && (info.tab == null || info.tab == tabManager.getCurrentTab())) { Text name = Objects.requireNonNullElseGet(info.name, () -> Text.translatable(translationPrefix + info.field.getName())); TextIconButtonWidget resetButton = TextIconButtonWidget.builder(Text.translatable("controls.reset"), (button -> { - info.value = info.defaultValue; + info.value = info.defaultValue; info.listIndex = 0; info.tempValue = info.toTemporaryValue(); - info.index = 0; - list.clear(); - fillList(); + list.clear(); fillList(); }), true).texture(Identifier.of("midnightlib","icon/reset"), 12, 12).dimension(20, 20).build(); resetButton.setPosition(width - 205 + 150 + 25, 0); @@ -403,12 +316,10 @@ public abstract class MidnightConfig { } else if (e.isSlider()) widget = new MidnightSliderWidget(width - 185, 0, 150, 20, Text.of(info.tempValue), (Double.parseDouble(info.tempValue) - e.min()) / (e.max() - e.min()), info); - else - widget = new MidnightTextFieldWidget(textRenderer, width - 185, 0, 150, 20, info); + else widget = new TextFieldWidget(textRenderer, width - 185, 0, 150, 20, Text.empty()); if (widget instanceof TextFieldWidget textField) { - textField.setMaxLength(info.width); - textField.setText(info.tempValue); + textField.setMaxLength(info.width); textField.setText(info.tempValue); Predicate processor = ((BiFunction>) info.function).apply(textField, done); textField.setTextPredicate(processor); } @@ -416,75 +327,59 @@ public abstract class MidnightConfig { ButtonWidget cycleButton = null; if (info.field.getType() == List.class) { - cycleButton = ButtonWidget.builder(Text.literal(String.valueOf(info.index)).formatted(Formatting.GOLD), (button -> { + cycleButton = ButtonWidget.builder(Text.literal(String.valueOf(info.listIndex)).formatted(Formatting.GOLD), (button -> { var values = (List) info.value; values.remove(""); - info.index = info.index + 1; - if (info.index > values.size()) info.index = 0; + info.listIndex = info.listIndex + 1; + if (info.listIndex > values.size()) info.listIndex = 0; info.tempValue = info.toTemporaryValue(); - if (info.index == values.size()) info.tempValue = ""; - list.clear(); - fillList(); + if (info.listIndex == values.size()) info.tempValue = ""; + list.clear(); fillList(); })).dimensions(width - 185, 0, 20, 20).build(); } if (e.isColor()) { - ButtonWidget colorButton = ButtonWidget.builder( - Text.literal("⬛"), - button -> new Thread(()-> { + ButtonWidget colorButton = ButtonWidget.builder(Text.literal("⬛"), + button -> new Thread(() -> { Color newColor = JColorChooser.showDialog(null, Text.translatable("midnightconfig.colorChooser.title").getString(), Color.decode(!Objects.equals(info.tempValue, "") ? info.tempValue : "#FFFFFF")); if (newColor != null) { info.setValue("#" + Integer.toHexString(newColor.getRGB()).substring(2)); - list.clear(); - fillList(); + list.clear(); fillList(); } }).start() ).dimensions(width - 185, 0, 20, 20).build(); - try { - colorButton.setMessage(Text.literal("⬛").setStyle(Style.EMPTY.withColor(Color.decode(info.tempValue).getRGB()))); + try { colorButton.setMessage(Text.literal("⬛").setStyle(Style.EMPTY.withColor(Color.decode(info.tempValue).getRGB()))); } catch (Exception ignored) {} info.actionButton = colorButton; } else if (e.selectionMode() > -1) { - ButtonWidget explorerButton = TextIconButtonWidget.builder( - Text.of(""), - button -> new Thread(()-> { + ButtonWidget explorerButton = TextIconButtonWidget.builder(Text.of(""), + button -> new Thread(() -> { JFileChooser fileChooser = new JFileChooser(); - fileChooser.setFileSelectionMode(e.selectionMode()); - fileChooser.setDialogType(e.fileChooserType()); - fileChooser.setDialogTitle(Text.translatable(translationPrefix + info.field.getName() + ".fileChooser.title").getString()); - if ((e.selectionMode() == JFileChooser.FILES_ONLY || e.selectionMode() == JFileChooser.FILES_AND_DIRECTORIES) && - Arrays.stream(e.fileExtensions()).noneMatch("*"::equals)) { + fileChooser.setFileSelectionMode(e.selectionMode()); fileChooser.setDialogType(e.fileChooserType()); + fileChooser.setDialogTitle(Text.translatable(translationPrefix + info.field.getName() + ".fileChooser").getString()); + if ((e.selectionMode() == JFileChooser.FILES_ONLY || e.selectionMode() == JFileChooser.FILES_AND_DIRECTORIES) && Arrays.stream(e.fileExtensions()).noneMatch("*"::equals)) fileChooser.setFileFilter(new FileNameExtensionFilter( - Text.translatable(translationPrefix + info.field.getName() + ".fileFilter.description").getString(), - e.fileExtensions())); - } + Text.translatable(translationPrefix + info.field.getName() + ".fileFilter").getString(), e.fileExtensions())); if (fileChooser.showDialog(null, null) == JFileChooser.APPROVE_OPTION) { info.setValue(fileChooser.getSelectedFile().getAbsolutePath()); - list.clear(); - fillList(); + list.clear(); fillList(); } - }).start(), - true + }).start(), true ).texture(Identifier.of("midnightlib", "icon/explorer"), 12, 12).dimension(20, 20).build(); explorerButton.setPosition(width - 185, 0); info.actionButton = explorerButton; } List widgets = Lists.newArrayList(widget, resetButton); if (info.actionButton != null) { - widget.setWidth(widget.getWidth() - 22); - widget.setX(widget.getX() + 22); + widget.setWidth(widget.getWidth() - 22); widget.setX(widget.getX() + 22); widgets.add(info.actionButton); } if (cycleButton != null) { if (info.actionButton != null) info.actionButton.setX(info.actionButton.getX() + 22); - widget.setWidth(widget.getWidth() - 22); - widget.setX(widget.getX() + 22); + widget.setWidth(widget.getWidth() - 22); widget.setX(widget.getX() + 22); widgets.add(cycleButton); } this.list.addButton(widgets, name, info); - } else { - this.list.addButton(List.of(), name, info); - } - } - list.setScrollAmount(scrollProgress); + } else this.list.addButton(List.of(), name, info); + } list.setScrollAmount(scrollProgress); updateButtons(); } } @@ -492,57 +387,48 @@ public abstract class MidnightConfig { public void render(DrawContext context, int mouseX, int mouseY, float delta) { super.render(context,mouseX,mouseY,delta); this.list.render(context, mouseX, mouseY, delta); + if (tabs.size() < 2) context.drawCenteredTextWithShadow(textRenderer, title, width / 2, 10, 0xFFFFFF); - if (tabs.size() < 2) - context.drawCenteredTextWithShadow(textRenderer, title, width / 2, 10, 0xFFFFFF); - } + if (this.list != null) { + for (ButtonEntry entry : this.list.children()) { + if (entry.buttons != null && entry.buttons.size() > 1) { + if (entry.buttons.getFirst() instanceof ClickableWidget widget) { + int idMode = entry.info.field.getAnnotation(Entry.class).idMode(); + if (idMode != -1) context.drawItem(idMode == 0 ? Registries.ITEM.get(Identifier.tryParse(entry.info.tempValue)).getDefaultStack() : Registries.BLOCK.get(Identifier.tryParse(entry.info.tempValue)).asItem().getDefaultStack(), widget.getX() + widget.getWidth() - 18, widget.getY() + 2); + }}}}} } @Environment(EnvType.CLIENT) public static class MidnightConfigListWidget extends ElementListWidget { boolean renderHeaderSeparator = true; - public MidnightConfigListWidget(MinecraftClient client, int width, int height, int y, int itemHeight) { - super(client, width, height, y, itemHeight); - } - @Override - public int getScrollbarX() { return this.width -7; } + public MidnightConfigListWidget(MinecraftClient client, int width, int height, int y, int itemHeight) { super(client, width, height, y, itemHeight); } + @Override public int getScrollbarX() { return this.width -7; } @Override protected void drawHeaderAndFooterSeparators(DrawContext context) { if (renderHeaderSeparator) super.drawHeaderAndFooterSeparators(context); - else { - RenderSystem.enableBlend(); + else { RenderSystem.enableBlend(); context.drawTexture(this.client.world == null ? Screen.FOOTER_SEPARATOR_TEXTURE : Screen.INWORLD_FOOTER_SEPARATOR_TEXTURE, this.getX(), this.getBottom(), 0.0F, 0.0F, this.getWidth(), 2, 32, 2); - RenderSystem.disableBlend(); - } - } - - public void addButton(List buttons, Text text, EntryInfo info) { - this.addEntry(new ButtonEntry(buttons, text, info)); + RenderSystem.disableBlend(); } } + public void addButton(List buttons, Text text, EntryInfo info) { this.addEntry(new ButtonEntry(buttons, text, info)); } public void clear() { this.clearEntries(); } - @Override - public int getRowWidth() { return 10000; } + @Override public int getRowWidth() { return 10000; } } public static class ButtonEntry extends ElementListWidget.Entry { private static final TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; - public final List buttons; private final Text text; + public final List buttons; public final EntryInfo info; public boolean centered = false; - public static final Map buttonsWithText = new HashMap<>(); public ButtonEntry(List buttons, Text text, EntryInfo info) { - if (!buttons.isEmpty()) buttonsWithText.put(buttons.getFirst(),text); - this.buttons = buttons; - this.text = text; - this.info = info; + this.buttons = buttons; this.text = text; this.info = info; if (info != null) this.centered = info.centered; } public void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { buttons.forEach(b -> { b.setY(y); b.render(context, mouseX, mouseY, tickDelta); }); - if (text != null && (!text.getString().contains("spacer") || !buttons.isEmpty())) { - int wrappedY = y; - for(Iterator textIterator = textRenderer.wrapLines(text, (buttons.size() > 1 ? buttons.get(1).getX()-24 : MinecraftClient.getInstance().getWindow().getScaledWidth() - 24)).iterator(); textIterator.hasNext(); wrappedY += 9) { + if (text != null && (!text.getString().contains("spacer") || !buttons.isEmpty())) { int wrappedY = y; + for (Iterator textIterator = textRenderer.wrapLines(text, (buttons.size() > 1 ? buttons.get(1).getX()-24 : MinecraftClient.getInstance().getWindow().getScaledWidth() - 24)).iterator(); textIterator.hasNext(); wrappedY += 9) { context.drawTextWithShadow(textRenderer, textIterator.next(), (centered) ? (MinecraftClient.getInstance().getWindow().getScaledWidth() / 2 - (textRenderer.getWidth(text) / 2)) : 12, wrappedY + 5, 0xFFFFFF); } } @@ -559,37 +445,19 @@ public abstract class MidnightConfig { } @Override - protected void updateMessage() { - this.setMessage(Text.of(info.tempValue)); - } + public void updateMessage() { this.setMessage(Text.of(info.tempValue)); } @Override - protected void applyValue() { + public void applyValue() { if (info.dataType == int.class) info.setValue(((Number) (e.min() + value * (e.max() - e.min()))).intValue()); else if (info.field.getType() == double.class) info.setValue(Math.round((e.min() + value * (e.max() - e.min())) * (double) e.precision()) / (double) e.precision()); else if (info.field.getType() == float.class) info.setValue(Math.round((e.min() + value * (e.max() - e.min())) * (float) e.precision()) / (float) e.precision()); } } - public static class MidnightTextFieldWidget extends TextFieldWidget { - private final EntryInfo info; - private final boolean isItem; - - public MidnightTextFieldWidget(TextRenderer textRenderer, int x, int y, int width, int height, EntryInfo info) { - super(textRenderer, x, y, width, height, Text.of(info.tempValue)); - this.info = info; - this.isItem = info.field.getAnnotation(Entry.class).isItem(); - } - - public void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) { - super.renderWidget(context, mouseX, mouseY, delta); - if (isItem) - context.drawItem(Registries.ITEM.get(Identifier.tryParse(info.tempValue)).getDefaultStack(), this.getX()+this.getWidth()-18, this.getY()+2); - } - } /** * Entry Annotation
- * - width: The maximum character length of the {@link String} or {@link List} field
+ * - width: The maximum character length of the {@link String}, {@link Identifier} or String/Identifier {@link List} field
* - min: The minimum value of the int, float or double field
* - max: The maximum value of the int, float or double field
* - name: The name of the field in the config screen
@@ -618,7 +486,7 @@ public abstract class MidnightConfig { int selectionMode() default -1; // -1 for none, 0 for file, 1 for directory, 2 for both int fileChooserType() default JFileChooser.OPEN_DIALOG; String[] fileExtensions() default {"*"}; - boolean isItem() default false; + int idMode() default -1; // -1 for none, 0 for item, 1 for block boolean isColor() default false; boolean isSlider() default false; int precision() default 100; @@ -635,8 +503,6 @@ public abstract class MidnightConfig { public static class HiddenAnnotationExclusionStrategy implements ExclusionStrategy { public boolean shouldSkipClass(Class clazz) { return false; } - public boolean shouldSkipField(FieldAttributes fieldAttributes) { - return fieldAttributes.getAnnotation(Entry.class) == null; - } + public boolean shouldSkipField(FieldAttributes fieldAttributes) { return fieldAttributes.getAnnotation(Entry.class) == null; } } } \ No newline at end of file diff --git a/common/src/main/java/eu/midnightdust/lib/util/MidnightColorUtil.java b/common/src/main/java/eu/midnightdust/lib/util/MidnightColorUtil.java index f858bc7..210ebc3 100755 --- a/common/src/main/java/eu/midnightdust/lib/util/MidnightColorUtil.java +++ b/common/src/main/java/eu/midnightdust/lib/util/MidnightColorUtil.java @@ -8,9 +8,7 @@ public class MidnightColorUtil { * @return Color as RGB */ public static Color hex2Rgb(String colorStr) { - try { - return Color.decode("#" + colorStr.replace("#", "")); - } catch (Exception ignored) {} - return Color.BLACK; + try { return Color.decode("#" + colorStr.replace("#", "")); + } catch (Exception ignored) { return Color.BLACK; } } } diff --git a/fabric-like/build.gradle b/fabric-like/build.gradle deleted file mode 100644 index eb27af5..0000000 --- a/fabric-like/build.gradle +++ /dev/null @@ -1,17 +0,0 @@ -architectury { - common(rootProject.enabled_platforms.split(",")) -} -repositories { - maven { url "https://maven.terraformersmc.com/releases" } -} - -loom { -} - -dependencies { - modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" - modApi "net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_api_version}" - modImplementation ("com.terraformersmc:modmenu:${rootProject.mod_menu_version}") - - compileOnly(project(path: ":common", configuration: "namedElements")) { transitive false } -} \ No newline at end of file diff --git a/fabric-like/src/main/java/eu/midnightdust/lib/config/AutoModMenu.java b/fabric-like/src/main/java/eu/midnightdust/lib/config/AutoModMenu.java deleted file mode 100755 index 72bcc21..0000000 --- a/fabric-like/src/main/java/eu/midnightdust/lib/config/AutoModMenu.java +++ /dev/null @@ -1,28 +0,0 @@ -package eu.midnightdust.lib.config; - -import com.terraformersmc.modmenu.api.ConfigScreenFactory; -import com.terraformersmc.modmenu.api.ModMenuApi; -import eu.midnightdust.core.MidnightLib; -import eu.midnightdust.core.config.MidnightLibConfig; - -import java.util.HashMap; -import java.util.Map; - -public class AutoModMenu implements ModMenuApi { - - @Override - public ConfigScreenFactory getModConfigScreenFactory() { - return parent -> MidnightLibConfig.getScreen(parent,"midnightlib"); - } - - @Override - public Map> getProvidedConfigScreenFactories() { - HashMap> map = new HashMap<>(); - MidnightConfig.configClass.forEach((modid, cClass) -> { - if (!MidnightLib.hiddenMods.contains(modid)) - map.put(modid, parent -> MidnightConfig.getScreen(parent, modid)); - } - ); - return map; - } -} \ No newline at end of file diff --git a/fabric/src/main/java/eu/midnightdust/lib/config/AutoModMenu.java b/fabric/src/main/java/eu/midnightdust/lib/config/AutoModMenu.java index 72bcc21..8f7ebd0 100755 --- a/fabric/src/main/java/eu/midnightdust/lib/config/AutoModMenu.java +++ b/fabric/src/main/java/eu/midnightdust/lib/config/AutoModMenu.java @@ -21,8 +21,6 @@ public class AutoModMenu implements ModMenuApi { MidnightConfig.configClass.forEach((modid, cClass) -> { if (!MidnightLib.hiddenMods.contains(modid)) map.put(modid, parent -> MidnightConfig.getScreen(parent, modid)); - } - ); - return map; + }); return map; } } \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index d64842c..d1592c9 100644 --- a/settings.gradle +++ b/settings.gradle @@ -8,7 +8,6 @@ pluginManagement { } include("common") -include("fabric-like") include("fabric") //include("quilt") include("neoforge") From 64d26e38b5dd2b95c668f464df0e3bb8041ad823 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Sun, 25 Aug 2024 12:52:37 +0200 Subject: [PATCH 026/100] Minify json files and images --- build.gradle | 11 +++++++++++ .../resources/assets/midnightlib/icon.png | Bin 2801 -> 2232 bytes .../textures/gui/sprites/icon/explorer.png | Bin 197 -> 136 bytes .../textures/gui/sprites/icon/midnightlib.png | Bin 189 -> 136 bytes .../textures/gui/sprites/icon/reset.png | Bin 178 -> 114 bytes fabric/src/main/resources/fabric.mod.json | 2 +- 6 files changed, 12 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index c2dac89..b2bf9d9 100644 --- a/build.gradle +++ b/build.gradle @@ -1,3 +1,6 @@ +import groovy.json.JsonSlurper +import groovy.json.JsonOutput + plugins { id "architectury-plugin" version "3.4-SNAPSHOT" id "dev.architectury.loom" version "1.6-SNAPSHOT" apply false @@ -58,6 +61,14 @@ allprojects { return changes.toString() } } + processResources { + // Minify json resources + doLast { + fileTree(dir: outputs.files.asPath, include: "**/*.json").each { + File file -> file.text = JsonOutput.toJson(new JsonSlurper().parse(file)) + } + } + } java { withSourcesJar() diff --git a/common/src/main/resources/assets/midnightlib/icon.png b/common/src/main/resources/assets/midnightlib/icon.png index d31b4c46823b2536b67007b68606f8b82c806a08..fee5d5676fb34e5df3197a910dede7e6d498ad90 100644 GIT binary patch delta 2199 zcmV;I2x#~56}S=f$u5!nb zjJw;~42|8kMyFPo+PUgzrK{$5Kb~_Ro{O5RbG^-*`F-&`=XuUK-|z4F{mwZ)_kVdj zzu3}ENg!D%N_D|mvbdgT;bf$|%21|OC|fzowV;;Gl}uW^^hi#CBSt!1nFzh60u^e5 zN>r*cm4h;BC0r>~0j=5eN~bsRSibvClMmumTB|n^tWcGzRjWGHs{zzgt5r2uchb6% zUaRQsV^sXHFygPsuY472iz; zo_kLvtJzR()HWS}{DjUR*QXK9XCt(9(c=U?_cLMxBeP*39Y5{fy~-k|>$Mf}p#I2x z4rmcZuWR%U>Hs6x!H_BMlH;HhbMFNz)gCoK7t)B9Vo&s$TGhblO)7vXU4JP{llLh{ zMchFR0llmt{RCrFJELo0DTFNp)}%#c-pJUsZB4zP^m+0rM$5TD9{caQ&=y-P&tNLzDpj7&m zs8*K*k;fot%I!Envwv<$1Yv2Rw4I`Dw=^98l;x&UEhIb;BO5opk#A?!T1Lw(A4_NhF5{!ZR2QSC8T1 zSl@SE+BzN$hC}xZ!}kMW0hA7@3{|f)1M;*Lhi@wq8gayJ1b;f8;()qGjnqivGa{g_ z*gjmfB@s~Tlp+>5AO{^!6zLnL2Agd~DTrd8nFUHBP6et^qn(T&pME)LIrd}lbQ@o(Gh~q>C-j>(Ys7S zMBq7RYNP~Wgnub<3O_cFStkV3+q-fcz-DA9LMVE5M_yaC>?|VM-AGe zZDZVKw-2!jQZ`B|;Yi?Nv}5Ji85E1eLbML7C+#2TB^qjbQC(pj$ikQ1YSEYa`%6PB zicSPLFbUPHul0?C(7j-PW52CGyc6sX_J_lblos#w-~1QHC_?v6ee0g}+;!`xzU}I5 ze9+kc@P7{FgPyzU1y-R&mBImc73{)+7`q~m{IV8~E;lcwMTuCR4(J=Z=$saJxAaCC zLUIiUcA=W-?gQI&M2|J-pnc3Z5E1q8kH&#fFJ*8nz-%v$Zbr?+lxiPi(c#por*^Zk zyJU%V03NR_LugbE|6|m)x%)tdR;f(2dQTS}oPWLT(W?`--hI_BH!tO{p0VXp+ND@* zh|k_;(U~P{mnWs(7-w1PH;+!=@vxKp8b^Io9XA|ylxk62J@|D>!KR0gNulivo1%#V3l4JI~z>r6QA;GnoSyA-^H3xrDP}@+N*QUTa))D5Y@INT^;eUg-BjkJd6XUdX?UVaa2jId1wqGfTG{*sVB^0Qf7<{Qj+83%86VUx_7#jmWp6$?KT~Mb!O8`1aK)tq- z|15j|^S_)5sKLC5ZChsWG8g$>T5n$2CC~SQB8@cU5uknQQX;Gi=28?g=f1pk_k%1I z(CGl-x}~uCmI-0lI$i~cIs8vB{v41BPoX>|! zRp>2P3dG$nPTpOTK73wH-ZpBJN~0*@Y$@2Fbz0+mL0YW5n+Pw%vT!3;uR)RvazJ(z ze!w}P#`!#OKjyi2za%G&8>tLWR|bD+_5-B@>JE}$h$M@6KieT@>3+6PwHCj8woZio Z4_qANfY17C4*&oF07*qoLQ%ov2&+-aJy%(|3lv1VMRVbU~4xvX}EtlZWNa?3SJqS~yIOPQg_ zZ6dcs#$6>s2_d(p5O&-dmwsoT{qMKG|Ms8X`99~I&w0P+^SAo%BIz^tyWPNUIeWMmo|8mgtp#TyV76x)l zOG`m;?AWpYA}J~=0!UO;6p#ZOfEHkgiHTve*$WE`2m~TEHMOUwCnF;xIXRh3CRbHe z6&4oe<>dhoqyYY*p&`IOH8oXRTl?zOtCW-!-~O>5s{KzfRBsX%Sjv*mJz5vJ)~=NQXJ`Ldv(je?!EkvZQ2ZPV+BKV<E?B0GbTi##1o2XaYn&}+3VR`)b%gp@x zf}x$Ir9b<&&8+=Hd+)8U?QHROJNc{gf{yW#-pN%S`|X>smY17LJJajq{X^RyKMZcq zjZTi%56mo1404x0bZmQa`CAi<{Pk(U+9&?%@Y>g%nRWh9%TU+yE`Md4|8&IXTekxQ z0)Irb!cm=C`qLeq6rE*b=>;=~{qdO()TN;K`(~fqu1bGys3m(1J<~9^J9aem^ZnZO*JcK1va@&V#*Jk>-qJ`) zp_PVz=t^ma=`_eSc`eG~p;_KsX-rlz?O|5y$LPR3d#|*u@Z=LSI>PDx0~U<@gcii> z%tuJO`_j=vEUE%F@g(sqE9fQS91~rg*pw!o9?{b$6{6H9n+4g<4kPw zl99J0()G5!nYz9}Fo|N0cStH`VRF4MOPbDL(lsj_>Mfn{AwR{_5LPqLCbmHQajBJL zwf(D}M0iL3_d-z;FqtQ$KvhqhMV;I;?F~|eD`E!aPn}eEOd_2b6ymH!?n$`Z9kg)r zCcZ@8kdcyy5;Y_#<5uiGP%WKee-!yTzvU8e-8|+ydVJjQN(1x5eFZ&sT@9u}FR_eh zPtV76yKSVvG3lz~Ss6u`Ig5LlGm4#GLW1^S$CFxC#3h@t@5Fat`X_rF_vG`lfAVpa zpdT_Bw&_}@2J6G*ed62C-4(0T_ev4#L*z){n*Z>YmXnbvGs7L2A|5k)k<`22Mp{C@ zkCi+T{HZcwpFCTeLBhppYs9uK@GVH&&BTOw5~aPvbP?8`eElvhgc=u)Pa`Eb2U&d2 zeXXW+h3UM2Epwr1yMCH`3j1R1dA|~MSJMd3J7t-Afm?HH-S_31E4u9ny7oH9Cbh(y zeb9gP-1p4**UwK5a3UV1dRSAH1}R*=MlKxU0?qVcPsou+tWp=b(8I8Il|89HuJ+hg zTK*>ER%a`FaFbYQELv$}S+s2Hf^hA|w-iHE>rnyZ)N}~hpNH6Bw5RMBNpJ2uN;JO6 zIM7&Un0?QIu)hlSN?5%~!2CRPTKI%7Yr?c~Zhhi&=V`GB{W{?r8GG%#n{Iy2fxc(W z8b>ii17YSPveiL4p3OPrF*?4>?Sl}aSSt^ju5<+ovk{WF7041FMIZMJwwLapm7jXwV%dyklz%FQ?qKAt+6(Xr6^>Tz-Ct@mj>$eqAEB7()VFKANcr^A^5Qj77$FQFJc30c&s7ihSVS0(5 z(WTh!|1lD+i>jh}pVK&o;Jq!edY*Z(E^FZ1$%^$Mp+wvB<@Uc@}NNvirsT5qH zr9dLr81j|8i9{%ib)IfCkbO}Dk(hgU30ViR9ccPO;3le$_e2zJzGHZ(-A?-X@Bv9a z%L4N$ER41HZ0?Cc!#}hYPwOVGiD+IpFSFb2?F;QReYP2^g?q;xN8f7S)Qi{{zqwc` zse-%cUm$toNR!*8^OppN46kKfINd6nU#Z)yxh|z(Tox5tIhE6U^t&1ll`fuc&8HkEdoL+%6~^lnYe+^ z%Bw3|3gbcK-)I|sfE=42%$felT4k`-X!7U65S=e!VX*f0eYVU-4$6O51QQMat?P_?@Xmm zdYWxHT=Zlgwp+Nf-%MSaO+i)lF=Lu56A(wk?^Ldj8a>fqx|an|L(Yd-QJ*L_cU&8G zI80wYl)0f)GGHl!ojC5%ip2#c{qEx%x{L?%DV`&wY^0@!`1K59(f#FZhlpG+%SRCZ;#IWw1%*%;(5>C3FE{-7;w~`h3|FARb94brb zU?||^;GNQ<-RQZ1ag%DoHKhjG04A+gu9Kfl7!0dDBr`)TO@YQRc)I$ztaD0e0sz+d B9yR~~ delta 159 zcmV;Q0AT-!0mT8386^e)0035XT;~7)00DDSM?wIu&K&6g000DMK}|sb0I`n?{9y%= zE*NiGNkl!P((rn%(7>^}vAer_ zV)IpFW@Z+_%*>oHT|GcLxO$LTaC#9C5fMFapsK3c_!wPubu%PruCWCG0000FMGaQgJI;f&b5c{v!bmT8u1Z0v$T6!MW^WP7|3{ zw-!%S@jEcHMb*GkV7Gw`gSZ>R+W!I`7cMghG1;$}z3*rq&=3YsS3j3^P6=1.20.4" + "minecraft": ">=1.21" }, "mixins": [ From 8039bf3fecb70dae52277104b8fc46871e4902c0 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Wed, 28 Aug 2024 11:38:35 +0200 Subject: [PATCH 027/100] Improved automatic command registration --- build.gradle | 2 +- .../eu/midnightdust/core/MidnightLib.java | 2 +- .../midnightdust/lib/config/AutoCommand.java | 147 ++++++++---------- .../lib/config/MidnightConfig.java | 2 +- gradle.properties | 2 +- 5 files changed, 67 insertions(+), 88 deletions(-) diff --git a/build.gradle b/build.gradle index b2bf9d9..98a36f7 100644 --- a/build.gradle +++ b/build.gradle @@ -50,7 +50,7 @@ allprojects { releaseChangelog = { def changes = new StringBuilder() changes << "## MidnightLib v$project.version for $project.minecraft_version\n[View the changelog](https://www.github.com/TeamMidnightDust/MidnightLib/commits/)" - def proc = "git log --max-count=1 --pretty=format:%s".execute() + def proc = "git log --max-count=10 --pretty=format:%s".execute() proc.in.eachLine { line -> def processedLine = line.toString() if (!processedLine.contains("New translations") && !processedLine.contains("Merge") && !processedLine.contains("branch")) { diff --git a/common/src/main/java/eu/midnightdust/core/MidnightLib.java b/common/src/main/java/eu/midnightdust/core/MidnightLib.java index 2999bc2..ba6ae79 100755 --- a/common/src/main/java/eu/midnightdust/core/MidnightLib.java +++ b/common/src/main/java/eu/midnightdust/core/MidnightLib.java @@ -29,7 +29,7 @@ public class MidnightLib { 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)) - new AutoCommand(field, modid).register(); + new AutoCommand(field, modid); } }); } 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 5598308..93df235 100644 --- a/common/src/main/java/eu/midnightdust/lib/config/AutoCommand.java +++ b/common/src/main/java/eu/midnightdust/lib/config/AutoCommand.java @@ -1,10 +1,8 @@ package eu.midnightdust.lib.config; -import com.mojang.brigadier.arguments.DoubleArgumentType; -import com.mojang.brigadier.arguments.FloatArgumentType; -import com.mojang.brigadier.arguments.IntegerArgumentType; -import com.mojang.brigadier.arguments.StringArgumentType; +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; import net.minecraft.server.command.ServerCommandSource; @@ -12,106 +10,87 @@ import net.minecraft.text.Text; import java.lang.reflect.Field; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; +import java.util.Objects; -@SuppressWarnings("unchecked") public class AutoCommand { public static List> commands = new ArrayList<>(); - final Field entry; + final static String VALUE = "value"; + final Field field; + final Class type; final String modid; + final boolean isList; - public AutoCommand(Field entry, String modid) { - this.entry = entry; + public AutoCommand(Field field, String modid) { + this.field = field; this.modid = modid; + this.type = field.getType(); + this.isList = field.getType() == List.class; + + LiteralArgumentBuilder command = CommandManager.literal("midnightconfig").requires(source -> source.hasPermissionLevel(2)).then( + CommandManager.literal(modid).then(CommandManager.literal(field.getName()).executes(this::getValue))); + + if (type.isEnum()) { + 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")) { + 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, ""))); + + PlatformFunctions.registerCommand(command); commands.add(command); } - public void register() { - LiteralArgumentBuilder command = CommandManager.literal(modid); - if (entry.getType() == int.class) - command = command.then(CommandManager.literal(this.entry.getName()).executes(ctx -> getValue(ctx.getSource())).then( - CommandManager.argument("value", IntegerArgumentType.integer((int) entry.getAnnotation(MidnightConfig.Entry.class).min(),(int) entry.getAnnotation(MidnightConfig.Entry.class).max())) - .executes(ctx -> this.setValue(ctx.getSource(), IntegerArgumentType.getInteger(ctx, "value"))) - )); - else if (entry.getType() == double.class) - command = command.then(CommandManager.literal(this.entry.getName()).executes(ctx -> getValue(ctx.getSource())).then( - CommandManager.argument("value", DoubleArgumentType.doubleArg(entry.getAnnotation(MidnightConfig.Entry.class).min(),entry.getAnnotation(MidnightConfig.Entry.class).max())) - .executes(ctx -> this.setValue(ctx.getSource(), DoubleArgumentType.getDouble(ctx, "value"))) - )); - else if (entry.getType() == float.class) - command = command.then(CommandManager.literal(this.entry.getName()).executes(ctx -> getValue(ctx.getSource())).then( - CommandManager.argument("value", FloatArgumentType.floatArg((float) entry.getAnnotation(MidnightConfig.Entry.class).min(), (float) entry.getAnnotation(MidnightConfig.Entry.class).max())) - .executes(ctx -> this.setValue(ctx.getSource(), FloatArgumentType.getFloat(ctx, "value"))) - )); - else if (entry.getType() == boolean.class) { - for (int i = 0; i < 2; i++) { - command = command.then(CommandManager.literal(this.entry.getName()).executes(ctx -> getValue(ctx.getSource())).then( - CommandManager.literal(i==0 ? "true":"false") - .executes(ctx -> this.setValue(ctx.getSource(), ctx.getInput().endsWith("true"))) - )); - } + public ArgumentType getArgType() { + MidnightConfig.Entry entry = type.getAnnotation(MidnightConfig.Entry.class); + if (type.isInstance(Number.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()); } - else if (entry.getType().isEnum()) { - for (int i = 0; i < entry.getType().getEnumConstants().length; ++i) { - Object enumValue = Arrays.stream(entry.getType().getEnumConstants()).toList().get(i); - command = command.then(CommandManager.literal(this.entry.getName()).executes(ctx -> getValue(ctx.getSource())).then( - CommandManager.literal(enumValue.toString()) - .executes(ctx -> this.setValue(ctx.getSource(), enumValue)) - )); - } - } - else if (entry.getType() == List.class) { - for (int i = 0; i < 2; i++) { - int finalI = i; - command = command.then(CommandManager.literal(this.entry.getName()).executes(ctx -> getValue(ctx.getSource())).then(CommandManager.literal(i==0 ? "add":"remove").then( - CommandManager.argument("value", StringArgumentType.string()) - .executes(ctx -> this.setList(ctx.getSource(), StringArgumentType.getString(ctx, "value"), finalI==0)) - ))); - } - } - else { - command = command.then(CommandManager.literal(this.entry.getName()).executes(ctx -> getValue(ctx.getSource())).then( - CommandManager.argument("value", StringArgumentType.string()) - .executes(ctx -> this.setValue(ctx.getSource(), StringArgumentType.getString(ctx, "value"))) - )); - } - LiteralArgumentBuilder finalized = CommandManager.literal("midnightconfig").requires(source -> source.hasPermissionLevel(2)).then(command); - - PlatformFunctions.registerCommand(finalized); commands.add(finalized); + else if (type == boolean.class) return BoolArgumentType.bool(); + return StringArgumentType.string(); } - private int setValue(ServerCommandSource source, Object value) { + public int setValueFromArg(CommandContext context, String action) { + if (type.isInstance(Number.class)) { + 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); + } + else if (type == boolean.class) return setValue(context.getSource(), BoolArgumentType.getBool(context, VALUE), action); + return setValue(context.getSource(), StringArgumentType.getString(context, VALUE), action); + } + private int setValue(ServerCommandSource source, Object value, String action) { + boolean add = Objects.equals(action, "add"); try { - if (entry.getType() != List.class) entry.set(null,value); + if (!isList) field.set(null, value); + else { + @SuppressWarnings("unchecked") var list = (List) field.get(null); + if (add) list.add(value); + else if (!list.contains(value)) throw new IllegalArgumentException("List does not contain this string!"); + else list.remove(value); + } MidnightConfig.write(modid); } catch (Exception e) { - source.sendError(Text.literal("Could not set "+entry.getName()+" to value "+value+": " + e)); + if (!isList) source.sendError(Text.literal("Could not set "+field.getName()+" to value "+value+": " + e)); + else source.sendError(Text.literal((add ? "Could not add "+value+" to " : "Could not remove "+value+" from ")+field.getName() +": " + e)); return 0; } - - source.sendFeedback(() -> Text.literal("Successfully set " + entry.getName()+" to "+value), true); + if (!isList) source.sendFeedback(() -> Text.literal("Successfully set " + field.getName()+" to "+value), true); + else source.sendFeedback(() -> Text.literal((add ? "Successfully added " +value+" to " : "Successfully removed " +value+" from ") +field.getName()), true); return 1; } - private int setList(ServerCommandSource source, String value, boolean add) { - try { - List e = (List)entry.get(null); - if (add) e.add(value); - else if (!e.contains(value)) throw new IllegalArgumentException("List does not contain this string!"); - else e.remove(value); - MidnightConfig.write(modid); - } - catch (Exception e) { - source.sendError(Text.literal((add ? "Could not add "+value+" to " : "Could not remove "+value+" from ")+entry.getName() +": " + e)); - return 0; - } - source.sendFeedback(() -> Text.literal((add ? "Successfully added " +value+" to " : "Successfully removed " +value+" from ") +entry.getName()), true); - return 1; - } - private int getValue(ServerCommandSource source) { - source.sendFeedback(() -> { - try {return Text.literal("The value of "+entry.getName()+" is "+entry.get(null)); + private int getValue(CommandContext context) { + context.getSource().sendFeedback(() -> { + try { return Text.literal("The value of "+field.getName()+" is "+field.get(null)); } catch (IllegalAccessException e) {throw new RuntimeException(e);} }, true); return 0; } -} +} \ No newline at end of file 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 da35c4c..76a18f8 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -351,7 +351,7 @@ public abstract class MidnightConfig { } catch (Exception ignored) {} info.actionButton = colorButton; } else if (e.selectionMode() > -1) { - ButtonWidget explorerButton = TextIconButtonWidget.builder(Text.of(""), + ButtonWidget explorerButton = TextIconButtonWidget.builder(Text.empty(), button -> new Thread(() -> { JFileChooser fileChooser = new JFileChooser(); fileChooser.setFileSelectionMode(e.selectionMode()); fileChooser.setDialogType(e.fileChooserType()); diff --git a/gradle.properties b/gradle.properties index 3b3a7b5..49f0784 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,7 +5,7 @@ yarn_mappings=1.21+build.1 enabled_platforms=fabric,neoforge archives_base_name=midnightlib -mod_version=1.6.0 +mod_version=1.6.1 maven_group=eu.midnightdust release_type=release curseforge_id=488090 From 545a845adda989c40cb25b0c36a4de86d3a91ce3 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Wed, 28 Aug 2024 12:28:51 +0200 Subject: [PATCH 028/100] Improved button injection --- .../eu/midnightdust/core/MidnightLib.java | 5 ++- .../core/config/MidnightLibConfig.java | 9 ++++- .../core/mixin/MixinOptionsScreen.java | 40 +++++++++---------- .../midnightdust/lib/config/AutoCommand.java | 3 +- 4 files changed, 32 insertions(+), 25 deletions(-) diff --git a/common/src/main/java/eu/midnightdust/core/MidnightLib.java b/common/src/main/java/eu/midnightdust/core/MidnightLib.java index ba6ae79..dd3561f 100755 --- a/common/src/main/java/eu/midnightdust/core/MidnightLib.java +++ b/common/src/main/java/eu/midnightdust/core/MidnightLib.java @@ -15,14 +15,15 @@ import java.util.List; public class MidnightLib { public static List hiddenMods = new ArrayList<>(); - public static final Logger LOGGER = LoggerFactory.getLogger("midnightlib"); + public static final String MOD_ID = "midnightlib"; + public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID); @Environment(EnvType.CLIENT) public static void onInitializeClient() { System.setProperty("java.awt.headless", "false"); try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception e) { LOGGER.error("Error setting system look and feel", e); } - MidnightLibConfig.init("midnightlib", MidnightLibConfig.class); + MidnightLibConfig.init(MOD_ID, MidnightLibConfig.class); } @Environment(EnvType.SERVER) public static void onInitializeServer() { diff --git a/common/src/main/java/eu/midnightdust/core/config/MidnightLibConfig.java b/common/src/main/java/eu/midnightdust/core/config/MidnightLibConfig.java index 393c1e3..8be89a8 100644 --- a/common/src/main/java/eu/midnightdust/core/config/MidnightLibConfig.java +++ b/common/src/main/java/eu/midnightdust/core/config/MidnightLibConfig.java @@ -6,10 +6,15 @@ import eu.midnightdust.lib.util.PlatformFunctions; import java.util.Objects; public class MidnightLibConfig extends MidnightConfig { - @Entry - public static ConfigButton config_screen_list = (PlatformFunctions.isModLoaded("modmenu") || Objects.equals(PlatformFunctions.getPlatformName(), "neoforge")) ? ConfigButton.MODMENU : ConfigButton.TRUE; + public static final boolean HAS_MODMENU = PlatformFunctions.isModLoaded("modmenu") || Objects.equals(PlatformFunctions.getPlatformName(), "neoforge"); + + @Entry public static ConfigButton config_screen_list = HAS_MODMENU ? ConfigButton.MODMENU : ConfigButton.TRUE; public enum ConfigButton { TRUE, FALSE, MODMENU } + + public static boolean shouldShowButton() { + return config_screen_list.equals(ConfigButton.TRUE) || (config_screen_list.equals(ConfigButton.MODMENU) && !HAS_MODMENU); + } } diff --git a/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java b/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java index 5fa9be6..3666193 100644 --- a/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java +++ b/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java @@ -1,9 +1,6 @@ package eu.midnightdust.core.mixin; -import eu.midnightdust.core.config.MidnightLibConfig; import eu.midnightdust.core.screen.MidnightConfigOverviewScreen; -import eu.midnightdust.lib.util.PlatformFunctions; -import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.option.OptionsScreen; import net.minecraft.client.gui.widget.TextIconButtonWidget; @@ -20,30 +17,33 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.util.Objects; -@Mixin(OptionsScreen.class) -public class MixinOptionsScreen extends Screen { - @Shadow @Final private ThreePartsLayoutWidget layout; - @Unique TextIconButtonWidget button = TextIconButtonWidget.builder(Text.translatable("midnightlib.overview.title"), ( - buttonWidget) -> Objects.requireNonNull(client).setScreen(new MidnightConfigOverviewScreen(this)), true) - .texture(Identifier.of("midnightlib","icon/midnightlib"), 16, 16).dimension(20, 20).build(); - @Unique boolean shouldShowButton = MidnightLibConfig.config_screen_list.equals(MidnightLibConfig.ConfigButton.TRUE) || (MidnightLibConfig.config_screen_list.equals(MidnightLibConfig.ConfigButton.MODMENU) && !PlatformFunctions.isModLoaded("modmenu") && PlatformFunctions.getPlatformName() != "neoforge"); +import static eu.midnightdust.core.MidnightLib.MOD_ID; +import static eu.midnightdust.core.config.MidnightLibConfig.shouldShowButton; + +@Mixin(OptionsScreen.class) +public abstract class MixinOptionsScreen extends Screen { + @Shadow @Final private ThreePartsLayoutWidget layout; + @Unique TextIconButtonWidget midnightlib$button = TextIconButtonWidget.builder(Text.translatable("midnightlib.overview.title"), ( + buttonWidget) -> Objects.requireNonNull(client).setScreen(new MidnightConfigOverviewScreen(this)), true) + .texture(Identifier.of(MOD_ID,"icon/"+MOD_ID), 16, 16).dimension(20, 20).build(); + + private MixinOptionsScreen(Text title) {super(title);} - protected MixinOptionsScreen(Text title) {super(title);} @Inject(at = @At("HEAD"), method = "init") public void midnightlib$onInit(CallbackInfo ci) { - if (shouldShowButton) { - this.midnightlib$setupButton(); - this.addDrawableChild(button); + if (shouldShowButton()) { + this.midnightlib$setButtonPos(); + this.addDrawableChild(midnightlib$button); } } - @Override - public void resize(MinecraftClient client, int width, int height) { - super.resize(client, width, height); - if (shouldShowButton) this.midnightlib$setupButton(); + @Inject(at = @At("TAIL"), method = "initTabNavigation") + public void midnightlib$onResize(CallbackInfo ci) { + if (shouldShowButton()) this.midnightlib$setButtonPos(); } + @Unique - public void midnightlib$setupButton() { - button.setPosition(layout.getWidth() / 2 + 158, layout.getY() + layout.getFooterHeight() - 4); + public void midnightlib$setButtonPos() { + midnightlib$button.setPosition(layout.getWidth() / 2 + 158, layout.getY() + layout.getFooterHeight() - 4); } } \ 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 93df235..45c8d4f 100644 --- a/common/src/main/java/eu/midnightdust/lib/config/AutoCommand.java +++ b/common/src/main/java/eu/midnightdust/lib/config/AutoCommand.java @@ -15,6 +15,7 @@ import java.util.Objects; 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; @@ -27,7 +28,7 @@ public class AutoCommand { this.type = field.getType(); this.isList = field.getType() == List.class; - LiteralArgumentBuilder command = CommandManager.literal("midnightconfig").requires(source -> source.hasPermissionLevel(2)).then( + LiteralArgumentBuilder command = CommandManager.literal(BASE).requires(source -> source.hasPermissionLevel(2)).then( CommandManager.literal(modid).then(CommandManager.literal(field.getName()).executes(this::getValue))); if (type.isEnum()) { From db32a41e2b7a5c608512c6bbdb230b3d0078d7ba Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Thu, 29 Aug 2024 13:38:38 +0200 Subject: [PATCH 029/100] 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" + } +} From 48390abf8fd696d40dc5dee3bebd73f31cc25d90 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Thu, 29 Aug 2024 13:43:34 +0200 Subject: [PATCH 030/100] Open path from last location - Also some gradle treats :) --- .../main/java/eu/midnightdust/lib/config/MidnightConfig.java | 2 +- fabric/build.gradle | 4 ++-- gradle.properties | 1 + neoforge/build.gradle | 4 ++-- 4 files changed, 6 insertions(+), 5 deletions(-) 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 0144f41..08e8cff 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -355,7 +355,7 @@ public abstract class MidnightConfig { } else if (e.selectionMode() > -1) { ButtonWidget explorerButton = TextIconButtonWidget.builder(Text.empty(), button -> new Thread(() -> { - JFileChooser fileChooser = new JFileChooser(); + JFileChooser fileChooser = new JFileChooser(info.tempValue); fileChooser.setFileSelectionMode(e.selectionMode()); fileChooser.setDialogType(e.fileChooserType()); fileChooser.setDialogTitle(Text.translatable(translationPrefix + info.field.getName() + ".fileChooser").getString()); if ((e.selectionMode() == JFileChooser.FILES_ONLY || e.selectionMode() == JFileChooser.FILES_AND_DIRECTORIES) && Arrays.stream(e.fileExtensions()).noneMatch("*"::equals)) diff --git a/fabric/build.gradle b/fabric/build.gradle index 932970e..910a32c 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -84,7 +84,7 @@ unifiedPublishing { curseforge { token = CURSEFORGE_TOKEN id = rootProject.curseforge_id - gameVersions.addAll "Java 21", project.minecraft_version + gameVersions.addAll "Java 21", project.minecraft_version, project.supported_versions } } @@ -94,7 +94,7 @@ unifiedPublishing { token = MODRINTH_TOKEN id = rootProject.modrinth_id version = "$project.version-$project.name" - gameVersions.addAll project.minecraft_version + gameVersions.addAll project.minecraft_version, project.supported_versions } } } diff --git a/gradle.properties b/gradle.properties index 49f0784..5786f2d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,7 @@ org.gradle.jvmargs=-Xmx4096M minecraft_version=1.21 +supported_versions=1.21.1 yarn_mappings=1.21+build.1 enabled_platforms=fabric,neoforge diff --git a/neoforge/build.gradle b/neoforge/build.gradle index ebedf83..e460f57 100644 --- a/neoforge/build.gradle +++ b/neoforge/build.gradle @@ -87,7 +87,7 @@ unifiedPublishing { curseforge { token = CURSEFORGE_TOKEN id = rootProject.curseforge_id - gameVersions.addAll "Java 21", project.minecraft_version + gameVersions.addAll "Java 21", project.minecraft_version, project.supported_versions } } @@ -97,7 +97,7 @@ unifiedPublishing { token = MODRINTH_TOKEN id = rootProject.modrinth_id version = "$project.version-$project.name" - gameVersions.addAll project.minecraft_version + gameVersions.addAll project.minecraft_version, project.supported_versions } } } From b8a54e339a4e63a0c687f11a3b1e1d0ba65f0bdb Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Mon, 2 Sep 2024 23:47:58 +0200 Subject: [PATCH 031/100] Run command registration after main method - Fixes commands being missing for certain mods - Possibly fix #67 --- build.gradle | 2 +- .../java/eu/midnightdust/core/MidnightLib.java | 8 +++++--- .../fabric/core/MidnightLibFabric.java | 14 +++++++------- fabric/src/main/resources/fabric.mod.json | 2 +- gradle.properties | 2 +- .../midnightdust/neoforge/MidnightLibNeoForge.java | 6 +++--- 6 files changed, 18 insertions(+), 16 deletions(-) diff --git a/build.gradle b/build.gradle index 98a36f7..b2bf9d9 100644 --- a/build.gradle +++ b/build.gradle @@ -50,7 +50,7 @@ allprojects { releaseChangelog = { def changes = new StringBuilder() changes << "## MidnightLib v$project.version for $project.minecraft_version\n[View the changelog](https://www.github.com/TeamMidnightDust/MidnightLib/commits/)" - def proc = "git log --max-count=10 --pretty=format:%s".execute() + def proc = "git log --max-count=1 --pretty=format:%s".execute() proc.in.eachLine { line -> def processedLine = line.toString() if (!processedLine.contains("New translations") && !processedLine.contains("Merge") && !processedLine.contains("branch")) { diff --git a/common/src/main/java/eu/midnightdust/core/MidnightLib.java b/common/src/main/java/eu/midnightdust/core/MidnightLib.java index c338573..e3601b4 100755 --- a/common/src/main/java/eu/midnightdust/core/MidnightLib.java +++ b/common/src/main/java/eu/midnightdust/core/MidnightLib.java @@ -13,6 +13,8 @@ import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; +import static net.minecraft.client.MinecraftClient.IS_SYSTEM_MAC; + public class MidnightLib { public static List hiddenMods = new ArrayList<>(); public static final String MOD_ID = "midnightlib"; @@ -20,12 +22,12 @@ public class MidnightLib { @Environment(EnvType.CLIENT) public static void onInitializeClient() { - System.setProperty("java.awt.headless", "false"); - try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + try { System.setProperty("java.awt.headless", "false"); + if (!IS_SYSTEM_MAC) UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception e) { LOGGER.error("Error setting system look and feel", e); } MidnightLibConfig.init(MOD_ID, MidnightLibConfig.class); } - public static void onInitialize() { + public static void registerAutoCommand() { 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/fabric/src/main/java/eu/midnightdust/fabric/core/MidnightLibFabric.java b/fabric/src/main/java/eu/midnightdust/fabric/core/MidnightLibFabric.java index 272a107..2538458 100644 --- a/fabric/src/main/java/eu/midnightdust/fabric/core/MidnightLibFabric.java +++ b/fabric/src/main/java/eu/midnightdust/fabric/core/MidnightLibFabric.java @@ -1,14 +1,14 @@ package eu.midnightdust.fabric.core; import eu.midnightdust.core.MidnightLib; -import net.fabricmc.api.ClientModInitializer; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.api.ModInitializer; +import net.fabricmc.api.*; -public class MidnightLibFabric implements ModInitializer, ClientModInitializer { +public class MidnightLibFabric implements DedicatedServerModInitializer, ClientModInitializer { @Override @Environment(EnvType.CLIENT) - public void onInitializeClient() {MidnightLib.onInitializeClient();} + public void onInitializeClient() { + MidnightLib.onInitializeClient(); + MidnightLib.registerAutoCommand(); + } @Override - public void onInitialize() {MidnightLib.onInitialize();} + public void onInitializeServer() {MidnightLib.registerAutoCommand();} } diff --git a/fabric/src/main/resources/fabric.mod.json b/fabric/src/main/resources/fabric.mod.json index 3b33107..ea1ee35 100644 --- a/fabric/src/main/resources/fabric.mod.json +++ b/fabric/src/main/resources/fabric.mod.json @@ -29,7 +29,7 @@ "environment": "*", "entrypoints": { - "main": [ + "server": [ "eu.midnightdust.fabric.core.MidnightLibFabric" ], "client": [ diff --git a/gradle.properties b/gradle.properties index 5786f2d..d3b6ba2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ yarn_mappings=1.21+build.1 enabled_platforms=fabric,neoforge archives_base_name=midnightlib -mod_version=1.6.1 +mod_version=1.6.2 maven_group=eu.midnightdust release_type=release curseforge_id=488090 diff --git a/neoforge/src/main/java/eu/midnightdust/neoforge/MidnightLibNeoForge.java b/neoforge/src/main/java/eu/midnightdust/neoforge/MidnightLibNeoForge.java index 26d7e4b..1d640a3 100644 --- a/neoforge/src/main/java/eu/midnightdust/neoforge/MidnightLibNeoForge.java +++ b/neoforge/src/main/java/eu/midnightdust/neoforge/MidnightLibNeoForge.java @@ -24,7 +24,7 @@ public class MidnightLibNeoForge { public MidnightLibNeoForge() { if (FMLEnvironment.dist == Dist.CLIENT) MidnightLib.onInitializeClient(); - MidnightLib.onInitialize(); + MidnightLib.registerAutoCommand(); } @EventBusSubscriber(modid = "midnightlib", bus = EventBusSubscriber.Bus.MOD, value = Dist.CLIENT) @@ -39,8 +39,8 @@ public class MidnightLibNeoForge { } } - @EventBusSubscriber(modid = "midnightlib", value = Dist.DEDICATED_SERVER) - public static class MidnightLibServerEvents { + @EventBusSubscriber(modid = "midnightlib") + public static class MidnightLibEvents { @SubscribeEvent public static void registerCommands(RegisterCommandsEvent event) { commands.forEach(command -> event.getDispatcher().register(command)); From 765ad60d0b5a8dc595fd3170a9c25bfa4fc82a4e Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Fri, 6 Sep 2024 12:00:06 +0200 Subject: [PATCH 032/100] Fix crash on MacOS since v1.6.0 - Closes #67 - Temporarily disabled function popups on MacOS until a solution without non-headless java mode is found - Also exposed a couple of fields for an upcoming Puzzle update --- common/src/main/java/eu/midnightdust/core/MidnightLib.java | 7 ++++--- .../java/eu/midnightdust/lib/config/MidnightConfig.java | 7 +++++-- gradle.properties | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/common/src/main/java/eu/midnightdust/core/MidnightLib.java b/common/src/main/java/eu/midnightdust/core/MidnightLib.java index e3601b4..99986cc 100755 --- a/common/src/main/java/eu/midnightdust/core/MidnightLib.java +++ b/common/src/main/java/eu/midnightdust/core/MidnightLib.java @@ -22,9 +22,10 @@ public class MidnightLib { @Environment(EnvType.CLIENT) public static void onInitializeClient() { - try { System.setProperty("java.awt.headless", "false"); - if (!IS_SYSTEM_MAC) UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - } catch (Exception e) { LOGGER.error("Error setting system look and feel", e); } + try { if (!IS_SYSTEM_MAC) { + System.setProperty("java.awt.headless", "false"); + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + }} catch (Exception e) { LOGGER.error("Error setting system look and feel", e); } MidnightLibConfig.init(MOD_ID, MidnightLibConfig.class); } public static void registerAutoCommand() { 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 08e8cff..041702d 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -25,6 +25,8 @@ import java.util.*; import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.Predicate; import java.util.regex.Pattern; +import static net.minecraft.client.MinecraftClient.IS_SYSTEM_MAC; + /** MidnightConfig v2.6.0 by Martin "Motschen" Prokoph * Single class config library - feel free to copy! * Based on ... @@ -372,6 +374,7 @@ public abstract class MidnightConfig { } List widgets = Lists.newArrayList(widget, resetButton); if (info.actionButton != null) { + if (IS_SYSTEM_MAC) info.actionButton.active = false; widget.setWidth(widget.getWidth() - 22); widget.setX(widget.getX() + 22); widgets.add(info.actionButton); } if (cycleButton != null) { @@ -401,7 +404,7 @@ public abstract class MidnightConfig { } @Environment(EnvType.CLIENT) public static class MidnightConfigListWidget extends ElementListWidget { - boolean renderHeaderSeparator = true; + public boolean renderHeaderSeparator = true; public MidnightConfigListWidget(MinecraftClient client, int width, int height, int y, int itemHeight) { super(client, width, height, y, itemHeight); } @Override public int getScrollbarX() { return this.width -7; } @@ -418,7 +421,7 @@ public abstract class MidnightConfig { } public static class ButtonEntry extends ElementListWidget.Entry { private static final TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; - private final Text text; + public final Text text; public final List buttons; public final EntryInfo info; public boolean centered = false; diff --git a/gradle.properties b/gradle.properties index d3b6ba2..16ef449 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ yarn_mappings=1.21+build.1 enabled_platforms=fabric,neoforge archives_base_name=midnightlib -mod_version=1.6.2 +mod_version=1.6.3 maven_group=eu.midnightdust release_type=release curseforge_id=488090 From 07e6049fa03fd5edd03548e6d7aeb41172e0f6d1 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Fri, 11 Oct 2024 00:08:45 +0200 Subject: [PATCH 033/100] Allow Entries to be conditionally shown - Define a required mod using `requiredMod = "modid"` in entries & comments --- .../eu/midnightdust/lib/config/MidnightConfig.java | 14 +++++++++++--- fabric/build.gradle | 9 +++++---- neoforge/build.gradle | 10 ++++++---- .../midnightdust/neoforge/MidnightLibNeoForge.java | 9 ++++++--- 4 files changed, 28 insertions(+), 14 deletions(-) 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 041702d..5d292f3 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -92,7 +92,6 @@ public abstract class MidnightConfig { EntryInfo info = new EntryInfo(); if ((field.isAnnotationPresent(Entry.class) || field.isAnnotationPresent(Comment.class)) && !field.isAnnotationPresent(Server.class) && !field.isAnnotationPresent(Hidden.class) && PlatformFunctions.isClientEnv()) initClient(modid, field, info); - if (field.isAnnotationPresent(Comment.class)) info.centered = field.getAnnotation(Comment.class).centered(); if (field.isAnnotationPresent(Entry.class)) try { info.defaultValue = field.get(null); } catch (IllegalAccessException ignored) {} @@ -111,10 +110,14 @@ public abstract class MidnightConfig { private static void initClient(String modid, Field field, EntryInfo info) { info.dataType = getUnderlyingType(field); Entry e = field.getAnnotation(Entry.class); + Comment c = field.getAnnotation(Comment.class); info.width = e != null ? e.width() : 0; info.field = field; info.modid = modid; + boolean requiredModLoaded = true; if (e != null) { + if (!e.requiredMod().isEmpty()) requiredModLoaded = PlatformFunctions.isModLoaded(e.requiredMod()); + if (!requiredModLoaded) return; if (!e.name().isEmpty()) info.name = Text.translatable(e.name()); if (info.dataType == int.class) textField(info, Integer::parseInt, INTEGER_ONLY, (int) e.min(), (int) e.max(), true); else if (info.dataType == float.class) textField(info, Float::parseFloat, DECIMAL_ONLY, (float) e.min(), (float) e.max(), false); @@ -132,8 +135,11 @@ public abstract class MidnightConfig { int index = values.indexOf(info.value) + 1; info.value = values.get(index >= values.size() ? 0 : index); button.setMessage(func.apply(info.value)); }, func); - }} - entries.add(info); + }} else if (c != null) { + if (!c.requiredMod().isEmpty()) requiredModLoaded = PlatformFunctions.isModLoaded(c.requiredMod()); + info.centered = c.centered(); + } + if (requiredModLoaded) entries.add(info); } public static Class getUnderlyingType(Field field) { if (field.getType() == List.class) { @@ -496,6 +502,7 @@ public abstract class MidnightConfig { boolean isSlider() default false; int precision() default 100; String category() default "default"; + String requiredMod() default ""; } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Client {} @@ -504,6 +511,7 @@ public abstract class MidnightConfig { @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Comment { boolean centered() default false; String category() default "default"; + String requiredMod() default ""; } public static class HiddenAnnotationExclusionStrategy implements ExclusionStrategy { diff --git a/fabric/build.gradle b/fabric/build.gradle index 910a32c..0c276e6 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -21,6 +21,7 @@ configurations { runtimeClasspath.extendsFrom common developmentFabric.extendsFrom common archivesBaseName = rootProject.archives_base_name + "-fabric" + version = rootProject.mod_version + "+" + rootProject.minecraft_version } dependencies { @@ -33,10 +34,10 @@ dependencies { } processResources { - inputs.property "version", project.version + inputs.property "version", rootProject.version filesMatching("fabric.mod.json") { - expand "version": project.version + expand "version": rootProject.version } } @@ -66,7 +67,7 @@ components.java { unifiedPublishing { project { - displayName = "MidnightLib $project.version - Fabric $project.minecraft_version" + displayName = "MidnightLib $rootProject.version - Fabric $project.minecraft_version" releaseType = "$project.release_type" changelog = releaseChangelog() gameVersions = [] @@ -93,7 +94,7 @@ unifiedPublishing { modrinth { token = MODRINTH_TOKEN id = rootProject.modrinth_id - version = "$project.version-$project.name" + version = "$rootProject.version-$project.name" gameVersions.addAll project.minecraft_version, project.supported_versions } } diff --git a/neoforge/build.gradle b/neoforge/build.gradle index e460f57..651b713 100644 --- a/neoforge/build.gradle +++ b/neoforge/build.gradle @@ -35,6 +35,8 @@ configurations { canBeResolved = true canBeConsumed = false } + archivesBaseName = rootProject.archives_base_name + "-neoforge" + version = rootProject.mod_version + "+" + rootProject.minecraft_version } dependencies { @@ -45,10 +47,10 @@ dependencies { } processResources { - inputs.property 'version', project.version + inputs.property 'version', rootProject.version filesMatching('META-INF/neoforge.mods.toml') { - expand version: project.version + expand version: rootProject.version } } @@ -75,7 +77,7 @@ components.java { unifiedPublishing { project { - displayName = "MidnightLib $project.version - NeoForge $project.minecraft_version" + displayName = "MidnightLib $rootProject.version - NeoForge $project.minecraft_version" releaseType = "$project.release_type" changelog = releaseChangelog() gameVersions = [] @@ -96,7 +98,7 @@ unifiedPublishing { modrinth { token = MODRINTH_TOKEN id = rootProject.modrinth_id - version = "$project.version-$project.name" + version = "$rootProject.version-$project.name" gameVersions.addAll project.minecraft_version, project.supported_versions } } diff --git a/neoforge/src/main/java/eu/midnightdust/neoforge/MidnightLibNeoForge.java b/neoforge/src/main/java/eu/midnightdust/neoforge/MidnightLibNeoForge.java index 1d640a3..91cb9ca 100644 --- a/neoforge/src/main/java/eu/midnightdust/neoforge/MidnightLibNeoForge.java +++ b/neoforge/src/main/java/eu/midnightdust/neoforge/MidnightLibNeoForge.java @@ -2,7 +2,6 @@ package eu.midnightdust.neoforge; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import eu.midnightdust.core.MidnightLib; -import eu.midnightdust.lib.config.AutoCommand; import eu.midnightdust.lib.config.MidnightConfig; import net.minecraft.server.command.ServerCommandSource; import net.neoforged.api.distmarker.Dist; @@ -16,6 +15,7 @@ import net.neoforged.neoforge.client.gui.IConfigScreenFactory; import net.neoforged.neoforge.event.RegisterCommandsEvent; import java.util.ArrayList; +import java.util.ConcurrentModificationException; import java.util.List; @Mod("midnightlib") @@ -32,7 +32,7 @@ public class MidnightLibNeoForge { @SubscribeEvent public static void onPostInit(FMLClientSetupEvent event) { ModList.get().forEachModContainer((modid, modContainer) -> { - if (MidnightConfig.configClass.containsKey(modid)) { + if (MidnightConfig.configClass.containsKey(modid) && !MidnightLib.hiddenMods.contains(modid)) { modContainer.registerExtensionPoint(IConfigScreenFactory.class, (minecraftClient, screen) -> MidnightConfig.getScreen(screen, modid)); } }); @@ -43,7 +43,10 @@ public class MidnightLibNeoForge { public static class MidnightLibEvents { @SubscribeEvent public static void registerCommands(RegisterCommandsEvent event) { - commands.forEach(command -> event.getDispatcher().register(command)); + try { + commands.forEach(command -> event.getDispatcher().register(command)); + } + catch (ConcurrentModificationException ignored) {} } } } From 18209609cbbda12189bd6987d8112f9c34bac021 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Tue, 29 Oct 2024 22:14:54 +0100 Subject: [PATCH 034/100] MidnightLib 1.6.4 (Port to 1.21.2/3) - Forgot to push this earlier, oops --- build.gradle | 2 +- .../core/mixin/MixinOptionsScreen.java | 2 +- .../eu/midnightdust/lib/config/MidnightConfig.java | 3 ++- gradle.properties | 14 +++++++------- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/build.gradle b/build.gradle index b2bf9d9..43297f8 100644 --- a/build.gradle +++ b/build.gradle @@ -3,7 +3,7 @@ import groovy.json.JsonOutput plugins { id "architectury-plugin" version "3.4-SNAPSHOT" - id "dev.architectury.loom" version "1.6-SNAPSHOT" apply false + id "dev.architectury.loom" version "1.7-SNAPSHOT" apply false id "me.shedaniel.unified-publishing" version "0.1.+" apply false id 'com.github.johnrengelman.shadow' version '8.1.1' apply false } diff --git a/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java b/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java index 3666193..13203b7 100644 --- a/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java +++ b/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java @@ -37,7 +37,7 @@ public abstract class MixinOptionsScreen extends Screen { } } - @Inject(at = @At("TAIL"), method = "initTabNavigation") + @Inject(at = @At("TAIL"), method = "refreshWidgetPositions") public void midnightlib$onResize(CallbackInfo ci) { if (shouldShowButton()) this.midnightlib$setButtonPos(); } 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 5d292f3..d0fb21b 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -9,6 +9,7 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.Te import net.minecraft.client.gui.Element; import net.minecraft.client.gui.Selectable; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.tab.GridScreenTab; import net.minecraft.client.gui.tab.Tab; import net.minecraft.client.gui.tab.TabManager; import net.minecraft.client.gui.tooltip.Tooltip; import net.minecraft.client.gui.widget.*; +import net.minecraft.client.render.RenderLayer; import net.minecraft.client.resource.language.I18n; import net.minecraft.registry.Registries; import net.minecraft.screen.ScreenTexts; @@ -418,7 +419,7 @@ public abstract class MidnightConfig { protected void drawHeaderAndFooterSeparators(DrawContext context) { if (renderHeaderSeparator) super.drawHeaderAndFooterSeparators(context); else { RenderSystem.enableBlend(); - context.drawTexture(this.client.world == null ? Screen.FOOTER_SEPARATOR_TEXTURE : Screen.INWORLD_FOOTER_SEPARATOR_TEXTURE, this.getX(), this.getBottom(), 0.0F, 0.0F, this.getWidth(), 2, 32, 2); + context.drawTexture(RenderLayer::getGuiTextured, this.client.world == null ? Screen.FOOTER_SEPARATOR_TEXTURE : Screen.INWORLD_FOOTER_SEPARATOR_TEXTURE, this.getX(), this.getBottom(), 0.0F, 0.0F, this.getWidth(), 2, 32, 2); RenderSystem.disableBlend(); } } public void addButton(List buttons, Text text, EntryInfo info) { this.addEntry(new ButtonEntry(buttons, text, info)); } diff --git a/gradle.properties b/gradle.properties index 16ef449..d8695d0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,21 +1,21 @@ org.gradle.jvmargs=-Xmx4096M -minecraft_version=1.21 -supported_versions=1.21.1 -yarn_mappings=1.21+build.1 +minecraft_version=1.21.3 +supported_versions=1.21.2 +yarn_mappings=1.21.3+build.2 enabled_platforms=fabric,neoforge archives_base_name=midnightlib -mod_version=1.6.3 +mod_version=1.6.4 maven_group=eu.midnightdust release_type=release curseforge_id=488090 modrinth_id=codAaoxh -fabric_loader_version=0.15.11 -fabric_api_version=0.100.1+1.21 +fabric_loader_version=0.16.7 +fabric_api_version=0.106.1+1.21.3 -neoforge_version=21.0.143 +neoforge_version=21.3.3-beta yarn_mappings_patch_neoforge_version = 1.21+build.4 quilt_loader_version=0.19.0-beta.18 From b4c4454ba8babfe52eb8c74528d5130530ecbb35 Mon Sep 17 00:00:00 2001 From: Number_Sir <52584526+NumberSir@users.noreply.github.com> Date: Thu, 14 Nov 2024 19:34:43 +0800 Subject: [PATCH 035/100] Update zh_cn.json --- .../resources/assets/midnightlib/lang/zh_cn.json | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/common/src/main/resources/assets/midnightlib/lang/zh_cn.json b/common/src/main/resources/assets/midnightlib/lang/zh_cn.json index 8ca70b6..6ac0bd2 100644 --- a/common/src/main/resources/assets/midnightlib/lang/zh_cn.json +++ b/common/src/main/resources/assets/midnightlib/lang/zh_cn.json @@ -1,11 +1,15 @@ { "midnightlib.overview.title":"MidnightConfig 概述", - "midnightlib.midnightconfig.title":"MidnightLib 设定", - "midnightlib.midnightconfig.config_screen_list":"启用设定画面列表", + "midnightlib.midnightconfig.title":"MidnightLib 配置", + "midnightlib.midnightconfig.config_screen_list":"启用配置屏幕列表", "midnightlib.midnightconfig.enum.ConfigButton.TRUE":"§a是", "midnightlib.midnightconfig.enum.ConfigButton.FALSE":"§c否", - "midnightlib.midnightconfig.enum.ConfigButton.MODMENU":"§b模組菜单", - "midnightlib.wiki":"维基", - "modmenu.descriptionTranslation.midnightlib": "MidnightDust 团队的常用库模组。 n提供设定 API、与其他模块自动整合、常用工具和美观。", - "modmenu.summaryTranslation.midnightlib": "MidnightDust 团队的常用库模组。" + "midnightlib.midnightconfig.enum.ConfigButton.MODMENU":"§b模组菜单", + "midnightlib.modrinth":"Modrinth", + "midnightlib.curseforge":"CurseForge", + "midnightlib.wiki":"Wiki", + "modmenu.descriptionTranslation.midnightlib": "本模组是一个便于模组配置的通用库模组。\n提供了一个配置接口,能够自动与其他模组兼容,还提供了一些通用功能。", + "modmenu.summaryTranslation.midnightlib": "一个便于模组配置的通用库模组", + + "midnightconfig.colorChooser.title": "选择一种颜色" } From a2c0a8afb039d4183094fcc8c0f4db1181ed5dae Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Tue, 3 Dec 2024 11:44:06 +0100 Subject: [PATCH 036/100] Update to 1.21.4 Neoforge will follow as soon as it's released --- .../eu/midnightdust/lib/config/MidnightConfig.java | 6 +++--- gradle.properties | 14 +++++++------- settings.gradle | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) 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 d0fb21b..131176e 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -247,9 +247,9 @@ public abstract class MidnightConfig { if (prevTab != null && prevTab != tabManager.getCurrentTab()) { prevTab = tabManager.getCurrentTab(); this.list.clear(); fillList(); - list.setScrollAmount(0); + list.setScrollY(0); } - scrollProgress = list.getScrollAmount(); + scrollProgress = list.getScrollY(); for (EntryInfo info : entries) try {info.field.set(null, info.value);} catch (IllegalAccessException ignored) {} updateButtons(); } @@ -391,7 +391,7 @@ public abstract class MidnightConfig { } this.list.addButton(widgets, name, info); } else this.list.addButton(List.of(), name, info); - } list.setScrollAmount(scrollProgress); + } list.setScrollY(scrollProgress); updateButtons(); } } diff --git a/gradle.properties b/gradle.properties index d8695d0..d2de749 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,19 +1,19 @@ org.gradle.jvmargs=-Xmx4096M -minecraft_version=1.21.3 -supported_versions=1.21.2 -yarn_mappings=1.21.3+build.2 -enabled_platforms=fabric,neoforge +minecraft_version=1.21.4-rc3 +supported_versions= +yarn_mappings=1.21.4-rc3+build.4 +enabled_platforms=fabric archives_base_name=midnightlib -mod_version=1.6.4 +mod_version=1.6.5 maven_group=eu.midnightdust release_type=release curseforge_id=488090 modrinth_id=codAaoxh -fabric_loader_version=0.16.7 -fabric_api_version=0.106.1+1.21.3 +fabric_loader_version=0.16.9 +fabric_api_version=0.110.5+1.21.4 neoforge_version=21.3.3-beta yarn_mappings_patch_neoforge_version = 1.21+build.4 diff --git a/settings.gradle b/settings.gradle index 6f5c32b..310a10d 100644 --- a/settings.gradle +++ b/settings.gradle @@ -10,8 +10,8 @@ pluginManagement { include("common") include("fabric") include("test-fabric") -include("neoforge") -include("test-neoforge") +//include("neoforge") +//include("test-neoforge") //include("quilt") rootProject.name = "midnightlib" From 56bbb8bac6e5c02e9e966b9fb580249a7bd5cd24 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Wed, 4 Dec 2024 20:46:12 +0100 Subject: [PATCH 037/100] Update to final 1.21.4 release --- fabric/build.gradle | 6 ++++-- gradle.properties | 10 +++++----- neoforge/build.gradle | 6 ++++-- settings.gradle | 4 ++-- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/fabric/build.gradle b/fabric/build.gradle index 0c276e6..7bdc94e 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -85,7 +85,8 @@ unifiedPublishing { curseforge { token = CURSEFORGE_TOKEN id = rootProject.curseforge_id - gameVersions.addAll "Java 21", project.minecraft_version, project.supported_versions + gameVersions.addAll "Java 21", project.minecraft_version + if (project.supported_versions != "") gameVersions.addAll project.supported_versions } } @@ -95,7 +96,8 @@ unifiedPublishing { token = MODRINTH_TOKEN id = rootProject.modrinth_id version = "$rootProject.version-$project.name" - gameVersions.addAll project.minecraft_version, project.supported_versions + gameVersions.addAll project.minecraft_version + if (project.supported_versions != "") gameVersions.addAll project.supported_versions } } } diff --git a/gradle.properties b/gradle.properties index d2de749..a4b1085 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,12 +1,12 @@ org.gradle.jvmargs=-Xmx4096M -minecraft_version=1.21.4-rc3 +minecraft_version=1.21.4 supported_versions= -yarn_mappings=1.21.4-rc3+build.4 -enabled_platforms=fabric +yarn_mappings=1.21.4+build.1 +enabled_platforms=fabric,neoforge archives_base_name=midnightlib -mod_version=1.6.5 +mod_version=1.6.6 maven_group=eu.midnightdust release_type=release curseforge_id=488090 @@ -15,7 +15,7 @@ modrinth_id=codAaoxh fabric_loader_version=0.16.9 fabric_api_version=0.110.5+1.21.4 -neoforge_version=21.3.3-beta +neoforge_version=21.4.3-beta yarn_mappings_patch_neoforge_version = 1.21+build.4 quilt_loader_version=0.19.0-beta.18 diff --git a/neoforge/build.gradle b/neoforge/build.gradle index 651b713..30e3c8b 100644 --- a/neoforge/build.gradle +++ b/neoforge/build.gradle @@ -89,7 +89,8 @@ unifiedPublishing { curseforge { token = CURSEFORGE_TOKEN id = rootProject.curseforge_id - gameVersions.addAll "Java 21", project.minecraft_version, project.supported_versions + gameVersions.addAll "Java 21", project.minecraft_version + if (project.supported_versions != "") gameVersions.addAll project.supported_versions } } @@ -99,7 +100,8 @@ unifiedPublishing { token = MODRINTH_TOKEN id = rootProject.modrinth_id version = "$rootProject.version-$project.name" - gameVersions.addAll project.minecraft_version, project.supported_versions + gameVersions.addAll project.minecraft_version + if (project.supported_versions != "") gameVersions.addAll project.supported_versions } } } diff --git a/settings.gradle b/settings.gradle index 310a10d..6f5c32b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -10,8 +10,8 @@ pluginManagement { include("common") include("fabric") include("test-fabric") -//include("neoforge") -//include("test-neoforge") +include("neoforge") +include("test-neoforge") //include("quilt") rootProject.name = "midnightlib" From a90cb02b2fbf1ce754bb65cea01d2fff40812131 Mon Sep 17 00:00:00 2001 From: NuruTheDoomer Date: Thu, 5 Dec 2024 15:26:52 +0800 Subject: [PATCH 038/100] Add Malay and Malay (Jawi) translations --- .../resources/assets/midnightlib/lang/ms_my.json | 13 +++++++++++++ .../resources/assets/midnightlib/lang/zlm_arab.json | 13 +++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 common/src/main/resources/assets/midnightlib/lang/ms_my.json create mode 100644 common/src/main/resources/assets/midnightlib/lang/zlm_arab.json diff --git a/common/src/main/resources/assets/midnightlib/lang/ms_my.json b/common/src/main/resources/assets/midnightlib/lang/ms_my.json new file mode 100644 index 0000000..a2b0533 --- /dev/null +++ b/common/src/main/resources/assets/midnightlib/lang/ms_my.json @@ -0,0 +1,13 @@ +{ + "midnightlib.overview.title": "Ikhtisar MidnightConfig", + "midnightlib.midnightconfig.title": "Konfigurasi MidnightLib", + "midnightlib.midnightconfig.config_screen_list": "Dayakan Senarai Skrin Konfigurasi", + "midnightlib.midnightconfig.enum.ConfigButton.TRUE": "§aYa", + "midnightlib.midnightconfig.enum.ConfigButton.FALSE": "§cTidak", + "midnightlib.midnightconfig.enum.ConfigButton.MODMENU": "§bModMenu", + "midnightlib.modrinth": "Modrinth", + "midnightlib.curseforge": "CurseForge", + "midnightlib.wiki": "Wiki", + "modmenu.descriptionTranslation.midnightlib": "Pustaka Biasa untuk konfigurasi mudah.\nMenyediakan API konfigurasi, integrasi automatik dengan mod lain dan utiliti biasa.", + "modmenu.summaryTranslation.midnightlib": "Pustaka Biasa untuk konfigurasi mudah." +} \ No newline at end of file diff --git a/common/src/main/resources/assets/midnightlib/lang/zlm_arab.json b/common/src/main/resources/assets/midnightlib/lang/zlm_arab.json new file mode 100644 index 0000000..8538914 --- /dev/null +++ b/common/src/main/resources/assets/midnightlib/lang/zlm_arab.json @@ -0,0 +1,13 @@ +{ + "midnightlib.overview.title": "اختصار MidnightConfig", + "midnightlib.midnightconfig.title": "کونفيݢوراسي MidnightLib", + "midnightlib.midnightconfig.config_screen_list": "داياکن سناراي سکرين کونفيݢوراسي", + "midnightlib.midnightconfig.enum.ConfigButton.TRUE": "§aيا", + "midnightlib.midnightconfig.enum.ConfigButton.FALSE": "§cتيدق", + "midnightlib.midnightconfig.enum.ConfigButton.MODMENU": "§bModMenu", + "midnightlib.modrinth": "Modrinth", + "midnightlib.curseforge": "CurseForge", + "midnightlib.wiki": "ويکي", + "modmenu.descriptionTranslation.midnightlib": "ڤوستاک بياسا اونتوق کونفيݢوراسي موده.\nمڽدياکن API کونفيݢوراسي⹁ اينتݢراسي اٴوتوماتيک دڠن مود لاٴين دان اوتيليتي بياسا.", + "modmenu.summaryTranslation.midnightlib": "ڤوستاک بياسا اونتوق کونفيݢوراسي موده." +} \ No newline at end of file From 7cdd7cdc73f9e7bda1ff86f0628a47ac26e4ebc0 Mon Sep 17 00:00:00 2001 From: maloryware Date: Tue, 31 Dec 2024 18:56:47 +0000 Subject: [PATCH 039/100] Entry Title rendered as MultilineTextWidget Added tooltip functionality for Entry Title --- .../lib/config/MidnightConfig.java | 60 +++++++++++++++++-- 1 file changed, 54 insertions(+), 6 deletions(-) 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 131176e..73f4f8e 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -33,6 +33,12 @@ import static net.minecraft.client.MinecraftClient.IS_SYSTEM_MAC; * Based on ... * Credits to Minenash */ +// hi mots! + // TODO: + // define identifier for fetching the title tooltip text from lang + // fetch title tooltip from entry info? + // refactor at will :p + @SuppressWarnings("unchecked") public abstract class MidnightConfig { private static final Pattern INTEGER_ONLY = Pattern.compile("(-?[0-9]*)"); @@ -79,6 +85,7 @@ public abstract class MidnightConfig { .registerTypeAdapter(Identifier.class, new Identifier.Serializer()) .setPrettyPrinting().create(); + @SuppressWarnings("unused") // shhhhhh... public static @Nullable Object getDefaultValue(String modid, String entry) { for (EntryInfo e : entries) { if (modid.equals(e.modid) && entry.equals(e.field.getName())) return e.defaultValue; @@ -107,6 +114,7 @@ public abstract class MidnightConfig { } catch (IllegalAccessException ignored) {} } } + @SuppressWarnings("ConstantValue") //pertains to requiredModLoaded @Environment(EnvType.CLIENT) private static void initClient(String modid, Field field, EntryInfo info) { info.dataType = getUnderlyingType(field); @@ -118,6 +126,7 @@ public abstract class MidnightConfig { if (e != null) { if (!e.requiredMod().isEmpty()) requiredModLoaded = PlatformFunctions.isModLoaded(e.requiredMod()); + if (!requiredModLoaded) return; if (!e.name().isEmpty()) info.name = Text.translatable(e.name()); if (info.dataType == int.class) textField(info, Integer::parseInt, INTEGER_ONLY, (int) e.min(), (int) e.max(), true); @@ -155,6 +164,7 @@ public abstract class MidnightConfig { } // TODO: Maybe move this into the screen class itself to free up some RAM? + private static void textField(EntryInfo info, Function f, Pattern pattern, double min, double max, boolean cast) { boolean isNumber = pattern != null; info.function = (BiFunction>) (t, b) -> s -> { @@ -412,7 +422,7 @@ public abstract class MidnightConfig { @Environment(EnvType.CLIENT) public static class MidnightConfigListWidget extends ElementListWidget { public boolean renderHeaderSeparator = true; - public MidnightConfigListWidget(MinecraftClient client, int width, int height, int y, int itemHeight) { super(client, width, height, y, itemHeight); } + public MidnightConfigListWidget(MinecraftClient client, int width, int height, int y, int itemHeight) { super(client, width, height, y, itemHeight); } @Override public int getScrollbarX() { return this.width -7; } @Override @@ -432,18 +442,56 @@ public abstract class MidnightConfig { public final List buttons; public final EntryInfo info; public boolean centered = false; + public final Text tooltipText; + public final TextWidget entryText; + public MultilineTextWidget title; + private final List tooltipLines; public ButtonEntry(List buttons, Text text, EntryInfo info) { this.buttons = buttons; this.text = text; this.info = info; + this.entryText = text != null ? new TextWidget(text, textRenderer) : null; if (info != null) this.centered = info.centered; + + this.tooltipText = Text.of("A very neat, original, thought out, yet badly worded tooltip, leading to uncomfortably long text."); + this.tooltipLines = textRenderer.wrapLines(tooltipText, MinecraftClient.getInstance().getWindow().getScaledWidth() / 2); + + // moved text declaration to constructor + if (text != null && (!text.getString().contains("spacer") || !buttons.isEmpty())) { + //int wrappedY = y; + title = new MultilineTextWidget( + (centered) // x + ? (MinecraftClient.getInstance().getWindow().getScaledWidth() / 2 - (textRenderer.getWidth(text) / 2)) + : 12, + 0, // will be set on render + Text.of(text), + textRenderer + ); + + title.setTooltip(Tooltip.of(Text.of("Test!"))); + title.setMaxWidth(buttons.size() > 1 + ? buttons.get(1).getX() - 24 + : MinecraftClient.getInstance().getWindow().getScaledWidth() - 24); + } } public void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { - buttons.forEach(b -> { b.setY(y); b.render(context, mouseX, mouseY, tickDelta); }); - if (text != null && (!text.getString().contains("spacer") || !buttons.isEmpty())) { int wrappedY = y; - for (Iterator textIterator = textRenderer.wrapLines(text, (buttons.size() > 1 ? buttons.get(1).getX()-24 : MinecraftClient.getInstance().getWindow().getScaledWidth() - 24)).iterator(); textIterator.hasNext(); wrappedY += 9) { - context.drawTextWithShadow(textRenderer, textIterator.next(), (centered) ? (MinecraftClient.getInstance().getWindow().getScaledWidth() / 2 - (textRenderer.getWidth(text) / 2)) : 12, wrappedY + 5, 0xFFFFFF); + buttons.forEach(b -> { b.setY(y); b.render(context, mouseX, mouseY, tickDelta);}); + + if(title != null) { + + title.setY(y + 9); + + title.render(context, mouseX, mouseY, tickDelta); + + + // isHovered and isMouseOver didn't work! sad! + if(mouseX >= title.getX() && mouseX < title.getWidth() + title.getX() + && mouseY >= title.getY() && mouseY < title.getHeight() + title.getY()) + context.drawOrderedTooltip(textRenderer, tooltipLines, mouseX, mouseY); + + // testing purposes + // else context.drawTooltip(textRenderer, Text.of(String.format("%s, %s", mouseX, mouseY)), mouseX, mouseY); } - } + } public List children() {return Lists.newArrayList(buttons);} public List selectableChildren() {return Lists.newArrayList(buttons);} From 00e080e7155e910d8e48845f7b5b1df43cbdf9ad Mon Sep 17 00:00:00 2001 From: maloryware Date: Tue, 31 Dec 2024 18:57:42 +0000 Subject: [PATCH 040/100] bunp. --- .../main/java/eu/midnightdust/lib/config/MidnightConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 73f4f8e..f65bebf 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -489,7 +489,7 @@ public abstract class MidnightConfig { context.drawOrderedTooltip(textRenderer, tooltipLines, mouseX, mouseY); // testing purposes - // else context.drawTooltip(textRenderer, Text.of(String.format("%s, %s", mouseX, mouseY)), mouseX, mouseY); + /* else context.drawTooltip(textRenderer, Text.of(String.format("%s, %s", mouseX, mouseY)), mouseX, mouseY); */ } } From 803607259ee662415a862d1c51aff3ff6de77902 Mon Sep 17 00:00:00 2001 From: maloryware Date: Tue, 31 Dec 2024 20:11:04 +0000 Subject: [PATCH 041/100] added javadocs for Server and Hidden annotations. --- .../eu/midnightdust/lib/config/MidnightConfig.java | 10 ++++++++++ 1 file changed, 10 insertions(+) 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 f65bebf..70cc323 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -555,7 +555,17 @@ public abstract class MidnightConfig { } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Client {} + + /** + * Hides the entry on singleplayer/client-side. + * Accessible through{@code /midnightconfig MOD_ID ENTRY} and through directly editing the config file. + */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Server {} + + /** + * Hides the entry entirely. + * Accessible only through directly editing the config file. + */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Hidden {} @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Comment { boolean centered() default false; From a32593ede0a71bd1ce3a69cc23877f05405b9eff Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Tue, 14 Jan 2025 10:27:35 +0100 Subject: [PATCH 042/100] feat: improve label tooltip code - Users can now define labels for text via this translation key pattern: "modid.midnightconfig.optionName.label.tooltip" --- .../lib/config/MidnightConfig.java | 59 ++++++------------- .../modid/{en_US.json => lang/en_us.json} | 1 + 2 files changed, 20 insertions(+), 40 deletions(-) rename test-fabric/src/main/resources/assets/modid/{en_US.json => lang/en_us.json} (94%) 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 70cc323..c1b2a78 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -13,7 +13,7 @@ import net.minecraft.client.render.RenderLayer; import net.minecraft.client.resource.language.I18n; import net.minecraft.registry.Registries; import net.minecraft.screen.ScreenTexts; -import net.minecraft.text.OrderedText; import net.minecraft.text.Style; import net.minecraft.text.Text; +import net.minecraft.text.Style; import net.minecraft.text.Text; import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; import org.jetbrains.annotations.Nullable; @@ -33,12 +33,6 @@ import static net.minecraft.client.MinecraftClient.IS_SYSTEM_MAC; * Based on ... * Credits to Minenash */ -// hi mots! - // TODO: - // define identifier for fetching the title tooltip text from lang - // fetch title tooltip from entry info? - // refactor at will :p - @SuppressWarnings("unchecked") public abstract class MidnightConfig { private static final Pattern INTEGER_ONLY = Pattern.compile("(-?[0-9]*)"); @@ -158,9 +152,9 @@ public abstract class MidnightConfig { } 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()); + public static Tooltip getTooltip(EntryInfo info, boolean isButton) { + String key = info.modid + ".midnightconfig."+info.field.getName()+(!isButton ? ".label" : "" )+".tooltip"; + return Tooltip.of(isButton && info.error != null ? info.error : I18n.hasTranslation(key) ? Text.translatable(key) : Text.empty()); } // TODO: Maybe move this into the screen class itself to free up some RAM? @@ -178,7 +172,7 @@ public abstract class MidnightConfig { info.error = inLimits? null : Text.literal(value.doubleValue() < min ? "§cMinimum " + (isNumber? "value" : "length") + (cast? " is " + (int)min : " is " + min) : "§cMaximum " + (isNumber? "value" : "length") + (cast? " is " + (int)max : " is " + max)).formatted(Formatting.RED); - t.setTooltip(getTooltip(info)); + t.setTooltip(getTooltip(info, true)); } info.tempValue = s; @@ -268,7 +262,7 @@ public abstract class MidnightConfig { for (ButtonEntry entry : this.list.children()) { if (entry.buttons != null && entry.buttons.size() > 1) { if (entry.buttons.get(0) instanceof ClickableWidget widget) - if (widget.isFocused() || widget.isHovered()) widget.setTooltip(getTooltip(entry.info)); + if (widget.isFocused() || widget.isHovered()) widget.setTooltip(getTooltip(entry.info, true)); if (entry.buttons.get(1) instanceof ButtonWidget button) button.active = !Objects.equals(entry.info.value.toString(), entry.info.defaultValue.toString()); }}}} @@ -333,7 +327,7 @@ public abstract class MidnightConfig { var values = (Map.Entry>) info.function; if (info.dataType.isEnum()) values.setValue(value -> Text.translatable(translationPrefix + "enum." + info.field.getType().getSimpleName() + "." + info.value.toString())); - widget = ButtonWidget.builder(values.getValue().apply(info.value), values.getKey()).dimensions(width - 185, 0, 150, 20).tooltip(getTooltip(info)).build(); + widget = ButtonWidget.builder(values.getValue().apply(info.value), values.getKey()).dimensions(width - 185, 0, 150, 20).tooltip(getTooltip(info, true)).build(); } else if (e.isSlider()) widget = new MidnightSliderWidget(width - 185, 0, 150, 20, Text.of(info.tempValue), (Double.parseDouble(info.tempValue) - e.min()) / (e.max() - e.min()), info); @@ -344,7 +338,7 @@ public abstract class MidnightConfig { Predicate processor = ((BiFunction>) info.function).apply(textField, done); textField.setTextPredicate(processor); } - widget.setTooltip(getTooltip(info)); + widget.setTooltip(getTooltip(info, true)); ButtonWidget cycleButton = null; if (info.field.getType() == List.class) { @@ -442,54 +436,39 @@ public abstract class MidnightConfig { public final List buttons; public final EntryInfo info; public boolean centered = false; - public final Text tooltipText; - public final TextWidget entryText; public MultilineTextWidget title; - private final List tooltipLines; public ButtonEntry(List buttons, Text text, EntryInfo info) { this.buttons = buttons; this.text = text; this.info = info; - this.entryText = text != null ? new TextWidget(text, textRenderer) : null; if (info != null) this.centered = info.centered; - - this.tooltipText = Text.of("A very neat, original, thought out, yet badly worded tooltip, leading to uncomfortably long text."); - this.tooltipLines = textRenderer.wrapLines(tooltipText, MinecraftClient.getInstance().getWindow().getScaledWidth() / 2); + int scaledWidth = MinecraftClient.getInstance().getWindow().getScaledWidth(); // moved text declaration to constructor if (text != null && (!text.getString().contains("spacer") || !buttons.isEmpty())) { - //int wrappedY = y; title = new MultilineTextWidget( (centered) // x - ? (MinecraftClient.getInstance().getWindow().getScaledWidth() / 2 - (textRenderer.getWidth(text) / 2)) + ? (scaledWidth / 2 - (textRenderer.getWidth(text) / 2)) : 12, 0, // will be set on render - Text.of(text), - textRenderer + Text.of(text), textRenderer ); - title.setTooltip(Tooltip.of(Text.of("Test!"))); + if (info != null) title.setTooltip(getTooltip(info, false)); title.setMaxWidth(buttons.size() > 1 ? buttons.get(1).getX() - 24 - : MinecraftClient.getInstance().getWindow().getScaledWidth() - 24); + : scaledWidth - 24); } } public void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { buttons.forEach(b -> { b.setY(y); b.render(context, mouseX, mouseY, tickDelta);}); - - if(title != null) { - + if (title != null) { title.setY(y + 9); + title.renderWidget(context, mouseX, mouseY, tickDelta); - title.render(context, mouseX, mouseY, tickDelta); - - - // isHovered and isMouseOver didn't work! sad! - if(mouseX >= title.getX() && mouseX < title.getWidth() + title.getX() - && mouseY >= title.getY() && mouseY < title.getHeight() + title.getY()) - context.drawOrderedTooltip(textRenderer, tooltipLines, mouseX, mouseY); - - // testing purposes - /* else context.drawTooltip(textRenderer, Text.of(String.format("%s, %s", mouseX, mouseY)), mouseX, mouseY); */ + boolean tooltipVisible = mouseX >= title.getX() && mouseX < title.getWidth() + title.getX() && mouseY >= title.getY() && mouseY < title.getHeight() + title.getY(); + if (tooltipVisible && title.getTooltip() != null) { + context.drawOrderedTooltip(textRenderer, title.getTooltip().getLines(MinecraftClient.getInstance()), mouseX, mouseY); + } } } diff --git a/test-fabric/src/main/resources/assets/modid/en_US.json b/test-fabric/src/main/resources/assets/modid/lang/en_us.json similarity index 94% rename from test-fabric/src/main/resources/assets/modid/en_US.json rename to test-fabric/src/main/resources/assets/modid/lang/en_us.json index 993eca1..8ac67dd 100644 --- a/test-fabric/src/main/resources/assets/modid/en_US.json +++ b/test-fabric/src/main/resources/assets/modid/lang/en_us.json @@ -3,6 +3,7 @@ "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.label.tooltip":"I am a label tooltip \nWohoo!", "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", From 6f35fb56584e051b93c869a79c59da19a7fe6d3a Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Tue, 14 Jan 2025 10:35:14 +0100 Subject: [PATCH 043/100] docs: improve javadocs --- .../java/eu/midnightdust/lib/config/MidnightConfig.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) 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 c1b2a78..1ec6c50 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -496,7 +496,7 @@ public abstract class MidnightConfig { /** * Entry Annotation
- * - width: The maximum character length of the {@link String}, {@link Identifier} or String/Identifier {@link List} field
+ * - width: The maximum character length of the {@link String}, {@link Identifier} or String/Identifier {@link List<>} field
* - min: The minimum value of the int, float or double field
* - max: The maximum value of the int, float or double field
* - name: The name of the field in the config screen
@@ -536,16 +536,18 @@ public abstract class MidnightConfig { @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Client {} /** - * Hides the entry on singleplayer/client-side. - * Accessible through{@code /midnightconfig MOD_ID ENTRY} and through directly editing the config file. + * Hides the entry in config screens, but still makes it + * accessible through the command {@code /midnightconfig MOD_ID ENTRY} and directly editing the config file. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Server {} /** * Hides the entry entirely. * Accessible only through directly editing the config file. + * Perfect for saving persistent internal data. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Hidden {} + @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Comment { boolean centered() default false; String category() default "default"; From 37fff5a9c5e7eba9430f05b3a9540bf79bbfb88f Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Tue, 14 Jan 2025 10:48:48 +0100 Subject: [PATCH 044/100] clean: compactify tooltip code --- .../lib/config/MidnightConfig.java | 31 ++++++------------- 1 file changed, 9 insertions(+), 22 deletions(-) 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 1ec6c50..dd313f4 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -79,7 +79,7 @@ public abstract class MidnightConfig { .registerTypeAdapter(Identifier.class, new Identifier.Serializer()) .setPrettyPrinting().create(); - @SuppressWarnings("unused") // shhhhhh... + @SuppressWarnings("unused") // Utility for mod authors public static @Nullable Object getDefaultValue(String modid, String entry) { for (EntryInfo e : entries) { if (modid.equals(e.modid) && entry.equals(e.field.getName())) return e.defaultValue; @@ -443,34 +443,21 @@ public abstract class MidnightConfig { if (info != null) this.centered = info.centered; int scaledWidth = MinecraftClient.getInstance().getWindow().getScaledWidth(); - // moved text declaration to constructor if (text != null && (!text.getString().contains("spacer") || !buttons.isEmpty())) { - title = new MultilineTextWidget( - (centered) // x - ? (scaledWidth / 2 - (textRenderer.getWidth(text) / 2)) - : 12, - 0, // will be set on render - Text.of(text), textRenderer - ); - + title = new MultilineTextWidget((centered) ? (scaledWidth / 2 - (textRenderer.getWidth(text) / 2)) : 12, 0, Text.of(text), textRenderer); if (info != null) title.setTooltip(getTooltip(info, false)); - title.setMaxWidth(buttons.size() > 1 - ? buttons.get(1).getX() - 24 - : scaledWidth - 24); + title.setMaxWidth(buttons.size() > 1 ? buttons.get(1).getX() - 24 : scaledWidth - 24); } } public void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { buttons.forEach(b -> { b.setY(y); b.render(context, mouseX, mouseY, tickDelta);}); - if (title != null) { - title.setY(y + 9); - title.renderWidget(context, mouseX, mouseY, tickDelta); - - boolean tooltipVisible = mouseX >= title.getX() && mouseX < title.getWidth() + title.getX() && mouseY >= title.getY() && mouseY < title.getHeight() + title.getY(); - if (tooltipVisible && title.getTooltip() != null) { - context.drawOrderedTooltip(textRenderer, title.getTooltip().getLines(MinecraftClient.getInstance()), mouseX, mouseY); - } - } + if (title != null) { + title.setY(y + 9); + title.renderWidget(context, mouseX, mouseY, tickDelta); + boolean tooltipVisible = mouseX >= title.getX() && mouseX < title.getWidth() + title.getX() && mouseY >= title.getY() && mouseY < title.getHeight() + title.getY(); + if (tooltipVisible && title.getTooltip() != null) context.drawOrderedTooltip(textRenderer, title.getTooltip().getLines(MinecraftClient.getInstance()), mouseX, mouseY); + } } public List children() {return Lists.newArrayList(buttons);} public List selectableChildren() {return Lists.newArrayList(buttons);} From e938682e51f4ad7e045e3c58d35712a6a040400a Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Sun, 19 Jan 2025 18:27:27 +0100 Subject: [PATCH 045/100] MidnightLib 1.6.7 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index a4b1085..152d372 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ yarn_mappings=1.21.4+build.1 enabled_platforms=fabric,neoforge archives_base_name=midnightlib -mod_version=1.6.6 +mod_version=1.6.7 maven_group=eu.midnightdust release_type=release curseforge_id=488090 From 6aa053665f9b130578232f0a256b50919e9a3fa6 Mon Sep 17 00:00:00 2001 From: maloryware Date: Mon, 27 Jan 2025 09:11:43 +0000 Subject: [PATCH 046/100] Backported to 1.21(.1) --- .../midnightdust/core/mixin/MixinOptionsScreen.java | 5 ++++- .../eu/midnightdust/lib/config/MidnightConfig.java | 8 ++++---- gradle.properties | 12 ++++++------ 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java b/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java index 13203b7..be1cfd8 100644 --- a/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java +++ b/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java @@ -37,11 +37,14 @@ public abstract class MixinOptionsScreen extends Screen { } } - @Inject(at = @At("TAIL"), method = "refreshWidgetPositions") + + + @Inject(at = @At("TAIL"), method = "initTabNavigation") public void midnightlib$onResize(CallbackInfo ci) { if (shouldShowButton()) this.midnightlib$setButtonPos(); } + @Unique public void midnightlib$setButtonPos() { midnightlib$button.setPosition(layout.getWidth() / 2 + 158, layout.getY() + layout.getFooterHeight() - 4); 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 dd313f4..87dcbb1 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -251,9 +251,9 @@ public abstract class MidnightConfig { if (prevTab != null && prevTab != tabManager.getCurrentTab()) { prevTab = tabManager.getCurrentTab(); this.list.clear(); fillList(); - list.setScrollY(0); + list.setScrollAmount(0); } - scrollProgress = list.getScrollY(); + scrollProgress = list.getScrollAmount(); for (EntryInfo info : entries) try {info.field.set(null, info.value);} catch (IllegalAccessException ignored) {} updateButtons(); } @@ -395,7 +395,7 @@ public abstract class MidnightConfig { } this.list.addButton(widgets, name, info); } else this.list.addButton(List.of(), name, info); - } list.setScrollY(scrollProgress); + } list.setScrollAmount(scrollProgress); updateButtons(); } } @@ -423,7 +423,7 @@ public abstract class MidnightConfig { protected void drawHeaderAndFooterSeparators(DrawContext context) { if (renderHeaderSeparator) super.drawHeaderAndFooterSeparators(context); else { RenderSystem.enableBlend(); - context.drawTexture(RenderLayer::getGuiTextured, this.client.world == null ? Screen.FOOTER_SEPARATOR_TEXTURE : Screen.INWORLD_FOOTER_SEPARATOR_TEXTURE, this.getX(), this.getBottom(), 0.0F, 0.0F, this.getWidth(), 2, 32, 2); + context.drawTexture(this.client.world == null ? Screen.FOOTER_SEPARATOR_TEXTURE : Screen.INWORLD_FOOTER_SEPARATOR_TEXTURE, this.getX(), this.getBottom(), 0.0F, 0.0F, this.getWidth(), 2, 32, 2); RenderSystem.disableBlend(); } } public void addButton(List buttons, Text text, EntryInfo info) { this.addEntry(new ButtonEntry(buttons, text, info)); } diff --git a/gradle.properties b/gradle.properties index a4b1085..8a832a2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,21 +1,21 @@ org.gradle.jvmargs=-Xmx4096M -minecraft_version=1.21.4 +minecraft_version=1.21 supported_versions= -yarn_mappings=1.21.4+build.1 +yarn_mappings=1.21+build.1 enabled_platforms=fabric,neoforge archives_base_name=midnightlib -mod_version=1.6.6 +mod_version=1.6.7-1.21 maven_group=eu.midnightdust release_type=release curseforge_id=488090 modrinth_id=codAaoxh -fabric_loader_version=0.16.9 -fabric_api_version=0.110.5+1.21.4 +fabric_loader_version=0.16.10 +fabric_api_version=0.115.0+1.21.1 -neoforge_version=21.4.3-beta +neoforge_version=21.0.167 yarn_mappings_patch_neoforge_version = 1.21+build.4 quilt_loader_version=0.19.0-beta.18 From 81d2a6645177d74f487efd7c771223a0b44d1b19 Mon Sep 17 00:00:00 2001 From: maloryware Date: Mon, 27 Jan 2025 09:15:21 +0000 Subject: [PATCH 047/100] i should really stop pressing "commit and push" unconditionally but it's such an attractive button... --- .../src/main/java/eu/midnightdust/lib/config/MidnightConfig.java | 1 - 1 file changed, 1 deletion(-) 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 87dcbb1..835978e 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -9,7 +9,6 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.Te import net.minecraft.client.gui.Element; import net.minecraft.client.gui.Selectable; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.tab.GridScreenTab; import net.minecraft.client.gui.tab.Tab; import net.minecraft.client.gui.tab.TabManager; import net.minecraft.client.gui.tooltip.Tooltip; import net.minecraft.client.gui.widget.*; -import net.minecraft.client.render.RenderLayer; import net.minecraft.client.resource.language.I18n; import net.minecraft.registry.Registries; import net.minecraft.screen.ScreenTexts; From fe6669e750913b845be97f3f0da6b01fa89bf521 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Sat, 15 Feb 2025 11:19:41 +0100 Subject: [PATCH 048/100] fix: crash on pure Wayland sessions - Closes #84 --- common/src/main/java/eu/midnightdust/core/MidnightLib.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/main/java/eu/midnightdust/core/MidnightLib.java b/common/src/main/java/eu/midnightdust/core/MidnightLib.java index 99986cc..1343567 100755 --- a/common/src/main/java/eu/midnightdust/core/MidnightLib.java +++ b/common/src/main/java/eu/midnightdust/core/MidnightLib.java @@ -25,7 +25,7 @@ public class MidnightLib { try { if (!IS_SYSTEM_MAC) { System.setProperty("java.awt.headless", "false"); UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - }} catch (Exception e) { LOGGER.error("Error setting system look and feel", e); } + }} catch (Exception | Error e) { LOGGER.error("Error setting system look and feel", e); } MidnightLibConfig.init(MOD_ID, MidnightLibConfig.class); } public static void registerAutoCommand() { From e29466401b8f9420ad64f4e254b5e86deb3477fb Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Sat, 15 Feb 2025 11:21:01 +0100 Subject: [PATCH 049/100] chore: improve version formatting & bump version --- fabric/build.gradle | 6 +++--- gradle.properties | 2 +- neoforge/build.gradle | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/fabric/build.gradle b/fabric/build.gradle index 7bdc94e..da56a04 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -20,8 +20,8 @@ configurations { compileClasspath.extendsFrom common runtimeClasspath.extendsFrom common developmentFabric.extendsFrom common - archivesBaseName = rootProject.archives_base_name + "-fabric" - version = rootProject.mod_version + "+" + rootProject.minecraft_version + archivesBaseName = rootProject.archives_base_name + version = rootProject.mod_version + "-" + project.name + "+" + rootProject.minecraft_version } dependencies { @@ -95,7 +95,7 @@ unifiedPublishing { modrinth { token = MODRINTH_TOKEN id = rootProject.modrinth_id - version = "$rootProject.version-$project.name" + version = version gameVersions.addAll project.minecraft_version if (project.supported_versions != "") gameVersions.addAll project.supported_versions } diff --git a/gradle.properties b/gradle.properties index 152d372..a18f146 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ yarn_mappings=1.21.4+build.1 enabled_platforms=fabric,neoforge archives_base_name=midnightlib -mod_version=1.6.7 +mod_version=1.6.8 maven_group=eu.midnightdust release_type=release curseforge_id=488090 diff --git a/neoforge/build.gradle b/neoforge/build.gradle index 30e3c8b..62d7b3f 100644 --- a/neoforge/build.gradle +++ b/neoforge/build.gradle @@ -35,8 +35,8 @@ configurations { canBeResolved = true canBeConsumed = false } - archivesBaseName = rootProject.archives_base_name + "-neoforge" - version = rootProject.mod_version + "+" + rootProject.minecraft_version + archivesBaseName = rootProject.archives_base_name + version = rootProject.mod_version + "-" + project.name + "+" + rootProject.minecraft_version } dependencies { @@ -99,7 +99,7 @@ unifiedPublishing { modrinth { token = MODRINTH_TOKEN id = rootProject.modrinth_id - version = "$rootProject.version-$project.name" + version = version gameVersions.addAll project.minecraft_version if (project.supported_versions != "") gameVersions.addAll project.supported_versions } From d73b9683f9d5c4c53a37d9ae271602262b597a2d Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Sat, 15 Feb 2025 12:01:44 +0100 Subject: [PATCH 050/100] feat: support non-primitive fields - Closes #69 (nice) --- .../eu/midnightdust/lib/config/MidnightConfig.java | 14 +++++++------- .../example/config/MidnightConfigExample.java | 2 ++ 2 files changed, 9 insertions(+), 7 deletions(-) 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 dd313f4..cb13e08 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -146,11 +146,11 @@ public abstract class MidnightConfig { if (requiredModLoaded) 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(); + Class rawType = field.getType(); + if (field.getType() == List.class) + rawType = (Class) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0]; + try { return (Class) rawType.getField("TYPE").get(null); // Tries to get primitive types from non-primitives (e.g. Boolean -> boolean) + } catch (NoSuchFieldException | IllegalAccessException ignored) { return rawType; } } public static Tooltip getTooltip(EntryInfo info, boolean isButton) { String key = info.modid + ".midnightconfig."+info.field.getName()+(!isButton ? ".label" : "" )+".tooltip"; @@ -476,8 +476,8 @@ public abstract class MidnightConfig { @Override public void applyValue() { if (info.dataType == int.class) info.setValue(((Number) (e.min() + value * (e.max() - e.min()))).intValue()); - else if (info.field.getType() == double.class) info.setValue(Math.round((e.min() + value * (e.max() - e.min())) * (double) e.precision()) / (double) e.precision()); - else if (info.field.getType() == float.class) info.setValue(Math.round((e.min() + value * (e.max() - e.min())) * (float) e.precision()) / (float) e.precision()); + else if (info.dataType == double.class) info.setValue(Math.round((e.min() + value * (e.max() - e.min())) * (double) e.precision()) / (double) e.precision()); + else if (info.dataType == float.class) info.setValue(Math.round((e.min() + value * (e.max() - e.min())) * (float) e.precision()) / (float) e.precision()); } } 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 index f16c370..12d29c2 100644 --- 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 @@ -22,6 +22,7 @@ public class MidnightConfigExample extends MidnightConfig { @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, name="I am a (non-primitive) Boolean") public static Boolean nonPrimitive = true; // Example for a non-primative 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! @@ -34,6 +35,7 @@ public class MidnightConfigExample extends MidnightConfig { @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 + @Entry(category = SLIDERS, name = "I am a non-primitive double slider!", isSlider = true, min = 0d, max = 4d, precision = 10000) public static Double nonPrimitiveDoubleSlider = 3.76d; // Even works for non-primitive fields // 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 From fdb4a1a5287afd003242141723d98c716e268055 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Sat, 15 Feb 2025 12:14:56 +0100 Subject: [PATCH 051/100] feat: use enum variant name when missing translation - Closes #79 --- .../main/java/eu/midnightdust/lib/config/MidnightConfig.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 cb13e08..037254b 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -134,7 +134,10 @@ public abstract class MidnightConfig { }, func); } else if (info.dataType.isEnum()) { List values = Arrays.asList(field.getType().getEnumConstants()); - Function func = value -> Text.translatable(modid + ".midnightconfig." + "enum." + info.dataType.getSimpleName() + "." + info.toTemporaryValue()); + Function func = value -> { + String translationKey = modid + ".midnightconfig.enum." + info.dataType.getSimpleName() + "." + info.toTemporaryValue(); + return I18n.hasTranslation(translationKey) ? Text.translatable(translationKey) : Text.literal(info.toTemporaryValue()); + }; info.function = new AbstractMap.SimpleEntry>(button -> { int index = values.indexOf(info.value) + 1; info.value = values.get(index >= values.size() ? 0 : index); button.setMessage(func.apply(info.value)); From 28166aaa3d29b4608ef503e0f532743b0143182e Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Sat, 15 Feb 2025 12:28:02 +0100 Subject: [PATCH 052/100] fix(neoforge): move command registration to post init - Closes #82 and #68 --- .../main/java/eu/midnightdust/neoforge/MidnightLibNeoForge.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neoforge/src/main/java/eu/midnightdust/neoforge/MidnightLibNeoForge.java b/neoforge/src/main/java/eu/midnightdust/neoforge/MidnightLibNeoForge.java index 91cb9ca..57e2d6b 100644 --- a/neoforge/src/main/java/eu/midnightdust/neoforge/MidnightLibNeoForge.java +++ b/neoforge/src/main/java/eu/midnightdust/neoforge/MidnightLibNeoForge.java @@ -24,7 +24,6 @@ public class MidnightLibNeoForge { public MidnightLibNeoForge() { if (FMLEnvironment.dist == Dist.CLIENT) MidnightLib.onInitializeClient(); - MidnightLib.registerAutoCommand(); } @EventBusSubscriber(modid = "midnightlib", bus = EventBusSubscriber.Bus.MOD, value = Dist.CLIENT) @@ -36,6 +35,7 @@ public class MidnightLibNeoForge { modContainer.registerExtensionPoint(IConfigScreenFactory.class, (minecraftClient, screen) -> MidnightConfig.getScreen(screen, modid)); } }); + MidnightLib.registerAutoCommand(); } } From 596f68f4d9e000d48fb9034c635afdbbe1f38987 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Sat, 15 Feb 2025 12:39:47 +0100 Subject: [PATCH 053/100] chore: adjust version naming for better integration --- fabric/build.gradle | 2 +- neoforge/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fabric/build.gradle b/fabric/build.gradle index da56a04..9da74e4 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -95,7 +95,7 @@ unifiedPublishing { modrinth { token = MODRINTH_TOKEN id = rootProject.modrinth_id - version = version + version = rootProject.mod_version + "+" + rootProject.minecraft_version + "-" + project.name gameVersions.addAll project.minecraft_version if (project.supported_versions != "") gameVersions.addAll project.supported_versions } diff --git a/neoforge/build.gradle b/neoforge/build.gradle index 62d7b3f..48ebf4f 100644 --- a/neoforge/build.gradle +++ b/neoforge/build.gradle @@ -99,7 +99,7 @@ unifiedPublishing { modrinth { token = MODRINTH_TOKEN id = rootProject.modrinth_id - version = version + version = rootProject.mod_version + "+" + rootProject.minecraft_version + "-" + project.name gameVersions.addAll project.minecraft_version if (project.supported_versions != "") gameVersions.addAll project.supported_versions } From 7c0e4d5b48f24b26e296885b77af9e8a2b2d57fa Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Sat, 15 Feb 2025 12:45:16 +0100 Subject: [PATCH 054/100] Revert "Merge branch 'architectury-1.21.1' into architectury-1.21.4" This reverts commit a0fde5da5c7c6c4b7d19a979988e51c7a721d349, reversing changes made to 596f68f4d9e000d48fb9034c635afdbbe1f38987. --- .../midnightdust/core/mixin/MixinOptionsScreen.java | 5 +---- .../eu/midnightdust/lib/config/MidnightConfig.java | 9 +++++---- gradle.properties | 12 ++++++------ 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java b/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java index be1cfd8..13203b7 100644 --- a/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java +++ b/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java @@ -37,14 +37,11 @@ public abstract class MixinOptionsScreen extends Screen { } } - - - @Inject(at = @At("TAIL"), method = "initTabNavigation") + @Inject(at = @At("TAIL"), method = "refreshWidgetPositions") public void midnightlib$onResize(CallbackInfo ci) { if (shouldShowButton()) this.midnightlib$setButtonPos(); } - @Unique public void midnightlib$setButtonPos() { midnightlib$button.setPosition(layout.getWidth() / 2 + 158, layout.getY() + layout.getFooterHeight() - 4); 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 b2b3e5a..037254b 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -9,6 +9,7 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.Te import net.minecraft.client.gui.Element; import net.minecraft.client.gui.Selectable; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.tab.GridScreenTab; import net.minecraft.client.gui.tab.Tab; import net.minecraft.client.gui.tab.TabManager; import net.minecraft.client.gui.tooltip.Tooltip; import net.minecraft.client.gui.widget.*; +import net.minecraft.client.render.RenderLayer; import net.minecraft.client.resource.language.I18n; import net.minecraft.registry.Registries; import net.minecraft.screen.ScreenTexts; @@ -253,9 +254,9 @@ public abstract class MidnightConfig { if (prevTab != null && prevTab != tabManager.getCurrentTab()) { prevTab = tabManager.getCurrentTab(); this.list.clear(); fillList(); - list.setScrollAmount(0); + list.setScrollY(0); } - scrollProgress = list.getScrollAmount(); + scrollProgress = list.getScrollY(); for (EntryInfo info : entries) try {info.field.set(null, info.value);} catch (IllegalAccessException ignored) {} updateButtons(); } @@ -397,7 +398,7 @@ public abstract class MidnightConfig { } this.list.addButton(widgets, name, info); } else this.list.addButton(List.of(), name, info); - } list.setScrollAmount(scrollProgress); + } list.setScrollY(scrollProgress); updateButtons(); } } @@ -425,7 +426,7 @@ public abstract class MidnightConfig { protected void drawHeaderAndFooterSeparators(DrawContext context) { if (renderHeaderSeparator) super.drawHeaderAndFooterSeparators(context); else { RenderSystem.enableBlend(); - context.drawTexture(this.client.world == null ? Screen.FOOTER_SEPARATOR_TEXTURE : Screen.INWORLD_FOOTER_SEPARATOR_TEXTURE, this.getX(), this.getBottom(), 0.0F, 0.0F, this.getWidth(), 2, 32, 2); + context.drawTexture(RenderLayer::getGuiTextured, this.client.world == null ? Screen.FOOTER_SEPARATOR_TEXTURE : Screen.INWORLD_FOOTER_SEPARATOR_TEXTURE, this.getX(), this.getBottom(), 0.0F, 0.0F, this.getWidth(), 2, 32, 2); RenderSystem.disableBlend(); } } public void addButton(List buttons, Text text, EntryInfo info) { this.addEntry(new ButtonEntry(buttons, text, info)); } diff --git a/gradle.properties b/gradle.properties index ae6f389..a18f146 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,8 +1,8 @@ org.gradle.jvmargs=-Xmx4096M -minecraft_version=1.21 -supported_versions=1.21.1 -yarn_mappings=1.21+build.1 +minecraft_version=1.21.4 +supported_versions= +yarn_mappings=1.21.4+build.1 enabled_platforms=fabric,neoforge archives_base_name=midnightlib @@ -12,10 +12,10 @@ release_type=release curseforge_id=488090 modrinth_id=codAaoxh -fabric_loader_version=0.16.10 -fabric_api_version=0.115.0+1.21.1 +fabric_loader_version=0.16.9 +fabric_api_version=0.110.5+1.21.4 -neoforge_version=21.0.167 +neoforge_version=21.4.3-beta yarn_mappings_patch_neoforge_version = 1.21+build.4 quilt_loader_version=0.19.0-beta.18 From d2f5b26c1f6965a25491c9641843226885696e92 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Sat, 22 Feb 2025 22:12:25 +0100 Subject: [PATCH 055/100] feat: maintain tab order - The ordering of tabs will now be defined by the order entries are sorted in config classes --- .../main/java/eu/midnightdust/lib/config/MidnightConfig.java | 2 +- gradle.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 037254b..8591097 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -241,7 +241,7 @@ public abstract class MidnightConfig { public final Screen parent; public MidnightConfigListWidget list; public TabManager tabManager = new TabManager(a -> {}, a -> {}); - public Map tabs = new HashMap<>(); + public Map tabs = new LinkedHashMap<>(); public Tab prevTab; public TabNavigationWidget tabNavigation; public ButtonWidget done; diff --git a/gradle.properties b/gradle.properties index a18f146..a1e95cc 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ yarn_mappings=1.21.4+build.1 enabled_platforms=fabric,neoforge archives_base_name=midnightlib -mod_version=1.6.8 +mod_version=1.6.9 maven_group=eu.midnightdust release_type=release curseforge_id=488090 From 422cb5f368dc9bba76e71a1572b90244c7c20eee Mon Sep 17 00:00:00 2001 From: Korben <92390626+mpustovoi@users.noreply.github.com> Date: Sun, 23 Feb 2025 12:48:02 +0300 Subject: [PATCH 056/100] Create `ru_ru.json` Parity with `en_us.json`. --- .../resources/assets/midnightlib/lang/ru_ru.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 common/src/main/resources/assets/midnightlib/lang/ru_ru.json diff --git a/common/src/main/resources/assets/midnightlib/lang/ru_ru.json b/common/src/main/resources/assets/midnightlib/lang/ru_ru.json new file mode 100644 index 0000000..fde22c3 --- /dev/null +++ b/common/src/main/resources/assets/midnightlib/lang/ru_ru.json @@ -0,0 +1,15 @@ +{ + "midnightlib.overview.title": "Обзор MidnightConfig", + "midnightlib.midnightconfig.title": "Конфигурация MidnightLib", + "midnightlib.midnightconfig.config_screen_list": "Включить список экранов настройки", + "midnightlib.midnightconfig.enum.ConfigButton.TRUE": "§aДа", + "midnightlib.midnightconfig.enum.ConfigButton.FALSE": "§cНет", + "midnightlib.midnightconfig.enum.ConfigButton.MODMENU": "§bModMenu", + "midnightlib.midnightconfig.background_texture": "Текстура фона экрана настройки", + "midnightlib.modrinth": "Modrinth", + "midnightlib.curseforge": "CurseForge", + "midnightlib.wiki": "Вики", + "modmenu.descriptionTranslation.midnightlib": "Общая библиотека для простой настройки.\nПредоставляет API настройки, автоматическую интеграцию с другими модами и распространённые утилиты.", + "modmenu.summaryTranslation.midnightlib": "Общая библиотека для простой настройки.", + "midnightconfig.colorChooser.title": "Выберите цвет" +} From 30fb35f807cee52a1a9f1334e642cd7aa896acf4 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Thu, 20 Mar 2025 20:40:36 +0100 Subject: [PATCH 057/100] feat: minimal custom type adapter for Identifiers - Needed for MC 1.21.5+ (The official Serializer was removed) --- .../java/eu/midnightdust/lib/config/MidnightConfig.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) 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 8591097..a827883 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -1,8 +1,8 @@ package eu.midnightdust.lib.config; import com.google.common.collect.Lists; -import com.google.gson.ExclusionStrategy; import com.google.gson.FieldAttributes; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.mojang.blaze3d.systems.RenderSystem; +import com.google.gson.*; import com.google.gson.stream.*; import eu.midnightdust.lib.util.PlatformFunctions; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; @@ -19,6 +19,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; import java.awt.Color; +import java.io.IOException; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; import java.nio.file.Files; import java.nio.file.Path; @@ -76,8 +77,10 @@ public abstract class MidnightConfig { private static final Gson gson = new GsonBuilder() .excludeFieldsWithModifiers(Modifier.TRANSIENT).excludeFieldsWithModifiers(Modifier.PRIVATE) .addSerializationExclusionStrategy(new HiddenAnnotationExclusionStrategy()) - .registerTypeAdapter(Identifier.class, new Identifier.Serializer()) - .setPrettyPrinting().create(); + .registerTypeAdapter(Identifier.class, new TypeAdapter() { + public void write(JsonWriter out, Identifier id) throws IOException { out.value(id.toString()); } + public Identifier read(JsonReader in) throws IOException { return Identifier.of(in.nextString()); } + }).setPrettyPrinting().create(); @SuppressWarnings("unused") // Utility for mod authors public static @Nullable Object getDefaultValue(String modid, String entry) { From 32822e60ed44f3b1dfdf8278479c71ccca279682 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Thu, 20 Mar 2025 20:46:43 +0100 Subject: [PATCH 058/100] clean: remove blend functions - No longer needed since 1.21.3 and not available in 1.21.5 --- .../main/java/eu/midnightdust/lib/config/MidnightConfig.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) 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 a827883..47b2f9d 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -1,7 +1,6 @@ package eu.midnightdust.lib.config; import com.google.common.collect.Lists; -import com.mojang.blaze3d.systems.RenderSystem; import com.google.gson.*; import com.google.gson.stream.*; import eu.midnightdust.lib.util.PlatformFunctions; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; @@ -428,9 +427,7 @@ public abstract class MidnightConfig { @Override protected void drawHeaderAndFooterSeparators(DrawContext context) { if (renderHeaderSeparator) super.drawHeaderAndFooterSeparators(context); - else { RenderSystem.enableBlend(); - context.drawTexture(RenderLayer::getGuiTextured, this.client.world == null ? Screen.FOOTER_SEPARATOR_TEXTURE : Screen.INWORLD_FOOTER_SEPARATOR_TEXTURE, this.getX(), this.getBottom(), 0.0F, 0.0F, this.getWidth(), 2, 32, 2); - RenderSystem.disableBlend(); } + else context.drawTexture(RenderLayer::getGuiTextured, this.client.world == null ? Screen.FOOTER_SEPARATOR_TEXTURE : Screen.INWORLD_FOOTER_SEPARATOR_TEXTURE, this.getX(), this.getBottom(), 0, 0, this.getWidth(), 2, 32, 2); } public void addButton(List buttons, Text text, EntryInfo info) { this.addEntry(new ButtonEntry(buttons, text, info)); } public void clear() { this.clearEntries(); } From 7902042a4490c8814063ac867eac32b8ba8fce19 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Thu, 20 Mar 2025 21:12:28 +0100 Subject: [PATCH 059/100] refactor: identifier item display - Now in the list entry render method - Also fixes z-overlap --- .../midnightdust/lib/config/MidnightConfig.java | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) 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 47b2f9d..275f435 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -406,17 +406,10 @@ public abstract class MidnightConfig { } @Override public void render(DrawContext context, int mouseX, int mouseY, float delta) { - super.render(context,mouseX,mouseY,delta); + super.render(context, mouseX, mouseY, delta); this.list.render(context, mouseX, mouseY, delta); if (tabs.size() < 2) context.drawCenteredTextWithShadow(textRenderer, title, width / 2, 10, 0xFFFFFF); - - if (this.list != null) { - for (ButtonEntry entry : this.list.children()) { - if (entry.buttons != null && entry.buttons.size() > 1) { - if (entry.buttons.getFirst() instanceof ClickableWidget widget) { - int idMode = entry.info.field.getAnnotation(Entry.class).idMode(); - if (idMode != -1) context.drawItem(idMode == 0 ? Registries.ITEM.get(Identifier.tryParse(entry.info.tempValue)).getDefaultStack() : Registries.BLOCK.get(Identifier.tryParse(entry.info.tempValue)).asItem().getDefaultStack(), widget.getX() + widget.getWidth() - 18, widget.getY() + 2); - }}}}} + } } @Environment(EnvType.CLIENT) public static class MidnightConfigListWidget extends ElementListWidget { @@ -460,6 +453,11 @@ public abstract class MidnightConfig { boolean tooltipVisible = mouseX >= title.getX() && mouseX < title.getWidth() + title.getX() && mouseY >= title.getY() && mouseY < title.getHeight() + title.getY(); if (tooltipVisible && title.getTooltip() != null) context.drawOrderedTooltip(textRenderer, title.getTooltip().getLines(MinecraftClient.getInstance()), mouseX, mouseY); + + if (!this.buttons.isEmpty() && this.buttons.getFirst() instanceof ClickableWidget widget) { + int idMode = this.info.field.getAnnotation(Entry.class).idMode(); + if (idMode != -1) context.drawItem(idMode == 0 ? Registries.ITEM.get(Identifier.tryParse(this.info.tempValue)).getDefaultStack() : Registries.BLOCK.get(Identifier.tryParse(this.info.tempValue)).asItem().getDefaultStack(), widget.getX() + widget.getWidth() - 18, y + 2); + } } } public List children() {return Lists.newArrayList(buttons);} From 5da96ac84e240be77aec60d3995a7f5abbcca74a Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Thu, 20 Mar 2025 22:56:52 +0100 Subject: [PATCH 060/100] chore: bump version --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index a1e95cc..13ede76 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,12 +1,12 @@ org.gradle.jvmargs=-Xmx4096M minecraft_version=1.21.4 -supported_versions= +supported_versions=1.21.5 yarn_mappings=1.21.4+build.1 enabled_platforms=fabric,neoforge archives_base_name=midnightlib -mod_version=1.6.9 +mod_version=1.6.10 maven_group=eu.midnightdust release_type=release curseforge_id=488090 From 060ca3389a43ed141816ded4979e7dbabf4146eb Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Wed, 26 Mar 2025 17:44:35 +0100 Subject: [PATCH 061/100] clean: various code improvements --- .../lib/config/MidnightConfig.java | 128 ++++++++---------- gradle.properties | 4 +- 2 files changed, 62 insertions(+), 70 deletions(-) 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 275f435..0e078ea 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -28,7 +28,7 @@ import java.util.regex.Pattern; import static net.minecraft.client.MinecraftClient.IS_SYSTEM_MAC; -/** MidnightConfig v2.6.0 by Martin "Motschen" Prokoph +/** MidnightConfig by Martin "Motschen" Prokoph * Single class config library - feel free to copy! * Based on ... * Credits to Minenash */ @@ -42,17 +42,26 @@ public abstract class MidnightConfig { private static final List entries = new ArrayList<>(); public static class EntryInfo { - Field field; + public Entry entry; + public Comment comment; + final Field field; Class dataType; - int width, listIndex; - boolean centered; + int listIndex; Object defaultValue, value, function; - String modid, tempValue; // The value visible in the config screen + String modid, fieldName, tempValue = ""; // The value visible in the config screen boolean inLimits = true; Text name, error; ClickableWidget actionButton; // color picker button / explorer button Tab tab; + public EntryInfo(Field field) { + this.field = field; + if (field != null) { + this.fieldName = field.getName(); + this.entry = field.getAnnotation(Entry.class); + this.comment = field.getAnnotation(Comment.class); + } + } public void setValue(Object value) { if (this.field.getType() != List.class) { this.value = value; this.tempValue = value.toString(); @@ -63,6 +72,9 @@ public abstract class MidnightConfig { if (this.field.getType() != List.class) return this.value.toString(); else try { return ((List) this.value).get(this.listIndex).toString(); } catch (Exception ignored) {return "";} } + public void updateFieldValue() { + try { this.field.set(null, this.value); } catch (IllegalAccessException ignored) {} + } public void writeList(int index, T value) { var list = (List) this.value; if (index >= list.size()) list.add(value); @@ -75,7 +87,7 @@ public abstract class MidnightConfig { private static final Gson gson = new GsonBuilder() .excludeFieldsWithModifiers(Modifier.TRANSIENT).excludeFieldsWithModifiers(Modifier.PRIVATE) - .addSerializationExclusionStrategy(new HiddenAnnotationExclusionStrategy()) + .addSerializationExclusionStrategy(new NonEntryExclusionStrategy()) .registerTypeAdapter(Identifier.class, new TypeAdapter() { public void write(JsonWriter out, Identifier id) throws IOException { out.value(id.toString()); } public Identifier read(JsonReader in) throws IOException { return Identifier.of(in.nextString()); } @@ -87,37 +99,35 @@ public abstract class MidnightConfig { if (modid.equals(e.modid) && entry.equals(e.field.getName())) return e.defaultValue; } return null; } + public static void loadValuesFromJson(String modid) { + try { gson.fromJson(Files.newBufferedReader(path), configClass.get(modid)); } + catch (Exception e) { write(modid); } + for (EntryInfo info : entries) if (info.field != null && info.entry != null) { + try { info.value = info.field.get(null); info.tempValue = info.toTemporaryValue(); + } catch (IllegalAccessException ignored) {} + } + } public static void init(String modid, Class config) { path = PlatformFunctions.getConfigDirectory().resolve(modid + ".json"); configClass.put(modid, config); for (Field field : config.getFields()) { - EntryInfo info = new EntryInfo(); + EntryInfo info = new EntryInfo(field); if ((field.isAnnotationPresent(Entry.class) || field.isAnnotationPresent(Comment.class)) && !field.isAnnotationPresent(Server.class) && !field.isAnnotationPresent(Hidden.class) && PlatformFunctions.isClientEnv()) initClient(modid, field, info); if (field.isAnnotationPresent(Entry.class)) try { info.defaultValue = field.get(null); } catch (IllegalAccessException ignored) {} } - try { gson.fromJson(Files.newBufferedReader(path), config); } - catch (Exception e) { write(modid); } - - for (EntryInfo info : entries) { - if (info.field.isAnnotationPresent(Entry.class)) try { - info.value = info.field.get(null); - info.tempValue = info.toTemporaryValue(); - } catch (IllegalAccessException ignored) {} - } + loadValuesFromJson(modid); } @SuppressWarnings("ConstantValue") //pertains to requiredModLoaded @Environment(EnvType.CLIENT) private static void initClient(String modid, Field field, EntryInfo info) { info.dataType = getUnderlyingType(field); - Entry e = field.getAnnotation(Entry.class); - Comment c = field.getAnnotation(Comment.class); - info.width = e != null ? e.width() : 0; - info.field = field; info.modid = modid; + Entry e = info.entry; Comment c = info.comment; + info.modid = modid; boolean requiredModLoaded = true; if (e != null) { @@ -146,7 +156,6 @@ public abstract class MidnightConfig { }, func); }} else if (c != null) { if (!c.requiredMod().isEmpty()) requiredModLoaded = PlatformFunctions.isModLoaded(c.requiredMod()); - info.centered = c.centered(); } if (requiredModLoaded) entries.add(info); } @@ -158,12 +167,10 @@ public abstract class MidnightConfig { } catch (NoSuchFieldException | IllegalAccessException ignored) { return rawType; } } public static Tooltip getTooltip(EntryInfo info, boolean isButton) { - String key = info.modid + ".midnightconfig."+info.field.getName()+(!isButton ? ".label" : "" )+".tooltip"; + String key = info.modid + ".midnightconfig."+info.fieldName+(!isButton ? ".label" : "" )+".tooltip"; return Tooltip.of(isButton && info.error != null ? info.error : I18n.hasTranslation(key) ? Text.translatable(key) : Text.empty()); } - // TODO: Maybe move this into the screen class itself to free up some RAM? - private static void textField(EntryInfo info, Function f, Pattern pattern, double min, double max, boolean cast) { boolean isNumber = pattern != null; info.function = (BiFunction>) (t, b) -> s -> { @@ -190,7 +197,7 @@ public abstract class MidnightConfig { else info.setValue(isNumber ? value : s); } - if (info.field.getAnnotation(Entry.class).isColor()) { + if (info.entry.isColor()) { if (!s.contains("#")) s = '#' + s; if (!HEXADECIMAL_ONLY.matcher(s).matches()) return false; try { info.actionButton.setMessage(Text.literal("⬛").setStyle(Style.EMPTY.withColor(Color.decode(info.tempValue).getRGB()))); @@ -219,20 +226,17 @@ public abstract class MidnightConfig { super(Text.translatable(modid + ".midnightconfig." + "title")); this.parent = parent; this.modid = modid; this.translationPrefix = modid + ".midnightconfig."; - loadValues(); + loadValuesFromJson(modid); - for (EntryInfo e : entries) { - if (e.modid.equals(modid)) { - String tabId = e.field.isAnnotationPresent(Entry.class) ? e.field.getAnnotation(Entry.class).category() : e.field.getAnnotation(Comment.class).category(); - String name = translationPrefix + "category." + tabId; - if (!I18n.hasTranslation(name) && tabId.equals("default")) - name = translationPrefix + "title"; - if (!tabs.containsKey(name)) { - Tab tab = new GridScreenTab(Text.translatable(name)); - e.tab = tab; - tabs.put(name, tab); - } else e.tab = tabs.get(name); - } + for (EntryInfo e : entries) if (e.modid.equals(modid)) { + String tabId = e.entry != null ? e.entry.category() : e.comment.category(); + String name = translationPrefix + "category." + tabId; + if (!I18n.hasTranslation(name) && tabId.equals("default")) + name = translationPrefix + "title"; + if (!tabs.containsKey(name)) { + Tab tab = new GridScreenTab(Text.translatable(name)); + e.tab = tab; tabs.put(name, tab); + } else e.tab = tabs.get(name); } tabNavigation = TabNavigationWidget.builder(tabManager, this.width).tabs(tabs.values().toArray(new Tab[0])).build(); tabNavigation.selectTab(0, false); @@ -259,7 +263,7 @@ public abstract class MidnightConfig { list.setScrollY(0); } scrollProgress = list.getScrollY(); - for (EntryInfo info : entries) try {info.field.set(null, info.value);} catch (IllegalAccessException ignored) {} + for (EntryInfo info : entries) info.updateFieldValue(); updateButtons(); } public void updateButtons() { @@ -271,16 +275,6 @@ public abstract class MidnightConfig { if (entry.buttons.get(1) instanceof ButtonWidget button) button.active = !Objects.equals(entry.info.value.toString(), entry.info.defaultValue.toString()); }}}} - public void loadValues() { - try { gson.fromJson(Files.newBufferedReader(path), configClass.get(modid)); } - catch (Exception e) { write(modid); } - - for (EntryInfo info : entries) { - if (info.field.isAnnotationPresent(Entry.class)) - try { info.value = info.field.get(null); info.tempValue = info.toTemporaryValue(); - } catch (IllegalAccessException ignored) {} - } - } @Override public boolean keyPressed(int keyCode, int scanCode, int modifiers) { if (this.tabNavigation.trySwitchTabsWithKey(keyCode)) return true; @@ -288,7 +282,7 @@ public abstract class MidnightConfig { } @Override public void close() { - loadValues(); cleanup(); + loadValuesFromJson(modid); cleanup(); Objects.requireNonNull(client).setScreen(parent); } private void cleanup() { @@ -304,7 +298,7 @@ public abstract class MidnightConfig { this.addDrawableChild(ButtonWidget.builder(ScreenTexts.CANCEL, button -> this.close()).dimensions(this.width / 2 - 154, this.height - 26, 150, 20).build()); done = this.addDrawableChild(ButtonWidget.builder(ScreenTexts.DONE, (button) -> { - for (EntryInfo info : entries) if (info.modid.equals(modid)) try { info.field.set(null, info.value); } catch (IllegalAccessException ignored) {} + for (EntryInfo info : entries) if (info.modid.equals(modid)) info.updateFieldValue(); write(modid); cleanup(); Objects.requireNonNull(client).setScreen(parent); }).dimensions(this.width / 2 + 4, this.height - 26, 150, 20).build()); @@ -316,7 +310,7 @@ public abstract class MidnightConfig { public void fillList() { for (EntryInfo info : entries) { if (info.modid.equals(modid) && (info.tab == null || info.tab == tabManager.getCurrentTab())) { - Text name = Objects.requireNonNullElseGet(info.name, () -> Text.translatable(translationPrefix + info.field.getName())); + Text name = Objects.requireNonNullElseGet(info.name, () -> Text.translatable(translationPrefix + info.fieldName)); TextIconButtonWidget resetButton = TextIconButtonWidget.builder(Text.translatable("controls.reset"), (button -> { info.value = info.defaultValue; info.listIndex = 0; info.tempValue = info.toTemporaryValue(); @@ -326,12 +320,12 @@ public abstract class MidnightConfig { if (info.function != null) { ClickableWidget widget; - Entry e = info.field.getAnnotation(Entry.class); + Entry e = info.entry; if (info.function instanceof Map.Entry) { // Enums & booleans var values = (Map.Entry>) info.function; if (info.dataType.isEnum()) - values.setValue(value -> Text.translatable(translationPrefix + "enum." + info.field.getType().getSimpleName() + "." + info.value.toString())); + values.setValue(value -> Text.translatable(translationPrefix + "enum." + info.dataType.getSimpleName() + "." + info.value.toString())); widget = ButtonWidget.builder(values.getValue().apply(info.value), values.getKey()).dimensions(width - 185, 0, 150, 20).tooltip(getTooltip(info, true)).build(); } else if (e.isSlider()) @@ -339,7 +333,7 @@ public abstract class MidnightConfig { else widget = new TextFieldWidget(textRenderer, width - 185, 0, 150, 20, Text.empty()); if (widget instanceof TextFieldWidget textField) { - textField.setMaxLength(info.width); textField.setText(info.tempValue); + textField.setMaxLength(e.width()); textField.setText(info.tempValue); Predicate processor = ((BiFunction>) info.function).apply(textField, done); textField.setTextPredicate(processor); } @@ -375,10 +369,10 @@ public abstract class MidnightConfig { button -> new Thread(() -> { JFileChooser fileChooser = new JFileChooser(info.tempValue); fileChooser.setFileSelectionMode(e.selectionMode()); fileChooser.setDialogType(e.fileChooserType()); - fileChooser.setDialogTitle(Text.translatable(translationPrefix + info.field.getName() + ".fileChooser").getString()); + fileChooser.setDialogTitle(Text.translatable(translationPrefix + info.fieldName + ".fileChooser").getString()); if ((e.selectionMode() == JFileChooser.FILES_ONLY || e.selectionMode() == JFileChooser.FILES_AND_DIRECTORIES) && Arrays.stream(e.fileExtensions()).noneMatch("*"::equals)) fileChooser.setFileFilter(new FileNameExtensionFilter( - Text.translatable(translationPrefix + info.field.getName() + ".fileFilter").getString(), e.fileExtensions())); + Text.translatable(translationPrefix + info.fieldName + ".fileFilter").getString(), e.fileExtensions())); if (fileChooser.showDialog(null, null) == JFileChooser.APPROVE_OPTION) { info.setValue(fileChooser.getSelectedFile().getAbsolutePath()); list.clear(); fillList(); @@ -436,7 +430,7 @@ public abstract class MidnightConfig { public ButtonEntry(List buttons, Text text, EntryInfo info) { this.buttons = buttons; this.text = text; this.info = info; - if (info != null) this.centered = info.centered; + if (info != null && info.comment != null) this.centered = info.comment.centered(); int scaledWidth = MinecraftClient.getInstance().getWindow().getScaledWidth(); if (text != null && (!text.getString().contains("spacer") || !buttons.isEmpty())) { @@ -454,8 +448,8 @@ public abstract class MidnightConfig { boolean tooltipVisible = mouseX >= title.getX() && mouseX < title.getWidth() + title.getX() && mouseY >= title.getY() && mouseY < title.getHeight() + title.getY(); if (tooltipVisible && title.getTooltip() != null) context.drawOrderedTooltip(textRenderer, title.getTooltip().getLines(MinecraftClient.getInstance()), mouseX, mouseY); - if (!this.buttons.isEmpty() && this.buttons.getFirst() instanceof ClickableWidget widget) { - int idMode = this.info.field.getAnnotation(Entry.class).idMode(); + if (info.entry != null && !this.buttons.isEmpty() && this.buttons.getFirst() instanceof ClickableWidget widget) { + int idMode = this.info.entry.idMode(); if (idMode != -1) context.drawItem(idMode == 0 ? Registries.ITEM.get(Identifier.tryParse(this.info.tempValue)).getDefaultStack() : Registries.BLOCK.get(Identifier.tryParse(this.info.tempValue)).asItem().getDefaultStack(), widget.getX() + widget.getWidth() - 18, y + 2); } } @@ -467,7 +461,7 @@ public abstract class MidnightConfig { private final EntryInfo info; private final Entry e; public MidnightSliderWidget(int x, int y, int width, int height, Text text, double value, EntryInfo info) { super(x, y, width, height, text, value); - this.e = info.field.getAnnotation(Entry.class); + this.e = info.entry; this.info = info; } @@ -481,6 +475,10 @@ public abstract class MidnightConfig { else if (info.dataType == float.class) info.setValue(Math.round((e.min() + value * (e.max() - e.min())) * (float) e.precision()) / (float) e.precision()); } } + public static class NonEntryExclusionStrategy implements ExclusionStrategy { + public boolean shouldSkipClass(Class clazz) { return false; } + public boolean shouldSkipField(FieldAttributes fieldAttributes) { return fieldAttributes.getAnnotation(Entry.class) == null; } + } /** * Entry Annotation
@@ -524,8 +522,7 @@ public abstract class MidnightConfig { @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Client {} /** - * Hides the entry in config screens, but still makes it - * accessible through the command {@code /midnightconfig MOD_ID ENTRY} and directly editing the config file. + * Hides the entry in config screens, but still makes it accessible through the command {@code /midnightconfig MOD_ID ENTRY} and directly editing the config file. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Server {} @@ -541,9 +538,4 @@ public abstract class MidnightConfig { String category() default "default"; String requiredMod() default ""; } - - public static class HiddenAnnotationExclusionStrategy implements ExclusionStrategy { - public boolean shouldSkipClass(Class clazz) { return false; } - public boolean shouldSkipField(FieldAttributes fieldAttributes) { return fieldAttributes.getAnnotation(Entry.class) == null; } - } } \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 13ede76..0ed0255 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,12 +1,12 @@ org.gradle.jvmargs=-Xmx4096M minecraft_version=1.21.4 -supported_versions=1.21.5 +supported_versions= yarn_mappings=1.21.4+build.1 enabled_platforms=fabric,neoforge archives_base_name=midnightlib -mod_version=1.6.10 +mod_version=1.6.11 maven_group=eu.midnightdust release_type=release curseforge_id=488090 From 465af9507e949fd6a72059b7de9d69eeb86f3435 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Wed, 26 Mar 2025 19:08:10 +0100 Subject: [PATCH 062/100] clean: optimize translation files & metadata --- .../assets/midnightlib/lang/de_de.json | 2 -- .../assets/midnightlib/lang/en_us.json | 2 -- .../assets/midnightlib/lang/fr_fr.json | 1 - .../assets/midnightlib/lang/ms_my.json | 5 ----- .../assets/midnightlib/lang/pt_br.json | 1 - .../assets/midnightlib/lang/ru_ru.json | 6 +----- .../assets/midnightlib/lang/tt_ru.json | 1 - .../assets/midnightlib/lang/uk_ua.json | 1 - .../assets/midnightlib/lang/zh_cn.json | 5 ----- .../assets/midnightlib/lang/zh_tw.json | 1 - .../assets/midnightlib/lang/zlm_arab.json | 4 ---- fabric/src/main/resources/fabric.mod.json | 17 +++++------------ 12 files changed, 6 insertions(+), 40 deletions(-) diff --git a/common/src/main/resources/assets/midnightlib/lang/de_de.json b/common/src/main/resources/assets/midnightlib/lang/de_de.json index cd0da97..2afbf42 100755 --- a/common/src/main/resources/assets/midnightlib/lang/de_de.json +++ b/common/src/main/resources/assets/midnightlib/lang/de_de.json @@ -2,8 +2,6 @@ "midnightlib.overview.title":"MidnightConfig Übersicht", "midnightlib.midnightconfig.title":"MidnightLib Konfiguration", "midnightlib.midnightconfig.config_screen_list":"Konfigurationsübersicht", - "modmenu.descriptionTranslation.midnightlib": "Code-Bibliothek für einfache Konfiguration.\nStellt eine Konfigurationsschnittstelle, automatische Kompatibilität und oft genutzten Code bereit.", "modmenu.summaryTranslation.midnightlib": "Code-Bibliothek für einfache Konfiguration.", - "midnightconfig.colorChooser.title": "Wähle eine Farbe" } \ No newline at end of file diff --git a/common/src/main/resources/assets/midnightlib/lang/en_us.json b/common/src/main/resources/assets/midnightlib/lang/en_us.json index 8579b86..d81ceab 100755 --- a/common/src/main/resources/assets/midnightlib/lang/en_us.json +++ b/common/src/main/resources/assets/midnightlib/lang/en_us.json @@ -8,8 +8,6 @@ "midnightlib.modrinth":"Modrinth", "midnightlib.curseforge":"CurseForge", "midnightlib.wiki":"Wiki", - "modmenu.descriptionTranslation.midnightlib": "Common Library for easy configuration.\nProvides a config api, automatic integration with other mods and common utils.", "modmenu.summaryTranslation.midnightlib": "Common Library for easy configuration.", - "midnightconfig.colorChooser.title": "Choose a color" } \ No newline at end of file diff --git a/common/src/main/resources/assets/midnightlib/lang/fr_fr.json b/common/src/main/resources/assets/midnightlib/lang/fr_fr.json index 49e7a92..5898303 100644 --- a/common/src/main/resources/assets/midnightlib/lang/fr_fr.json +++ b/common/src/main/resources/assets/midnightlib/lang/fr_fr.json @@ -4,6 +4,5 @@ "midnightlib.midnightconfig.config_screen_list":"Activer la liste de l'écran de configuration", "midnightlib.midnightconfig.enum.ConfigButton.TRUE":"§aOui", "midnightlib.midnightconfig.enum.ConfigButton.FALSE":"§cNon", - "modmenu.descriptionTranslation.midnightlib": "Bibliothèque commune pour les mods de la Team MidnightDust.\nFournit une API de configuration, une intégration automatique avec d'autres mods et des utilitaires courants.", "modmenu.summaryTranslation.midnightlib": "Bibliothèque commune pour les mods de la Team MidnightDust." } diff --git a/common/src/main/resources/assets/midnightlib/lang/ms_my.json b/common/src/main/resources/assets/midnightlib/lang/ms_my.json index a2b0533..6a5e177 100644 --- a/common/src/main/resources/assets/midnightlib/lang/ms_my.json +++ b/common/src/main/resources/assets/midnightlib/lang/ms_my.json @@ -4,10 +4,5 @@ "midnightlib.midnightconfig.config_screen_list": "Dayakan Senarai Skrin Konfigurasi", "midnightlib.midnightconfig.enum.ConfigButton.TRUE": "§aYa", "midnightlib.midnightconfig.enum.ConfigButton.FALSE": "§cTidak", - "midnightlib.midnightconfig.enum.ConfigButton.MODMENU": "§bModMenu", - "midnightlib.modrinth": "Modrinth", - "midnightlib.curseforge": "CurseForge", - "midnightlib.wiki": "Wiki", - "modmenu.descriptionTranslation.midnightlib": "Pustaka Biasa untuk konfigurasi mudah.\nMenyediakan API konfigurasi, integrasi automatik dengan mod lain dan utiliti biasa.", "modmenu.summaryTranslation.midnightlib": "Pustaka Biasa untuk konfigurasi mudah." } \ No newline at end of file diff --git a/common/src/main/resources/assets/midnightlib/lang/pt_br.json b/common/src/main/resources/assets/midnightlib/lang/pt_br.json index 3a47a49..08262fc 100644 --- a/common/src/main/resources/assets/midnightlib/lang/pt_br.json +++ b/common/src/main/resources/assets/midnightlib/lang/pt_br.json @@ -4,6 +4,5 @@ "midnightlib.midnightconfig.config_screen_list":"Ativar lista de telas de configuração", "midnightlib.midnightconfig.enum.ConfigButton.TRUE":"§aVerdadeiro", "midnightlib.midnightconfig.enum.ConfigButton.FALSE":"§cFalso", - "modmenu.descriptionTranslation.midnightlib": "Biblioteca comum para mods do Team MidnightDust.\nFornece uma API de configuração, integração automática com outros mods e utilitários comuns.", "modmenu.summaryTranslation.midnightlib": "Biblioteca comum para mods do Team MidnightDust." } \ No newline at end of file diff --git a/common/src/main/resources/assets/midnightlib/lang/ru_ru.json b/common/src/main/resources/assets/midnightlib/lang/ru_ru.json index fde22c3..614b28e 100644 --- a/common/src/main/resources/assets/midnightlib/lang/ru_ru.json +++ b/common/src/main/resources/assets/midnightlib/lang/ru_ru.json @@ -5,11 +5,7 @@ "midnightlib.midnightconfig.enum.ConfigButton.TRUE": "§aДа", "midnightlib.midnightconfig.enum.ConfigButton.FALSE": "§cНет", "midnightlib.midnightconfig.enum.ConfigButton.MODMENU": "§bModMenu", - "midnightlib.midnightconfig.background_texture": "Текстура фона экрана настройки", - "midnightlib.modrinth": "Modrinth", - "midnightlib.curseforge": "CurseForge", "midnightlib.wiki": "Вики", - "modmenu.descriptionTranslation.midnightlib": "Общая библиотека для простой настройки.\nПредоставляет API настройки, автоматическую интеграцию с другими модами и распространённые утилиты.", "modmenu.summaryTranslation.midnightlib": "Общая библиотека для простой настройки.", "midnightconfig.colorChooser.title": "Выберите цвет" -} +} \ No newline at end of file diff --git a/common/src/main/resources/assets/midnightlib/lang/tt_ru.json b/common/src/main/resources/assets/midnightlib/lang/tt_ru.json index 9118e46..c06a27d 100644 --- a/common/src/main/resources/assets/midnightlib/lang/tt_ru.json +++ b/common/src/main/resources/assets/midnightlib/lang/tt_ru.json @@ -5,6 +5,5 @@ "midnightlib.midnightconfig.enum.ConfigButton.TRUE":"§aӘйе", "midnightlib.midnightconfig.enum.ConfigButton.FALSE":"§cЮк", "midnightlib.wiki":"Вики", - "modmenu.descriptionTranslation.midnightlib": "MidnightDust төркеменең модлары өчен гомуми китапханә.\nКөйләүләр API-ын, башка модлар белән автоматик интеграцияне, гомуми хезмәти программаларны һәм бизәнүләрне тәэмин ителә.", "modmenu.summaryTranslation.midnightlib": "MidnightDust төркеменең модлары өчен гомуми китапханә." } diff --git a/common/src/main/resources/assets/midnightlib/lang/uk_ua.json b/common/src/main/resources/assets/midnightlib/lang/uk_ua.json index 41e542f..b785e26 100644 --- a/common/src/main/resources/assets/midnightlib/lang/uk_ua.json +++ b/common/src/main/resources/assets/midnightlib/lang/uk_ua.json @@ -3,6 +3,5 @@ "midnightlib.midnightconfig.title":"Конфігурація MidnightLib", "midnightlib.midnightconfig.config_screen_list":"Увімкнути список екрана конфігурації", "midnightlib.wiki":"Вікі", - "modmenu.descriptionTranslation.midnightlib": "Загальна бібліотека для модів команди MidnightDust.\nНадає конфігураційний API, автоматичну інтеграцію з іншими модами, загальні утиліти та косметику.", "modmenu.summaryTranslation.midnightlib": "Загальна бібліотека для модів команди MidnightDust." } diff --git a/common/src/main/resources/assets/midnightlib/lang/zh_cn.json b/common/src/main/resources/assets/midnightlib/lang/zh_cn.json index 6ac0bd2..6dc1df7 100644 --- a/common/src/main/resources/assets/midnightlib/lang/zh_cn.json +++ b/common/src/main/resources/assets/midnightlib/lang/zh_cn.json @@ -5,11 +5,6 @@ "midnightlib.midnightconfig.enum.ConfigButton.TRUE":"§a是", "midnightlib.midnightconfig.enum.ConfigButton.FALSE":"§c否", "midnightlib.midnightconfig.enum.ConfigButton.MODMENU":"§b模组菜单", - "midnightlib.modrinth":"Modrinth", - "midnightlib.curseforge":"CurseForge", - "midnightlib.wiki":"Wiki", - "modmenu.descriptionTranslation.midnightlib": "本模组是一个便于模组配置的通用库模组。\n提供了一个配置接口,能够自动与其他模组兼容,还提供了一些通用功能。", "modmenu.summaryTranslation.midnightlib": "一个便于模组配置的通用库模组", - "midnightconfig.colorChooser.title": "选择一种颜色" } diff --git a/common/src/main/resources/assets/midnightlib/lang/zh_tw.json b/common/src/main/resources/assets/midnightlib/lang/zh_tw.json index 9b689cb..e710f86 100644 --- a/common/src/main/resources/assets/midnightlib/lang/zh_tw.json +++ b/common/src/main/resources/assets/midnightlib/lang/zh_tw.json @@ -6,6 +6,5 @@ "midnightlib.midnightconfig.enum.ConfigButton.FALSE":"§c否", "midnightlib.midnightconfig.enum.ConfigButton.MODMENU":"§b模組選單", "midnightlib.wiki":"維基", - "modmenu.descriptionTranslation.midnightlib": "MidnightDust 團隊的常用程式庫模組。\n提供設定 API、與其他模組自動整合、常用工具和美觀。", "modmenu.summaryTranslation.midnightlib": "MidnightDust 團隊的常用程式庫模組。" } diff --git a/common/src/main/resources/assets/midnightlib/lang/zlm_arab.json b/common/src/main/resources/assets/midnightlib/lang/zlm_arab.json index 8538914..ddd1a99 100644 --- a/common/src/main/resources/assets/midnightlib/lang/zlm_arab.json +++ b/common/src/main/resources/assets/midnightlib/lang/zlm_arab.json @@ -4,10 +4,6 @@ "midnightlib.midnightconfig.config_screen_list": "داياکن سناراي سکرين کونفيݢوراسي", "midnightlib.midnightconfig.enum.ConfigButton.TRUE": "§aيا", "midnightlib.midnightconfig.enum.ConfigButton.FALSE": "§cتيدق", - "midnightlib.midnightconfig.enum.ConfigButton.MODMENU": "§bModMenu", - "midnightlib.modrinth": "Modrinth", - "midnightlib.curseforge": "CurseForge", "midnightlib.wiki": "ويکي", - "modmenu.descriptionTranslation.midnightlib": "ڤوستاک بياسا اونتوق کونفيݢوراسي موده.\nمڽدياکن API کونفيݢوراسي⹁ اينتݢراسي اٴوتوماتيک دڠن مود لاٴين دان اوتيليتي بياسا.", "modmenu.summaryTranslation.midnightlib": "ڤوستاک بياسا اونتوق کونفيݢوراسي موده." } \ No newline at end of file diff --git a/fabric/src/main/resources/fabric.mod.json b/fabric/src/main/resources/fabric.mod.json index ea1ee35..1d3ecd3 100644 --- a/fabric/src/main/resources/fabric.mod.json +++ b/fabric/src/main/resources/fabric.mod.json @@ -10,13 +10,8 @@ "TeamMidnightDust" ], "contributors": [ - { - "name": "Jaffe2718", - "contact": { - "email": "qqyttwqeei@163.com", - "homepage": "https://space.bilibili.com/1671742926" - } - } + "maloryware", + "Jaffe2718" ], "contact": { "homepage": "https://www.midnightdust.eu/", @@ -51,11 +46,9 @@ "custom": { "modmenu": { "links": { - "modmenu.discord": "https://discord.midnightdust.eu/", - "modmenu.website": "https://www.midnightdust.eu/", - "midnightlib.curseforge": "https://www.curseforge.com/minecraft/mc-mods/midnightlib", - "midnightlib.modrinth": "https://modrinth.com/mod/midnightlib", - "midnightlib.wiki": "https://github.com/TeamMidnightDust/MidnightLib/wiki" + "modmenu.discord": "http://discord.midnightdust.eu/", + "modmenu.website": "https://midnightdust.eu/midnightlib", + "midnightlib.wiki": "https://midnightdust.eu/wiki/midnightlib" }, "badges": [ "library" ] } From 2abf9040a77fa1b9d34b0df12bc27400fb318e31 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Thu, 27 Mar 2025 23:30:03 +0100 Subject: [PATCH 063/100] feat: conditions! + large cleanup --- .../lib/config/MidnightConfig.java | 96 +++++++++++++------ .../example/config/MidnightConfigExample.java | 28 ++++++ .../resources/assets/modid/lang/en_us.json | 3 +- 3 files changed, 95 insertions(+), 32 deletions(-) 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 0e078ea..27021b1 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -40,27 +40,34 @@ public abstract class MidnightConfig { private static final Pattern HEXADECIMAL_ONLY = Pattern.compile("(-?[#0-9a-fA-F]*)"); private static final List entries = new ArrayList<>(); + private static boolean reloadScreen = false; public static class EntryInfo { public Entry entry; public Comment comment; - final Field field; - Class dataType; + public Condition condition; + public final Field field; + public final Class dataType; + public final String modid, fieldName; int listIndex; Object defaultValue, value, function; - String modid, fieldName, tempValue = ""; // The value visible in the config screen + String tempValue; // The value visible in the config screen boolean inLimits = true; Text name, error; ClickableWidget actionButton; // color picker button / explorer button Tab tab; + boolean conditionsMet = true; - public EntryInfo(Field field) { - this.field = field; + public EntryInfo(Field field, String modid) { + this.field = field; this.modid = modid; if (field != null) { - this.fieldName = field.getName(); - this.entry = field.getAnnotation(Entry.class); - this.comment = field.getAnnotation(Comment.class); + this.fieldName = field.getName(); this.dataType = getUnderlyingType(field); + this.entry = field.getAnnotation(Entry.class); this.comment = field.getAnnotation(Comment.class); this.condition = field.getAnnotation(Condition.class); + } else { + this.fieldName = ""; this.dataType = null; } + if (entry != null && !entry.name().isEmpty()) this.name = Text.translatable(entry.name()); + else if (comment != null && !comment.name().isEmpty()) this.name = Text.translatable(comment.name()); } public void setValue(Object value) { if (this.field.getType() != List.class) { this.value = value; @@ -73,7 +80,19 @@ public abstract class MidnightConfig { else try { return ((List) this.value).get(this.listIndex).toString(); } catch (Exception ignored) {return "";} } public void updateFieldValue() { - try { this.field.set(null, this.value); } catch (IllegalAccessException ignored) {} + try { if (this.field.get(null) != value) updateConditions(tempValue); + this.field.set(null, this.value); + } catch (IllegalAccessException ignored) {} + } + @SuppressWarnings("ConstantValue") //pertains to requiredModLoaded + public void updateConditions(String newTempValue) { + for (EntryInfo info : entries) { + boolean prevConditionState = info.conditionsMet; + if (info.condition != null && ((info.condition.requiredOption().contains(":") ? "" : info.modid + ":") + info.condition.requiredOption()).equals(this.modid + ":" + this.fieldName)) + info.conditionsMet = Objects.equals(info.condition.requiredValue(), newTempValue); + if (info.condition != null && !info.condition.requiredModId().isEmpty() && !PlatformFunctions.isModLoaded(info.condition.requiredModId())) info.conditionsMet = false; + if (prevConditionState != info.conditionsMet) reloadScreen = true; + } } public void writeList(int index, T value) { var list = (List) this.value; @@ -105,6 +124,7 @@ public abstract class MidnightConfig { for (EntryInfo info : entries) if (info.field != null && info.entry != null) { try { info.value = info.field.get(null); info.tempValue = info.toTemporaryValue(); + info.updateConditions(info.tempValue); } catch (IllegalAccessException ignored) {} } } @@ -113,7 +133,7 @@ public abstract class MidnightConfig { configClass.put(modid, config); for (Field field : config.getFields()) { - EntryInfo info = new EntryInfo(field); + EntryInfo info = new EntryInfo(field, modid); if ((field.isAnnotationPresent(Entry.class) || field.isAnnotationPresent(Comment.class)) && !field.isAnnotationPresent(Server.class) && !field.isAnnotationPresent(Hidden.class) && PlatformFunctions.isClientEnv()) initClient(modid, field, info); if (field.isAnnotationPresent(Entry.class)) @@ -122,19 +142,10 @@ public abstract class MidnightConfig { } loadValuesFromJson(modid); } - @SuppressWarnings("ConstantValue") //pertains to requiredModLoaded @Environment(EnvType.CLIENT) private static void initClient(String modid, Field field, EntryInfo info) { - info.dataType = getUnderlyingType(field); - Entry e = info.entry; Comment c = info.comment; - info.modid = modid; - boolean requiredModLoaded = true; - + Entry e = info.entry; if (e != null) { - if (!e.requiredMod().isEmpty()) requiredModLoaded = PlatformFunctions.isModLoaded(e.requiredMod()); - - if (!requiredModLoaded) return; - if (!e.name().isEmpty()) info.name = Text.translatable(e.name()); if (info.dataType == int.class) textField(info, Integer::parseInt, INTEGER_ONLY, (int) e.min(), (int) e.max(), true); else if (info.dataType == float.class) textField(info, Float::parseFloat, DECIMAL_ONLY, (float) e.min(), (float) e.max(), false); else if (info.dataType == double.class) textField(info, Double::parseDouble, DECIMAL_ONLY, e.min(), e.max(), false); @@ -154,10 +165,9 @@ public abstract class MidnightConfig { int index = values.indexOf(info.value) + 1; info.value = values.get(index >= values.size() ? 0 : index); button.setMessage(func.apply(info.value)); }, func); - }} else if (c != null) { - if (!c.requiredMod().isEmpty()) requiredModLoaded = PlatformFunctions.isModLoaded(c.requiredMod()); + } } - if (requiredModLoaded) entries.add(info); + entries.add(info); } public static Class getUnderlyingType(Field field) { Class rawType = field.getType(); @@ -259,12 +269,12 @@ public abstract class MidnightConfig { super.tick(); if (prevTab != null && prevTab != tabManager.getCurrentTab()) { prevTab = tabManager.getCurrentTab(); - this.list.clear(); fillList(); - list.setScrollY(0); + updateList(); list.setScrollY(0); } scrollProgress = list.getScrollY(); for (EntryInfo info : entries) info.updateFieldValue(); updateButtons(); + if (reloadScreen) { updateList(); reloadScreen = false; } } public void updateButtons() { if (this.list != null) { @@ -307,14 +317,18 @@ public abstract class MidnightConfig { this.addSelectableChild(this.list); fillList(); if (tabs.size() > 1) list.renderHeaderSeparator = false; } + public void updateList() { + this.list.clear(); fillList(); + } public void fillList() { for (EntryInfo info : entries) { + if (!info.conditionsMet && info.condition != null && !info.condition.visibleButLocked()) continue; if (info.modid.equals(modid) && (info.tab == null || info.tab == tabManager.getCurrentTab())) { Text name = Objects.requireNonNullElseGet(info.name, () -> Text.translatable(translationPrefix + info.fieldName)); TextIconButtonWidget resetButton = TextIconButtonWidget.builder(Text.translatable("controls.reset"), (button -> { info.value = info.defaultValue; info.listIndex = 0; info.tempValue = info.toTemporaryValue(); - list.clear(); fillList(); + updateList(); }), true).texture(Identifier.of("midnightlib","icon/reset"), 12, 12).dimension(20, 20).build(); resetButton.setPosition(width - 205 + 150 + 25, 0); @@ -348,7 +362,7 @@ public abstract class MidnightConfig { if (info.listIndex > values.size()) info.listIndex = 0; info.tempValue = info.toTemporaryValue(); if (info.listIndex == values.size()) info.tempValue = ""; - list.clear(); fillList(); + updateList(); })).dimensions(width - 185, 0, 20, 20).build(); } if (e.isColor()) { @@ -357,7 +371,7 @@ public abstract class MidnightConfig { Color newColor = JColorChooser.showDialog(null, Text.translatable("midnightconfig.colorChooser.title").getString(), Color.decode(!Objects.equals(info.tempValue, "") ? info.tempValue : "#FFFFFF")); if (newColor != null) { info.setValue("#" + Integer.toHexString(newColor.getRGB()).substring(2)); - list.clear(); fillList(); + updateList(); } }).start() ).dimensions(width - 185, 0, 20, 20).build(); @@ -375,13 +389,14 @@ public abstract class MidnightConfig { Text.translatable(translationPrefix + info.fieldName + ".fileFilter").getString(), e.fileExtensions())); if (fileChooser.showDialog(null, null) == JFileChooser.APPROVE_OPTION) { info.setValue(fileChooser.getSelectedFile().getAbsolutePath()); - list.clear(); fillList(); + updateList(); } }).start(), true ).texture(Identifier.of("midnightlib", "icon/explorer"), 12, 12).dimension(20, 20).build(); explorerButton.setPosition(width - 185, 0); info.actionButton = explorerButton; } + if (!info.conditionsMet) widget.active = false; List widgets = Lists.newArrayList(widget, resetButton); if (info.actionButton != null) { if (IS_SYSTEM_MAC) info.actionButton.active = false; @@ -516,7 +531,7 @@ public abstract class MidnightConfig { boolean isSlider() default false; int precision() default 100; String category() default "default"; - String requiredMod() default ""; + @Deprecated String requiredMod() default ""; } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Client {} @@ -536,6 +551,25 @@ public abstract class MidnightConfig { @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Comment { boolean centered() default false; String category() default "default"; - String requiredMod() default ""; + String name() default ""; + @Deprecated String requiredMod() default ""; + } + /** + * Condition Annotation
+ * - {@link Condition#requiredModId()}: The id of a mod that is required to be loaded.
+ * - {@link Condition#requiredOption()}: The {@link Field} which will be used to check the condition. Can also access options of other MidnightLib mods ("modid:optionName").
+ * - {@link Condition#requiredValue()}: The value that {@link Condition#requiredOption()} should be set to for the condition to be met.
+ * - {@link Condition#visibleButLocked()}: The behaviour to take when {@link Condition#requiredModId} is not loaded + * or {@link Condition#requiredOption()} returns a value that is not {@link Condition#requiredValue()}.
+ * true – Option is visible, but not editable
+ * false – Option is completely hidden + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + public @interface Condition { + String requiredModId() default ""; + String requiredOption() default ""; + String requiredValue() default "true"; + boolean visibleButLocked() default false; } } \ No newline at end of file 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 index 12d29c2..bee921b 100644 --- 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 @@ -17,6 +17,7 @@ public class MidnightConfigExample extends MidnightConfig { public static final String SLIDERS = "sliders"; public static final String LISTS = "lists"; public static final String FILES = "files"; + public static final String CONDITIONS = "conditions"; @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! @@ -69,5 +70,32 @@ public class MidnightConfigExample extends MidnightConfig { 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 + @Condition(requiredModId = "midnightlib") // Conditional options are here! + @Entry(category = CONDITIONS, name="Turn me on!") + public static boolean turnMeOn = false; + @Condition(requiredOption = "modid:turnMeOn", visibleButLocked = true) + @Entry(category = CONDITIONS, name="Turn me off!") + public static Boolean turnMeOff = true; + @Condition(requiredOption = "modid:turnMeOff", requiredValue = "false") + @Entry(category = CONDITIONS, name="Which is the best modloader?") + public static String bestModloader = ""; + @Condition(requiredOption = "bestModloader", requiredValue = "Forge") + @Comment(category = CONDITIONS, name="❌ You have bad taste :(", centered = true) // Don't take this too seriously btw :) + public static Comment answerForge; // Comments can also be conditional! + @Condition(requiredOption = "bestModloader", requiredValue = "NeoForge") + @Comment(category = CONDITIONS, name="⛏ Not quite, but it's alright!", centered = true) + public static Comment answerNeoforge; + @Condition(requiredOption = "bestModloader", requiredValue = "Fabric") + @Comment(category = CONDITIONS, name="⭐ Correct! Fabric (and Quilt) are the best!", centered = true) + public static Comment answerFabric; + @Condition(requiredOption = "bestModloader", requiredValue = "Quilt") + @Comment(category = CONDITIONS, name="⭐ Correct! Quilt (and Fabric) are the best!", centered = true) + public static Comment answerQuilt; + + @Condition(requiredOption = "midnightlib:config_screen_list", requiredValue = "FALSE") // Access options of other mods that are also using MidnightLib + @Comment(category = CONDITIONS) public static Comment spaceracer; + @Condition(requiredOption = "midnightlib:config_screen_list", requiredValue = "FALSE") + @Comment(category = CONDITIONS, name="You disabled MidnightLib's config screen list. Why? :(", centered = true) public static Comment why; + 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/lang/en_us.json b/test-fabric/src/main/resources/assets/modid/lang/en_us.json index 8ac67dd..463f00b 100644 --- a/test-fabric/src/main/resources/assets/modid/lang/en_us.json +++ b/test-fabric/src/main/resources/assets/modid/lang/en_us.json @@ -20,5 +20,6 @@ "modid.midnightconfig.category.text": "Text", "modid.midnightconfig.category.sliders": "Sliders", "modid.midnightconfig.category.lists": "Lists", - "modid.midnightconfig.category.files": "Files" + "modid.midnightconfig.category.files": "Files", + "modid.midnightconfig.category.conditions": "Quiz" } \ No newline at end of file From ebcafa6b0910b0355113a8a2f7ee54fbff720894 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Thu, 27 Mar 2025 23:36:48 +0100 Subject: [PATCH 064/100] chore: bump version 1.7.0, baby! --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 0ed0255..beb5c67 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ yarn_mappings=1.21.4+build.1 enabled_platforms=fabric,neoforge archives_base_name=midnightlib -mod_version=1.6.11 +mod_version=1.7.0 maven_group=eu.midnightdust release_type=release curseforge_id=488090 From faf8c199b443eb5dbcd963c465823fbe9cca75e4 Mon Sep 17 00:00:00 2001 From: Jaffe2718 Date: Wed, 2 Apr 2025 22:00:54 +0800 Subject: [PATCH 065/100] fix bug: the `@Condition` does not trigger in real-time to update the menu UI --- .../main/java/eu/midnightdust/lib/config/MidnightConfig.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 27021b1..79874f5 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -163,7 +163,9 @@ public abstract class MidnightConfig { }; info.function = new AbstractMap.SimpleEntry>(button -> { int index = values.indexOf(info.value) + 1; - info.value = values.get(index >= values.size() ? 0 : index); button.setMessage(func.apply(info.value)); + //info.value = values.get(index >= values.size() ? 0 : index); button.setMessage(func.apply(info.value)); + info.setValue(values.get(index >= values.size() ? 0 : index)); + button.setMessage(func.apply(info.value)); }, func); } } From 6eceaded3a6e2f6a086e86f8c747c7ed252477ec Mon Sep 17 00:00:00 2001 From: Jaffe2718 Date: Thu, 3 Apr 2025 11:13:19 +0800 Subject: [PATCH 066/100] fix bugs: The condition update algorithm is chaotic and does not work properly when the condition values conflict new features: multi-conditions config is supported --- .../lib/config/MidnightConfig.java | 60 ++++++++++++++----- 1 file changed, 46 insertions(+), 14 deletions(-) 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 79874f5..63b263f 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -14,12 +14,13 @@ import net.minecraft.registry.Registries; import net.minecraft.screen.ScreenTexts; import net.minecraft.text.Style; import net.minecraft.text.Text; import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; import java.awt.Color; import java.io.IOException; -import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import java.lang.annotation.*; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; import java.nio.file.Files; import java.nio.file.Path; import java.util.*; @@ -45,7 +46,8 @@ public abstract class MidnightConfig { public static class EntryInfo { public Entry entry; public Comment comment; - public Condition condition; +// @ApiStatus.Obsolete public Condition condition; + public Condition[] conditions; public final Field field; public final Class dataType; public final String modid, fieldName; @@ -61,8 +63,13 @@ public abstract class MidnightConfig { public EntryInfo(Field field, String modid) { this.field = field; this.modid = modid; if (field != null) { - this.fieldName = field.getName(); this.dataType = getUnderlyingType(field); - this.entry = field.getAnnotation(Entry.class); this.comment = field.getAnnotation(Comment.class); this.condition = field.getAnnotation(Condition.class); + this.fieldName = field.getName(); + this.dataType = getUnderlyingType(field); + this.entry = field.getAnnotation(Entry.class); + this.comment = field.getAnnotation(Comment.class); + // TODO: use multiple annotations +// this.condition = field.getAnnotation(Condition.class); + this.conditions = field.getAnnotationsByType(Condition.class); } else { this.fieldName = ""; this.dataType = null; } @@ -80,19 +87,30 @@ public abstract class MidnightConfig { else try { return ((List) this.value).get(this.listIndex).toString(); } catch (Exception ignored) {return "";} } public void updateFieldValue() { - try { if (this.field.get(null) != value) updateConditions(tempValue); + try { + if (this.field.get(null) != value) entries.forEach(EntryInfo::updateConditions); this.field.set(null, this.value); } catch (IllegalAccessException ignored) {} } @SuppressWarnings("ConstantValue") //pertains to requiredModLoaded - public void updateConditions(String newTempValue) { - for (EntryInfo info : entries) { - boolean prevConditionState = info.conditionsMet; - if (info.condition != null && ((info.condition.requiredOption().contains(":") ? "" : info.modid + ":") + info.condition.requiredOption()).equals(this.modid + ":" + this.fieldName)) - info.conditionsMet = Objects.equals(info.condition.requiredValue(), newTempValue); - if (info.condition != null && !info.condition.requiredModId().isEmpty() && !PlatformFunctions.isModLoaded(info.condition.requiredModId())) info.conditionsMet = false; - if (prevConditionState != info.conditionsMet) reloadScreen = true; + public void updateConditions() { + boolean prevConditionState = this.conditionsMet; + if (this.conditions.length > 0) this.conditionsMet = true; // reset conditions + for (Condition condition : this.conditions) { + // TODO: redefine entries as a HashMap to optimize complexity + for (EntryInfo info : entries) { + if (((condition.requiredOption().contains(":") ? "" : (this.modid + ":")) + condition.requiredOption()).equals(info.modid + ":" + info.fieldName)) { + this.conditionsMet &= info.tempValue.equals(condition.requiredValue()); +// System.out.println(this.modid + ":" + this.fieldName + "#" + condition.requiredOption() + ": " + condition.requiredValue() + " " + info.tempValue); + } + if (!condition.requiredModId().isEmpty() && !PlatformFunctions.isModLoaded(condition.requiredModId())) { + this.conditionsMet = false; + } + if (!this.conditionsMet) break; + } + if (!this.conditionsMet) break; } + if (prevConditionState != this.conditionsMet) reloadScreen = true; } public void writeList(int index, T value) { var list = (List) this.value; @@ -124,7 +142,7 @@ public abstract class MidnightConfig { for (EntryInfo info : entries) if (info.field != null && info.entry != null) { try { info.value = info.field.get(null); info.tempValue = info.toTemporaryValue(); - info.updateConditions(info.tempValue); + info.updateConditions(); } catch (IllegalAccessException ignored) {} } } @@ -324,7 +342,14 @@ public abstract class MidnightConfig { } public void fillList() { for (EntryInfo info : entries) { - if (!info.conditionsMet && info.condition != null && !info.condition.visibleButLocked()) continue; +// if (!info.conditionsMet && info.condition != null && !info.condition.visibleButLocked()) continue; + if (!info.conditionsMet) { + boolean visibleButLocked = false; + for (Condition condition : info.conditions) { + visibleButLocked |= condition.visibleButLocked(); + } + if (!visibleButLocked) continue; + } if (info.modid.equals(modid) && (info.tab == null || info.tab == tabManager.getCurrentTab())) { Text name = Objects.requireNonNullElseGet(info.name, () -> Text.translatable(translationPrefix + info.fieldName)); TextIconButtonWidget resetButton = TextIconButtonWidget.builder(Text.translatable("controls.reset"), (button -> { @@ -567,6 +592,7 @@ public abstract class MidnightConfig { * false – Option is completely hidden */ @Retention(RetentionPolicy.RUNTIME) + @Repeatable(Conditions.class) @Target(ElementType.FIELD) public @interface Condition { String requiredModId() default ""; @@ -574,4 +600,10 @@ public abstract class MidnightConfig { String requiredValue() default "true"; boolean visibleButLocked() default false; } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + public @interface Conditions { + Condition[] value(); + } } \ No newline at end of file From c1299c219522f929fa2eb72a08e44947cf290583 Mon Sep 17 00:00:00 2001 From: Jaffe2718 Date: Thu, 3 Apr 2025 11:14:02 +0800 Subject: [PATCH 067/100] add examples --- .../example/config/MidnightConfigExample.java | 38 +++++++++++++++++-- .../resources/assets/modid/lang/en_us.json | 20 +++++++--- 2 files changed, 49 insertions(+), 9 deletions(-) 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 index bee921b..c0fedc6 100644 --- 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 @@ -18,6 +18,7 @@ public class MidnightConfigExample extends MidnightConfig { public static final String LISTS = "lists"; public static final String FILES = "files"; public static final String CONDITIONS = "conditions"; + public static final String MULTI_CONDITIONS = "multiConditions"; @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! @@ -27,9 +28,9 @@ public class MidnightConfigExample extends MidnightConfig { @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 = TEXT) public static ModPlatform modPlatform = ModPlatform.FABRIC; // Example for an enum option + public enum ModPlatform { // Enums allow the user to cycle through predefined options + QUILT, FABRIC, FORGE, NEOFORGE, VANILLA } @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 @@ -74,7 +75,7 @@ public class MidnightConfigExample extends MidnightConfig { @Entry(category = CONDITIONS, name="Turn me on!") public static boolean turnMeOn = false; @Condition(requiredOption = "modid:turnMeOn", visibleButLocked = true) - @Entry(category = CONDITIONS, name="Turn me off!") + @Entry(category = CONDITIONS, name="Turn me off (locked if modid:turnMeOn is false)!") public static Boolean turnMeOff = true; @Condition(requiredOption = "modid:turnMeOff", requiredValue = "false") @Entry(category = CONDITIONS, name="Which is the best modloader?") @@ -97,5 +98,34 @@ public class MidnightConfigExample extends MidnightConfig { @Condition(requiredOption = "midnightlib:config_screen_list", requiredValue = "FALSE") @Comment(category = CONDITIONS, name="You disabled MidnightLib's config screen list. Why? :(", centered = true) public static Comment why; + + // Multi-Conditions are also supported! + public enum Arch {X86, X86_64, AARCH64, RISCV64} + public enum OS {WINDOWS, MAC, LINUX} + @Entry(category = MULTI_CONDITIONS, name = "Arch") public static Arch myArch = Arch.X86; + @Entry(category = MULTI_CONDITIONS, name = "OS") public static OS myOS = OS.WINDOWS; + @Entry(category = MULTI_CONDITIONS, name = "Mod Platform") public static ModPlatform myPlatform = ModPlatform.FABRIC; + + @Condition(requiredOption = "modid:myArch", requiredValue = "X86_64") + @Condition(requiredOption = "modid:myOS", requiredValue = "WINDOWS") + @Condition(requiredOption = "modid:myPlatform", requiredValue = "FABRIC") + @Comment(category = MULTI_CONDITIONS, name = "MidnightLib can be used on Windows x86_64 with Fabric!", centered = true) public static Comment x86_64_windows_fabric; + + @Condition(requiredOption = "modid:myArch", requiredValue = "X86_64") + @Condition(requiredOption = "modid:myOS", requiredValue = "LINUX") + @Condition(requiredOption = "modid:myPlatform", requiredValue = "FABRIC") + @Comment(category = MULTI_CONDITIONS, name = "MidnightLib can be used on Linux x86_64 with Fabric!", centered = true) public static Comment x86_64_linux_fabric; + + @Condition(requiredOption = "modid:myArch", requiredValue = "X86_64") + @Condition(requiredOption = "modid:myOS", requiredValue = "WINDOWS") + @Condition(requiredOption = "modid:myPlatform", requiredValue = "NEOFORGE") + @Comment(category = MULTI_CONDITIONS, name = "MidnightLib can be used on Windows x86_64 with NeoForge!", centered = true) public static Comment x86_64_windows_neoforge; + + @Condition(requiredOption = "modid:myArch", requiredValue = "X86_64") + @Condition(requiredOption = "modid:myOS", requiredValue = "LINUX") + @Condition(requiredOption = "modid:myPlatform", requiredValue = "NEOFORGE") + @Comment(category = MULTI_CONDITIONS, name = "MidnightLib can be used on Linux x86_64 with NeoForge!", centered = true) public static Comment x86_64_linux_neoforge; + + 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/lang/en_us.json b/test-fabric/src/main/resources/assets/modid/lang/en_us.json index 463f00b..b014330 100644 --- a/test-fabric/src/main/resources/assets/modid/lang/en_us.json +++ b/test-fabric/src/main/resources/assets/modid/lang/en_us.json @@ -10,10 +10,19 @@ "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.modPlatform":"I am an enum!", + "modid.midnightconfig.enum.Arch.X86":"X86", + "modid.midnightconfig.enum.Arch.X86_64":"X86_64", + "modid.midnightconfig.enum.Arch.AARCH64":"AARCH64", + "modid.midnightconfig.enum.Arch.RISCV64":"RISCV64", + "modid.midnightconfig.enum.OS.LINUX":"Linux", + "modid.midnightconfig.enum.OS.WINDOWS":"Windows", + "modid.midnightconfig.enum.OS.MAC":"MacOS", + "modid.midnightconfig.enum.ModPlatform.FORGE":"Forge", + "modid.midnightconfig.enum.ModPlatform.FABRIC":"Fabric", + "modid.midnightconfig.enum.ModPlatform.QUILT":"Quilt", + "modid.midnightconfig.enum.ModPlatform.NEOFORGE":"NeoForge", + "modid.midnightconfig.enum.ModPlatform.VANILLA":"Vanilla", "modid.midnightconfig.myFileOrDirectory.fileChooser": "Select an image or directory", "modid.midnightconfig.myFileOrDirectory.fileFilter": "Supported Images (.png, .jpg, .jpeg)", "modid.midnightconfig.category.numbers": "Numbers", @@ -21,5 +30,6 @@ "modid.midnightconfig.category.sliders": "Sliders", "modid.midnightconfig.category.lists": "Lists", "modid.midnightconfig.category.files": "Files", - "modid.midnightconfig.category.conditions": "Quiz" + "modid.midnightconfig.category.conditions": "Quiz", + "modid.midnightconfig.category.multiConditions": "Multi-Conditions" } \ No newline at end of file From 170363ef359167960d5e56d785a6d8b7f5ee3920 Mon Sep 17 00:00:00 2001 From: Jaffe2718 Date: Thu, 3 Apr 2025 11:15:03 +0800 Subject: [PATCH 068/100] chore: bump version --- gradle.properties | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index beb5c67..59fae1b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ yarn_mappings=1.21.4+build.1 enabled_platforms=fabric,neoforge archives_base_name=midnightlib -mod_version=1.7.0 +mod_version=1.7.1-rc.1 maven_group=eu.midnightdust release_type=release curseforge_id=488090 @@ -18,6 +18,4 @@ fabric_api_version=0.110.5+1.21.4 neoforge_version=21.4.3-beta yarn_mappings_patch_neoforge_version = 1.21+build.4 -quilt_loader_version=0.19.0-beta.18 -quilt_fabric_api_version=7.0.1+0.83.0-1.20 mod_menu_version = 9.0.0 \ No newline at end of file From f4d11832706f2d6558410e6af355e0de5b137b45 Mon Sep 17 00:00:00 2001 From: Jaffe2718 Date: Thu, 3 Apr 2025 11:19:03 +0800 Subject: [PATCH 069/100] cleanup & suppress unused warnings --- .../main/java/eu/midnightdust/lib/config/MidnightConfig.java | 2 -- .../fabric/example/config/MidnightConfigExample.java | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) 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 63b263f..18ea2c2 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -67,8 +67,6 @@ public abstract class MidnightConfig { this.dataType = getUnderlyingType(field); this.entry = field.getAnnotation(Entry.class); this.comment = field.getAnnotation(Comment.class); - // TODO: use multiple annotations -// this.condition = field.getAnnotation(Condition.class); this.conditions = field.getAnnotationsByType(Condition.class); } else { this.fieldName = ""; this.dataType = null; 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 index c0fedc6..50495cb 100644 --- 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 @@ -10,7 +10,7 @@ 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*/ - +@SuppressWarnings("unused") public class MidnightConfigExample extends MidnightConfig { public static final String TEXT = "text"; public static final String NUMBERS = "numbers"; From ac5a035906a63f85ffb612939ae8220e522a2610 Mon Sep 17 00:00:00 2001 From: Jaffe2718 Date: Thu, 3 Apr 2025 13:30:46 +0800 Subject: [PATCH 070/100] optimize: use hash tables to reduce complexity --- .../lib/config/MidnightConfig.java | 81 ++++++++++--------- gradle.properties | 2 +- 2 files changed, 42 insertions(+), 41 deletions(-) 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 18ea2c2..10c2668 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -14,7 +14,6 @@ import net.minecraft.registry.Registries; import net.minecraft.screen.ScreenTexts; import net.minecraft.text.Style; import net.minecraft.text.Text; import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; -import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; @@ -40,7 +39,9 @@ public abstract class MidnightConfig { private static final Pattern DECIMAL_ONLY = Pattern.compile("-?(\\d+\\.?\\d*|\\d*\\.?\\d+|\\.)"); private static final Pattern HEXADECIMAL_ONLY = Pattern.compile("(-?[#0-9a-fA-F]*)"); - private static final List entries = new ArrayList<>(); +// private static final List entries = new ArrayList<>(); + private static final Hashtable entries = new Hashtable<>(); // modid:fieldName -> EntryInfo + private static final List entryOrder = Lists.newArrayList(); // ordered list of entries private static boolean reloadScreen = false; public static class EntryInfo { @@ -86,7 +87,7 @@ public abstract class MidnightConfig { } public void updateFieldValue() { try { - if (this.field.get(null) != value) entries.forEach(EntryInfo::updateConditions); + if (this.field.get(null) != value) entries.values().forEach(EntryInfo::updateConditions); this.field.set(null, this.value); } catch (IllegalAccessException ignored) {} } @@ -95,16 +96,12 @@ public abstract class MidnightConfig { boolean prevConditionState = this.conditionsMet; if (this.conditions.length > 0) this.conditionsMet = true; // reset conditions for (Condition condition : this.conditions) { - // TODO: redefine entries as a HashMap to optimize complexity - for (EntryInfo info : entries) { - if (((condition.requiredOption().contains(":") ? "" : (this.modid + ":")) + condition.requiredOption()).equals(info.modid + ":" + info.fieldName)) { - this.conditionsMet &= info.tempValue.equals(condition.requiredValue()); -// System.out.println(this.modid + ":" + this.fieldName + "#" + condition.requiredOption() + ": " + condition.requiredValue() + " " + info.tempValue); - } - if (!condition.requiredModId().isEmpty() && !PlatformFunctions.isModLoaded(condition.requiredModId())) { - this.conditionsMet = false; - } - if (!this.conditionsMet) break; + if (!condition.requiredModId().isEmpty() && !PlatformFunctions.isModLoaded(condition.requiredModId())) { + this.conditionsMet = false; + } + String requiredOption = condition.requiredOption().contains(":") ? condition.requiredOption() : (this.modid + ":" + condition.requiredOption()); + if (entries.get(requiredOption) instanceof EntryInfo info) { + this.conditionsMet &= condition.requiredValue().equals(info.tempValue); } if (!this.conditionsMet) break; } @@ -130,19 +127,21 @@ public abstract class MidnightConfig { @SuppressWarnings("unused") // Utility for mod authors public static @Nullable Object getDefaultValue(String modid, String entry) { - for (EntryInfo e : entries) { - if (modid.equals(e.modid) && entry.equals(e.field.getName())) return e.defaultValue; - } return null; + String key = modid + ":" + entry; + return entries.containsKey(key) ? entries.get(key).defaultValue : null; } public static void loadValuesFromJson(String modid) { try { gson.fromJson(Files.newBufferedReader(path), configClass.get(modid)); } catch (Exception e) { write(modid); } - - for (EntryInfo info : entries) if (info.field != null && info.entry != null) { - try { info.value = info.field.get(null); info.tempValue = info.toTemporaryValue(); - info.updateConditions(); - } catch (IllegalAccessException ignored) {} - } + entries.values().forEach(info -> { + if (info.field != null && info.entry != null) { + try { + info.value = info.field.get(null); + info.tempValue = info.toTemporaryValue(); + info.updateConditions(); + } catch (IllegalAccessException ignored) {} + } + }); } public static void init(String modid, Class config) { path = PlatformFunctions.getConfigDirectory().resolve(modid + ".json"); @@ -161,6 +160,7 @@ public abstract class MidnightConfig { @Environment(EnvType.CLIENT) private static void initClient(String modid, Field field, EntryInfo info) { Entry e = info.entry; + String key = modid + ":" + field.getName(); if (e != null) { if (info.dataType == int.class) textField(info, Integer::parseInt, INTEGER_ONLY, (int) e.min(), (int) e.max(), true); else if (info.dataType == float.class) textField(info, Float::parseFloat, DECIMAL_ONLY, (float) e.min(), (float) e.max(), false); @@ -185,7 +185,8 @@ public abstract class MidnightConfig { }, func); } } - entries.add(info); + entries.put(key, info); + entryOrder.add(key); } public static Class getUnderlyingType(Field field) { Class rawType = field.getType(); @@ -218,7 +219,7 @@ public abstract class MidnightConfig { info.tempValue = s; t.setEditableColor(inLimits? 0xFFFFFFFF : 0xFFFF7777); info.inLimits = inLimits; - b.active = entries.stream().allMatch(e -> e.inLimits); + b.active = entries.values().stream().allMatch(e -> e.inLimits); if (inLimits) { if (info.dataType == Identifier.class) info.setValue(Identifier.tryParse(s)); @@ -255,17 +256,18 @@ public abstract class MidnightConfig { this.parent = parent; this.modid = modid; this.translationPrefix = modid + ".midnightconfig."; loadValuesFromJson(modid); - - for (EntryInfo e : entries) if (e.modid.equals(modid)) { - String tabId = e.entry != null ? e.entry.category() : e.comment.category(); - String name = translationPrefix + "category." + tabId; - if (!I18n.hasTranslation(name) && tabId.equals("default")) - name = translationPrefix + "title"; - if (!tabs.containsKey(name)) { - Tab tab = new GridScreenTab(Text.translatable(name)); - e.tab = tab; tabs.put(name, tab); - } else e.tab = tabs.get(name); - } + entryOrder.stream().map(entries::get).forEach(info -> { + if (info.modid.equals(modid)) { + String tabId = info.entry != null ? info.entry.category() : info.comment.category(); + String name = translationPrefix + "category." + tabId; + if (!I18n.hasTranslation(name) && tabId.equals("default")) + name = translationPrefix + "title"; + if (!tabs.containsKey(name)) { + Tab tab = new GridScreenTab(Text.translatable(name)); + info.tab = tab; tabs.put(name, tab); + } else info.tab = tabs.get(name); + } + }); tabNavigation = TabNavigationWidget.builder(tabManager, this.width).tabs(tabs.values().toArray(new Tab[0])).build(); tabNavigation.selectTab(0, false); tabNavigation.init(); @@ -290,7 +292,7 @@ public abstract class MidnightConfig { updateList(); list.setScrollY(0); } scrollProgress = list.getScrollY(); - for (EntryInfo info : entries) info.updateFieldValue(); + for (EntryInfo info : entries.values()) info.updateFieldValue(); updateButtons(); if (reloadScreen) { updateList(); reloadScreen = false; } } @@ -314,7 +316,7 @@ public abstract class MidnightConfig { Objects.requireNonNull(client).setScreen(parent); } private void cleanup() { - entries.forEach(info -> { + entries.values().forEach(info -> { info.error = null; info.value = null; info.tempValue = null; info.actionButton = null; info.listIndex = 0; info.tab = null; info.inLimits = true; }); } @@ -326,7 +328,7 @@ public abstract class MidnightConfig { this.addDrawableChild(ButtonWidget.builder(ScreenTexts.CANCEL, button -> this.close()).dimensions(this.width / 2 - 154, this.height - 26, 150, 20).build()); done = this.addDrawableChild(ButtonWidget.builder(ScreenTexts.DONE, (button) -> { - for (EntryInfo info : entries) if (info.modid.equals(modid)) info.updateFieldValue(); + for (EntryInfo info : entries.values()) if (info.modid.equals(modid)) info.updateFieldValue(); write(modid); cleanup(); Objects.requireNonNull(client).setScreen(parent); }).dimensions(this.width / 2 + 4, this.height - 26, 150, 20).build()); @@ -339,8 +341,7 @@ public abstract class MidnightConfig { this.list.clear(); fillList(); } public void fillList() { - for (EntryInfo info : entries) { -// if (!info.conditionsMet && info.condition != null && !info.condition.visibleButLocked()) continue; + for (EntryInfo info : entryOrder.stream().map(entries::get).toList()) { if (!info.conditionsMet) { boolean visibleButLocked = false; for (Condition condition : info.conditions) { diff --git a/gradle.properties b/gradle.properties index 59fae1b..8435a28 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ yarn_mappings=1.21.4+build.1 enabled_platforms=fabric,neoforge archives_base_name=midnightlib -mod_version=1.7.1-rc.1 +mod_version=1.7.1-rc.2 maven_group=eu.midnightdust release_type=release curseforge_id=488090 From ee705b2cbdfc4a96db858c8f8abc19b3c276f6af Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Sat, 5 Apr 2025 11:47:04 +0200 Subject: [PATCH 071/100] feat: replace Hashtable with LinkedHashMap - Keeps the entry order in tact without the need to store it separately --- .../midnightdust/lib/config/MidnightConfig.java | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) 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 10c2668..ddbd496 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -39,15 +39,12 @@ public abstract class MidnightConfig { private static final Pattern DECIMAL_ONLY = Pattern.compile("-?(\\d+\\.?\\d*|\\d*\\.?\\d+|\\.)"); private static final Pattern HEXADECIMAL_ONLY = Pattern.compile("(-?[#0-9a-fA-F]*)"); -// private static final List entries = new ArrayList<>(); - private static final Hashtable entries = new Hashtable<>(); // modid:fieldName -> EntryInfo - private static final List entryOrder = Lists.newArrayList(); // ordered list of entries + private static final LinkedHashMap entries = new LinkedHashMap<>(); // modid:fieldName -> EntryInfo private static boolean reloadScreen = false; public static class EntryInfo { public Entry entry; public Comment comment; -// @ApiStatus.Obsolete public Condition condition; public Condition[] conditions; public final Field field; public final Class dataType; @@ -96,13 +93,11 @@ public abstract class MidnightConfig { boolean prevConditionState = this.conditionsMet; if (this.conditions.length > 0) this.conditionsMet = true; // reset conditions for (Condition condition : this.conditions) { - if (!condition.requiredModId().isEmpty() && !PlatformFunctions.isModLoaded(condition.requiredModId())) { + if (!condition.requiredModId().isEmpty() && !PlatformFunctions.isModLoaded(condition.requiredModId())) this.conditionsMet = false; - } String requiredOption = condition.requiredOption().contains(":") ? condition.requiredOption() : (this.modid + ":" + condition.requiredOption()); - if (entries.get(requiredOption) instanceof EntryInfo info) { + if (entries.get(requiredOption) instanceof EntryInfo info) this.conditionsMet &= condition.requiredValue().equals(info.tempValue); - } if (!this.conditionsMet) break; } if (prevConditionState != this.conditionsMet) reloadScreen = true; @@ -186,7 +181,6 @@ public abstract class MidnightConfig { } } entries.put(key, info); - entryOrder.add(key); } public static Class getUnderlyingType(Field field) { Class rawType = field.getType(); @@ -256,7 +250,7 @@ public abstract class MidnightConfig { this.parent = parent; this.modid = modid; this.translationPrefix = modid + ".midnightconfig."; loadValuesFromJson(modid); - entryOrder.stream().map(entries::get).forEach(info -> { + entries.forEach((id, info) -> { if (info.modid.equals(modid)) { String tabId = info.entry != null ? info.entry.category() : info.comment.category(); String name = translationPrefix + "category." + tabId; @@ -341,7 +335,7 @@ public abstract class MidnightConfig { this.list.clear(); fillList(); } public void fillList() { - for (EntryInfo info : entryOrder.stream().map(entries::get).toList()) { + for (EntryInfo info : entries.sequencedValues()) { if (!info.conditionsMet) { boolean visibleButLocked = false; for (Condition condition : info.conditions) { From 64be14f1362382ec33db4c972a344345294d794c Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Sat, 5 Apr 2025 12:02:58 +0200 Subject: [PATCH 072/100] clean: improve entry access further --- .../main/java/eu/midnightdust/lib/config/MidnightConfig.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) 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 ddbd496..4487db3 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -174,7 +174,6 @@ public abstract class MidnightConfig { }; info.function = new AbstractMap.SimpleEntry>(button -> { int index = values.indexOf(info.value) + 1; - //info.value = values.get(index >= values.size() ? 0 : index); button.setMessage(func.apply(info.value)); info.setValue(values.get(index >= values.size() ? 0 : index)); button.setMessage(func.apply(info.value)); }, func); @@ -250,7 +249,7 @@ public abstract class MidnightConfig { this.parent = parent; this.modid = modid; this.translationPrefix = modid + ".midnightconfig."; loadValuesFromJson(modid); - entries.forEach((id, info) -> { + entries.values().forEach(info -> { if (info.modid.equals(modid)) { String tabId = info.entry != null ? info.entry.category() : info.comment.category(); String name = translationPrefix + "category." + tabId; @@ -335,7 +334,7 @@ public abstract class MidnightConfig { this.list.clear(); fillList(); } public void fillList() { - for (EntryInfo info : entries.sequencedValues()) { + for (EntryInfo info : entries.values()) { if (!info.conditionsMet) { boolean visibleButLocked = false; for (Condition condition : info.conditions) { From 386a95aca82d2a81c78887a398e3973d70d00410 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Sat, 5 Apr 2025 12:10:11 +0200 Subject: [PATCH 073/100] feat: optimize AutoCommand's file-size --- .../midnightdust/lib/config/AutoCommand.java | 40 +++++++++---------- 1 file changed, 18 insertions(+), 22 deletions(-) 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 95571c8..e41f920 100644 --- a/common/src/main/java/eu/midnightdust/lib/config/AutoCommand.java +++ b/common/src/main/java/eu/midnightdust/lib/config/AutoCommand.java @@ -18,44 +18,41 @@ public class AutoCommand { final Field field; final Class type; final String modid; - final boolean isList, isNumber; + final boolean isList; public AutoCommand(Field field, String modid) { 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; var command = CommandManager.literal(field.getName()).executes(this::getValue); if (type.isEnum()) { for (Object enumValue : field.getType().getEnumConstants()) - command = command.then(CommandManager.literal(enumValue.toString()).executes(ctx -> this.setValue(ctx.getSource(), enumValue, ""))); + command = command.then(CommandManager.literal(enumValue.toString()) + .executes(ctx -> this.setValue(ctx.getSource(), enumValue, ""))); } 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)))); + for (String action : new String[]{"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, ""))); PlatformFunctions.registerCommand(CommandManager.literal("midnightconfig").requires(source -> source.hasPermissionLevel(2)).then(CommandManager.literal(modid).then(command))); } public ArgumentType getArgType() { - 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()); - } + 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()); else if (type == boolean.class) return BoolArgumentType.bool(); return StringArgumentType.string(); } + public int setValueFromArg(CommandContext context, String action) { - 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); - } + 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); else if (type == boolean.class) return setValue(context.getSource(), BoolArgumentType.getBool(context, VALUE), action); return setValue(context.getSource(), StringArgumentType.getString(context, VALUE), action); } @@ -72,17 +69,16 @@ public class AutoCommand { MidnightConfig.write(modid); } catch (Exception e) { - if (!isList) source.sendError(Text.literal("Could not set "+field.getName()+" to value "+value+": " + e)); - else source.sendError(Text.literal((add ? "Could not add "+value+" to " : "Could not remove "+value+" from ")+field.getName() +": " + e)); + source.sendError(Text.literal(isList ? "Could not %s %s %s %s: %s".formatted(add ? "add" : "remove", value, add ? "to" : "from", field.getName(), e) : "Could not set %s to value %s: %s".formatted(field.getName(), value, e))); return 0; } - if (!isList) source.sendFeedback(() -> Text.literal("Successfully set " + field.getName()+" to "+value), true); - else source.sendFeedback(() -> Text.literal((add ? "Successfully added " +value+" to " : "Successfully removed " +value+" from ") +field.getName()), true); + source.sendFeedback(() -> Text.literal(isList ? "Successfully %s %s %s %s".formatted(add ? "added" : "removed", value, add ? "to" : "from", field.getName()) : + "Successfully set %s to %s".formatted(field.getName(), value)), true); return 1; } private int getValue(CommandContext context) { context.getSource().sendFeedback(() -> { - try { return Text.literal("The value of "+field.getName()+" is "+field.get(null)); + try { return Text.literal("The value of %s is %s".formatted(field.getName(), field.get(null))); } catch (IllegalAccessException e) {throw new RuntimeException(e);} }, true); return 0; From 9b29b208ebbcaf57999068890e45b2b246b12538 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Sat, 5 Apr 2025 12:38:38 +0200 Subject: [PATCH 074/100] docs: improve multi-conditions example --- .../example/config/MidnightConfigExample.java | 39 +++++-------------- 1 file changed, 9 insertions(+), 30 deletions(-) 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 index 50495cb..ec599de 100644 --- 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 @@ -18,7 +18,6 @@ public class MidnightConfigExample extends MidnightConfig { public static final String LISTS = "lists"; public static final String FILES = "files"; public static final String CONDITIONS = "conditions"; - public static final String MULTI_CONDITIONS = "multiConditions"; @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! @@ -77,18 +76,27 @@ public class MidnightConfigExample extends MidnightConfig { @Condition(requiredOption = "modid:turnMeOn", visibleButLocked = true) @Entry(category = CONDITIONS, name="Turn me off (locked if modid:turnMeOn is false)!") public static Boolean turnMeOff = true; + @Condition(requiredOption = "turnMeOn") // You can also use multiple conditions for the same entry @Condition(requiredOption = "modid:turnMeOff", requiredValue = "false") @Entry(category = CONDITIONS, name="Which is the best modloader?") public static String bestModloader = ""; + @Condition(requiredOption = "turnMeOn") + @Condition(requiredOption = "turnMeOff", requiredValue = "false") @Condition(requiredOption = "bestModloader", requiredValue = "Forge") @Comment(category = CONDITIONS, name="❌ You have bad taste :(", centered = true) // Don't take this too seriously btw :) public static Comment answerForge; // Comments can also be conditional! + @Condition(requiredOption = "turnMeOn") + @Condition(requiredOption = "turnMeOff", requiredValue = "false") @Condition(requiredOption = "bestModloader", requiredValue = "NeoForge") @Comment(category = CONDITIONS, name="⛏ Not quite, but it's alright!", centered = true) public static Comment answerNeoforge; + @Condition(requiredOption = "turnMeOn") + @Condition(requiredOption = "turnMeOff", requiredValue = "false") @Condition(requiredOption = "bestModloader", requiredValue = "Fabric") @Comment(category = CONDITIONS, name="⭐ Correct! Fabric (and Quilt) are the best!", centered = true) public static Comment answerFabric; + @Condition(requiredOption = "turnMeOn") + @Condition(requiredOption = "turnMeOff", requiredValue = "false") @Condition(requiredOption = "bestModloader", requiredValue = "Quilt") @Comment(category = CONDITIONS, name="⭐ Correct! Quilt (and Fabric) are the best!", centered = true) public static Comment answerQuilt; @@ -98,34 +106,5 @@ public class MidnightConfigExample extends MidnightConfig { @Condition(requiredOption = "midnightlib:config_screen_list", requiredValue = "FALSE") @Comment(category = CONDITIONS, name="You disabled MidnightLib's config screen list. Why? :(", centered = true) public static Comment why; - - // Multi-Conditions are also supported! - public enum Arch {X86, X86_64, AARCH64, RISCV64} - public enum OS {WINDOWS, MAC, LINUX} - @Entry(category = MULTI_CONDITIONS, name = "Arch") public static Arch myArch = Arch.X86; - @Entry(category = MULTI_CONDITIONS, name = "OS") public static OS myOS = OS.WINDOWS; - @Entry(category = MULTI_CONDITIONS, name = "Mod Platform") public static ModPlatform myPlatform = ModPlatform.FABRIC; - - @Condition(requiredOption = "modid:myArch", requiredValue = "X86_64") - @Condition(requiredOption = "modid:myOS", requiredValue = "WINDOWS") - @Condition(requiredOption = "modid:myPlatform", requiredValue = "FABRIC") - @Comment(category = MULTI_CONDITIONS, name = "MidnightLib can be used on Windows x86_64 with Fabric!", centered = true) public static Comment x86_64_windows_fabric; - - @Condition(requiredOption = "modid:myArch", requiredValue = "X86_64") - @Condition(requiredOption = "modid:myOS", requiredValue = "LINUX") - @Condition(requiredOption = "modid:myPlatform", requiredValue = "FABRIC") - @Comment(category = MULTI_CONDITIONS, name = "MidnightLib can be used on Linux x86_64 with Fabric!", centered = true) public static Comment x86_64_linux_fabric; - - @Condition(requiredOption = "modid:myArch", requiredValue = "X86_64") - @Condition(requiredOption = "modid:myOS", requiredValue = "WINDOWS") - @Condition(requiredOption = "modid:myPlatform", requiredValue = "NEOFORGE") - @Comment(category = MULTI_CONDITIONS, name = "MidnightLib can be used on Windows x86_64 with NeoForge!", centered = true) public static Comment x86_64_windows_neoforge; - - @Condition(requiredOption = "modid:myArch", requiredValue = "X86_64") - @Condition(requiredOption = "modid:myOS", requiredValue = "LINUX") - @Condition(requiredOption = "modid:myPlatform", requiredValue = "NEOFORGE") - @Comment(category = MULTI_CONDITIONS, name = "MidnightLib can be used on Linux x86_64 with NeoForge!", centered = true) public static Comment x86_64_linux_neoforge; - - public static int imposter = 16777215; // - Entries without an @Entry or @Comment annotation are ignored } \ No newline at end of file From a3f4dfc9db9ac50207455604e27f0e63e817bec9 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Sat, 5 Apr 2025 12:43:07 +0200 Subject: [PATCH 075/100] chore: bump version --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 8435a28..6903179 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,12 +1,12 @@ org.gradle.jvmargs=-Xmx4096M minecraft_version=1.21.4 -supported_versions= +supported_versions=1.21.5 yarn_mappings=1.21.4+build.1 enabled_platforms=fabric,neoforge archives_base_name=midnightlib -mod_version=1.7.1-rc.2 +mod_version=1.7.1 maven_group=eu.midnightdust release_type=release curseforge_id=488090 From 1606646e8750b08ee9c02c48f4056951d7dd318b Mon Sep 17 00:00:00 2001 From: Jaffe2718 Date: Sun, 13 Apr 2025 18:32:35 +0800 Subject: [PATCH 076/100] - fix bug: avoid the crash due to `Identifier` syntax not legitimate. - new feature: multiple expect values for `@Condition` - change: use `net.minecraft.client.gui.widget.CheckboxWidget` for boolean `@Entry` instead of `net.minecraft.client.gui.widget.ButtonWidget` - misc: cleanup for `en_us.json` and example code & bump version --- .../lib/config/MidnightConfig.java | 32 +++++++++---------- gradle.properties | 2 +- .../example/config/MidnightConfigExample.java | 8 ++++- .../resources/assets/modid/lang/en_us.json | 7 ---- 4 files changed, 24 insertions(+), 25 deletions(-) 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 4487db3..65eafca 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -97,7 +97,7 @@ public abstract class MidnightConfig { this.conditionsMet = false; String requiredOption = condition.requiredOption().contains(":") ? condition.requiredOption() : (this.modid + ":" + condition.requiredOption()); if (entries.get(requiredOption) instanceof EntryInfo info) - this.conditionsMet &= condition.requiredValue().equals(info.tempValue); + this.conditionsMet &= List.of(condition.requiredValue()).contains(info.tempValue); if (!this.conditionsMet) break; } if (prevConditionState != this.conditionsMet) reloadScreen = true; @@ -162,10 +162,7 @@ public abstract class MidnightConfig { else if (info.dataType == double.class) textField(info, Double::parseDouble, DECIMAL_ONLY, e.min(), e.max(), false); else if (info.dataType == String.class || info.dataType == Identifier.class) textField(info, String::length, null, Math.min(e.min(), 0), Math.max(e.max(), 1), true); else if (info.dataType == boolean.class) { - Function func = value -> Text.translatable((Boolean) value ? "gui.yes" : "gui.no").formatted((Boolean) value ? Formatting.GREEN : Formatting.RED); - info.function = new AbstractMap.SimpleEntry>(button -> { - info.setValue(!(Boolean) info.value); button.setMessage(func.apply(info.value)); - }, func); + info.function = (CheckboxWidget.Callback) (ch, b) -> info.setValue(b); } else if (info.dataType.isEnum()) { List values = Arrays.asList(field.getType().getEnumConstants()); Function func = value -> { @@ -215,7 +212,11 @@ public abstract class MidnightConfig { b.active = entries.values().stream().allMatch(e -> e.inLimits); if (inLimits) { - if (info.dataType == Identifier.class) info.setValue(Identifier.tryParse(s)); + if (info.dataType == Identifier.class) { // avoid the crash due to Identifier syntax not legitimate + Identifier id = Identifier.tryParse(s); + if (id == null) return false; + info.setValue(Identifier.tryParse(s)); + } else info.setValue(isNumber ? value : s); } @@ -296,7 +297,7 @@ public abstract class MidnightConfig { if (entry.buttons.get(0) instanceof ClickableWidget widget) if (widget.isFocused() || widget.isHovered()) widget.setTooltip(getTooltip(entry.info, true)); if (entry.buttons.get(1) instanceof ButtonWidget button) - button.active = !Objects.equals(entry.info.value.toString(), entry.info.defaultValue.toString()); + button.active = !Objects.equals(String.valueOf(entry.info.value), String.valueOf(entry.info.defaultValue)); }}}} @Override public boolean keyPressed(int keyCode, int scanCode, int modifiers) { @@ -354,17 +355,16 @@ public abstract class MidnightConfig { if (info.function != null) { ClickableWidget widget; Entry e = info.entry; - - if (info.function instanceof Map.Entry) { // Enums & booleans + if (info.dataType == boolean.class) { + widget = CheckboxWidget.builder(Text.empty(), textRenderer).pos(width - 185, 0).callback((CheckboxWidget.Callback) info.function).checked((boolean) info.value).build(); + } else if (info.dataType.isEnum()) { var values = (Map.Entry>) info.function; - if (info.dataType.isEnum()) - values.setValue(value -> Text.translatable(translationPrefix + "enum." + info.dataType.getSimpleName() + "." + info.value.toString())); + values.setValue(value -> Text.translatable(translationPrefix + "enum." + info.dataType.getSimpleName() + "." + info.value.toString())); widget = ButtonWidget.builder(values.getValue().apply(info.value), values.getKey()).dimensions(width - 185, 0, 150, 20).tooltip(getTooltip(info, true)).build(); - } - else if (e.isSlider()) + } else if (e.isSlider()) widget = new MidnightSliderWidget(width - 185, 0, 150, 20, Text.of(info.tempValue), (Double.parseDouble(info.tempValue) - e.min()) / (e.max() - e.min()), info); - else widget = new TextFieldWidget(textRenderer, width - 185, 0, 150, 20, Text.empty()); - + else + widget = new TextFieldWidget(textRenderer, width - 185, 0, 150, 20, Text.empty()); if (widget instanceof TextFieldWidget textField) { textField.setMaxLength(e.width()); textField.setText(info.tempValue); Predicate processor = ((BiFunction>) info.function).apply(textField, done); @@ -589,7 +589,7 @@ public abstract class MidnightConfig { public @interface Condition { String requiredModId() default ""; String requiredOption() default ""; - String requiredValue() default "true"; + String[] requiredValue() default {"true"}; boolean visibleButLocked() default false; } diff --git a/gradle.properties b/gradle.properties index 6903179..b847844 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ yarn_mappings=1.21.4+build.1 enabled_platforms=fabric,neoforge archives_base_name=midnightlib -mod_version=1.7.1 +mod_version=1.7.2-rc.1 maven_group=eu.midnightdust release_type=release curseforge_id=488090 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 index ec599de..512f7a3 100644 --- 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 @@ -74,7 +74,7 @@ public class MidnightConfigExample extends MidnightConfig { @Entry(category = CONDITIONS, name="Turn me on!") public static boolean turnMeOn = false; @Condition(requiredOption = "modid:turnMeOn", visibleButLocked = true) - @Entry(category = CONDITIONS, name="Turn me off (locked if modid:turnMeOn is false)!") + @Entry(category = CONDITIONS, name="Turn me off (locked)!") public static Boolean turnMeOff = true; @Condition(requiredOption = "turnMeOn") // You can also use multiple conditions for the same entry @Condition(requiredOption = "modid:turnMeOff", requiredValue = "false") @@ -101,6 +101,12 @@ public class MidnightConfigExample extends MidnightConfig { @Comment(category = CONDITIONS, name="⭐ Correct! Quilt (and Fabric) are the best!", centered = true) public static Comment answerQuilt; + @Entry(category = CONDITIONS, name="Enter any prime number below 10") + public static int primeNumber = 0; + @Comment(category = CONDITIONS, name="Correct!") + @Condition(requiredOption = "primeNumber", requiredValue = {"2", "3", "5", "7"}) + public static Comment answerPrime; + @Condition(requiredOption = "midnightlib:config_screen_list", requiredValue = "FALSE") // Access options of other mods that are also using MidnightLib @Comment(category = CONDITIONS) public static Comment spaceracer; @Condition(requiredOption = "midnightlib:config_screen_list", requiredValue = "FALSE") diff --git a/test-fabric/src/main/resources/assets/modid/lang/en_us.json b/test-fabric/src/main/resources/assets/modid/lang/en_us.json index b014330..702947c 100644 --- a/test-fabric/src/main/resources/assets/modid/lang/en_us.json +++ b/test-fabric/src/main/resources/assets/modid/lang/en_us.json @@ -11,13 +11,6 @@ "modid.midnightconfig.hello":"I am a limited int!", "modid.midnightconfig.id":"I am an Item Identifier!", "modid.midnightconfig.modPlatform":"I am an enum!", - "modid.midnightconfig.enum.Arch.X86":"X86", - "modid.midnightconfig.enum.Arch.X86_64":"X86_64", - "modid.midnightconfig.enum.Arch.AARCH64":"AARCH64", - "modid.midnightconfig.enum.Arch.RISCV64":"RISCV64", - "modid.midnightconfig.enum.OS.LINUX":"Linux", - "modid.midnightconfig.enum.OS.WINDOWS":"Windows", - "modid.midnightconfig.enum.OS.MAC":"MacOS", "modid.midnightconfig.enum.ModPlatform.FORGE":"Forge", "modid.midnightconfig.enum.ModPlatform.FABRIC":"Fabric", "modid.midnightconfig.enum.ModPlatform.QUILT":"Quilt", From a4ce16482c6ad96ff1c92d16c205e4c84e62ead9 Mon Sep 17 00:00:00 2001 From: Jaffe2718 Date: Sun, 13 Apr 2025 18:42:24 +0800 Subject: [PATCH 077/100] - fix bug+: illegal Identifier cannot input character --- .../main/java/eu/midnightdust/lib/config/MidnightConfig.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 65eafca..04b312e 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -74,12 +74,12 @@ public abstract class MidnightConfig { } public void setValue(Object value) { if (this.field.getType() != List.class) { this.value = value; - this.tempValue = value.toString(); + this.tempValue = value == null ? "" : value.toString(); // fix bug+: illegal Identifier cannot input character } else { writeList(this.listIndex, value); this.tempValue = toTemporaryValue(); } } public String toTemporaryValue() { - if (this.field.getType() != List.class) return this.value.toString(); + if (this.field.getType() != List.class) return this.value == null ? "" : this.value.toString(); // fix bug+: illegal Identifier cannot input character else try { return ((List) this.value).get(this.listIndex).toString(); } catch (Exception ignored) {return "";} } public void updateFieldValue() { From e046463f669ccff32c85294135c26641683092c5 Mon Sep 17 00:00:00 2001 From: Jaffe2718 Date: Mon, 14 Apr 2025 20:00:51 +0800 Subject: [PATCH 078/100] - rollback: boolean field (`CheckboxWidget` -> `ButtonWidget`) --- .../eu/midnightdust/lib/config/MidnightConfig.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) 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 04b312e..1c27dc9 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -162,7 +162,10 @@ public abstract class MidnightConfig { else if (info.dataType == double.class) textField(info, Double::parseDouble, DECIMAL_ONLY, e.min(), e.max(), false); else if (info.dataType == String.class || info.dataType == Identifier.class) textField(info, String::length, null, Math.min(e.min(), 0), Math.max(e.max(), 1), true); else if (info.dataType == boolean.class) { - info.function = (CheckboxWidget.Callback) (ch, b) -> info.setValue(b); + Function func = value -> Text.translatable((Boolean) value ? "gui.yes" : "gui.no").formatted((Boolean) value ? Formatting.GREEN : Formatting.RED); + info.function = new AbstractMap.SimpleEntry>(button -> { + info.setValue(!(Boolean) info.value); button.setMessage(func.apply(info.value)); + }, func); } else if (info.dataType.isEnum()) { List values = Arrays.asList(field.getType().getEnumConstants()); Function func = value -> { @@ -355,11 +358,10 @@ public abstract class MidnightConfig { if (info.function != null) { ClickableWidget widget; Entry e = info.entry; - if (info.dataType == boolean.class) { - widget = CheckboxWidget.builder(Text.empty(), textRenderer).pos(width - 185, 0).callback((CheckboxWidget.Callback) info.function).checked((boolean) info.value).build(); - } else if (info.dataType.isEnum()) { + if (info.function instanceof Map.Entry) { var values = (Map.Entry>) info.function; - values.setValue(value -> Text.translatable(translationPrefix + "enum." + info.dataType.getSimpleName() + "." + info.value.toString())); + if (info.dataType.isEnum()) + values.setValue(value -> Text.translatable(translationPrefix + "enum." + info.dataType.getSimpleName() + "." + info.value.toString())); widget = ButtonWidget.builder(values.getValue().apply(info.value), values.getKey()).dimensions(width - 185, 0, 150, 20).tooltip(getTooltip(info, true)).build(); } else if (e.isSlider()) widget = new MidnightSliderWidget(width - 185, 0, 150, 20, Text.of(info.tempValue), (Double.parseDouble(info.tempValue) - e.min()) / (e.max() - e.min()), info); From 517d3c8a0ee5921d583dcc332f196b751c75b45e Mon Sep 17 00:00:00 2001 From: Jaffe2718 Date: Mon, 14 Apr 2025 20:05:21 +0800 Subject: [PATCH 079/100] - adjust: optimize code & add comment --- .../main/java/eu/midnightdust/lib/config/MidnightConfig.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 1c27dc9..34ad33b 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -218,7 +218,7 @@ public abstract class MidnightConfig { if (info.dataType == Identifier.class) { // avoid the crash due to Identifier syntax not legitimate Identifier id = Identifier.tryParse(s); if (id == null) return false; - info.setValue(Identifier.tryParse(s)); + info.setValue(id); } else info.setValue(isNumber ? value : s); } @@ -358,7 +358,7 @@ public abstract class MidnightConfig { if (info.function != null) { ClickableWidget widget; Entry e = info.entry; - if (info.function instanceof Map.Entry) { + if (info.function instanceof Map.Entry) { // Enums & booleans var values = (Map.Entry>) info.function; if (info.dataType.isEnum()) values.setValue(value -> Text.translatable(translationPrefix + "enum." + info.dataType.getSimpleName() + "." + info.value.toString())); From dcf0dbcaabae15e61335a36ed8eb0cb4f3081bc2 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Mon, 14 Apr 2025 17:47:11 +0200 Subject: [PATCH 080/100] fix: improve identifier crash fix Now uses Minecraft's built-in Identifier.validate function to check validity before applying changes --- .../midnightdust/lib/config/MidnightConfig.java | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) 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 34ad33b..2f706a1 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -66,20 +66,18 @@ public abstract class MidnightConfig { this.entry = field.getAnnotation(Entry.class); this.comment = field.getAnnotation(Comment.class); this.conditions = field.getAnnotationsByType(Condition.class); - } else { - this.fieldName = ""; this.dataType = null; - } + } else { this.fieldName = ""; this.dataType = null; } if (entry != null && !entry.name().isEmpty()) this.name = Text.translatable(entry.name()); else if (comment != null && !comment.name().isEmpty()) this.name = Text.translatable(comment.name()); } public void setValue(Object value) { if (this.field.getType() != List.class) { this.value = value; - this.tempValue = value == null ? "" : value.toString(); // fix bug+: illegal Identifier cannot input character + this.tempValue = value.toString(); } else { writeList(this.listIndex, value); this.tempValue = toTemporaryValue(); } } public String toTemporaryValue() { - if (this.field.getType() != List.class) return this.value == null ? "" : this.value.toString(); // fix bug+: illegal Identifier cannot input character + if (this.field.getType() != List.class) return this.value.toString(); else try { return ((List) this.value).get(this.listIndex).toString(); } catch (Exception ignored) {return "";} } public void updateFieldValue() { @@ -197,7 +195,8 @@ public abstract class MidnightConfig { boolean isNumber = pattern != null; info.function = (BiFunction>) (t, b) -> s -> { s = s.trim(); - if (!(s.isEmpty() || !isNumber || pattern.matcher(s).matches())) return false; + if (!(s.isEmpty() || !isNumber || pattern.matcher(s).matches()) || + (info.dataType == Identifier.class && Identifier.validate(s).isError())) return false; Number value = 0; boolean inLimits = false; info.error = null; if (!(isNumber && s.isEmpty()) && !s.equals("-") && !s.equals(".")) { @@ -215,11 +214,7 @@ public abstract class MidnightConfig { b.active = entries.values().stream().allMatch(e -> e.inLimits); if (inLimits) { - if (info.dataType == Identifier.class) { // avoid the crash due to Identifier syntax not legitimate - Identifier id = Identifier.tryParse(s); - if (id == null) return false; - info.setValue(id); - } + if (info.dataType == Identifier.class) info.setValue(Identifier.tryParse(s)); else info.setValue(isNumber ? value : s); } From 3e6a72cda40bc66050afc3335a9cfafd9824a3c2 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Mon, 14 Apr 2025 17:49:02 +0200 Subject: [PATCH 081/100] feat: checkbox buttons next to boolean yes/no text buttons --- .../java/eu/midnightdust/lib/config/MidnightConfig.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) 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 2f706a1..da71553 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -162,6 +162,9 @@ public abstract class MidnightConfig { else if (info.dataType == boolean.class) { Function func = value -> Text.translatable((Boolean) value ? "gui.yes" : "gui.no").formatted((Boolean) value ? Formatting.GREEN : Formatting.RED); info.function = new AbstractMap.SimpleEntry>(button -> { + if (info.actionButton instanceof CheckboxWidget checkbox && checkbox.isChecked() == (Boolean) info.value) { + checkbox.onPress(); return; + } info.setValue(!(Boolean) info.value); button.setMessage(func.apply(info.value)); }, func); } else if (info.dataType.isEnum()) { @@ -358,10 +361,10 @@ public abstract class MidnightConfig { if (info.dataType.isEnum()) values.setValue(value -> Text.translatable(translationPrefix + "enum." + info.dataType.getSimpleName() + "." + info.value.toString())); widget = ButtonWidget.builder(values.getValue().apply(info.value), values.getKey()).dimensions(width - 185, 0, 150, 20).tooltip(getTooltip(info, true)).build(); + if (info.dataType == boolean.class) info.actionButton = CheckboxWidget.builder(Text.empty(), textRenderer).callback((checkbox, checked) -> values.getKey().onPress((ButtonWidget) widget)).checked((Boolean) info.value).pos(widget.getX(), 1).build(); } else if (e.isSlider()) widget = new MidnightSliderWidget(width - 185, 0, 150, 20, Text.of(info.tempValue), (Double.parseDouble(info.tempValue) - e.min()) / (e.max() - e.min()), info); - else - widget = new TextFieldWidget(textRenderer, width - 185, 0, 150, 20, Text.empty()); + else widget = new TextFieldWidget(textRenderer, width - 185, 0, 150, 20, Text.empty()); if (widget instanceof TextFieldWidget textField) { textField.setMaxLength(e.width()); textField.setText(info.tempValue); Predicate processor = ((BiFunction>) info.function).apply(textField, done); @@ -471,7 +474,7 @@ public abstract class MidnightConfig { } } public void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { - buttons.forEach(b -> { b.setY(y); b.render(context, mouseX, mouseY, tickDelta);}); + buttons.forEach(b -> { b.setY(y + (b instanceof CheckboxWidget ? 1 : 0)); b.render(context, mouseX, mouseY, tickDelta);}); if (title != null) { title.setY(y + 9); title.renderWidget(context, mouseX, mouseY, tickDelta); From 0297d91e703ebac235b95861b290ede23a5a1154 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Mon, 14 Apr 2025 18:02:56 +0200 Subject: [PATCH 082/100] feat: 'visibleButLocked' now applies for all buttons --- .../main/java/eu/midnightdust/lib/config/MidnightConfig.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 da71553..c689277 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -298,7 +298,7 @@ public abstract class MidnightConfig { if (entry.buttons.get(0) instanceof ClickableWidget widget) if (widget.isFocused() || widget.isHovered()) widget.setTooltip(getTooltip(entry.info, true)); if (entry.buttons.get(1) instanceof ButtonWidget button) - button.active = !Objects.equals(String.valueOf(entry.info.value), String.valueOf(entry.info.defaultValue)); + button.active = !Objects.equals(String.valueOf(entry.info.value), String.valueOf(entry.info.defaultValue)) && entry.info.conditionsMet; }}}} @Override public boolean keyPressed(int keyCode, int scanCode, int modifiers) { @@ -415,7 +415,6 @@ public abstract class MidnightConfig { explorerButton.setPosition(width - 185, 0); info.actionButton = explorerButton; } - if (!info.conditionsMet) widget.active = false; List widgets = Lists.newArrayList(widget, resetButton); if (info.actionButton != null) { if (IS_SYSTEM_MAC) info.actionButton.active = false; @@ -426,6 +425,7 @@ public abstract class MidnightConfig { widget.setWidth(widget.getWidth() - 22); widget.setX(widget.getX() + 22); widgets.add(cycleButton); } + if (!info.conditionsMet) widgets.forEach(w -> w.active = false); this.list.addButton(widgets, name, info); } else this.list.addButton(List.of(), name, info); } list.setScrollY(scrollProgress); From 5905eed58f5fd4ee79658c0a37b436dae7869afe Mon Sep 17 00:00:00 2001 From: Jaffe2718 Date: Fri, 18 Apr 2025 17:01:35 +0800 Subject: [PATCH 083/100] - feat: add clickable url for `@Comment` - chore: bump version `1.7.2-rc.2` --- .../lib/config/MidnightConfig.java | 29 +++++++++++++++++-- gradle.properties | 2 +- .../example/config/MidnightConfigExample.java | 4 ++- 3 files changed, 31 insertions(+), 4 deletions(-) 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 c689277..f132d45 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -5,7 +5,9 @@ import com.google.gson.*; import com.google.gson.stream.*; import eu.midnightdust.lib.util.PlatformFunctions; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.Element; import net.minecraft.client.gui.Selectable; import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.Element; import net.minecraft.client.gui.Selectable; +import net.minecraft.client.gui.screen.ConfirmLinkScreen; +import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.tab.GridScreenTab; import net.minecraft.client.gui.tab.Tab; import net.minecraft.client.gui.tab.TabManager; import net.minecraft.client.gui.tooltip.Tooltip; import net.minecraft.client.gui.widget.*; import net.minecraft.client.render.RenderLayer; @@ -14,6 +16,7 @@ import net.minecraft.registry.Registries; import net.minecraft.screen.ScreenTexts; import net.minecraft.text.Style; import net.minecraft.text.Text; import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; +import net.minecraft.util.Util; import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; @@ -488,6 +491,20 @@ public abstract class MidnightConfig { } } } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + boolean result = super.mouseClicked(mouseX, mouseY, button); + if (this.info != null && this.info.comment != null && !this.info.comment.url().isBlank()) { + Screen parent = MinecraftClient.getInstance().currentScreen; + MinecraftClient.getInstance().setScreen(new ConfirmLinkScreen((confirm)->{ + if (confirm) Util.getOperatingSystem().open(this.info.comment.url()); + MinecraftClient.getInstance().setScreen(parent); + }, this.info.comment.url(), true)); + } + return result; + } + public List children() {return Lists.newArrayList(buttons);} public List selectableChildren() {return Lists.newArrayList(buttons);} } @@ -567,11 +584,19 @@ public abstract class MidnightConfig { */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Hidden {} + /** + * Comment Annotation
+ * - {@link Comment#centered()}: If the comment should be centered (default: false)
+ * - {@link Comment#category()}: The category of the comment in the config screen (default + * "default")
+ * - {@link Comment#name()}: The name of the comment in the config screen (default: "")
+ * - {@link Comment#url()}: The url of the comment in the config screen, empty or blank means no url (default: "")
+ * */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Comment { boolean centered() default false; String category() default "default"; String name() default ""; - @Deprecated String requiredMod() default ""; + String url() default ""; } /** * Condition Annotation
diff --git a/gradle.properties b/gradle.properties index b847844..fcb7bd9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ yarn_mappings=1.21.4+build.1 enabled_platforms=fabric,neoforge archives_base_name=midnightlib -mod_version=1.7.2-rc.1 +mod_version=1.7.2-rc.2 maven_group=eu.midnightdust release_type=release curseforge_id=488090 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 index 512f7a3..3ffa54d 100644 --- 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 @@ -10,7 +10,7 @@ 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*/ -@SuppressWarnings("unused") +@SuppressWarnings({"unused", "DefaultAnnotationParam"}) public class MidnightConfigExample extends MidnightConfig { public static final String TEXT = "text"; public static final String NUMBERS = "numbers"; @@ -31,6 +31,8 @@ public class MidnightConfigExample extends MidnightConfig { public enum ModPlatform { // Enums allow the user to cycle through predefined options QUILT, FABRIC, FORGE, NEOFORGE, VANILLA } + @Comment(category = TEXT, name = "§nMidnightLib Wiki", centered = true, url = "https://www.midnightdust.eu/wiki/midnightlib/") public static Comment wiki; // Example for a comment with a url + @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 From e58c7fc0fdc527d24818211f9c5170f98437774a Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Fri, 18 Apr 2025 12:37:46 +0200 Subject: [PATCH 084/100] feat: improve URL handling - Uses the `open` method of `ConfirmLinkScreen` instead of manually instantiating it - Also re-add the `requiredMod` field for `@Comment` to prevent mods that haven't adjusted yet from outright crashing --- .../eu/midnightdust/lib/config/MidnightConfig.java | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) 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 f132d45..588b1dd 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -494,15 +494,9 @@ public abstract class MidnightConfig { @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { - boolean result = super.mouseClicked(mouseX, mouseY, button); - if (this.info != null && this.info.comment != null && !this.info.comment.url().isBlank()) { - Screen parent = MinecraftClient.getInstance().currentScreen; - MinecraftClient.getInstance().setScreen(new ConfirmLinkScreen((confirm)->{ - if (confirm) Util.getOperatingSystem().open(this.info.comment.url()); - MinecraftClient.getInstance().setScreen(parent); - }, this.info.comment.url(), true)); - } - return result; + if (this.info != null && this.info.comment != null && !this.info.comment.url().isBlank()) + ConfirmLinkScreen.open(MinecraftClient.getInstance().currentScreen, this.info.comment.url(), true); + return super.mouseClicked(mouseX, mouseY, button); } public List children() {return Lists.newArrayList(buttons);} @@ -597,6 +591,7 @@ public abstract class MidnightConfig { String category() default "default"; String name() default ""; String url() default ""; + @Deprecated String requiredMod() default ""; } /** * Condition Annotation
From 82889b8c061ae6debb21d46506feba1d1ef09482 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Mon, 21 Apr 2025 10:43:40 +0200 Subject: [PATCH 085/100] docs: improve JavaDocs --- .../eu/midnightdust/lib/config/MidnightConfig.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) 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 588b1dd..355e2b8 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -530,7 +530,7 @@ public abstract class MidnightConfig { * - width: The maximum character length of the {@link String}, {@link Identifier} or String/Identifier {@link List<>} field
* - min: The minimum value of the int, float or double field
* - max: The maximum value of the int, float or double field
- * - name: The name of the field in the config screen
+ * - name: Will be used instead of the default translation key, if not empty
* - selectionMode: The selection mode of the file picker button for {@link String} fields, * -1 for none, {@link JFileChooser#FILES_ONLY} for files, {@link JFileChooser#DIRECTORIES_ONLY} for directories, * {@link JFileChooser#FILES_AND_DIRECTORIES} for both (default: -1). Remember to set the translation key @@ -580,11 +580,10 @@ public abstract class MidnightConfig { /** * Comment Annotation
- * - {@link Comment#centered()}: If the comment should be centered (default: false)
- * - {@link Comment#category()}: The category of the comment in the config screen (default - * "default")
- * - {@link Comment#name()}: The name of the comment in the config screen (default: "")
- * - {@link Comment#url()}: The url of the comment in the config screen, empty or blank means no url (default: "")
+ * - {@link Comment#centered()}: If the comment should be centered
+ * - {@link Comment#category()}: The category of the comment in the config screen
+ * - {@link Comment#name()}: Will be used instead of the default translation key, if not empty
+ * - {@link Comment#url()}: The url of the comment should link to in the config screen (none if left empty)
* */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Comment { boolean centered() default false; From 06ef4fdcf77c6a4c02fc6b134a1108d4e4d029ff Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Mon, 21 Apr 2025 10:45:02 +0200 Subject: [PATCH 086/100] clean: remove unused import --- .../main/java/eu/midnightdust/lib/config/MidnightConfig.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) 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 355e2b8..3832f0e 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -6,8 +6,7 @@ import eu.midnightdust.lib.util.PlatformFunctions; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.Element; import net.minecraft.client.gui.Selectable; -import net.minecraft.client.gui.screen.ConfirmLinkScreen; -import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.ConfirmLinkScreen; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.tab.GridScreenTab; import net.minecraft.client.gui.tab.Tab; import net.minecraft.client.gui.tab.TabManager; import net.minecraft.client.gui.tooltip.Tooltip; import net.minecraft.client.gui.widget.*; import net.minecraft.client.render.RenderLayer; @@ -16,7 +15,6 @@ import net.minecraft.registry.Registries; import net.minecraft.screen.ScreenTexts; import net.minecraft.text.Style; import net.minecraft.text.Text; import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; -import net.minecraft.util.Util; import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; From 356064b052f51fd409d5e9f9f9fe459f0b873f48 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Mon, 21 Apr 2025 10:46:02 +0200 Subject: [PATCH 087/100] chore: bump version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index fcb7bd9..13e4aee 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ yarn_mappings=1.21.4+build.1 enabled_platforms=fabric,neoforge archives_base_name=midnightlib -mod_version=1.7.2-rc.2 +mod_version=1.7.2 maven_group=eu.midnightdust release_type=release curseforge_id=488090 From daec2a31879dbaf0721b72cec6aecab599c9beca Mon Sep 17 00:00:00 2001 From: Joris Kleiber Date: Sat, 26 Apr 2025 01:10:57 +0200 Subject: [PATCH 088/100] feat: respect TranslatableOption on enums --- .../lib/config/MidnightConfig.java | 20 +++++++---- .../example/config/MidnightConfigExample.java | 35 +++++++++++++++++++ .../resources/assets/modid/lang/en_us.json | 1 + 3 files changed, 50 insertions(+), 6 deletions(-) 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 3832f0e..6c0a753 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -15,6 +15,7 @@ import net.minecraft.registry.Registries; import net.minecraft.screen.ScreenTexts; import net.minecraft.text.Style; import net.minecraft.text.Text; import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; +import net.minecraft.util.TranslatableOption; import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; @@ -170,10 +171,7 @@ public abstract class MidnightConfig { }, func); } else if (info.dataType.isEnum()) { List values = Arrays.asList(field.getType().getEnumConstants()); - Function func = value -> { - String translationKey = modid + ".midnightconfig.enum." + info.dataType.getSimpleName() + "." + info.toTemporaryValue(); - return I18n.hasTranslation(translationKey) ? Text.translatable(translationKey) : Text.literal(info.toTemporaryValue()); - }; + Function func = value -> getEnumTranslatableText(value, modid, info); info.function = new AbstractMap.SimpleEntry>(button -> { int index = values.indexOf(info.value) + 1; info.setValue(values.get(index >= values.size() ? 0 : index)); @@ -195,6 +193,15 @@ public abstract class MidnightConfig { return Tooltip.of(isButton && info.error != null ? info.error : I18n.hasTranslation(key) ? Text.translatable(key) : Text.empty()); } + private static Text getEnumTranslatableText(Object value, String modid, EntryInfo info) { + if (value instanceof TranslatableOption translatableOption) { + return translatableOption.getText(); + } + + String translationKey = modid + ".midnightconfig.enum." + info.dataType.getSimpleName() + "." + info.toTemporaryValue(); + return I18n.hasTranslation(translationKey) ? Text.translatable(translationKey) : Text.literal(info.toTemporaryValue()); + } + private static void textField(EntryInfo info, Function f, Pattern pattern, double min, double max, boolean cast) { boolean isNumber = pattern != null; info.function = (BiFunction>) (t, b) -> s -> { @@ -359,8 +366,9 @@ public abstract class MidnightConfig { Entry e = info.entry; if (info.function instanceof Map.Entry) { // Enums & booleans var values = (Map.Entry>) info.function; - if (info.dataType.isEnum()) - values.setValue(value -> Text.translatable(translationPrefix + "enum." + info.dataType.getSimpleName() + "." + info.value.toString())); + if (info.dataType.isEnum()) { + values.setValue(value -> getEnumTranslatableText(value, modid, info)); + } widget = ButtonWidget.builder(values.getValue().apply(info.value), values.getKey()).dimensions(width - 185, 0, 150, 20).tooltip(getTooltip(info, true)).build(); if (info.dataType == boolean.class) info.actionButton = CheckboxWidget.builder(Text.empty(), textRenderer).callback((checkbox, checked) -> values.getKey().onPress((ButtonWidget) widget)).checked((Boolean) info.value).pos(widget.getX(), 1).build(); } else if (e.isSlider()) 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 index 3ffa54d..2b9c172 100644 --- 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 @@ -2,7 +2,11 @@ package eu.midnightdust.fabric.example.config; import com.google.common.collect.Lists; import eu.midnightdust.lib.config.MidnightConfig; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; +import net.minecraft.util.TranslatableOption; import javax.swing.*; import java.util.ArrayList; @@ -31,6 +35,37 @@ public class MidnightConfigExample extends MidnightConfig { public enum ModPlatform { // Enums allow the user to cycle through predefined options QUILT, FABRIC, FORGE, NEOFORGE, VANILLA } + @Entry(category = TEXT) public static GraphicsSteps graphicsSteps = GraphicsSteps.FABULOUS; // Example for an enum option with TranslatableOption + public enum GraphicsSteps implements TranslatableOption { + FAST(0, "options.graphics.fast"), + FANCY(1, "options.graphics.fancy"), + FABULOUS(2, "options.graphics.fabulous"); + + private final int id; + private final String translationKey; + + GraphicsSteps(int id, String translationKey) { + this.id = id; + this.translationKey = translationKey; + } + + @Override + public Text getText() { + MutableText mutableText = Text.translatable(this.getTranslationKey()); + return this == GraphicsSteps.FABULOUS ? mutableText.formatted(Formatting.ITALIC).formatted(Formatting.AQUA) : mutableText; + } + + @Override + public int getId() { + return this.id; + } + + @Override + public String getTranslationKey() { + return this.translationKey; + } + } + @Comment(category = TEXT, name = "§nMidnightLib Wiki", centered = true, url = "https://www.midnightdust.eu/wiki/midnightlib/") public static Comment wiki; // Example for a comment with a url @Entry(category = NUMBERS) public static int fabric = 16777215; // Example for an int option diff --git a/test-fabric/src/main/resources/assets/modid/lang/en_us.json b/test-fabric/src/main/resources/assets/modid/lang/en_us.json index 702947c..976393b 100644 --- a/test-fabric/src/main/resources/assets/modid/lang/en_us.json +++ b/test-fabric/src/main/resources/assets/modid/lang/en_us.json @@ -16,6 +16,7 @@ "modid.midnightconfig.enum.ModPlatform.QUILT":"Quilt", "modid.midnightconfig.enum.ModPlatform.NEOFORGE":"NeoForge", "modid.midnightconfig.enum.ModPlatform.VANILLA":"Vanilla", + "modid.midnightconfig.graphicsSteps":"I am an enum with TranslatableOption!", "modid.midnightconfig.myFileOrDirectory.fileChooser": "Select an image or directory", "modid.midnightconfig.myFileOrDirectory.fileFilter": "Supported Images (.png, .jpg, .jpeg)", "modid.midnightconfig.category.numbers": "Numbers", From 03223b8d9bf35d2cead844581cf1f152a64ff4bb Mon Sep 17 00:00:00 2001 From: Texaliuz <152565569+Texaliuz@users.noreply.github.com> Date: Tue, 29 Apr 2025 19:41:32 -0300 Subject: [PATCH 089/100] Translation into Argentine Spanish (es_ar) for MidnightLib Hello, I would appreciate if you could add the translation to my language (es_ar) for version 1.21.1 please and thank you. --- .../resources/assets/modid/lang/es_ar.json | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 test-fabric/src/main/resources/assets/modid/lang/es_ar.json diff --git a/test-fabric/src/main/resources/assets/modid/lang/es_ar.json b/test-fabric/src/main/resources/assets/modid/lang/es_ar.json new file mode 100644 index 0000000..d87e7a8 --- /dev/null +++ b/test-fabric/src/main/resources/assets/modid/lang/es_ar.json @@ -0,0 +1,28 @@ +{ + "modid.midnightconfig.title": "Soy un título", + "modid.midnightconfig.text1": "Soy un comentario *u*", + "modid.midnightconfig.text2": "Soy un comentario centrado (╯°□°)╯︵ ┻━┻", + "modid.midnightconfig.name": "¡Soy una cadena de texto!", + "modid.midnightconfig.name.label.tooltip": "Soy el tooltip de una etiqueta \n¡Wujuu!", + "modid.midnightconfig.name.tooltip": "Soy un tooltip uwu \nY una nueva línea", + "modid.midnightconfig.fabric": "Soy un entero", + "modid.midnightconfig.world": "Soy un número decimal", + "modid.midnightconfig.showInfo": "Soy un booleano", + "modid.midnightconfig.hello": "¡Soy un entero limitado!", + "modid.midnightconfig.id": "¡Soy un identificador de ítem!", + "modid.midnightconfig.modPlatform": "¡Soy un enumerador!", + "modid.midnightconfig.enum.ModPlatform.FORGE": "Forge", + "modid.midnightconfig.enum.ModPlatform.FABRIC": "Fabric", + "modid.midnightconfig.enum.ModPlatform.QUILT": "Quilt", + "modid.midnightconfig.enum.ModPlatform.NEOFORGE": "NeoForge", + "modid.midnightconfig.enum.ModPlatform.VANILLA": "Vanilla", + "modid.midnightconfig.myFileOrDirectory.fileChooser": "Seleccioná una imagen o carpeta", + "modid.midnightconfig.myFileOrDirectory.fileFilter": "Imágenes compatibles (.png, .jpg, .jpeg)", + "modid.midnightconfig.category.numbers": "Números", + "modid.midnightconfig.category.text": "Texto", + "modid.midnightconfig.category.sliders": "Deslizadores", + "modid.midnightconfig.category.lists": "Listas", + "modid.midnightconfig.category.files": "Archivos", + "modid.midnightconfig.category.conditions": "Cuestionario", + "modid.midnightconfig.category.multiConditions": "Condiciones múltiples" +} From f986d10e1f8a6911fc60dfd70f47d62eacd9a014 Mon Sep 17 00:00:00 2001 From: Texaliuz <152565569+Texaliuz@users.noreply.github.com> Date: Tue, 29 Apr 2025 19:45:28 -0300 Subject: [PATCH 090/100] Translation into Argentine Spanish (es_ar) for MidnightLib Hello, I would appreciate if you could add the translation to my language (es_ar) for version 1.21.1 please and thank you. --- .../resources/assets/midnightlib/lang/es_ar.json | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 common/src/main/resources/assets/midnightlib/lang/es_ar.json diff --git a/common/src/main/resources/assets/midnightlib/lang/es_ar.json b/common/src/main/resources/assets/midnightlib/lang/es_ar.json new file mode 100644 index 0000000..44af0ad --- /dev/null +++ b/common/src/main/resources/assets/midnightlib/lang/es_ar.json @@ -0,0 +1,13 @@ +{ + "midnightlib.overview.title": "Resumen de MidnightConfig", + "midnightlib.midnightconfig.title": "Configuración de MidnightLib", + "midnightlib.midnightconfig.config_screen_list": "Habilitar lista de pantallas de configuración", + "midnightlib.midnightconfig.enum.ConfigButton.TRUE": "§aSí", + "midnightlib.midnightconfig.enum.ConfigButton.FALSE": "§cNo", + "midnightlib.midnightconfig.enum.ConfigButton.MODMENU": "§bModMenu", + "midnightlib.modrinth": "Modrinth", + "midnightlib.curseforge": "CurseForge", + "midnightlib.wiki": "Wiki", + "modmenu.summaryTranslation.midnightlib": "Librería común para facilitar la configuración.", + "midnightconfig.colorChooser.title": "Elegí un color" +} From 3eb345ce3ca767f220aa71e501c87f07baf712a1 Mon Sep 17 00:00:00 2001 From: Texaliuz <152565569+Texaliuz@users.noreply.github.com> Date: Sun, 4 May 2025 13:10:32 -0300 Subject: [PATCH 091/100] Update es_ar.json Minor corrections --- common/src/main/resources/assets/midnightlib/lang/es_ar.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/main/resources/assets/midnightlib/lang/es_ar.json b/common/src/main/resources/assets/midnightlib/lang/es_ar.json index 44af0ad..1f559e8 100644 --- a/common/src/main/resources/assets/midnightlib/lang/es_ar.json +++ b/common/src/main/resources/assets/midnightlib/lang/es_ar.json @@ -1,5 +1,5 @@ { - "midnightlib.overview.title": "Resumen de MidnightConfig", + "midnightlib.overview.title": "Visión general de MidnightConfig", "midnightlib.midnightconfig.title": "Configuración de MidnightLib", "midnightlib.midnightconfig.config_screen_list": "Habilitar lista de pantallas de configuración", "midnightlib.midnightconfig.enum.ConfigButton.TRUE": "§aSí", From 302728192f0f3176264b7057d07cbffa1299b26a Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Mon, 12 May 2025 12:35:20 +0200 Subject: [PATCH 092/100] feat: new method to manually add widgets - Also added a keybind widget as an example for this. It will not be included in the base jar, but can be manually copied into mods that rely on it. --- .../lib/config/MidnightConfig.java | 36 ++++--- .../fabric/example/MidnightLibExtras.java | 96 +++++++++++++++++++ .../example/config/MidnightConfigExample.java | 16 ++++ .../resources/assets/modid/lang/en_us.json | 1 + 4 files changed, 134 insertions(+), 15 deletions(-) create mode 100644 test-fabric/src/main/java/eu/midnightdust/fabric/example/MidnightLibExtras.java 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 3832f0e..e8e0f56 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -14,6 +14,7 @@ import net.minecraft.client.resource.language.I18n; import net.minecraft.registry.Registries; import net.minecraft.screen.ScreenTexts; import net.minecraft.text.Style; import net.minecraft.text.Text; +import net.minecraft.text.TranslatableTextContent; import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; import org.jetbrains.annotations.Nullable; @@ -106,6 +107,10 @@ public abstract class MidnightConfig { if (index >= list.size()) list.add(value); else list.set(index, value); } + public Tooltip getTooltip(boolean isButton) { + String key = this.modid + ".midnightconfig."+this.fieldName+(!isButton ? ".label" : "" )+".tooltip"; + return Tooltip.of(isButton && this.error != null ? this.error : I18n.hasTranslation(key) ? Text.translatable(key) : Text.empty()); + } } public static final Map> configClass = new HashMap<>(); @@ -119,11 +124,6 @@ public abstract class MidnightConfig { public Identifier read(JsonReader in) throws IOException { return Identifier.of(in.nextString()); } }).setPrettyPrinting().create(); - @SuppressWarnings("unused") // Utility for mod authors - public static @Nullable Object getDefaultValue(String modid, String entry) { - String key = modid + ":" + entry; - return entries.containsKey(key) ? entries.get(key).defaultValue : null; - } public static void loadValuesFromJson(String modid) { try { gson.fromJson(Files.newBufferedReader(path), configClass.get(modid)); } catch (Exception e) { write(modid); } @@ -190,10 +190,6 @@ public abstract class MidnightConfig { try { return (Class) rawType.getField("TYPE").get(null); // Tries to get primitive types from non-primitives (e.g. Boolean -> boolean) } catch (NoSuchFieldException | IllegalAccessException ignored) { return rawType; } } - public static Tooltip getTooltip(EntryInfo info, boolean isButton) { - String key = info.modid + ".midnightconfig."+info.fieldName+(!isButton ? ".label" : "" )+".tooltip"; - return Tooltip.of(isButton && info.error != null ? info.error : I18n.hasTranslation(key) ? Text.translatable(key) : Text.empty()); - } private static void textField(EntryInfo info, Function f, Pattern pattern, double min, double max, boolean cast) { boolean isNumber = pattern != null; @@ -209,7 +205,7 @@ public abstract class MidnightConfig { info.error = inLimits? null : Text.literal(value.doubleValue() < min ? "§cMinimum " + (isNumber? "value" : "length") + (cast? " is " + (int)min : " is " + min) : "§cMaximum " + (isNumber? "value" : "length") + (cast? " is " + (int)max : " is " + max)).formatted(Formatting.RED); - t.setTooltip(getTooltip(info, true)); + t.setTooltip(info.getTooltip(true)); } info.tempValue = s; @@ -241,6 +237,15 @@ public abstract class MidnightConfig { Files.write(path, gson.toJson(getClass(modid)).getBytes()); } catch (Exception e) { e.fillInStackTrace(); } } + + @SuppressWarnings("unused") // Utility for mod authors + public static @Nullable Object getDefaultValue(String modid, String entry) { + String key = modid + ":" + entry; + return entries.containsKey(key) ? entries.get(key).defaultValue : null; + } + + public void onTabInit(String tabName, MidnightConfigListWidget list, MidnightConfigScreen screen) {} + @Environment(EnvType.CLIENT) public static Screen getScreen(Screen parent, String modid) { return new MidnightConfigScreen(parent, modid); @@ -295,9 +300,9 @@ public abstract class MidnightConfig { public void updateButtons() { if (this.list != null) { for (ButtonEntry entry : this.list.children()) { - if (entry.buttons != null && entry.buttons.size() > 1) { + if (entry.buttons != null && entry.buttons.size() > 1 && entry.info.field != null) { if (entry.buttons.get(0) instanceof ClickableWidget widget) - if (widget.isFocused() || widget.isHovered()) widget.setTooltip(getTooltip(entry.info, true)); + if (widget.isFocused() || widget.isHovered()) widget.setTooltip(entry.info.getTooltip(true)); if (entry.buttons.get(1) instanceof ButtonWidget button) button.active = !Objects.equals(String.valueOf(entry.info.value), String.valueOf(entry.info.defaultValue)) && entry.info.conditionsMet; }}}} @@ -337,6 +342,7 @@ public abstract class MidnightConfig { this.list.clear(); fillList(); } public void fillList() { + MidnightConfig.getClass(modid).onTabInit(prevTab.getTitle().getContent() instanceof TranslatableTextContent translatable ? translatable.getKey().replace("%s.midnightconfig.category.".formatted(modid), "") : prevTab.getTitle().toString(), list, this); for (EntryInfo info : entries.values()) { if (!info.conditionsMet) { boolean visibleButLocked = false; @@ -361,7 +367,7 @@ public abstract class MidnightConfig { var values = (Map.Entry>) info.function; if (info.dataType.isEnum()) values.setValue(value -> Text.translatable(translationPrefix + "enum." + info.dataType.getSimpleName() + "." + info.value.toString())); - widget = ButtonWidget.builder(values.getValue().apply(info.value), values.getKey()).dimensions(width - 185, 0, 150, 20).tooltip(getTooltip(info, true)).build(); + widget = ButtonWidget.builder(values.getValue().apply(info.value), values.getKey()).dimensions(width - 185, 0, 150, 20).tooltip(info.getTooltip(true)).build(); if (info.dataType == boolean.class) info.actionButton = CheckboxWidget.builder(Text.empty(), textRenderer).callback((checkbox, checked) -> values.getKey().onPress((ButtonWidget) widget)).checked((Boolean) info.value).pos(widget.getX(), 1).build(); } else if (e.isSlider()) widget = new MidnightSliderWidget(width - 185, 0, 150, 20, Text.of(info.tempValue), (Double.parseDouble(info.tempValue) - e.min()) / (e.max() - e.min()), info); @@ -371,7 +377,7 @@ public abstract class MidnightConfig { Predicate processor = ((BiFunction>) info.function).apply(textField, done); textField.setTextPredicate(processor); } - widget.setTooltip(getTooltip(info, true)); + widget.setTooltip(info.getTooltip(true)); ButtonWidget cycleButton = null; if (info.field.getType() == List.class) { @@ -470,7 +476,7 @@ public abstract class MidnightConfig { if (text != null && (!text.getString().contains("spacer") || !buttons.isEmpty())) { title = new MultilineTextWidget((centered) ? (scaledWidth / 2 - (textRenderer.getWidth(text) / 2)) : 12, 0, Text.of(text), textRenderer); - if (info != null) title.setTooltip(getTooltip(info, false)); + if (info != null) title.setTooltip(info.getTooltip(false)); title.setMaxWidth(buttons.size() > 1 ? buttons.get(1).getX() - 24 : scaledWidth - 24); } } diff --git a/test-fabric/src/main/java/eu/midnightdust/fabric/example/MidnightLibExtras.java b/test-fabric/src/main/java/eu/midnightdust/fabric/example/MidnightLibExtras.java new file mode 100644 index 0000000..12deb14 --- /dev/null +++ b/test-fabric/src/main/java/eu/midnightdust/fabric/example/MidnightLibExtras.java @@ -0,0 +1,96 @@ +package eu.midnightdust.fabric.example; + +import com.google.common.collect.Lists; +import eu.midnightdust.lib.config.MidnightConfig; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.tooltip.Tooltip; +import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.gui.widget.ClickableWidget; +import net.minecraft.client.gui.widget.TextIconButtonWidget; +import net.minecraft.client.option.KeyBinding; +import net.minecraft.client.util.InputUtil; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; +import net.minecraft.util.Identifier; +import org.jetbrains.annotations.Nullable; +import org.lwjgl.glfw.GLFW; + +/* + Pre-made additional (niche) functionality that is not included in MidnightLib to keep the file size small. + Feel free to copy the parts you need :) +*/ +public class MidnightLibExtras { + public static class KeybindButton extends ButtonWidget { + public static ButtonWidget focusedButton; + + public static void add(KeyBinding binding, MidnightConfig.MidnightConfigListWidget list, MidnightConfig.MidnightConfigScreen screen) { + KeybindButton editButton = new KeybindButton(screen.width - 185, 0, 150, 20, binding); + TextIconButtonWidget resetButton = TextIconButtonWidget.builder(Text.translatable("controls.reset"), (button -> { + binding.setBoundKey(binding.getDefaultKey()); + screen.updateList(); + }), true).texture(Identifier.of("midnightlib","icon/reset"), 12, 12).dimension(20, 20).build(); + resetButton.setPosition(screen.width - 205 + 150 + 25, 0); + editButton.resetButton = resetButton; + editButton.updateMessage(false); + MidnightConfig.EntryInfo info = new MidnightConfig.EntryInfo(null, screen.modid); + + list.addButton(Lists.newArrayList(editButton, resetButton), Text.translatable(binding.getTranslationKey()), info); + } + + private final KeyBinding binding; + private @Nullable ClickableWidget resetButton; + public KeybindButton(int x, int y, int width, int height, KeyBinding binding) { + super(x, y, width, height, binding.getBoundKeyLocalizedText(), (button) -> { + ((KeybindButton) button).updateMessage(true); + focusedButton = button; + }, (textSupplier) -> binding.isUnbound() ? Text.translatable("narrator.controls.unbound", binding.getTranslationKey()) : Text.translatable("narrator.controls.bound", binding.getTranslationKey(), textSupplier.get())); + this.binding = binding; + updateMessage(false); + } + @Override + public boolean keyPressed(int keyCode, int scanCode, int modifiers) { + if (focusedButton == this) { + if (keyCode == GLFW.GLFW_KEY_ESCAPE) { + this.binding.setBoundKey(InputUtil.UNKNOWN_KEY); + } else { + this.binding.setBoundKey(InputUtil.fromKeyCode(keyCode, scanCode)); + } + updateMessage(false); + + focusedButton = null; + return true; + } + return super.keyPressed(keyCode, scanCode, modifiers); + } + + public void updateMessage(boolean focused) { + boolean hasConflicts = false; + MutableText conflictingBindings = Text.empty(); + if (focused) this.setMessage(Text.literal("> ").append(this.binding.getBoundKeyLocalizedText().copy().formatted(Formatting.WHITE, Formatting.UNDERLINE)).append(" <").formatted(Formatting.YELLOW)); + else { + this.setMessage(this.binding.getBoundKeyLocalizedText()); + + if (!this.binding.isUnbound()) { + for(KeyBinding keyBinding : MinecraftClient.getInstance().options.allKeys) { + if (keyBinding != this.binding && this.binding.equals(keyBinding)) { + if (hasConflicts) conflictingBindings.append(", "); + + hasConflicts = true; + conflictingBindings.append(Text.translatable(keyBinding.getTranslationKey())); + } + } + } + } + + if (this.resetButton != null) this.resetButton.active = !this.binding.isDefault(); + + if (hasConflicts) { + this.setMessage(Text.literal("[ ").append(this.getMessage().copy().formatted(Formatting.WHITE)).append(" ]").formatted(Formatting.RED)); + this.setTooltip(Tooltip.of(Text.translatable("controls.keybinds.duplicateKeybinds", conflictingBindings))); + } else { + this.setTooltip(null); + } + } + } +} 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 index 3ffa54d..80d4a15 100644 --- 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 @@ -1,12 +1,15 @@ package eu.midnightdust.fabric.example.config; import com.google.common.collect.Lists; +import eu.midnightdust.fabric.example.MidnightLibExtras; import eu.midnightdust.lib.config.MidnightConfig; +import net.minecraft.client.MinecraftClient; import net.minecraft.util.Identifier; import javax.swing.*; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** 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*/ @@ -18,6 +21,7 @@ public class MidnightConfigExample extends MidnightConfig { public static final String LISTS = "lists"; public static final String FILES = "files"; public static final String CONDITIONS = "conditions"; + public static final String EXTRAS = "extras"; @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! @@ -115,4 +119,16 @@ public class MidnightConfigExample extends MidnightConfig { @Comment(category = CONDITIONS, name="You disabled MidnightLib's config screen list. Why? :(", centered = true) public static Comment why; public static int imposter = 16777215; // - Entries without an @Entry or @Comment annotation are ignored + + @Condition(requiredModId = "thismoddoesnotexist") + @Comment(category = EXTRAS) public static Comment iAmJustADummy; // We only have this to initialize an empty tab for the keybinds below + + @Override + public void onTabInit(String tabName, MidnightConfigListWidget list, MidnightConfigScreen screen) { + if (Objects.equals(tabName, EXTRAS)) { + MidnightLibExtras.KeybindButton.add(MinecraftClient.getInstance().options.advancementsKey, list, screen); + MidnightLibExtras.KeybindButton.add(MinecraftClient.getInstance().options.dropKey, list, screen); + } + } + } \ No newline at end of file diff --git a/test-fabric/src/main/resources/assets/modid/lang/en_us.json b/test-fabric/src/main/resources/assets/modid/lang/en_us.json index 702947c..273f0da 100644 --- a/test-fabric/src/main/resources/assets/modid/lang/en_us.json +++ b/test-fabric/src/main/resources/assets/modid/lang/en_us.json @@ -24,5 +24,6 @@ "modid.midnightconfig.category.lists": "Lists", "modid.midnightconfig.category.files": "Files", "modid.midnightconfig.category.conditions": "Quiz", + "modid.midnightconfig.category.extras": "Extras", "modid.midnightconfig.category.multiConditions": "Multi-Conditions" } \ No newline at end of file From b2c24010da58e4e9f625a2908fdeff05c33844c8 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Mon, 12 May 2025 12:45:27 +0200 Subject: [PATCH 093/100] fix: adjust option title position --- .../main/java/eu/midnightdust/lib/config/MidnightConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 e8e0f56..054fa8d 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -483,7 +483,7 @@ public abstract class MidnightConfig { public void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { buttons.forEach(b -> { b.setY(y + (b instanceof CheckboxWidget ? 1 : 0)); b.render(context, mouseX, mouseY, tickDelta);}); if (title != null) { - title.setY(y + 9); + title.setY(y+5); title.renderWidget(context, mouseX, mouseY, tickDelta); boolean tooltipVisible = mouseX >= title.getX() && mouseX < title.getWidth() + title.getX() && mouseY >= title.getY() && mouseY < title.getHeight() + title.getY(); From 7a15f1fb8dc947a574981fd9e5b4f618369aeef5 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Mon, 12 May 2025 18:53:54 +0200 Subject: [PATCH 094/100] fix: conditions are not applied in default tab - Closes #104 --- .../src/main/java/eu/midnightdust/lib/config/MidnightConfig.java | 1 + 1 file changed, 1 insertion(+) 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 054fa8d..25364c5 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -344,6 +344,7 @@ public abstract class MidnightConfig { public void fillList() { MidnightConfig.getClass(modid).onTabInit(prevTab.getTitle().getContent() instanceof TranslatableTextContent translatable ? translatable.getKey().replace("%s.midnightconfig.category.".formatted(modid), "") : prevTab.getTitle().toString(), list, this); for (EntryInfo info : entries.values()) { + info.updateConditions(); if (!info.conditionsMet) { boolean visibleButLocked = false; for (Condition condition : info.conditions) { From f1fe868192e71b69b8ee08a2dff47e0c9f72e0ee Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Mon, 12 May 2025 22:57:15 +0200 Subject: [PATCH 095/100] feat: remove checkbox widgets - As voted on in a recent MidnightDust Discord Poll --- .../java/eu/midnightdust/lib/config/MidnightConfig.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) 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 99b4250..c24bef1 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -164,9 +164,6 @@ public abstract class MidnightConfig { else if (info.dataType == boolean.class) { Function func = value -> Text.translatable((Boolean) value ? "gui.yes" : "gui.no").formatted((Boolean) value ? Formatting.GREEN : Formatting.RED); info.function = new AbstractMap.SimpleEntry>(button -> { - if (info.actionButton instanceof CheckboxWidget checkbox && checkbox.isChecked() == (Boolean) info.value) { - checkbox.onPress(); return; - } info.setValue(!(Boolean) info.value); button.setMessage(func.apply(info.value)); }, func); } else if (info.dataType.isEnum()) { @@ -377,7 +374,6 @@ public abstract class MidnightConfig { values.setValue(value -> getEnumTranslatableText(value, modid, info)); } widget = ButtonWidget.builder(values.getValue().apply(info.value), values.getKey()).dimensions(width - 185, 0, 150, 20).tooltip(info.getTooltip(true)).build(); - if (info.dataType == boolean.class) info.actionButton = CheckboxWidget.builder(Text.empty(), textRenderer).callback((checkbox, checked) -> values.getKey().onPress((ButtonWidget) widget)).checked((Boolean) info.value).pos(widget.getX(), 1).build(); } else if (e.isSlider()) widget = new MidnightSliderWidget(width - 185, 0, 150, 20, Text.of(info.tempValue), (Double.parseDouble(info.tempValue) - e.min()) / (e.max() - e.min()), info); else widget = new TextFieldWidget(textRenderer, width - 185, 0, 150, 20, Text.empty()); @@ -490,7 +486,7 @@ public abstract class MidnightConfig { } } public void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { - buttons.forEach(b -> { b.setY(y + (b instanceof CheckboxWidget ? 1 : 0)); b.render(context, mouseX, mouseY, tickDelta);}); + buttons.forEach(b -> { b.setY(y); b.render(context, mouseX, mouseY, tickDelta);}); if (title != null) { title.setY(y+5); title.renderWidget(context, mouseX, mouseY, tickDelta); From 6bbaf1ab5d93b7685b569c1e57861da3e1706220 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Mon, 12 May 2025 22:58:22 +0200 Subject: [PATCH 096/100] optimize: remove unchanged translations in es_ar --- common/src/main/resources/assets/midnightlib/lang/es_ar.json | 5 ----- 1 file changed, 5 deletions(-) diff --git a/common/src/main/resources/assets/midnightlib/lang/es_ar.json b/common/src/main/resources/assets/midnightlib/lang/es_ar.json index 1f559e8..0829d0a 100644 --- a/common/src/main/resources/assets/midnightlib/lang/es_ar.json +++ b/common/src/main/resources/assets/midnightlib/lang/es_ar.json @@ -3,11 +3,6 @@ "midnightlib.midnightconfig.title": "Configuración de MidnightLib", "midnightlib.midnightconfig.config_screen_list": "Habilitar lista de pantallas de configuración", "midnightlib.midnightconfig.enum.ConfigButton.TRUE": "§aSí", - "midnightlib.midnightconfig.enum.ConfigButton.FALSE": "§cNo", - "midnightlib.midnightconfig.enum.ConfigButton.MODMENU": "§bModMenu", - "midnightlib.modrinth": "Modrinth", - "midnightlib.curseforge": "CurseForge", - "midnightlib.wiki": "Wiki", "modmenu.summaryTranslation.midnightlib": "Librería común para facilitar la configuración.", "midnightconfig.colorChooser.title": "Elegí un color" } From 7ddfadd4ec84c62f8ffa97b1cfcda155bd5c2ced Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Tue, 13 May 2025 12:05:07 +0200 Subject: [PATCH 097/100] clean: some code cleanup --- .../lib/config/MidnightConfig.java | 8 +-- .../example/config/MidnightConfigExample.java | 59 ++++++++++--------- 2 files changed, 33 insertions(+), 34 deletions(-) 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 c24bef1..e85d89c 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -187,11 +187,9 @@ public abstract class MidnightConfig { } private static Text getEnumTranslatableText(Object value, String modid, EntryInfo info) { - if (value instanceof TranslatableOption translatableOption) { - return translatableOption.getText(); - } + if (value instanceof TranslatableOption translatableOption) return translatableOption.getText(); - String translationKey = modid + ".midnightconfig.enum." + info.dataType.getSimpleName() + "." + info.toTemporaryValue(); + String translationKey = "%s.midnightconfig.enum.%s.%s".formatted(modid, info.dataType.getSimpleName(), info.toTemporaryValue()); return I18n.hasTranslation(translationKey) ? Text.translatable(translationKey) : Text.literal(info.toTemporaryValue()); } @@ -257,7 +255,7 @@ public abstract class MidnightConfig { @Environment(EnvType.CLIENT) public static class MidnightConfigScreen extends Screen { protected MidnightConfigScreen(Screen parent, String modid) { - super(Text.translatable(modid + ".midnightconfig." + "title")); + super(Text.translatable(modid + ".midnightconfig.title")); this.parent = parent; this.modid = modid; this.translationPrefix = modid + ".midnightconfig."; loadValuesFromJson(modid); 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 index 137ded6..095581b 100644 --- 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 @@ -40,35 +40,6 @@ public class MidnightConfigExample extends MidnightConfig { QUILT, FABRIC, FORGE, NEOFORGE, VANILLA } @Entry(category = TEXT) public static GraphicsSteps graphicsSteps = GraphicsSteps.FABULOUS; // Example for an enum option with TranslatableOption - public enum GraphicsSteps implements TranslatableOption { - FAST(0, "options.graphics.fast"), - FANCY(1, "options.graphics.fancy"), - FABULOUS(2, "options.graphics.fabulous"); - - private final int id; - private final String translationKey; - - GraphicsSteps(int id, String translationKey) { - this.id = id; - this.translationKey = translationKey; - } - - @Override - public Text getText() { - MutableText mutableText = Text.translatable(this.getTranslationKey()); - return this == GraphicsSteps.FABULOUS ? mutableText.formatted(Formatting.ITALIC).formatted(Formatting.AQUA) : mutableText; - } - - @Override - public int getId() { - return this.id; - } - - @Override - public String getTranslationKey() { - return this.translationKey; - } - } @Comment(category = TEXT, name = "§nMidnightLib Wiki", centered = true, url = "https://www.midnightdust.eu/wiki/midnightlib/") public static Comment wiki; // Example for a comment with a url @@ -155,6 +126,36 @@ public class MidnightConfigExample extends MidnightConfig { public static int imposter = 16777215; // - Entries without an @Entry or @Comment annotation are ignored + public enum GraphicsSteps implements TranslatableOption { + FAST(0, "options.graphics.fast"), + FANCY(1, "options.graphics.fancy"), + FABULOUS(2, "options.graphics.fabulous"); + + private final int id; + private final String translationKey; + + GraphicsSteps(int id, String translationKey) { + this.id = id; + this.translationKey = translationKey; + } + + @Override + public Text getText() { + MutableText mutableText = Text.translatable(this.getTranslationKey()); + return this == GraphicsSteps.FABULOUS ? mutableText.formatted(Formatting.ITALIC).formatted(Formatting.AQUA) : mutableText; + } + + @Override + public int getId() { + return this.id; + } + + @Override + public String getTranslationKey() { + return this.translationKey; + } + } + @Condition(requiredModId = "thismoddoesnotexist") @Comment(category = EXTRAS) public static Comment iAmJustADummy; // We only have this to initialize an empty tab for the keybinds below From a1ad6dd1f085d1782de9f0ab11efd70b8290460d Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Tue, 13 May 2025 12:05:21 +0200 Subject: [PATCH 098/100] chore: bump version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 13e4aee..8d2a03d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ yarn_mappings=1.21.4+build.1 enabled_platforms=fabric,neoforge archives_base_name=midnightlib -mod_version=1.7.2 +mod_version=1.7.3 maven_group=eu.midnightdust release_type=release curseforge_id=488090 From aea85598315422204174df0623e4f7e095ae46d4 Mon Sep 17 00:00:00 2001 From: maloryware Date: Sun, 3 Aug 2025 03:08:22 +0100 Subject: [PATCH 099/100] prepare 1.20.1 backport --- build.gradle | 6 +- .../core/mixin/MixinOptionsScreen.java | 43 ++----- .../screen/MidnightConfigOverviewScreen.java | 70 +++++++++--- .../lib/config/MidnightConfig.java | 86 +++++++++----- .../screen/TexturedOverlayButtonWidget.java | 40 +++++++ .../resources/assets/midnightlib/icon.png | Bin 2232 -> 2801 bytes .../gui/{sprites/icon => }/explorer.png | Bin .../textures/gui/midnightlib_button.png | Bin 0 -> 960 bytes .../textures/gui/{sprites/icon => }/reset.png | Bin .../textures/gui/sprites/icon/midnightlib.png | Bin 136 -> 0 bytes .../main/resources/midnightlib.mixins.json | 13 ++- fabric/build.gradle | 6 +- fabric/src/main/resources/fabric.mod.json | 2 +- gradle.properties | 25 ++-- gradle/wrapper/gradle-wrapper.properties | 2 +- neoforge/build.gradle | 108 ------------------ neoforge/gradle.properties | 1 - .../util/neoforge/PlatformFunctionsImpl.java | 33 ------ .../neoforge/MidnightLibNeoForge.java | 52 --------- .../resources/META-INF/neoforge.mods.toml | 31 ----- neoforge/src/main/resources/midnightlib.png | Bin 2801 -> 0 bytes quilt/build.gradle | 2 + settings.gradle | 4 +- 23 files changed, 196 insertions(+), 328 deletions(-) create mode 100644 common/src/main/java/eu/midnightdust/lib/util/screen/TexturedOverlayButtonWidget.java rename common/src/main/resources/assets/midnightlib/textures/gui/{sprites/icon => }/explorer.png (100%) create mode 100644 common/src/main/resources/assets/midnightlib/textures/gui/midnightlib_button.png rename common/src/main/resources/assets/midnightlib/textures/gui/{sprites/icon => }/reset.png (100%) delete mode 100644 common/src/main/resources/assets/midnightlib/textures/gui/sprites/icon/midnightlib.png delete mode 100644 neoforge/build.gradle delete mode 100644 neoforge/gradle.properties delete mode 100644 neoforge/src/main/java/eu/midnightdust/lib/util/neoforge/PlatformFunctionsImpl.java delete mode 100644 neoforge/src/main/java/eu/midnightdust/neoforge/MidnightLibNeoForge.java delete mode 100644 neoforge/src/main/resources/META-INF/neoforge.mods.toml delete mode 100644 neoforge/src/main/resources/midnightlib.png diff --git a/build.gradle b/build.gradle index 43297f8..b22cbbe 100644 --- a/build.gradle +++ b/build.gradle @@ -3,7 +3,7 @@ import groovy.json.JsonOutput plugins { id "architectury-plugin" version "3.4-SNAPSHOT" - id "dev.architectury.loom" version "1.7-SNAPSHOT" apply false + id "dev.architectury.loom" version "1.10-SNAPSHOT" apply false id "me.shedaniel.unified-publishing" version "0.1.+" apply false id 'com.github.johnrengelman.shadow' version '8.1.1' apply false } @@ -20,7 +20,7 @@ subprojects { // The following line declares the yarn mappings you may select this one as well. mappings loom.layered { it.mappings("net.fabricmc:yarn:$rootProject.yarn_mappings:v2") - it.mappings("dev.architectury:yarn-mappings-patch-neoforge:$rootProject.yarn_mappings_patch_neoforge_version") + // it.mappings("dev.architectury:yarn-mappings-patch-neoforge:$rootProject.yarn_mappings_patch_neoforge_version") } } } @@ -44,7 +44,7 @@ allprojects { tasks.withType(JavaCompile) { options.encoding = "UTF-8" - options.release = 21 + options.release = 17 } ext { releaseChangelog = { diff --git a/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java b/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java index 13203b7..1f3da97 100644 --- a/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java +++ b/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java @@ -1,49 +1,30 @@ package eu.midnightdust.core.mixin; +import eu.midnightdust.core.config.MidnightLibConfig; import eu.midnightdust.core.screen.MidnightConfigOverviewScreen; +import eu.midnightdust.lib.util.PlatformFunctions; +import eu.midnightdust.lib.util.screen.TexturedOverlayButtonWidget; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.option.OptionsScreen; -import net.minecraft.client.gui.widget.TextIconButtonWidget; -import net.minecraft.client.gui.widget.ThreePartsLayoutWidget; import net.minecraft.text.Text; import net.minecraft.util.Identifier; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -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.util.Objects; -import static eu.midnightdust.core.MidnightLib.MOD_ID; -import static eu.midnightdust.core.config.MidnightLibConfig.shouldShowButton; - @Mixin(OptionsScreen.class) -public abstract class MixinOptionsScreen extends Screen { - @Shadow @Final private ThreePartsLayoutWidget layout; - @Unique TextIconButtonWidget midnightlib$button = TextIconButtonWidget.builder(Text.translatable("midnightlib.overview.title"), ( - buttonWidget) -> Objects.requireNonNull(client).setScreen(new MidnightConfigOverviewScreen(this)), true) - .texture(Identifier.of(MOD_ID,"icon/"+MOD_ID), 16, 16).dimension(20, 20).build(); - - private MixinOptionsScreen(Text title) {super(title);} - - @Inject(at = @At("HEAD"), method = "init") - public void midnightlib$onInit(CallbackInfo ci) { - if (shouldShowButton()) { - this.midnightlib$setButtonPos(); - this.addDrawableChild(midnightlib$button); - } +public class MixinOptionsScreen extends Screen { + private static final Identifier MIDNIGHTLIB_ICON_TEXTURE = new Identifier("midnightlib","textures/gui/midnightlib_button.png"); + protected MixinOptionsScreen(Text title) { + super(title); } - @Inject(at = @At("TAIL"), method = "refreshWidgetPositions") - public void midnightlib$onResize(CallbackInfo ci) { - if (shouldShowButton()) this.midnightlib$setButtonPos(); + @Inject(at = @At("HEAD"),method = "init") + private void midnightlib$init(CallbackInfo ci) { + if (MidnightLibConfig.config_screen_list.equals(MidnightLibConfig.ConfigButton.TRUE) || (MidnightLibConfig.config_screen_list.equals(MidnightLibConfig.ConfigButton.MODMENU) && !PlatformFunctions.isModLoaded("modmenu"))) + this.addDrawableChild(new TexturedOverlayButtonWidget(this.width / 2 + 158, this.height / 6 - 12, 20, 20, 0, 0, 20, MIDNIGHTLIB_ICON_TEXTURE, 32, 64, (buttonWidget) -> Objects.requireNonNull(client).setScreen(new MidnightConfigOverviewScreen(this)), Text.translatable("midnightlib.overview.title"))); } - - @Unique - public void midnightlib$setButtonPos() { - midnightlib$button.setPosition(layout.getWidth() / 2 + 158, layout.getY() + layout.getFooterHeight() - 4); - } -} \ No newline at end of file +} 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 7a1df8a..d08d956 100755 --- a/common/src/main/java/eu/midnightdust/core/screen/MidnightConfigOverviewScreen.java +++ b/common/src/main/java/eu/midnightdust/core/screen/MidnightConfigOverviewScreen.java @@ -4,18 +4,16 @@ import eu.midnightdust.core.MidnightLib; import eu.midnightdust.lib.config.MidnightConfig; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.Element; +import net.minecraft.client.gui.Selectable; import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.gui.widget.*; import net.minecraft.screen.ScreenTexts; -import net.minecraft.text.Text; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Objects; - -import static eu.midnightdust.lib.config.MidnightConfig.MidnightConfigListWidget; +import net.minecraft.text.*; +import java.util.*; @Environment(EnvType.CLIENT) public class MidnightConfigOverviewScreen extends Screen { @@ -25,26 +23,64 @@ public class MidnightConfigOverviewScreen extends Screen { this.parent = parent; } private final Screen parent; - private MidnightConfigListWidget list; + private MidnightOverviewListWidget 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.addDrawableChild(ButtonWidget.builder(ScreenTexts.DONE, (button) -> Objects.requireNonNull(client).setScreen(parent)).dimensions(this.width / 2 - 100, this.height - 28, 200, 20).build()); - this.addSelectableChild(this.list = new MidnightConfigListWidget(this.client, this.width, this.height - 57, 24, 25)); + this.list = new MidnightOverviewListWidget(this.client, this.width, this.height, 32, this.height - 32, 25); + if (this.client != null && this.client.world != null) this.list.setRenderBackground(false); + this.addSelectableChild(this.list); 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); - }}); + list.addButton(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()); + } + }); super.init(); } @Override public void render(DrawContext context, int mouseX, int mouseY, float delta) { - super.render(context, mouseX, mouseY, delta); + this.renderBackground(context); this.list.render(context, mouseX, mouseY, delta); - context.drawCenteredTextWithShadow(textRenderer, title, width / 2, 10, 0xFFFFFF); + context.drawCenteredTextWithShadow(textRenderer, title, width / 2, 15, 0xFFFFFF); + super.render(context, mouseX, mouseY, delta); + } + @Environment(EnvType.CLIENT) + public static class MidnightOverviewListWidget extends ElementListWidget { + TextRenderer textRenderer; + + public MidnightOverviewListWidget(MinecraftClient minecraftClient, int i, int j, int k, int l, int m) { + super(minecraftClient, i, j, k, l, m); + this.centerListVertically = false; + textRenderer = minecraftClient.textRenderer; + } + @Override + public int getScrollbarPositionX() {return this.width-7;} + + public void addButton(ClickableWidget button) { + this.addEntry(OverviewButtonEntry.create(button)); + } + @Override + public int getRowWidth() { return 400; } + } + public static class OverviewButtonEntry extends ElementListWidget.Entry { + private final ClickableWidget button; + private final List buttonList = new ArrayList<>(); + + private OverviewButtonEntry(ClickableWidget button) { + this.button = button; + this.buttonList.add(button); + } + public static OverviewButtonEntry create(ClickableWidget button) {return new OverviewButtonEntry(button);} + public void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { + button.setY(y); + button.render(context, mouseX, mouseY, tickDelta); + } + public List children() {return buttonList;} + public List selectableChildren() {return buttonList;} } } \ No newline at end of file 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 e85d89c..eaf0796 100755 --- a/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java +++ b/common/src/main/java/eu/midnightdust/lib/config/MidnightConfig.java @@ -2,14 +2,16 @@ package eu.midnightdust.lib.config; import com.google.common.collect.Lists; import com.google.gson.*; import com.google.gson.stream.*; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.serialization.DataResult; import eu.midnightdust.lib.util.PlatformFunctions; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; -import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.Element; import net.minecraft.client.gui.Selectable; import net.minecraft.client.gui.screen.ConfirmLinkScreen; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.tab.GridScreenTab; import net.minecraft.client.gui.tab.Tab; import net.minecraft.client.gui.tab.TabManager; import net.minecraft.client.gui.tooltip.Tooltip; import net.minecraft.client.gui.widget.*; -import net.minecraft.client.render.RenderLayer; import net.minecraft.client.resource.language.I18n; import net.minecraft.registry.Registries; import net.minecraft.screen.ScreenTexts; @@ -21,7 +23,6 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; import java.awt.Color; -import java.io.IOException; import java.lang.annotation.*; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; import java.nio.file.Files; import java.nio.file.Path; @@ -31,6 +32,26 @@ import java.util.regex.Pattern; import static net.minecraft.client.MinecraftClient.IS_SYSTEM_MAC; + +/* FIXME: + * hi martin :wave: + * before anythinge else: + * DON'T ANNOY YOURSELF WITH THIS + * BACKPORT UNLESS YOU REALLY DON'T HAVE + * ANYTHING BETTER TO DO!!!!! + * i don't wish to waste your time in any capacity, + * and this backport is going to be a *huge* mess, + * as you surely know + * so please!! take it easy! + * much love <3 + * . + * this being your codebase, i'm guessing + * (moreso hoping) you'll know what's in need + * of fixing given the rendering changes between + * 1.20 & 1.21 + * gave it my best shot but... got completely lost. + */ + /** MidnightConfig by Martin "Motschen" Prokoph * Single class config library - feel free to copy! * Based on ... @@ -97,8 +118,10 @@ public abstract class MidnightConfig { if (!condition.requiredModId().isEmpty() && !PlatformFunctions.isModLoaded(condition.requiredModId())) this.conditionsMet = false; String requiredOption = condition.requiredOption().contains(":") ? condition.requiredOption() : (this.modid + ":" + condition.requiredOption()); - if (entries.get(requiredOption) instanceof EntryInfo info) + if (entries.get(requiredOption) != null) { + EntryInfo info = entries.get(requiredOption); this.conditionsMet &= List.of(condition.requiredValue()).contains(info.tempValue); + } if (!this.conditionsMet) break; } if (prevConditionState != this.conditionsMet) reloadScreen = true; @@ -120,10 +143,7 @@ public abstract class MidnightConfig { private static final Gson gson = new GsonBuilder() .excludeFieldsWithModifiers(Modifier.TRANSIENT).excludeFieldsWithModifiers(Modifier.PRIVATE) .addSerializationExclusionStrategy(new NonEntryExclusionStrategy()) - .registerTypeAdapter(Identifier.class, new TypeAdapter() { - public void write(JsonWriter out, Identifier id) throws IOException { out.value(id.toString()); } - public Identifier read(JsonReader in) throws IOException { return Identifier.of(in.nextString()); } - }).setPrettyPrinting().create(); + .registerTypeAdapter(Identifier.class, new Identifier.Serializer()).setPrettyPrinting().create(); public static void loadValuesFromJson(String modid) { try { gson.fromJson(Files.newBufferedReader(path), configClass.get(modid)); } @@ -198,8 +218,7 @@ public abstract class MidnightConfig { info.function = (BiFunction>) (t, b) -> s -> { s = s.trim(); if (!(s.isEmpty() || !isNumber || pattern.matcher(s).matches()) || - (info.dataType == Identifier.class && Identifier.validate(s).isError())) return false; - + (info.dataType == Identifier.class && Identifier.validate(s).equals(DataResult.success(new Identifier(s))))) return false; // inline substitution for "isError" Number value = 0; boolean inLimits = false; info.error = null; if (!(isNumber && s.isEmpty()) && !s.equals("-") && !s.equals(".")) { try { value = f.apply(s); } catch(NumberFormatException e){ return false; } @@ -292,9 +311,9 @@ public abstract class MidnightConfig { super.tick(); if (prevTab != null && prevTab != tabManager.getCurrentTab()) { prevTab = tabManager.getCurrentTab(); - updateList(); list.setScrollY(0); + updateList(); list.setScrollAmount(0); } - scrollProgress = list.getScrollY(); + scrollProgress = list.getScrollAmount(); for (EntryInfo info : entries.values()) info.updateFieldValue(); updateButtons(); if (reloadScreen) { updateList(); reloadScreen = false; } @@ -303,8 +322,10 @@ public abstract class MidnightConfig { if (this.list != null) { for (ButtonEntry entry : this.list.children()) { if (entry.buttons != null && entry.buttons.size() > 1 && entry.info.field != null) { - if (entry.buttons.get(0) instanceof ClickableWidget widget) + if (entry.buttons.get(0) != null) { + ClickableWidget widget = entry.buttons.get(0); if (widget.isFocused() || widget.isHovered()) widget.setTooltip(entry.info.getTooltip(true)); + } if (entry.buttons.get(1) instanceof ButtonWidget button) button.active = !Objects.equals(String.valueOf(entry.info.value), String.valueOf(entry.info.defaultValue)) && entry.info.conditionsMet; }}}} @@ -336,7 +357,7 @@ public abstract class MidnightConfig { Objects.requireNonNull(client).setScreen(parent); }).dimensions(this.width / 2 + 4, this.height - 26, 150, 20).build()); - this.list = new MidnightConfigListWidget(this.client, this.width, this.height - 57, 24, 25); + this.list = new MidnightConfigListWidget(this.client, this.width, this.height, this.height - 57, 24, 25); this.addSelectableChild(this.list); fillList(); if (tabs.size() > 1) list.renderHeaderSeparator = false; } @@ -356,11 +377,11 @@ public abstract class MidnightConfig { } if (info.modid.equals(modid) && (info.tab == null || info.tab == tabManager.getCurrentTab())) { Text name = Objects.requireNonNullElseGet(info.name, () -> Text.translatable(translationPrefix + info.fieldName)); - TextIconButtonWidget resetButton = TextIconButtonWidget.builder(Text.translatable("controls.reset"), (button -> { + IconButtonWidget resetButton = IconButtonWidget.builder(Text.translatable("controls.reset"), Identifier.of("midnightlib","icon/reset"), (button -> { info.value = info.defaultValue; info.listIndex = 0; info.tempValue = info.toTemporaryValue(); updateList(); - }), true).texture(Identifier.of("midnightlib","icon/reset"), 12, 12).dimension(20, 20).build(); + }) ).build(); resetButton.setPosition(width - 205 + 150 + 25, 0); if (info.function != null) { @@ -408,7 +429,7 @@ public abstract class MidnightConfig { } catch (Exception ignored) {} info.actionButton = colorButton; } else if (e.selectionMode() > -1) { - ButtonWidget explorerButton = TextIconButtonWidget.builder(Text.empty(), + ButtonWidget explorerButton = IconButtonWidget.builder(Text.empty(), Identifier.of("midnightlib", "icon/explorer"), button -> new Thread(() -> { JFileChooser fileChooser = new JFileChooser(info.tempValue); fileChooser.setFileSelectionMode(e.selectionMode()); fileChooser.setDialogType(e.fileChooserType()); @@ -420,8 +441,8 @@ public abstract class MidnightConfig { info.setValue(fileChooser.getSelectedFile().getAbsolutePath()); updateList(); } - }).start(), true - ).texture(Identifier.of("midnightlib", "icon/explorer"), 12, 12).dimension(20, 20).build(); + }).start() + ).build(); explorerButton.setPosition(width - 185, 0); info.actionButton = explorerButton; } @@ -438,7 +459,7 @@ public abstract class MidnightConfig { if (!info.conditionsMet) widgets.forEach(w -> w.active = false); this.list.addButton(widgets, name, info); } else this.list.addButton(List.of(), name, info); - } list.setScrollY(scrollProgress); + } list.setScrollAmount(scrollProgress); updateButtons(); } } @@ -446,20 +467,24 @@ public abstract class MidnightConfig { public void render(DrawContext context, int mouseX, int mouseY, float delta) { super.render(context, mouseX, mouseY, delta); this.list.render(context, mouseX, mouseY, delta); - if (tabs.size() < 2) context.drawCenteredTextWithShadow(textRenderer, title, width / 2, 10, 0xFFFFFF); + if (tabs.size() < 2) context.drawCenteredTextWithShadow(textRenderer, title, width / 2, 10, 0xFFFFFFFF); } } @Environment(EnvType.CLIENT) public static class MidnightConfigListWidget extends ElementListWidget { public boolean renderHeaderSeparator = true; - public MidnightConfigListWidget(MinecraftClient client, int width, int height, int y, int itemHeight) { super(client, width, height, y, itemHeight); } - @Override public int getScrollbarX() { return this.width -7; } + public MidnightConfigListWidget(MinecraftClient client, int width, int height, int yStart, int y, int itemHeight) { super(client, width, height, yStart, y, itemHeight); } + @Override public int getScrollbarPositionX() { return this.width -7; } + /* @Override protected void drawHeaderAndFooterSeparators(DrawContext context) { if (renderHeaderSeparator) super.drawHeaderAndFooterSeparators(context); - else context.drawTexture(RenderLayer::getGuiTextured, this.client.world == null ? Screen.FOOTER_SEPARATOR_TEXTURE : Screen.INWORLD_FOOTER_SEPARATOR_TEXTURE, this.getX(), this.getBottom(), 0, 0, this.getWidth(), 2, 32, 2); + else { RenderSystem.enableBlend(); + context.drawTexture(this.client.world == null ? Screen.FOOTER_SEPARATOR_TEXTURE : Screen.INWORLD_FOOTER_SEPARATOR_TEXTURE, this.getX(), this.getBottom(), 0.0F, 0.0F, this.getWidth(), 2, 32, 2); + RenderSystem.disableBlend(); } } + */ public void addButton(List buttons, Text text, EntryInfo info) { this.addEntry(new ButtonEntry(buttons, text, info)); } public void clear() { this.clearEntries(); } @Override public int getRowWidth() { return 10000; } @@ -478,21 +503,22 @@ public abstract class MidnightConfig { int scaledWidth = MinecraftClient.getInstance().getWindow().getScaledWidth(); if (text != null && (!text.getString().contains("spacer") || !buttons.isEmpty())) { - title = new MultilineTextWidget((centered) ? (scaledWidth / 2 - (textRenderer.getWidth(text) / 2)) : 12, 0, Text.of(text), textRenderer); + title = new MultilineTextWidget((centered) ? (scaledWidth / 2 - (textRenderer.getWidth(text) / 2)) : 12, 0, text, textRenderer); + title.setCentered(centered); if (info != null) title.setTooltip(info.getTooltip(false)); - title.setMaxWidth(buttons.size() > 1 ? buttons.get(1).getX() - 24 : scaledWidth - 24); + title.setMaxWidth(!buttons.isEmpty() ? buttons.get(buttons.size() > 2 ? buttons.size()-1 : 0).getX() - 16 : scaledWidth - 24); } } public void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { buttons.forEach(b -> { b.setY(y); b.render(context, mouseX, mouseY, tickDelta);}); if (title != null) { title.setY(y+5); - title.renderWidget(context, mouseX, mouseY, tickDelta); - + title.render(context, mouseX, mouseY, tickDelta); boolean tooltipVisible = mouseX >= title.getX() && mouseX < title.getWidth() + title.getX() && mouseY >= title.getY() && mouseY < title.getHeight() + title.getY(); if (tooltipVisible && title.getTooltip() != null) context.drawOrderedTooltip(textRenderer, title.getTooltip().getLines(MinecraftClient.getInstance()), mouseX, mouseY); - if (info.entry != null && !this.buttons.isEmpty() && this.buttons.getFirst() instanceof ClickableWidget widget) { + if (info.entry != null && !this.buttons.isEmpty() && this.buttons.get(0) != null) { + ClickableWidget widget = this.buttons.get(0); int idMode = this.info.entry.idMode(); if (idMode != -1) context.drawItem(idMode == 0 ? Registries.ITEM.get(Identifier.tryParse(this.info.tempValue)).getDefaultStack() : Registries.BLOCK.get(Identifier.tryParse(this.info.tempValue)).asItem().getDefaultStack(), widget.getX() + widget.getWidth() - 18, y + 2); } @@ -502,7 +528,7 @@ public abstract class MidnightConfig { @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { if (this.info != null && this.info.comment != null && !this.info.comment.url().isBlank()) - ConfirmLinkScreen.open(MinecraftClient.getInstance().currentScreen, this.info.comment.url(), true); + ConfirmLinkScreen.open(this.info.comment.url(), MinecraftClient.getInstance().currentScreen, true); return super.mouseClicked(mouseX, mouseY, button); } diff --git a/common/src/main/java/eu/midnightdust/lib/util/screen/TexturedOverlayButtonWidget.java b/common/src/main/java/eu/midnightdust/lib/util/screen/TexturedOverlayButtonWidget.java new file mode 100644 index 0000000..e5f1f38 --- /dev/null +++ b/common/src/main/java/eu/midnightdust/lib/util/screen/TexturedOverlayButtonWidget.java @@ -0,0 +1,40 @@ +package eu.midnightdust.lib.util.screen; + +import com.mojang.blaze3d.systems.RenderSystem; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.widget.TexturedButtonWidget; +import net.minecraft.client.render.GameRenderer; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; + +public class TexturedOverlayButtonWidget extends TexturedButtonWidget { + + public TexturedOverlayButtonWidget(int x, int y, int width, int height, int u, int v, Identifier texture, PressAction pressAction) { + super(x, y, width, height, u, v, texture, pressAction); + } + + public TexturedOverlayButtonWidget(int x, int y, int width, int height, int u, int v, int hoveredVOffset, Identifier texture, PressAction pressAction) { + super(x, y, width, height, u, v, hoveredVOffset, texture, pressAction); + } + + public TexturedOverlayButtonWidget(int x, int y, int width, int height, int u, int v, int hoveredVOffset, Identifier texture, int textureWidth, int textureHeight, PressAction pressAction) { + super(x, y, width, height, u, v, hoveredVOffset, texture, textureWidth, textureHeight, pressAction); + } + + public TexturedOverlayButtonWidget(int x, int y, int width, int height, int u, int v, int hoveredVOffset, Identifier texture, int textureWidth, int textureHeight, PressAction pressAction, Text text) { + super(x, y, width, height, u, v, hoveredVOffset, texture, textureWidth, textureHeight, pressAction, text); + } + + @Override + public void renderButton(DrawContext context, int mouseX, int mouseY, float delta) { + int i = 66; + if (!this.isNarratable()) { + i += hoveredVOffset * 2; + } else if (this.isSelected()) { + i += hoveredVOffset; + } + context.drawNineSlicedTexture(WIDGETS_TEXTURE, this.getX(), this.getY(), this.width, this.height, 4, 200, 20, 0, i); + super.renderButton(context, mouseX, mouseY, delta); + } +} diff --git a/common/src/main/resources/assets/midnightlib/icon.png b/common/src/main/resources/assets/midnightlib/icon.png index fee5d5676fb34e5df3197a910dede7e6d498ad90..d31b4c46823b2536b67007b68606f8b82c806a08 100644 GIT binary patch literal 2801 zcmd5-dpOkDAD)>Q%ov2&+-aJy%(|3lv1VMRVbU~4xvX}EtlZWNa?3SJqS~yIOPQg_ zZ6dcs#$6>s2_d(p5O&-dmwsoT{qMKG|Ms8X`99~I&w0P+^SAo%BIz^tyWPNUIeWMmo|8mgtp#TyV76x)l zOG`m;?AWpYA}J~=0!UO;6p#ZOfEHkgiHTve*$WE`2m~TEHMOUwCnF;xIXRh3CRbHe z6&4oe<>dhoqyYY*p&`IOH8oXRTl?zOtCW-!-~O>5s{KzfRBsX%Sjv*mJz5vJ)~=NQXJ`Ldv(je?!EkvZQ2ZPV+BKV<E?B0GbTi##1o2XaYn&}+3VR`)b%gp@x zf}x$Ir9b<&&8+=Hd+)8U?QHROJNc{gf{yW#-pN%S`|X>smY17LJJajq{X^RyKMZcq zjZTi%56mo1404x0bZmQa`CAi<{Pk(U+9&?%@Y>g%nRWh9%TU+yE`Md4|8&IXTekxQ z0)Irb!cm=C`qLeq6rE*b=>;=~{qdO()TN;K`(~fqu1bGys3m(1J<~9^J9aem^ZnZO*JcK1va@&V#*Jk>-qJ`) zp_PVz=t^ma=`_eSc`eG~p;_KsX-rlz?O|5y$LPR3d#|*u@Z=LSI>PDx0~U<@gcii> z%tuJO`_j=vEUE%F@g(sqE9fQS91~rg*pw!o9?{b$6{6H9n+4g<4kPw zl99J0()G5!nYz9}Fo|N0cStH`VRF4MOPbDL(lsj_>Mfn{AwR{_5LPqLCbmHQajBJL zwf(D}M0iL3_d-z;FqtQ$KvhqhMV;I;?F~|eD`E!aPn}eEOd_2b6ymH!?n$`Z9kg)r zCcZ@8kdcyy5;Y_#<5uiGP%WKee-!yTzvU8e-8|+ydVJjQN(1x5eFZ&sT@9u}FR_eh zPtV76yKSVvG3lz~Ss6u`Ig5LlGm4#GLW1^S$CFxC#3h@t@5Fat`X_rF_vG`lfAVpa zpdT_Bw&_}@2J6G*ed62C-4(0T_ev4#L*z){n*Z>YmXnbvGs7L2A|5k)k<`22Mp{C@ zkCi+T{HZcwpFCTeLBhppYs9uK@GVH&&BTOw5~aPvbP?8`eElvhgc=u)Pa`Eb2U&d2 zeXXW+h3UM2Epwr1yMCH`3j1R1dA|~MSJMd3J7t-Afm?HH-S_31E4u9ny7oH9Cbh(y zeb9gP-1p4**UwK5a3UV1dRSAH1}R*=MlKxU0?qVcPsou+tWp=b(8I8Il|89HuJ+hg zTK*>ER%a`FaFbYQELv$}S+s2Hf^hA|w-iHE>rnyZ)N}~hpNH6Bw5RMBNpJ2uN;JO6 zIM7&Un0?QIu)hlSN?5%~!2CRPTKI%7Yr?c~Zhhi&=V`GB{W{?r8GG%#n{Iy2fxc(W z8b>ii17YSPveiL4p3OPrF*?4>?Sl}aSSt^ju5<+ovk{WF7041FMIZMJwwLapm7jXwV%dyklz%FQ?qKAt+6(Xr6^>Tz-Ct@mj>$eqAEB7()VFKANcr^A^5Qj77$FQFJc30c&s7ihSVS0(5 z(WTh!|1lD+i>jh}pVK&o;Jq!edY*Z(E^FZ1$%^$Mp+wvB<@Uc@}NNvirsT5qH zr9dLr81j|8i9{%ib)IfCkbO}Dk(hgU30ViR9ccPO;3le$_e2zJzGHZ(-A?-X@Bv9a z%L4N$ER41HZ0?Cc!#}hYPwOVGiD+IpFSFb2?F;QReYP2^g?q;xN8f7S)Qi{{zqwc` zse-%cUm$toNR!*8^OppN46kKfINd6nU#Z)yxh|z(Tox5tIhE6U^t&1ll`fuc&8HkEdoL+%6~^lnYe+^ z%Bw3|3gbcK-)I|sfE=42%$felT4k`-X!7U65S=e!VX*f0eYVU-4$6O51QQMat?P_?@Xmm zdYWxHT=Zlgwp+Nf-%MSaO+i)lF=Lu56A(wk?^Ldj8a>fqx|an|L(Yd-QJ*L_cU&8G zI80wYl)0f)GGHl!ojC5%ip2#c{qEx%x{L?%DV`&wY^0@!`1K59=f$u5!nb zjJw;~42|8kMyFPo+PUgzrK{$5Kb~_Ro{O5RbG^-*`F-&`=XuUK-|z4F{mwZ)_kVdj zzu3}ENg!D%N_D|mvbdgT;bf$|%21|OC|fzowV;;Gl}uW^^hi#CBSt!1nFzh60u^e5 zN>r*cm4h;BC0r>~0j=5eN~bsRSibvClMmumTB|n^tWcGzRjWGHs{zzgt5r2uchb6% zUaRQsV^sXHFygPsuY472iz; zo_kLvtJzR()HWS}{DjUR*QXK9XCt(9(c=U?_cLMxBeP*39Y5{fy~-k|>$Mf}p#I2x z4rmcZuWR%U>Hs6x!H_BMlH;HhbMFNz)gCoK7t)B9Vo&s$TGhblO)7vXU4JP{llLh{ zMchFR0llmt{RCrFJELo0DTFNp)}%#c-pJUsZB4zP^m+0rM$5TD9{caQ&=y-P&tNLzDpj7&m zs8*K*k;fot%I!Envwv<$1Yv2Rw4I`Dw=^98l;x&UEhIb;BO5opk#A?!T1Lw(A4_NhF5{!ZR2QSC8T1 zSl@SE+BzN$hC}xZ!}kMW0hA7@3{|f)1M;*Lhi@wq8gayJ1b;f8;()qGjnqivGa{g_ z*gjmfB@s~Tlp+>5AO{^!6zLnL2Agd~DTrd8nFUHBP6et^qn(T&pME)LIrd}lbQ@o(Gh~q>C-j>(Ys7S zMBq7RYNP~Wgnub<3O_cFStkV3+q-fcz-DA9LMVE5M_yaC>?|VM-AGe zZDZVKw-2!jQZ`B|;Yi?Nv}5Ji85E1eLbML7C+#2TB^qjbQC(pj$ikQ1YSEYa`%6PB zicSPLFbUPHul0?C(7j-PW52CGyc6sX_J_lblos#w-~1QHC_?v6ee0g}+;!`xzU}I5 ze9+kc@P7{FgPyzU1y-R&mBImc73{)+7`q~m{IV8~E;lcwMTuCR4(J=Z=$saJxAaCC zLUIiUcA=W-?gQI&M2|J-pnc3Z5E1q8kH&#fFJ*8nz-%v$Zbr?+lxiPi(c#por*^Zk zyJU%V03NR_LugbE|6|m)x%)tdR;f(2dQTS}oPWLT(W?`--hI_BH!tO{p0VXp+ND@* zh|k_;(U~P{mnWs(7-w1PH;+!=@vxKp8b^Io9XA|ylxk62J@|D>!KR0gNulivo1%#V3l4JI~z>r6QA;GnoSyA-^H3xrDP}@+N*QUTa))D5Y@INT^;eUg-BjkJd6XUdX?UVaa2jId1wqGfTG{*sVB^0Qf7<{Qj+83%86VUx_7#jmWp6$?KT~Mb!O8`1aK)tq- z|15j|^S_)5sKLC5ZChsWG8g$>T5n$2CC~SQB8@cU5uknQQX;Gi=28?g=f1pk_k%1I z(CGl-x}~uCmI-0lI$i~cIs8vB{v41BPoX>|! zRp>2P3dG$nPTpOTK73wH-ZpBJN~0*@Y$@2Fbz0+mL0YW5n+Pw%vT!3;uR)RvazJ(z ze!w}P#`!#OKjyi2za%G&8>tLWR|bD+_5-B@>JE}$h$M@6KieT@>3+6PwHCj8woZio Z4_qANfY17C4*&oF07*qoL(_%#9VJFXV6cZkl$!hxpc@%Wg8YIR9G=}s19I{_T^vIy;*t|2Dh_ZgoU!oE z{sPWLj5k05=pY;OmK_3))7v!@1X=^uKNLF5&C_Y(*(}n^=Mio&OU?bDhJ+>qLq?mVSq|rc QU{Fwby85}Sb4q9e00g0E>Hq)$ literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/midnightlib/textures/gui/sprites/icon/reset.png b/common/src/main/resources/assets/midnightlib/textures/gui/reset.png similarity index 100% rename from common/src/main/resources/assets/midnightlib/textures/gui/sprites/icon/reset.png rename to common/src/main/resources/assets/midnightlib/textures/gui/reset.png diff --git a/common/src/main/resources/assets/midnightlib/textures/gui/sprites/icon/midnightlib.png b/common/src/main/resources/assets/midnightlib/textures/gui/sprites/icon/midnightlib.png deleted file mode 100644 index f76adb6b0fa44613c26f5f52246e26b89cc9cfc6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 136 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6I14-?iy0WWg+Z8+Vb&Z8prDnf zi(^Q|tz-qMKkm#tDvkdw7=Hc|Z17T>^P^u{$f$8blemHVqe=1.21" + "minecraft": ">=1.20" }, "mixins": [ diff --git a/gradle.properties b/gradle.properties index 8d2a03d..955bccb 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,21 +1,18 @@ org.gradle.jvmargs=-Xmx4096M -minecraft_version=1.21.4 -supported_versions=1.21.5 -yarn_mappings=1.21.4+build.1 -enabled_platforms=fabric,neoforge +minecraft_version=1.20.1 +supported_versions=1.20 +yarn_mappings=1.20.1+build.10 +enabled_platforms=fabric archives_base_name=midnightlib -mod_version=1.7.3 +mod_version=1.7.5 maven_group=eu.midnightdust -release_type=release -curseforge_id=488090 -modrinth_id=codAaoxh +# release_type=release +# curseforge_id=488090 +# modrinth_id=codAaoxh -fabric_loader_version=0.16.9 -fabric_api_version=0.110.5+1.21.4 +fabric_loader_version=0.16.14 +fabric_api_version=0.92.6+1.20.1 -neoforge_version=21.4.3-beta -yarn_mappings_patch_neoforge_version = 1.21+build.4 - -mod_menu_version = 9.0.0 \ No newline at end of file +mod_menu_version = 7.2.2 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0d18421..2733ed5 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/neoforge/build.gradle b/neoforge/build.gradle deleted file mode 100644 index 48ebf4f..0000000 --- a/neoforge/build.gradle +++ /dev/null @@ -1,108 +0,0 @@ -plugins { - id 'com.github.johnrengelman.shadow' - id "me.shedaniel.unified-publishing" -} - -repositories { - maven { - name = 'NeoForged' - url = 'https://maven.neoforged.net/releases' - } -} - - -architectury { - platformSetupLoomIde() - neoForge() -} - -loom { - accessWidenerPath = project(":common").loom.accessWidenerPath -} - -configurations { - common { - canBeResolved = true - canBeConsumed = false - } - compileClasspath.extendsFrom common - runtimeClasspath.extendsFrom common - developmentNeoForge.extendsFrom common - - // Files in this configuration will be bundled into your mod using the Shadow plugin. - // Don't use the `shadow` configuration from the plugin itself as it's meant for excluding files. - shadowBundle { - canBeResolved = true - canBeConsumed = false - } - archivesBaseName = rootProject.archives_base_name - version = rootProject.mod_version + "-" + project.name + "+" + rootProject.minecraft_version -} - -dependencies { - neoForge "net.neoforged:neoforge:$rootProject.neoforge_version" - - common(project(path: ':common', configuration: 'namedElements')) { transitive false } - shadowBundle project(path: ':common', configuration: 'transformProductionNeoForge') -} - -processResources { - inputs.property 'version', rootProject.version - - filesMatching('META-INF/neoforge.mods.toml') { - expand version: rootProject.version - } -} - -shadowJar { - configurations = [project.configurations.shadowBundle] - archiveClassifier = 'dev-shadow' -} - -remapJar { - input.set shadowJar.archiveFile -} - -sourcesJar { - def commonSources = project(":common").sourcesJar - dependsOn commonSources - from commonSources.archiveFile.map { zipTree(it) } -} - -components.java { - withVariantsFromConfiguration(project.configurations.shadowRuntimeElements) { - skip() - } -} - -unifiedPublishing { - project { - displayName = "MidnightLib $rootProject.version - NeoForge $project.minecraft_version" - releaseType = "$project.release_type" - changelog = releaseChangelog() - gameVersions = [] - gameLoaders = ["neoforge"] - mainPublication remapJar - - var CURSEFORGE_TOKEN = project.findProperty("CURSEFORGE_TOKEN") ?: System.getenv("CURSEFORGE_TOKEN") - if (CURSEFORGE_TOKEN != null) { - curseforge { - token = CURSEFORGE_TOKEN - id = rootProject.curseforge_id - gameVersions.addAll "Java 21", project.minecraft_version - if (project.supported_versions != "") gameVersions.addAll project.supported_versions - } - } - - var MODRINTH_TOKEN = project.findProperty("MODRINTH_TOKEN") ?: System.getenv("MODRINTH_TOKEN") - if (MODRINTH_TOKEN != null) { - modrinth { - token = MODRINTH_TOKEN - id = rootProject.modrinth_id - version = rootProject.mod_version + "+" + rootProject.minecraft_version + "-" + project.name - gameVersions.addAll project.minecraft_version - if (project.supported_versions != "") gameVersions.addAll project.supported_versions - } - } - } -} diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties deleted file mode 100644 index 2914393..0000000 --- a/neoforge/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -loom.platform=neoforge \ No newline at end of file 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 deleted file mode 100644 index 5e92f60..0000000 --- a/neoforge/src/main/java/eu/midnightdust/lib/util/neoforge/PlatformFunctionsImpl.java +++ /dev/null @@ -1,33 +0,0 @@ -package eu.midnightdust.lib.util.neoforge; - -import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import eu.midnightdust.lib.util.PlatformFunctions; -import net.minecraft.server.command.ServerCommandSource; -import net.neoforged.fml.ModList; -import net.neoforged.fml.loading.FMLEnvironment; -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"; - } - /** - * This is our actual method to {@link PlatformFunctions#getConfigDirectory()}. - */ - public static Path getConfigDirectory() { - return FMLPaths.CONFIGDIR.get(); - } - public static boolean isClientEnv() { - return FMLEnvironment.dist.isClient(); - } - public static boolean isModLoaded(String modid) { - return ModList.get().isLoaded(modid); - } - public static void registerCommand(LiteralArgumentBuilder command) { - 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 deleted file mode 100644 index 57e2d6b..0000000 --- a/neoforge/src/main/java/eu/midnightdust/neoforge/MidnightLibNeoForge.java +++ /dev/null @@ -1,52 +0,0 @@ -package eu.midnightdust.neoforge; - -import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import eu.midnightdust.core.MidnightLib; -import eu.midnightdust.lib.config.MidnightConfig; -import net.minecraft.server.command.ServerCommandSource; -import net.neoforged.api.distmarker.Dist; -import net.neoforged.bus.api.SubscribeEvent; -import net.neoforged.fml.ModList; -import net.neoforged.fml.common.EventBusSubscriber; -import net.neoforged.fml.common.Mod; -import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent; -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.ConcurrentModificationException; -import java.util.List; - -@Mod("midnightlib") -public class MidnightLibNeoForge { - public static List> commands = new ArrayList<>(); - - public MidnightLibNeoForge() { - if (FMLEnvironment.dist == Dist.CLIENT) MidnightLib.onInitializeClient(); - } - - @EventBusSubscriber(modid = "midnightlib", bus = EventBusSubscriber.Bus.MOD, value = Dist.CLIENT) - public static class MidnightLibBusEvents { - @SubscribeEvent - public static void onPostInit(FMLClientSetupEvent event) { - ModList.get().forEachModContainer((modid, modContainer) -> { - if (MidnightConfig.configClass.containsKey(modid) && !MidnightLib.hiddenMods.contains(modid)) { - modContainer.registerExtensionPoint(IConfigScreenFactory.class, (minecraftClient, screen) -> MidnightConfig.getScreen(screen, modid)); - } - }); - MidnightLib.registerAutoCommand(); - } - } - - @EventBusSubscriber(modid = "midnightlib") - public static class MidnightLibEvents { - @SubscribeEvent - public static void registerCommands(RegisterCommandsEvent event) { - try { - commands.forEach(command -> event.getDispatcher().register(command)); - } - catch (ConcurrentModificationException ignored) {} - } - } -} diff --git a/neoforge/src/main/resources/META-INF/neoforge.mods.toml b/neoforge/src/main/resources/META-INF/neoforge.mods.toml deleted file mode 100644 index 0887a3c..0000000 --- a/neoforge/src/main/resources/META-INF/neoforge.mods.toml +++ /dev/null @@ -1,31 +0,0 @@ -modLoader = "javafml" -loaderVersion = "[2,)" -#issueTrackerURL = "" -license = "MIT License" - -[[mods]] -modId = "midnightlib" -version = "${version}" -displayName = "MidnightLib" -logoFile = "midnightlib.png" -authors = "TeamMidnightDust, Motschen" -description = ''' -Common Library for Team MidnightDust's mods. -''' - -[[mixins]] -config = "midnightlib.mixins.json" - -[[dependencies.midnightlib]] -modId = "neoforge" -mandatory = true -versionRange = "[20.5,)" -ordering = "NONE" -side = "BOTH" - -[[dependencies.midnightlib]] -modId = "minecraft" -mandatory = true -versionRange = "[1.20.5,)" -ordering = "NONE" -side = "BOTH" \ No newline at end of file diff --git a/neoforge/src/main/resources/midnightlib.png b/neoforge/src/main/resources/midnightlib.png deleted file mode 100644 index d31b4c46823b2536b67007b68606f8b82c806a08..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2801 zcmd5-dpOkDAD)>Q%ov2&+-aJy%(|3lv1VMRVbU~4xvX}EtlZWNa?3SJqS~yIOPQg_ zZ6dcs#$6>s2_d(p5O&-dmwsoT{qMKG|Ms8X`99~I&w0P+^SAo%BIz^tyWPNUIeWMmo|8mgtp#TyV76x)l zOG`m;?AWpYA}J~=0!UO;6p#ZOfEHkgiHTve*$WE`2m~TEHMOUwCnF;xIXRh3CRbHe z6&4oe<>dhoqyYY*p&`IOH8oXRTl?zOtCW-!-~O>5s{KzfRBsX%Sjv*mJz5vJ)~=NQXJ`Ldv(je?!EkvZQ2ZPV+BKV<E?B0GbTi##1o2XaYn&}+3VR`)b%gp@x zf}x$Ir9b<&&8+=Hd+)8U?QHROJNc{gf{yW#-pN%S`|X>smY17LJJajq{X^RyKMZcq zjZTi%56mo1404x0bZmQa`CAi<{Pk(U+9&?%@Y>g%nRWh9%TU+yE`Md4|8&IXTekxQ z0)Irb!cm=C`qLeq6rE*b=>;=~{qdO()TN;K`(~fqu1bGys3m(1J<~9^J9aem^ZnZO*JcK1va@&V#*Jk>-qJ`) zp_PVz=t^ma=`_eSc`eG~p;_KsX-rlz?O|5y$LPR3d#|*u@Z=LSI>PDx0~U<@gcii> z%tuJO`_j=vEUE%F@g(sqE9fQS91~rg*pw!o9?{b$6{6H9n+4g<4kPw zl99J0()G5!nYz9}Fo|N0cStH`VRF4MOPbDL(lsj_>Mfn{AwR{_5LPqLCbmHQajBJL zwf(D}M0iL3_d-z;FqtQ$KvhqhMV;I;?F~|eD`E!aPn}eEOd_2b6ymH!?n$`Z9kg)r zCcZ@8kdcyy5;Y_#<5uiGP%WKee-!yTzvU8e-8|+ydVJjQN(1x5eFZ&sT@9u}FR_eh zPtV76yKSVvG3lz~Ss6u`Ig5LlGm4#GLW1^S$CFxC#3h@t@5Fat`X_rF_vG`lfAVpa zpdT_Bw&_}@2J6G*ed62C-4(0T_ev4#L*z){n*Z>YmXnbvGs7L2A|5k)k<`22Mp{C@ zkCi+T{HZcwpFCTeLBhppYs9uK@GVH&&BTOw5~aPvbP?8`eElvhgc=u)Pa`Eb2U&d2 zeXXW+h3UM2Epwr1yMCH`3j1R1dA|~MSJMd3J7t-Afm?HH-S_31E4u9ny7oH9Cbh(y zeb9gP-1p4**UwK5a3UV1dRSAH1}R*=MlKxU0?qVcPsou+tWp=b(8I8Il|89HuJ+hg zTK*>ER%a`FaFbYQELv$}S+s2Hf^hA|w-iHE>rnyZ)N}~hpNH6Bw5RMBNpJ2uN;JO6 zIM7&Un0?QIu)hlSN?5%~!2CRPTKI%7Yr?c~Zhhi&=V`GB{W{?r8GG%#n{Iy2fxc(W z8b>ii17YSPveiL4p3OPrF*?4>?Sl}aSSt^ju5<+ovk{WF7041FMIZMJwwLapm7jXwV%dyklz%FQ?qKAt+6(Xr6^>Tz-Ct@mj>$eqAEB7()VFKANcr^A^5Qj77$FQFJc30c&s7ihSVS0(5 z(WTh!|1lD+i>jh}pVK&o;Jq!edY*Z(E^FZ1$%^$Mp+wvB<@Uc@}NNvirsT5qH zr9dLr81j|8i9{%ib)IfCkbO}Dk(hgU30ViR9ccPO;3le$_e2zJzGHZ(-A?-X@Bv9a z%L4N$ER41HZ0?Cc!#}hYPwOVGiD+IpFSFb2?F;QReYP2^g?q;xN8f7S)Qi{{zqwc` zse-%cUm$toNR!*8^OppN46kKfINd6nU#Z)yxh|z(Tox5tIhE6U^t&1ll`fuc&8HkEdoL+%6~^lnYe+^ z%Bw3|3gbcK-)I|sfE=42%$felT4k`-X!7U65S=e!VX*f0eYVU-4$6O51QQMat?P_?@Xmm zdYWxHT=Zlgwp+Nf-%MSaO+i)lF=Lu56A(wk?^Ldj8a>fqx|an|L(Yd-QJ*L_cU&8G zI80wYl)0f)GGHl!ojC5%ip2#c{qEx%x{L?%DV`&wY^0@!`1K59 Date: Mon, 4 Aug 2025 01:23:51 +0200 Subject: [PATCH 100/100] fix weird compilation issues Signed-off-by: xtrm --- build.gradle | 2 +- common/build.gradle | 3 ++- .../core/mixin/MixinOptionsScreen.java | 3 +++ gradle.properties | 2 +- .../fabric/example/MidnightLibExtras.java | 20 ++++++++++++------- .../example/config/MidnightConfigExample.java | 4 ++-- 6 files changed, 22 insertions(+), 12 deletions(-) diff --git a/build.gradle b/build.gradle index b22cbbe..38eed5b 100644 --- a/build.gradle +++ b/build.gradle @@ -42,7 +42,7 @@ allprojects { // for more information about repositories. } - tasks.withType(JavaCompile) { + tasks.withType(JavaCompile).configureEach { options.encoding = "UTF-8" options.release = 17 } diff --git a/common/build.gradle b/common/build.gradle index ceedbf7..d1f0ac2 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -5,7 +5,8 @@ architectury { dependencies { // We depend on fabric loader here to use the fabric @Environment annotations and get the mixin dependencies // Do NOT use other classes from fabric loader - modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" +// implementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" + modImplementation "net.fabricmc:fabric-loader:0.16.13" //FIXME: Using the same floader version doesn't let you access it..? architectury moment } publishing { diff --git a/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java b/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java index 1f3da97..29746e7 100644 --- a/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java +++ b/common/src/main/java/eu/midnightdust/core/mixin/MixinOptionsScreen.java @@ -9,6 +9,7 @@ import net.minecraft.client.gui.screen.option.OptionsScreen; import net.minecraft.text.Text; import net.minecraft.util.Identifier; 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; @@ -17,7 +18,9 @@ import java.util.Objects; @Mixin(OptionsScreen.class) public class MixinOptionsScreen extends Screen { + @Unique private static final Identifier MIDNIGHTLIB_ICON_TEXTURE = new Identifier("midnightlib","textures/gui/midnightlib_button.png"); + protected MixinOptionsScreen(Text title) { super(title); } diff --git a/gradle.properties b/gradle.properties index 955bccb..35fa262 100644 --- a/gradle.properties +++ b/gradle.properties @@ -15,4 +15,4 @@ maven_group=eu.midnightdust fabric_loader_version=0.16.14 fabric_api_version=0.92.6+1.20.1 -mod_menu_version = 7.2.2 \ No newline at end of file +mod_menu_version=7.2.2 \ No newline at end of file diff --git a/test-fabric/src/main/java/eu/midnightdust/fabric/example/MidnightLibExtras.java b/test-fabric/src/main/java/eu/midnightdust/fabric/example/MidnightLibExtras.java index 12deb14..89b9dcd 100644 --- a/test-fabric/src/main/java/eu/midnightdust/fabric/example/MidnightLibExtras.java +++ b/test-fabric/src/main/java/eu/midnightdust/fabric/example/MidnightLibExtras.java @@ -6,7 +6,7 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.tooltip.Tooltip; import net.minecraft.client.gui.widget.ButtonWidget; import net.minecraft.client.gui.widget.ClickableWidget; -import net.minecraft.client.gui.widget.TextIconButtonWidget; +import net.minecraft.client.gui.widget.IconButtonWidget; import net.minecraft.client.option.KeyBinding; import net.minecraft.client.util.InputUtil; import net.minecraft.text.MutableText; @@ -26,10 +26,13 @@ public class MidnightLibExtras { public static void add(KeyBinding binding, MidnightConfig.MidnightConfigListWidget list, MidnightConfig.MidnightConfigScreen screen) { KeybindButton editButton = new KeybindButton(screen.width - 185, 0, 150, 20, binding); - TextIconButtonWidget resetButton = TextIconButtonWidget.builder(Text.translatable("controls.reset"), (button -> { - binding.setBoundKey(binding.getDefaultKey()); - screen.updateList(); - }), true).texture(Identifier.of("midnightlib","icon/reset"), 12, 12).dimension(20, 20).build(); + IconButtonWidget resetButton = IconButtonWidget.builder( + Text.translatable("controls.reset"), + Identifier.of("midnightlib", "icon/reset"), + (button -> { + binding.setBoundKey(binding.getDefaultKey()); + screen.updateList(); + })).textureSize(12, 12).iconSize(20, 20).build(); resetButton.setPosition(screen.width - 205 + 150 + 25, 0); editButton.resetButton = resetButton; editButton.updateMessage(false); @@ -40,6 +43,7 @@ public class MidnightLibExtras { private final KeyBinding binding; private @Nullable ClickableWidget resetButton; + public KeybindButton(int x, int y, int width, int height, KeyBinding binding) { super(x, y, width, height, binding.getBoundKeyLocalizedText(), (button) -> { ((KeybindButton) button).updateMessage(true); @@ -48,6 +52,7 @@ public class MidnightLibExtras { this.binding = binding; updateMessage(false); } + @Override public boolean keyPressed(int keyCode, int scanCode, int modifiers) { if (focusedButton == this) { @@ -67,12 +72,13 @@ public class MidnightLibExtras { public void updateMessage(boolean focused) { boolean hasConflicts = false; MutableText conflictingBindings = Text.empty(); - if (focused) this.setMessage(Text.literal("> ").append(this.binding.getBoundKeyLocalizedText().copy().formatted(Formatting.WHITE, Formatting.UNDERLINE)).append(" <").formatted(Formatting.YELLOW)); + if (focused) + this.setMessage(Text.literal("> ").append(this.binding.getBoundKeyLocalizedText().copy().formatted(Formatting.WHITE, Formatting.UNDERLINE)).append(" <").formatted(Formatting.YELLOW)); else { this.setMessage(this.binding.getBoundKeyLocalizedText()); if (!this.binding.isUnbound()) { - for(KeyBinding keyBinding : MinecraftClient.getInstance().options.allKeys) { + for (KeyBinding keyBinding : MinecraftClient.getInstance().options.allKeys) { if (keyBinding != this.binding && this.binding.equals(keyBinding)) { if (hasConflicts) conflictingBindings.append(", "); 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 index 095581b..68e80bd 100644 --- 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 @@ -34,7 +34,7 @@ public class MidnightConfigExample extends MidnightConfig { @Entry(category = TEXT, name="I am a (non-primitive) Boolean") public static Boolean nonPrimitive = true; // Example for a non-primative 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, idMode = 0) public static Identifier id = new Identifier("diamond"); // Example for an identifier with matching items displayed next to it! @Entry(category = TEXT) public static ModPlatform modPlatform = ModPlatform.FABRIC; // Example for an enum option public enum ModPlatform { // Enums allow the user to cycle through predefined options QUILT, FABRIC, FORGE, NEOFORGE, VANILLA @@ -52,7 +52,7 @@ public class MidnightConfigExample extends MidnightConfig { // 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 identifier list!", idMode = 1) public static List idList = Lists.newArrayList(new Identifier("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);