### Open Configuration GUI Source: https://context7.com/notenoughupdates/moulconfig/llms.txt Call this method to open the configuration GUI. Ensure the necessary setup for MoulConfig is completed beforehand. ```java config.openConfigGui(); ``` -------------------------------- ### Initialize and Use ManagedConfig Source: https://context7.com/notenoughupdates/moulconfig/llms.txt Creates a `ManagedConfig` instance for the `CompleteModConfig` class, specifying the configuration file path. Includes examples of listening to property changes and opening the config GUI. ```java // Usage public static void main(String[] args) { ManagedConfig config = ManagedConfig.create( new File("config/mymod.json"), CompleteModConfig.class ); // Listen for changes config.getInstance().general.enabled.whenChanged((old, newVal) -> { System.out.println("Mod " + (newVal ? "enabled" : "disabled")); }); config.getInstance().appearance.uiScale.whenChanged((old, newVal) -> { System.out.println("Scale changed to " + newVal + "%"); }); // Open the config GUI } ``` -------------------------------- ### Legacy Minecraft Installation with Gradle Source: https://github.com/notenoughupdates/moulconfig/blob/v4/src/doc/docs/index.md Set up your Gradle build for legacy Minecraft (1.8.9) to shadow and relocate MoulConfig. This includes using a development resource tweaker for development environments. ```gradle repositories { maven("https://maven.notenoughupdates.org/releases/") } // Your Gradle template probably already includes something like this configuration. // **Make sure that the configuration is extending modImplementation, otherwise you will run into name issues** val shadowModImpl by configurations.creating { configurations.modImplementation.get().extendsFrom(this) } dependencies { // Where shadowModImpl is a gradle configuration that remaps and shades the jar. "shadowModImpl"("org.notenoughupdates.moulconfig:legacy:") } tasks.shadowJar { // Make sure to relocate MoulConfig to avoid version clashes with other mods configurations = listOf(shadowModImpl) relocate("io.github.notenoughupdates.moulconfig", "my.mod.deps.moulconfig") } ``` -------------------------------- ### Modern Minecraft Installation with Gradle Source: https://github.com/notenoughupdates/moulconfig/blob/v4/src/doc/docs/index.md Configure your Gradle build to shadow and relocate MoulConfig for modern Minecraft versions. Ensure your configuration extends modImplementation to avoid name conflicts. ```gradle repositories { maven("https://maven.notenoughupdates.org/releases/") } // Your gradle template probably already includes something like this configuration. // **Make sure that the configuration is extending modImplementation, otherwise you will run into name issues** val shadowModImpl by configurations.creating { configurations.modImplementation.get().extendsFrom(this) } dependencies { // Where shadowModImpl is a gradle configuration that remaps and shades the jar. "shadowModImpl"("org.notenoughupdates.moulconfig:modern-:") } tasks.shadowJar { // Make sure to relocate MoulConfig to avoid version clashes with other mods configurations = listOf(shadowModImpl) relocate("io.github.notenoughupdates.moulconfig", "my.mod.deps.moulconfig") } ``` -------------------------------- ### Gradle Configuration for MoulConfig Source: https://github.com/notenoughupdates/moulconfig/blob/v4/docs/Module.md Example Gradle configuration for integrating MoulConfig into a Minecraft mod project using Architectury Loom. It includes setting up repositories, configurations for development and shading, and dependency declarations. Ensure the 'modImplementation' configuration extends the shadow configuration to avoid naming conflicts. ```kotlin repositories { /// Your other releases maven("https://maven.notenoughupdates.org/releases/") } val devenvMod by configurations.creating { isTransitive = false isVisible = false } // Your gradle template probably already includes something like this configuration. // **Make sure that the configuration is extending modImplementation, otherwise you will run into name issues** val shadowModImpl by configurations.creating { configurations.modImplementation.get().extendsFrom(this) } dependencies { // Where shadowModImpl is a gradle configuration that remaps and shades the jar. // This version should not have :test at the end (so that you don't accidentally reference the test mod) "shadowModImpl"("org.notenoughupdates.moulconfig:MoulConfig:") // Where devenvMod is a gradle configuration from which all resolved jars are loaded as mod. // Be aware of the :test at the end. "devenvMod"("org.notenoughupdates.moulconfig:MoulConfig::test") } // The code below is just to demonstrate how a gradle configuration might be loaded as a list of development environment // mods without user interaction loom { launchConfigs { "client" { arg("--mods", devenvMod.resolve().joinToString(",") { it.relativeTo(file("run")).path }) } } } tasks.shadowJar { // Make sure to relocate MoulConfig to avoid version clashes with other mods configurations = listOf(shadowModImpl) relocate("io.github.notenoughupdates.moulconfig", "my.mod.deps.moulconfig") } ``` -------------------------------- ### Create a Base Config Class Source: https://context7.com/notenoughupdates/moulconfig/llms.txt Extend the `Config` base class and define categories using the `@Category` annotation. Implement `getTitle()` to set the screen's title. ```java import io.github.notenoughupdates.moulconfig.Config; import io.github.notenoughupdates.moulconfig.annotations.Category; import io.github.notenoughupdates.moulconfig.common.text.StructuredText; public class MyModConfig extends Config { @Override public StructuredText getTitle() { return StructuredText.of("My Mod Settings").green(); } @Category(name = "General", desc = "General mod settings") public GeneralCategory general = new GeneralCategory(); @Category(name = "Display", desc = "Visual and display options") public DisplayCategory display = new DisplayCategory(); } ``` -------------------------------- ### Create Git Tag and Push for Release Source: https://github.com/notenoughupdates/moulconfig/blob/v4/CONTRIBUTING.md These commands are used to create a new release by tagging the current commit and pushing the tag to GitHub. GitHub Actions will then automatically generate a new release on Maven. ```bash git tag "" git push origin "" ``` -------------------------------- ### Run Development Environment Source: https://github.com/notenoughupdates/moulconfig/blob/v4/CONTRIBUTING.md Use this command to run the mod in a development environment. Ensure you run the Gradle task directly, not an IntelliJ task with a similar name, to avoid potential configuration issues. ```bash ./gradlew runClient ``` -------------------------------- ### Create ManagedConfig with Automatic JSON Persistence Source: https://context7.com/notenoughupdates/moulconfig/llms.txt Use ManagedConfig.create to automatically handle loading and saving configuration from a JSON file. Specify the file path and the configuration class. ```java import io.github.notenoughupdates.moulconfig.managed.ManagedConfig; import io.github.notenoughupdates.moulconfig.common.IMinecraft; import java.io.File; public class MyMod { private ManagedConfig config; public void initialize() { // Create managed config with automatic JSON persistence config = ManagedConfig.create( new File("config/mymod/settings.json"), MyModConfig.class ); // Access config values if (config.getInstance().general.enableFeature) { System.out.println("Feature is enabled!"); } // Open config GUI config.openConfigGui(); // Or get the editor for custom handling var editor = config.getEditor(); editor.setWide(true); // Use wide layout IMinecraft.INSTANCE.openWrappedScreen(editor); } // With builder customization public void initializeWithOptions() { config = ManagedConfig.create( new File("config/mymod/settings.json"), MyModConfig.class, builder -> { builder.setCheckExpose(true); // Only save @Expose fields builder.setUseDefaultProcessors(true); // Use built-in editors } ); } } ``` -------------------------------- ### XML-Based UI with @Bind in Java Source: https://context7.com/notenoughupdates/moulconfig/llms.txt Demonstrates how to use @Bind annotation for data binding in XML layouts. Fields and methods annotated with @Bind are accessible from XML. Requires XMLUniverse to load the UI. ```java import io.github.notenoughupdates.moulconfig.xml.Bind; import io.github.notenoughupdates.moulconfig.xml.XMLUniverse; import io.github.notenoughupdates.moulconfig.observer.ObservableList; import io.github.notenoughupdates.moulconfig.gui.CloseEventListener; import io.github.notenoughupdates.moulconfig.common.IMinecraft; import io.github.notenoughupdates.moulconfig.common.MyResourceLocation; import java.util.ArrayList; import java.util.Arrays; public class XmlBoundScreen { // Fields annotated with @Bind are accessible from XML @Bind public boolean showAdvanced = false; @Bind public String searchText = ""; @Bind public float progress = 0.5f; @Bind public ObservableList items = new ObservableList<>( new ArrayList<>(Arrays.asList( new ListItem("Item 1"), new ListItem("Item 2") )) ); // Bound methods can be called from XML @Bind public void addItem() { items.add(new ListItem("New Item")); } @Bind public void clearItems() { items.clear(); } @Bind public Runnable requestClose = null; // Set by XML loader @Bind public CloseEventListener.CloseAction beforeClose() { System.out.println("Saving before close..."); return CloseEventListener.CloseAction.NO_OBJECTIONS_TO_CLOSE; } public static class ListItem { @Bind public String name; @Bind public boolean selected = false; public ListItem(String name) { this.name = name; } @Bind public void toggle() { selected = !selected; } } public void show() { XMLUniverse universe = XMLUniverse.getDefaultUniverse(); var screen = universe.load( this, IMinecraft.INSTANCE.loadResourceLocation( MyResourceLocation.Companion.parse("mymod:screens/main.xml") ) ); IMinecraft.INSTANCE.openWrappedScreen(screen); } } ``` -------------------------------- ### Manually Configure MoulConfigProcessor Source: https://context7.com/notenoughupdates/moulconfig/llms.txt For advanced scenarios, manually create and configure MoulConfigProcessor. Register custom editors for custom annotations and control processing behavior. ```java import io.github.notenoughupdates.moulconfig.processor.*; import io.github.notenoughupdates.moulconfig.gui.MoulConfigEditor; import io.github.notenoughupdates.moulconfig.gui.GuiOptionEditor; import io.github.notenoughupdates.moulconfig.common.IMinecraft; import java.lang.annotation.Annotation; import java.util.function.BiFunction; public class ManualConfigSetup { public void setupConfig(MyModConfig config) { // Create processor with default editors MoulConfigProcessor processor = MoulConfigProcessor.withDefaults(config); // Or manually configure MoulConfigProcessor manualProcessor = new MoulConfigProcessor<>(config); BuiltinMoulConfigGuis.addProcessors(manualProcessor); // Add standard editors // Register custom editor for custom annotation manualProcessor.registerConfigEditor( MyCustomAnnotation.class, (ProcessedOption option, MyCustomAnnotation annotation) -> { return new MyCustomEditor(option, annotation); } ); // Process the config structure ConfigProcessorDriver driver = new ConfigProcessorDriver(processor); driver.processConfig(config); // Create and display editor MoulConfigEditor editor = new MoulConfigEditor<>(processor); // Configure editor options editor.setWide(true); editor.search("display"); // Pre-filter options // Navigate to specific option ProcessedOption option = processor.getOptionFromField( MyModConfig.class.getDeclaredField("someField") ); if (option != null) { editor.goToOption(option); } IMinecraft.INSTANCE.openWrappedScreen(editor); } } ``` -------------------------------- ### Ordering Configuration Options with @ConfigOrder Source: https://context7.com/notenoughupdates/moulconfig/llms.txt Control the display order of options within a category using @ConfigOrder. Lower numbers appear earlier. Values can be negative. ```java import io.github.notenoughupdates.moulconfig.annotations.*; public class OrderedCategory { // Will appear at the bottom despite being declared first @ConfigOrder(Integer.MAX_VALUE) @ConfigOption(name = "Advanced Setting", desc = "Shows at bottom") @ConfigEditorBoolean public boolean advancedSetting = false; // Normal order (declaration order by default) @ConfigOption(name = "Regular Setting", desc = "Shows in middle") @ConfigEditorBoolean public boolean regularSetting = true; // Will appear at the top despite being declared last @ConfigOrder(-100) @ConfigOption(name = "Important Setting", desc = "Shows at top") @ConfigEditorBoolean public boolean importantSetting = true; // Another top-priority option @ConfigOrder(-50) @ConfigOption(name = "Second Most Important", desc = "Shows near top") @ConfigEditorSlider(minValue = 0, maxValue = 10, minStep = 1) public int priority = 5; } ``` -------------------------------- ### Add MoulConfig Dependency and Shading Source: https://context7.com/notenoughupdates/moulconfig/llms.txt Configure your build.gradle to include the MoulConfig library and set up shading to relocate it, preventing version conflicts with other mods. ```gradle repositories { maven("https://maven.notenoughupdates.org/releases/") } // Configuration for shading val shadowModImpl by configurations.creating { configurations.modImplementation.get().extendsFrom(this) } dependencies { // For modern Minecraft (1.20+) "shadowModImpl"("org.notenoughupdates.moulconfig:modern-:") // For legacy 1.8.9 Forge "shadowModImpl"("org.notenoughupdates.moulconfig:legacy:") } tasks.shadowJar { configurations = listOf(shadowModImpl) // Always relocate MoulConfig to avoid conflicts relocate("io.github.notenoughupdates.moulconfig", "my.mod.deps.moulconfig") } ``` -------------------------------- ### Define Top-Level Config Structure Source: https://github.com/notenoughupdates/moulconfig/blob/v4/src/doc/docs/config/index.md Extend the `Config` class and override `getTitle()` to set the GUI title. Use the `@Category` annotation to define top-level categories and their descriptions. Nested categories are supported once. ```java public class MyConfig extends Config { @Override public String getTitle() { return "§bMyMod Config"; } @Category(name = "Category Name", desc = "Category Description") public MyCategory myCategory = new MyCategory(); public static class MyCategory { @Category(name = "SubCategory", desc = "Sub category description") public MySubCategory subCategory = new MySubCategory(); } } ``` -------------------------------- ### Define Reactive Settings with Properties Source: https://context7.com/notenoughupdates/moulconfig/llms.txt Utilize the Property class for observable configuration values. Listen for changes using whenChanged and map values to derived observables. ```java import io.github.notenoughupdates.moulconfig.observer.Property; import io.github.notenoughupdates.moulconfig.observer.Observable; import io.github.notenoughupdates.moulconfig.annotations.*; public class ReactiveSettings { @ConfigOption(name = "Scale", desc = "UI scale percentage") @ConfigEditorSlider(minValue = 50, maxValue = 200, minStep = 10) public Property scale = Property.of(100); @ConfigOption(name = "Theme", desc = "Color theme") @ConfigEditorDropdown public Property theme = Property.of(Theme.DARK); public enum Theme { LIGHT, DARK, CUSTOM } } public class ReactiveHandler { public void setupReactivity(ReactiveSettings settings) { // Listen for scale changes settings.scale.whenChanged((oldValue, newValue) -> { System.out.println("Scale changed from " + oldValue + " to " + newValue); updateUIScale(newValue); }); // Map to derived value Observable scaleAsFloat = settings.scale.map(i -> i / 100.0f); // Listen for theme changes settings.theme.whenChanged((oldTheme, newTheme) -> { System.out.println("Theme changed to: " + newTheme); applyTheme(newTheme); }); // Programmatically update (triggers observers) settings.scale.set(150); } private void updateUIScale(int scale) { /* ... */ } private void applyTheme(ReactiveSettings.Theme theme) { /* ... */ } } ``` -------------------------------- ### Define Complete Mod Configuration Class Source: https://context7.com/notenoughupdates/moulconfig/llms.txt Extends the base `Config` class and defines various settings organized into categories using annotations. Includes custom enums for dropdowns and specific editors like sliders and keybinds. ```java import io.github.notenoughupdates.moulconfig.Config; import io.github.notenoughupdates.moulconfig.ChromaColour; import io.github.notenoughupdates.moulconfig.annotations.*; import io.github.notenoughupdates.moulconfig.common.text.StructuredText; import io.github.notenoughupdates.moulconfig.observer.Property; import io.github.notenoughupdates.moulconfig.managed.ManagedConfig; import org.lwjgl.glfw.GLFW; import java.io.File; import java.util.*; public class CompleteModConfig extends Config { @Override public StructuredText getTitle() { return StructuredText.of("Complete Mod Config").gold(); } @Override public boolean shouldAutoFocusSearchbar() { return true; } @Category(name = "General", desc = "Main mod settings") public GeneralSettings general = new GeneralSettings(); @Category(name = "Appearance", desc = "Visual customization") public AppearanceSettings appearance = new AppearanceSettings(); @Category(name = "Controls", desc = "Keybinds and input") public ControlSettings controls = new ControlSettings(); public static class GeneralSettings { @ConfigOrder(-100) @ConfigOption(name = "Enable Mod", desc = "Master toggle for all features") @ConfigEditorBoolean public Property enabled = Property.of(true); @ConfigOption(name = "Update Mode", desc = "How to handle updates") @ConfigEditorDropdown public UpdateMode updateMode = UpdateMode.AUTO; public enum UpdateMode { AUTO("Automatic"), NOTIFY("Notify Only"), MANUAL("Manual"); private final String label; UpdateMode(String label) { this.label = label; } @Override public String toString() { return label; } } @Accordion @ConfigOption(name = "Advanced Options", desc = "") public AdvancedOptions advanced = new AdvancedOptions(); public static class AdvancedOptions { @ConfigOption(name = "Debug Mode", desc = "Enable debug logging") @ConfigEditorBoolean public boolean debug = false; @ConfigOption(name = "Cache Duration", desc = "Cache timeout in seconds") @ConfigEditorSlider(minValue = 30, maxValue = 600, minStep = 30) public int cacheDuration = 300; } } public static class AppearanceSettings { @ConfigOption(name = "Theme", desc = "UI color theme") @ConfigEditorDropdown public Property theme = Property.of(Theme.DARK); public enum Theme { LIGHT, DARK, CUSTOM } @ConfigOption(name = "Primary Color", desc = "Main accent color") @ConfigEditorColour public ChromaColour primaryColor = new ChromaColour(0F, 1f, 0.8f, 0, 0x3498db); @ConfigOption(name = "UI Scale", desc = "Interface scale percentage") @ConfigEditorSlider(minValue = 75, maxValue = 150, minStep = 5) public Property uiScale = Property.of(100); @ConfigOption(name = "HUD Elements", desc = "Order of HUD components") @ConfigEditorDraggableList public List hudOrder = new ArrayList<>(Arrays.asList( HudElement.HEALTH, HudElement.MANA, HudElement.STATUS )); public enum HudElement { HEALTH("Health"), MANA("Mana"), STATUS("Status"), MINIMAP("Minimap"); private final String label; HudElement(String label) { this.label = label; } @Override public String toString() { return label; } } } public static class ControlSettings { @ConfigOption(name = "Open Menu", desc = "Key to open config menu") @ConfigEditorKeybind(defaultKey = GLFW.GLFW_KEY_COMMA) public int openMenuKey = GLFW.GLFW_KEY_COMMA; @ConfigOption(name = "Quick Toggle", desc = "Quickly toggle the mod") @ConfigEditorKeybind(defaultKey = GLFW.GLFW_KEY_PERIOD) public int quickToggleKey = GLFW.GLFW_KEY_PERIOD; @ConfigOption(name = "Reset Keybinds", desc = "Reset all keybinds to defaults") @ConfigEditorButton(buttonText = "Reset") public Runnable resetKeybinds = () -> { // Reset logic }; } } ``` -------------------------------- ### Define Configurable Fields Source: https://context7.com/notenoughupdates/moulconfig/llms.txt Annotate fields with `@ConfigOption` for a name and description, and use editor annotations like `@ConfigEditorBoolean`, `@ConfigEditorSlider`, or `@ConfigEditorText` to specify the GUI element. ```java import io.github.notenoughupdates.moulconfig.annotations.*; public class GeneralCategory { @ConfigOption(name = "Enable Feature", desc = "Turns the main feature on or off") @ConfigEditorBoolean public boolean enableFeature = true; @ConfigOption(name = "Update Interval", desc = "How often to check for updates (seconds)") @ConfigEditorSlider(minValue = 1, maxValue = 60, minStep = 1) public int updateInterval = 10; @ConfigOption(name = "Username", desc = "Your display name") @ConfigEditorText public String username = "Player"; } ``` -------------------------------- ### Action Buttons with Runnables Source: https://context7.com/notenoughupdates/moulconfig/llms.txt Use @ConfigEditorButton to create clickable buttons that execute a Runnable when clicked. Useful for actions like resetting settings or exporting data. ```java import io.github.notenoughupdates.moulconfig.annotations.*; public class ActionSettings { @ConfigOption(name = "Reset to Defaults", desc = "Reset all settings to default values") @ConfigEditorButton(buttonText = "Reset") public Runnable resetButton = () -> { System.out.println("Resetting configuration..."); // Reset logic here }; @ConfigOption(name = "Export Config", desc = "Export settings to file") @ConfigEditorButton(buttonText = "Export") public Runnable exportButton = () -> { System.out.println("Exporting configuration..."); // Export logic here }; @ConfigOption(name = "Open Wiki", desc = "View documentation online") @ConfigEditorButton(buttonText = "Open") public Runnable openWikiButton = () -> { // Open URL in browser }; } ``` -------------------------------- ### Organize Options with @Accordion Source: https://context7.com/notenoughupdates/moulconfig/llms.txt Use the @Accordion annotation to group related options into collapsible sections. The annotated field must be a POJO containing other ConfigOptions. ```java import io.github.notenoughupdates.moulconfig.annotations.*; public class AdvancedSettings { @Accordion @ConfigOption(name = "Performance", desc = "") public PerformanceOptions performance = new PerformanceOptions(); @Accordion @ConfigOption(name = "Experimental", desc = "") public ExperimentalOptions experimental = new ExperimentalOptions(); public static class PerformanceOptions { @ConfigOption(name = "Max FPS", desc = "Frame rate limit") @ConfigEditorSlider(minValue = 30, maxValue = 240, minStep = 10) public int maxFps = 60; @ConfigOption(name = "Reduce Particles", desc = "Lower particle count for better performance") @ConfigEditorBoolean public boolean reduceParticles = false; @ConfigOption(name = "Cache Size", desc = "Memory cache size in MB") @ConfigEditorSlider(minValue = 64, maxValue = 512, minStep = 64) public int cacheSize = 128; } public static class ExperimentalOptions { @ConfigOption(name = "Beta Features", desc = "Enable experimental features") @ConfigEditorBoolean public boolean betaFeatures = false; @ConfigOption(name = "Debug Overlay", desc = "Show debug information") @ConfigEditorBoolean public boolean debugOverlay = false; } } ``` -------------------------------- ### Key Binding Editor Source: https://context7.com/notenoughupdates/moulconfig/llms.txt Use @ConfigEditorKeybind to create a field for capturing keyboard input. The field must be an int representing the GLFW key code. A default key can be specified. ```java import io.github.notenoughupdates.moulconfig.annotations.*; import org.lwjgl.glfw.GLFW; public class KeybindSettings { @ConfigOption(name = "Open Menu", desc = "Key to open the mod menu") @ConfigEditorKeybind(defaultKey = GLFW.GLFW_KEY_M) public int openMenuKey = GLFW.GLFW_KEY_M; @ConfigOption(name = "Quick Action", desc = "Shortcut for quick action") @ConfigEditorKeybind(defaultKey = GLFW.GLFW_KEY_G) public int quickActionKey = GLFW.GLFW_KEY_G; @ConfigOption(name = "Toggle HUD", desc = "Show/hide the HUD overlay") @ConfigEditorKeybind(defaultKey = GLFW.GLFW_KEY_H) public int toggleHudKey = GLFW.GLFW_KEY_H; } ``` -------------------------------- ### Displaying Informational Text with @ConfigEditorInfoText Source: https://context7.com/notenoughupdates/moulconfig/llms.txt Use @ConfigEditorInfoText to display static informational text or notices in the config GUI. The associated field's value is ignored. ```java import io.github.notenoughupdates.moulconfig.annotations.*; public class InfoSettings { @ConfigOption(name = "Warning", desc = "Important information for users") @ConfigEditorInfoText(infoTitle = "Warning: Changing these settings may affect performance") public boolean warningNotice = false; // Value is ignored @ConfigOption(name = "Beta Notice", desc = "Feature status information") @ConfigEditorInfoText(infoTitle = "This feature is in beta and may have bugs") public String betaInfo = ""; // Value is ignored @ConfigOption(name = "Help", desc = "Link to documentation") @ConfigEditorInfoText(infoTitle = "Visit wiki.example.com for detailed documentation") public boolean helpLink = false; } ``` -------------------------------- ### Define Config Options within a Category Source: https://github.com/notenoughupdates/moulconfig/blob/v4/src/doc/docs/config/index.md Inside a category class, use `@ConfigOption` along with a specific editor annotation (e.g., `@ConfigEditorText`, `@ConfigEditorSlider`, `@ConfigEditorKeybind`) to define configurable fields. Ensure the field type matches the editor's requirements. ```java public class MySubCategory { @ConfigOption(name = "Text Test", desc = "Text Editor Test") @ConfigEditorText public String text = "Text"; @ConfigOption(name = "Number", desc = "Slider test") @ConfigEditorSlider(minValue = 0, maxValue = 10, minStep = 1) public int slider = 0; @ConfigOption(name = "Key Binding", desc = "Key Binding") @ConfigEditorKeybind(defaultKey = Keyboard.KEY_F) public int keyBoard = Keyboard.KEY_F; } ``` -------------------------------- ### Implement Accordion for Nested Options Source: https://github.com/notenoughupdates/moulconfig/blob/v4/src/doc/docs/config/index.md Use the `@Accordion` annotation to group options further within a category. This allows for arbitrary nesting of configuration options, similar to subcategories but with more flexibility. ```java public class MySubCategory { @ConfigOption(name = "Text Test", desc = "Text Editor Test") @ConfigEditorText public String text = "Text"; @Accordion @ConfigOption(name = "Hehe", desc = "hoho") public MyAccordion myAccordion = new MyAccordion(); public static class MyAccordion { @ConfigOption(name = "Number", desc = "Slider test") @ConfigEditorSlider(minValue = 0, maxValue = 10, minStep = 1) public int slider = 0; @ConfigOption(name = "Key Binding", desc = "Key Binding") @ConfigEditorKeybind(defaultKey = Keyboard.KEY_F) public int keyBoard = Keyboard.KEY_F; } } ``` -------------------------------- ### Dropdown Selection with Enums and Properties Source: https://context7.com/notenoughupdates/moulconfig/llms.txt Use @ConfigEditorDropdown with enums for type-safe selections or with Property for reactive bindings. Ensure enum members have a displayable string representation. ```java import io.github.notenoughupdates.moulconfig.annotations.*; import io.github.notenoughupdates.moulconfig.observer.Property; public class PreferenceSettings { // Recommended: Use enum for type-safe dropdowns @ConfigOption(name = "Theme", desc = "Choose color theme") @ConfigEditorDropdown public Theme selectedTheme = Theme.DARK; public enum Theme { LIGHT("Light Mode"), DARK("Dark Mode"), SYSTEM("System Default"); private final String label; Theme(String label) { this.label = label; } @Override public String toString() { return label; } } // With Property for reactive bindings @ConfigOption(name = "Language", desc = "Display language") @ConfigEditorDropdown public Property language = Property.of(Language.ENGLISH); public enum Language { ENGLISH("English"), SPANISH("Español"), FRENCH("Français"); private final String label; Language(String label) { this.label = label; } @Override public String toString() { return label; } } } ``` -------------------------------- ### Create Nested Categories with @Category Source: https://context7.com/notenoughupdates/moulconfig/llms.txt Use the @Category annotation to organize configuration options into main categories and subcategories. Nested categories allow for a structured UI. ```java import io.github.notenoughupdates.moulconfig.Config; import io.github.notenoughupdates.moulconfig.annotations.*; public class OrganizedConfig extends Config { @Category(name = "Main", desc = "Primary settings") public MainCategory main = new MainCategory(); } public class MainCategory { @ConfigOption(name = "Enabled", desc = "Enable the mod") @ConfigEditorBoolean public boolean enabled = true; // Subcategory within Main @Category(name = "Audio Settings", desc = "Sound configuration") public AudioSubcategory audio = new AudioSubcategory(); // Another subcategory @Category(name = "Visual Settings", desc = "Display configuration") public VisualSubcategory visual = new VisualSubcategory(); } public class AudioSubcategory { @ConfigOption(name = "Master Volume", desc = "Overall sound level") @ConfigEditorSlider(minValue = 0, maxValue = 100, minStep = 5) public int masterVolume = 100; @ConfigOption(name = "Mute", desc = "Mute all sounds") @ConfigEditorBoolean public boolean mute = false; } public class VisualSubcategory { @ConfigOption(name = "Show HUD", desc = "Display the overlay") @ConfigEditorBoolean public boolean showHud = true; } ``` -------------------------------- ### Color Picker with ChromaColour and Legacy Strings Source: https://context7.com/notenoughupdates/moulconfig/llms.txt Use @ConfigEditorColour for color selection. Supports ChromaColour objects or legacy string formats. ChromaColour offers advanced features like rainbow colors. ```java import io.github.notenoughupdates.moulconfig.annotations.*; import io.github.notenoughupdates.moulconfig.ChromaColour; public class ColorSettings { @ConfigOption(name = "Highlight Color", desc = "Color for highlighted items") @ConfigEditorColour public ChromaColour highlightColor = new ChromaColour(0F, 1f, 1f, 0, 0xFF00FF); @ConfigOption(name = "Background Color", desc = "HUD background tint") @ConfigEditorColour public ChromaColour backgroundColor = ChromaColour.special(0, 255, 128, 128, 200); // Legacy string format (still supported) @ConfigOption(name = "Border Color", desc = "Window border color") @ConfigEditorColour public String borderColor = ChromaColour.special(0, 255, 0, 0, 255).toLegacyString(); } ``` -------------------------------- ### Numeric Slider Source: https://context7.com/notenoughupdates/moulconfig/llms.txt Use `@ConfigEditorSlider` for numeric fields. Supports `int`, `float`, `double`, and their `Property` wrappers. Configure `minValue`, `maxValue`, and `minStep`. ```java import io.github.notenoughupdates.moulconfig.annotations.*; public class DisplaySettings { @ConfigOption(name = "Volume", desc = "Sound volume level") @ConfigEditorSlider(minValue = 0, maxValue = 100, minStep = 1) public int volume = 50; @ConfigOption(name = "Opacity", desc = "HUD element transparency") @ConfigEditorSlider(minValue = 0.0f, maxValue = 1.0f, minStep = 0.05f) public float opacity = 0.8f; @ConfigOption(name = "Scale Factor", desc = "UI scale multiplier") @ConfigEditorSlider(minValue = 0.5f, maxValue = 2.0f, minStep = 0.1f) public float scaleFactor = 1.0f; } ``` -------------------------------- ### Boolean Toggle Switch Source: https://context7.com/notenoughupdates/moulconfig/llms.txt Use `@ConfigEditorBoolean` for boolean fields or `Property` for reactive updates. The field must be of type `boolean` or `Property`. ```java import io.github.notenoughupdates.moulconfig.annotations.*; import io.github.notenoughupdates.moulconfig.observer.Property; public class FeatureSettings { @ConfigOption(name = "Auto-Save", desc = "Automatically save progress") @ConfigEditorBoolean public boolean autoSave = true; // Using Property for reactive updates @ConfigOption(name = "Debug Mode", desc = "Enable debug logging") @ConfigEditorBoolean public Property debugMode = Property.of(false); } ``` -------------------------------- ### Create Draggable Lists with @ConfigEditorDraggableList Source: https://context7.com/notenoughupdates/moulconfig/llms.txt Use @ConfigEditorDraggableList to create reorderable lists for enum types. The 'requireNonEmpty' parameter ensures the list always has at least one item. ```java import io.github.notenoughupdates.moulconfig.annotations.*; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class ListSettings { @ConfigOption(name = "Display Order", desc = "Drag to reorder HUD elements") @ConfigEditorDraggableList public List displayOrder = new ArrayList<>(Arrays.asList( HudElement.HEALTH, HudElement.MANA, HudElement.ARMOR )); public enum HudElement { HEALTH("Health Bar"), MANA("Mana Bar"), ARMOR("Armor Status"), COMPASS("Compass"), MINIMAP("Mini Map"); private final String label; HudElement(String label) { this.label = label; } @Override public String toString() { return label; } } // Require at least one item in the list @ConfigOption(name = "Active Modules", desc = "Enabled feature modules") @ConfigEditorDraggableList(requireNonEmpty = true) public List activeModules = new ArrayList<>(Arrays.asList(Module.CORE)); public enum Module { CORE("Core"), UTILS("Utilities"), EXTRAS("Extras"); private final String label; Module(String label) { this.label = label; } @Override public String toString() { return label; } } } ``` -------------------------------- ### Text Input with Forbidden Characters Source: https://context7.com/notenoughupdates/moulconfig/llms.txt Use @ConfigEditorText for string inputs. Optionally specify forbidden characters to prevent their use. Supports reactive Property. ```java import io.github.notenoughupdates.moulconfig.annotations.*; import io.github.notenoughupdates.moulconfig.observer.Property; public class CustomizationSettings { @ConfigOption(name = "Custom Title", desc = "Set a custom window title") @ConfigEditorText public String customTitle = "My Mod"; // Forbid certain characters (§ is forbidden by default for Minecraft formatting) @ConfigOption(name = "Chat Prefix", desc = "Prefix for chat messages") @ConfigEditorText(forbidden = "§&") public String chatPrefix = "[MyMod]"; // Reactive text field @ConfigOption(name = "Search Filter", desc = "Filter items by name") @ConfigEditorText public Property searchFilter = Property.of(""); } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.