Merge pull request #94 from TeamMidnightDust/dev

MidnightLib 1.7.1 – Multi-conditions & Performance improvements
This commit is contained in:
Martin Prokoph
2025-04-05 12:46:45 +02:00
committed by GitHub
5 changed files with 116 additions and 77 deletions

View File

@@ -18,44 +18,41 @@ public class AutoCommand {
final Field field; final Field field;
final Class<?> type; final Class<?> type;
final String modid; final String modid;
final boolean isList, isNumber; final boolean isList;
public AutoCommand(Field field, String modid) { public AutoCommand(Field field, String modid) {
this.field = field; this.modid = modid; this.field = field; this.modid = modid;
this.type = MidnightConfig.getUnderlyingType(field); this.type = MidnightConfig.getUnderlyingType(field);
this.isList = field.getType() == List.class; 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); var command = CommandManager.literal(field.getName()).executes(this::getValue);
if (type.isEnum()) { 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, ""))); command = command.then(CommandManager.literal(enumValue.toString())
.executes(ctx -> this.setValue(ctx.getSource(), enumValue, "")));
} else if (isList) { } else if (isList) {
for (String action : List.of("add", "remove")) for (String action : new String[]{"add", "remove"})
command = command.then(CommandManager.literal(action).then( command = command.then(CommandManager.literal(action)
CommandManager.argument(VALUE, getArgType()).executes(ctx -> setValueFromArg(ctx, 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(CommandManager.literal("midnightconfig").requires(source -> source.hasPermissionLevel(2)).then(CommandManager.literal(modid).then(command))); PlatformFunctions.registerCommand(CommandManager.literal("midnightconfig").requires(source -> source.hasPermissionLevel(2)).then(CommandManager.literal(modid).then(command)));
} }
public ArgumentType<?> getArgType() { public ArgumentType<?> getArgType() {
if (isNumber) { Entry entry = field.getAnnotation(Entry.class);
Entry entry = field.getAnnotation(Entry.class); if (type == int.class) return IntegerArgumentType.integer((int) entry.min(), (int) entry.max());
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 == 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 == float.class) return FloatArgumentType.floatArg((float) entry.min(), (float) entry.max());
}
else if (type == boolean.class) return BoolArgumentType.bool(); else if (type == boolean.class) return BoolArgumentType.bool();
return StringArgumentType.string(); return StringArgumentType.string();
} }
public int setValueFromArg(CommandContext<ServerCommandSource> context, String action) { public int setValueFromArg(CommandContext<ServerCommandSource> context, String action) {
if (isNumber) { if (type == int.class) return setValue(context.getSource(), IntegerArgumentType.getInteger(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 == 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 == 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); else if (type == boolean.class) return setValue(context.getSource(), BoolArgumentType.getBool(context, VALUE), action);
return setValue(context.getSource(), StringArgumentType.getString(context, VALUE), action); return setValue(context.getSource(), StringArgumentType.getString(context, VALUE), action);
} }
@@ -72,17 +69,16 @@ public class AutoCommand {
MidnightConfig.write(modid); MidnightConfig.write(modid);
} }
catch (Exception e) { catch (Exception e) {
if (!isList) source.sendError(Text.literal("Could not set "+field.getName()+" to value "+value+": " + 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)));
else source.sendError(Text.literal((add ? "Could not add "+value+" to " : "Could not remove "+value+" from ")+field.getName() +": " + e));
return 0; return 0;
} }
if (!isList) source.sendFeedback(() -> Text.literal("Successfully set " + field.getName()+" to "+value), true); source.sendFeedback(() -> Text.literal(isList ? "Successfully %s %s %s %s".formatted(add ? "added" : "removed", value, add ? "to" : "from", field.getName()) :
else source.sendFeedback(() -> Text.literal((add ? "Successfully added " +value+" to " : "Successfully removed " +value+" from ") +field.getName()), true); "Successfully set %s to %s".formatted(field.getName(), value)), true);
return 1; return 1;
} }
private int getValue(CommandContext<ServerCommandSource> context) { private int getValue(CommandContext<ServerCommandSource> context) {
context.getSource().sendFeedback(() -> { 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);} } catch (IllegalAccessException e) {throw new RuntimeException(e);}
}, true); }, true);
return 0; return 0;

View File

@@ -19,7 +19,7 @@ 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.awt.Color;
import java.io.IOException; 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.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.nio.file.Files; import java.nio.file.Path;
import java.util.*; import java.util.*;
@@ -39,13 +39,13 @@ public abstract class MidnightConfig {
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 Pattern HEXADECIMAL_ONLY = Pattern.compile("(-?[#0-9a-fA-F]*)");
private static final List<EntryInfo> entries = new ArrayList<>(); private static final LinkedHashMap<String, EntryInfo> entries = new LinkedHashMap<>(); // modid:fieldName -> EntryInfo
private static boolean reloadScreen = false; private static boolean reloadScreen = false;
public static class EntryInfo { public static class EntryInfo {
public Entry entry; public Entry entry;
public Comment comment; public Comment comment;
public Condition condition; public Condition[] conditions;
public final Field field; public final Field field;
public final Class<?> dataType; public final Class<?> dataType;
public final String modid, fieldName; public final String modid, fieldName;
@@ -61,8 +61,11 @@ public abstract class MidnightConfig {
public EntryInfo(Field field, String modid) { public EntryInfo(Field field, String modid) {
this.field = field; this.modid = modid; this.field = field; this.modid = modid;
if (field != null) { if (field != null) {
this.fieldName = field.getName(); this.dataType = getUnderlyingType(field); this.fieldName = field.getName();
this.entry = field.getAnnotation(Entry.class); this.comment = field.getAnnotation(Comment.class); this.condition = field.getAnnotation(Condition.class); this.dataType = getUnderlyingType(field);
this.entry = field.getAnnotation(Entry.class);
this.comment = field.getAnnotation(Comment.class);
this.conditions = field.getAnnotationsByType(Condition.class);
} else { } else {
this.fieldName = ""; this.dataType = null; this.fieldName = ""; this.dataType = null;
} }
@@ -80,19 +83,24 @@ public abstract class MidnightConfig {
else try { return ((List<?>) this.value).get(this.listIndex).toString(); } catch (Exception ignored) {return "";} else try { return ((List<?>) this.value).get(this.listIndex).toString(); } catch (Exception ignored) {return "";}
} }
public void updateFieldValue() { public void updateFieldValue() {
try { if (this.field.get(null) != value) updateConditions(tempValue); try {
if (this.field.get(null) != value) entries.values().forEach(EntryInfo::updateConditions);
this.field.set(null, this.value); this.field.set(null, this.value);
} catch (IllegalAccessException ignored) {} } catch (IllegalAccessException ignored) {}
} }
@SuppressWarnings("ConstantValue") //pertains to requiredModLoaded @SuppressWarnings("ConstantValue") //pertains to requiredModLoaded
public void updateConditions(String newTempValue) { public void updateConditions() {
for (EntryInfo info : entries) { boolean prevConditionState = this.conditionsMet;
boolean prevConditionState = info.conditionsMet; if (this.conditions.length > 0) this.conditionsMet = true; // reset conditions
if (info.condition != null && ((info.condition.requiredOption().contains(":") ? "" : info.modid + ":") + info.condition.requiredOption()).equals(this.modid + ":" + this.fieldName)) for (Condition condition : this.conditions) {
info.conditionsMet = Objects.equals(info.condition.requiredValue(), newTempValue); if (!condition.requiredModId().isEmpty() && !PlatformFunctions.isModLoaded(condition.requiredModId()))
if (info.condition != null && !info.condition.requiredModId().isEmpty() && !PlatformFunctions.isModLoaded(info.condition.requiredModId())) info.conditionsMet = false; this.conditionsMet = false;
if (prevConditionState != info.conditionsMet) reloadScreen = true; 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;
} }
if (prevConditionState != this.conditionsMet) reloadScreen = true;
} }
public <T> void writeList(int index, T value) { public <T> void writeList(int index, T value) {
var list = (List<T>) this.value; var list = (List<T>) this.value;
@@ -114,19 +122,21 @@ public abstract class MidnightConfig {
@SuppressWarnings("unused") // Utility for mod authors @SuppressWarnings("unused") // Utility for mod authors
public static @Nullable Object getDefaultValue(String modid, String entry) { public static @Nullable Object getDefaultValue(String modid, String entry) {
for (EntryInfo e : entries) { String key = modid + ":" + entry;
if (modid.equals(e.modid) && entry.equals(e.field.getName())) return e.defaultValue; return entries.containsKey(key) ? entries.get(key).defaultValue : null;
} return null;
} }
public static void loadValuesFromJson(String modid) { public static void loadValuesFromJson(String modid) {
try { gson.fromJson(Files.newBufferedReader(path), configClass.get(modid)); } try { gson.fromJson(Files.newBufferedReader(path), configClass.get(modid)); }
catch (Exception e) { write(modid); } catch (Exception e) { write(modid); }
entries.values().forEach(info -> {
for (EntryInfo info : entries) if (info.field != null && info.entry != null) { if (info.field != null && info.entry != null) {
try { info.value = info.field.get(null); info.tempValue = info.toTemporaryValue(); try {
info.updateConditions(info.tempValue); info.value = info.field.get(null);
} catch (IllegalAccessException ignored) {} info.tempValue = info.toTemporaryValue();
} info.updateConditions();
} catch (IllegalAccessException ignored) {}
}
});
} }
public static void init(String modid, Class<? extends MidnightConfig> config) { public static void init(String modid, Class<? extends MidnightConfig> config) {
path = PlatformFunctions.getConfigDirectory().resolve(modid + ".json"); path = PlatformFunctions.getConfigDirectory().resolve(modid + ".json");
@@ -145,6 +155,7 @@ public abstract class MidnightConfig {
@Environment(EnvType.CLIENT) @Environment(EnvType.CLIENT)
private static void initClient(String modid, Field field, EntryInfo info) { private static void initClient(String modid, Field field, EntryInfo info) {
Entry e = info.entry; Entry e = info.entry;
String key = modid + ":" + field.getName();
if (e != null) { if (e != null) {
if (info.dataType == int.class) textField(info, Integer::parseInt, INTEGER_ONLY, (int) e.min(), (int) e.max(), true); 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 == float.class) textField(info, Float::parseFloat, DECIMAL_ONLY, (float) e.min(), (float) e.max(), false);
@@ -163,11 +174,12 @@ public abstract class MidnightConfig {
}; };
info.function = new AbstractMap.SimpleEntry<ButtonWidget.PressAction, Function<Object, Text>>(button -> { info.function = new AbstractMap.SimpleEntry<ButtonWidget.PressAction, Function<Object, Text>>(button -> {
int index = values.indexOf(info.value) + 1; 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); }, func);
} }
} }
entries.add(info); entries.put(key, info);
} }
public static Class<?> getUnderlyingType(Field field) { public static Class<?> getUnderlyingType(Field field) {
Class<?> rawType = field.getType(); Class<?> rawType = field.getType();
@@ -200,7 +212,7 @@ public abstract class MidnightConfig {
info.tempValue = s; info.tempValue = s;
t.setEditableColor(inLimits? 0xFFFFFFFF : 0xFFFF7777); t.setEditableColor(inLimits? 0xFFFFFFFF : 0xFFFF7777);
info.inLimits = inLimits; info.inLimits = inLimits;
b.active = entries.stream().allMatch(e -> e.inLimits); b.active = entries.values().stream().allMatch(e -> e.inLimits);
if (inLimits) { if (inLimits) {
if (info.dataType == Identifier.class) info.setValue(Identifier.tryParse(s)); if (info.dataType == Identifier.class) info.setValue(Identifier.tryParse(s));
@@ -237,17 +249,18 @@ public abstract class MidnightConfig {
this.parent = parent; this.modid = modid; this.parent = parent; this.modid = modid;
this.translationPrefix = modid + ".midnightconfig."; this.translationPrefix = modid + ".midnightconfig.";
loadValuesFromJson(modid); loadValuesFromJson(modid);
entries.values().forEach(info -> {
for (EntryInfo e : entries) if (e.modid.equals(modid)) { if (info.modid.equals(modid)) {
String tabId = e.entry != null ? e.entry.category() : e.comment.category(); String tabId = info.entry != null ? info.entry.category() : info.comment.category();
String name = translationPrefix + "category." + tabId; String name = translationPrefix + "category." + tabId;
if (!I18n.hasTranslation(name) && tabId.equals("default")) if (!I18n.hasTranslation(name) && tabId.equals("default"))
name = translationPrefix + "title"; name = translationPrefix + "title";
if (!tabs.containsKey(name)) { if (!tabs.containsKey(name)) {
Tab tab = new GridScreenTab(Text.translatable(name)); Tab tab = new GridScreenTab(Text.translatable(name));
e.tab = tab; tabs.put(name, tab); info.tab = tab; tabs.put(name, tab);
} else e.tab = tabs.get(name); } else info.tab = tabs.get(name);
} }
});
tabNavigation = TabNavigationWidget.builder(tabManager, this.width).tabs(tabs.values().toArray(new Tab[0])).build(); tabNavigation = TabNavigationWidget.builder(tabManager, this.width).tabs(tabs.values().toArray(new Tab[0])).build();
tabNavigation.selectTab(0, false); tabNavigation.selectTab(0, false);
tabNavigation.init(); tabNavigation.init();
@@ -272,7 +285,7 @@ public abstract class MidnightConfig {
updateList(); list.setScrollY(0); updateList(); list.setScrollY(0);
} }
scrollProgress = list.getScrollY(); scrollProgress = list.getScrollY();
for (EntryInfo info : entries) info.updateFieldValue(); for (EntryInfo info : entries.values()) info.updateFieldValue();
updateButtons(); updateButtons();
if (reloadScreen) { updateList(); reloadScreen = false; } if (reloadScreen) { updateList(); reloadScreen = false; }
} }
@@ -296,7 +309,7 @@ public abstract class MidnightConfig {
Objects.requireNonNull(client).setScreen(parent); Objects.requireNonNull(client).setScreen(parent);
} }
private void cleanup() { 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; info.error = null; info.value = null; info.tempValue = null; info.actionButton = null; info.listIndex = 0; info.tab = null; info.inLimits = true;
}); });
} }
@@ -308,7 +321,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()); 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) -> { 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(); write(modid); cleanup();
Objects.requireNonNull(client).setScreen(parent); Objects.requireNonNull(client).setScreen(parent);
}).dimensions(this.width / 2 + 4, this.height - 26, 150, 20).build()); }).dimensions(this.width / 2 + 4, this.height - 26, 150, 20).build());
@@ -321,8 +334,14 @@ public abstract class MidnightConfig {
this.list.clear(); fillList(); this.list.clear(); fillList();
} }
public void fillList() { public void fillList() {
for (EntryInfo info : entries) { for (EntryInfo info : entries.values()) {
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())) { if (info.modid.equals(modid) && (info.tab == null || info.tab == tabManager.getCurrentTab())) {
Text name = Objects.requireNonNullElseGet(info.name, () -> Text.translatable(translationPrefix + info.fieldName)); Text name = Objects.requireNonNullElseGet(info.name, () -> Text.translatable(translationPrefix + info.fieldName));
TextIconButtonWidget resetButton = TextIconButtonWidget.builder(Text.translatable("controls.reset"), (button -> { TextIconButtonWidget resetButton = TextIconButtonWidget.builder(Text.translatable("controls.reset"), (button -> {
@@ -565,6 +584,7 @@ public abstract class MidnightConfig {
* <code>false</code> Option is completely hidden * <code>false</code> Option is completely hidden
*/ */
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Repeatable(Conditions.class)
@Target(ElementType.FIELD) @Target(ElementType.FIELD)
public @interface Condition { public @interface Condition {
String requiredModId() default ""; String requiredModId() default "";
@@ -572,4 +592,10 @@ public abstract class MidnightConfig {
String requiredValue() default "true"; String requiredValue() default "true";
boolean visibleButLocked() default false; boolean visibleButLocked() default false;
} }
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Conditions {
Condition[] value();
}
} }

View File

@@ -1,12 +1,12 @@
org.gradle.jvmargs=-Xmx4096M org.gradle.jvmargs=-Xmx4096M
minecraft_version=1.21.4 minecraft_version=1.21.4
supported_versions= supported_versions=1.21.5
yarn_mappings=1.21.4+build.1 yarn_mappings=1.21.4+build.1
enabled_platforms=fabric,neoforge enabled_platforms=fabric,neoforge
archives_base_name=midnightlib archives_base_name=midnightlib
mod_version=1.7.0 mod_version=1.7.1
maven_group=eu.midnightdust maven_group=eu.midnightdust
release_type=release release_type=release
curseforge_id=488090 curseforge_id=488090
@@ -18,6 +18,4 @@ fabric_api_version=0.110.5+1.21.4
neoforge_version=21.4.3-beta neoforge_version=21.4.3-beta
yarn_mappings_patch_neoforge_version = 1.21+build.4 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 mod_menu_version = 9.0.0

View File

@@ -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. /** 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*/ * The config class also has to extend MidnightConfig*/
@SuppressWarnings("unused")
public class MidnightConfigExample extends MidnightConfig { public class MidnightConfigExample extends MidnightConfig {
public static final String TEXT = "text"; public static final String TEXT = "text";
public static final String NUMBERS = "numbers"; public static final String NUMBERS = "numbers";
@@ -27,9 +27,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) 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, 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 = 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 @Entry(category = TEXT) public static ModPlatform modPlatform = ModPlatform.FABRIC; // Example for an enum option
public enum TestEnum { // Enums allow the user to cycle through predefined options public enum ModPlatform { // Enums allow the user to cycle through predefined options
QUILT, FABRIC, FORGE QUILT, FABRIC, FORGE, NEOFORGE, VANILLA
} }
@Entry(category = NUMBERS) public static int fabric = 16777215; // Example for an int option @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) public static double world = 1.4D; // Example for a double option
@@ -74,20 +74,29 @@ public class MidnightConfigExample extends MidnightConfig {
@Entry(category = CONDITIONS, name="Turn me on!") @Entry(category = CONDITIONS, name="Turn me on!")
public static boolean turnMeOn = false; public static boolean turnMeOn = false;
@Condition(requiredOption = "modid:turnMeOn", visibleButLocked = true) @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; public static Boolean turnMeOff = true;
@Condition(requiredOption = "turnMeOn") // You can also use multiple conditions for the same entry
@Condition(requiredOption = "modid:turnMeOff", requiredValue = "false") @Condition(requiredOption = "modid:turnMeOff", requiredValue = "false")
@Entry(category = CONDITIONS, name="Which is the best modloader?") @Entry(category = CONDITIONS, name="Which is the best modloader?")
public static String bestModloader = ""; public static String bestModloader = "";
@Condition(requiredOption = "turnMeOn")
@Condition(requiredOption = "turnMeOff", requiredValue = "false")
@Condition(requiredOption = "bestModloader", requiredValue = "Forge") @Condition(requiredOption = "bestModloader", requiredValue = "Forge")
@Comment(category = CONDITIONS, name="❌ You have bad taste :(", centered = true) // Don't take this too seriously btw :) @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! public static Comment answerForge; // Comments can also be conditional!
@Condition(requiredOption = "turnMeOn")
@Condition(requiredOption = "turnMeOff", requiredValue = "false")
@Condition(requiredOption = "bestModloader", requiredValue = "NeoForge") @Condition(requiredOption = "bestModloader", requiredValue = "NeoForge")
@Comment(category = CONDITIONS, name="⛏ Not quite, but it's alright!", centered = true) @Comment(category = CONDITIONS, name="⛏ Not quite, but it's alright!", centered = true)
public static Comment answerNeoforge; public static Comment answerNeoforge;
@Condition(requiredOption = "turnMeOn")
@Condition(requiredOption = "turnMeOff", requiredValue = "false")
@Condition(requiredOption = "bestModloader", requiredValue = "Fabric") @Condition(requiredOption = "bestModloader", requiredValue = "Fabric")
@Comment(category = CONDITIONS, name="⭐ Correct! Fabric (and Quilt) are the best!", centered = true) @Comment(category = CONDITIONS, name="⭐ Correct! Fabric (and Quilt) are the best!", centered = true)
public static Comment answerFabric; public static Comment answerFabric;
@Condition(requiredOption = "turnMeOn")
@Condition(requiredOption = "turnMeOff", requiredValue = "false")
@Condition(requiredOption = "bestModloader", requiredValue = "Quilt") @Condition(requiredOption = "bestModloader", requiredValue = "Quilt")
@Comment(category = CONDITIONS, name="⭐ Correct! Quilt (and Fabric) are the best!", centered = true) @Comment(category = CONDITIONS, name="⭐ Correct! Quilt (and Fabric) are the best!", centered = true)
public static Comment answerQuilt; public static Comment answerQuilt;

View File

@@ -10,10 +10,19 @@
"modid.midnightconfig.showInfo":"I am a boolean", "modid.midnightconfig.showInfo":"I am a boolean",
"modid.midnightconfig.hello":"I am a limited int!", "modid.midnightconfig.hello":"I am a limited int!",
"modid.midnightconfig.id":"I am an Item Identifier!", "modid.midnightconfig.id":"I am an Item Identifier!",
"modid.midnightconfig.testEnum":"I am an enum!", "modid.midnightconfig.modPlatform":"I am an enum!",
"modid.midnightconfig.enum.TestEnum.FORGE":"Slow", "modid.midnightconfig.enum.Arch.X86":"X86",
"modid.midnightconfig.enum.TestEnum.FABRIC":"Fancy", "modid.midnightconfig.enum.Arch.X86_64":"X86_64",
"modid.midnightconfig.enum.TestEnum.QUILT":"Fabulous", "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.fileChooser": "Select an image or directory",
"modid.midnightconfig.myFileOrDirectory.fileFilter": "Supported Images (.png, .jpg, .jpeg)", "modid.midnightconfig.myFileOrDirectory.fileFilter": "Supported Images (.png, .jpg, .jpeg)",
"modid.midnightconfig.category.numbers": "Numbers", "modid.midnightconfig.category.numbers": "Numbers",
@@ -21,5 +30,6 @@
"modid.midnightconfig.category.sliders": "Sliders", "modid.midnightconfig.category.sliders": "Sliders",
"modid.midnightconfig.category.lists": "Lists", "modid.midnightconfig.category.lists": "Lists",
"modid.midnightconfig.category.files": "Files", "modid.midnightconfig.category.files": "Files",
"modid.midnightconfig.category.conditions": "Quiz" "modid.midnightconfig.category.conditions": "Quiz",
"modid.midnightconfig.category.multiConditions": "Multi-Conditions"
} }