From f036350b0a5c2527edad5cc17bdfb81b0003bb44 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Fri, 28 Jul 2023 21:04:53 -0400 Subject: [PATCH] Add option parenting, gate changes to sub-options when parent option is off --- .../core/config/ModernFixEarlyConfig.java | 28 +++++++++---------- .../modernfix/core/config/Option.java | 17 +++++++++++ .../modernfix/screen/OptionList.java | 15 ++++++++-- 3 files changed, 43 insertions(+), 17 deletions(-) diff --git a/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java b/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java index 3ddd4905..c50a365e 100644 --- a/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java +++ b/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java @@ -128,21 +128,8 @@ public class ModernFixEarlyConfig { mixinsMissingMods.put(mixinClassName, requiredModId); else if(isClientOnly && !ModernFixPlatformHooks.INSTANCE.isClient()) mixinsMissingMods.put(mixinClassName, "[not client]"); - List mixinOptionNames = dotSplitter.splitToList(mixinClassName); - StringBuilder optionBuilder = new StringBuilder(mixinClassName.length()); - optionBuilder.append("mixin"); - // mixin.core, mixin.safety can be top-level, everything else must have a subcategory - boolean allowTopLevel; - if(mixinOptionNames.size() > 0) - allowTopLevel = mixinOptionNames.get(0).equals("core") || mixinOptionNames.get(0).equals("safety"); - else - allowTopLevel = false; - for(int i = 0; i < mixinOptionNames.size() - 1; i++) { - optionBuilder.append('.'); - optionBuilder.append(mixinOptionNames.get(i)); - if(i > 0 || allowTopLevel) - mixinOptions.add(optionBuilder.toString()); - } + String mixinCategoryName = "mixin." + mixinClassName.substring(0, mixinClassName.lastIndexOf('.')); + mixinOptions.add(mixinCategoryName); } } catch(IOException e) { ModernFix.LOGGER.error("Error scanning file " + mixinPath, e); @@ -202,6 +189,17 @@ public class ModernFixEarlyConfig { this.options.putIfAbsent(optionName, option); this.optionsByCategory.put(OptionCategories.getCategoryForOption(optionName), option); } + for(Map.Entry entry : this.options.entrySet()) { + int idx = entry.getKey().lastIndexOf('.'); + if(idx <= 0) + continue; + String potentialParentKey = entry.getKey().substring(0, idx); + Option potentialParent = this.options.get(potentialParentKey); + if(potentialParent != null) { + System.out.println(potentialParentKey + " -> " + entry.getKey()); + entry.getValue().setParent(potentialParent); + } + } // Defines the default rules which can be configured by the user or other mods. // You must manually add a rule for any new mixins not covered by an existing package rule. this.addMixinRule("launch.class_search_cache", true); diff --git a/common/src/main/java/org/embeddedt/modernfix/core/config/Option.java b/common/src/main/java/org/embeddedt/modernfix/core/config/Option.java index f370e8bc..ed245764 100644 --- a/common/src/main/java/org/embeddedt/modernfix/core/config/Option.java +++ b/common/src/main/java/org/embeddedt/modernfix/core/config/Option.java @@ -11,6 +11,7 @@ public class Option { private Set modDefined = null; private boolean enabled; private boolean userDefined; + private Option parent = null; public Option(String name, boolean enabled, boolean userDefined) { this.name = name; @@ -37,10 +38,26 @@ public class Option { this.modDefined.add(modId); } + public void setParent(Option option) { + this.parent = option; + } + + public Option getParent() { + return this.parent; + } + public boolean isEnabled() { return this.enabled; } + /** + * Checks if this option will effectively be disabled (regardless of its own status) + * by the parent rule being disabled. + */ + public boolean isEffectivelyDisabledByParent() { + return this.parent != null && (!this.parent.enabled || this.parent.isEffectivelyDisabledByParent()); + } + public boolean isOverridden() { return this.isUserDefined() || this.isModDefined(); } diff --git a/common/src/main/java/org/embeddedt/modernfix/screen/OptionList.java b/common/src/main/java/org/embeddedt/modernfix/screen/OptionList.java index 8adc08e2..cc18edec 100644 --- a/common/src/main/java/org/embeddedt/modernfix/screen/OptionList.java +++ b/common/src/main/java/org/embeddedt/modernfix/screen/OptionList.java @@ -40,6 +40,13 @@ public class OptionList extends ContainerObjectSelectionList { return baseComponent; } + public void updateOptionEntryStatuses() { + for(Entry e : this.children()) { + if(e instanceof OptionEntry) { + ((OptionEntry)e).updateStatus(); + } + } + } public OptionList(ModernFixConfigScreen arg, Minecraft arg2) { super(arg2,arg.width + 45, arg.height, 43, arg.height - 32, 20); @@ -128,6 +135,7 @@ public class OptionList extends ContainerObjectSelectionList { this.option.setEnabled(!this.option.isEnabled(), !this.option.isUserDefined()); ModernFix.LOGGER.error("Unable to save config", e); } + OptionList.this.updateOptionEntryStatuses(); }, (btn, gfx, x, y) -> { if(this.option.isModDefined()) { String disablingMods = String.join(", ", this.option.getDefiningMods()); @@ -140,8 +148,7 @@ public class OptionList extends ContainerObjectSelectionList { ); } }); - if(this.option.isModDefined()) - this.toggleButton.active = false; + updateStatus(); this.helpButton = new Button(75, 0, 20, 20, new TextComponent("?"), (arg) -> { Minecraft.getInstance().setScreen(new ModernFixOptionInfoScreen(mainScreen, optionName)); }); @@ -152,6 +159,10 @@ public class OptionList extends ContainerObjectSelectionList { } } + void updateStatus() { + this.toggleButton.active = !(this.option.isModDefined() || this.option.isEffectivelyDisabledByParent()); + } + @Override public void render(PoseStack matrixStack, int index, int top, int left, int width, int height, int mouseX, int mouseY, boolean isMouseOver, float partialTicks) { MutableComponent nameComponent = getOptionComponent(this.name);