Skip to content

Config Module

The Config module provides an annotation-based configuration management system that eliminates the need to manually write NeoForge ModConfigSpec. Simply define a plain Java class, annotate its fields, and registration, range validation, comment generation, and client GUI creation are all handled automatically.

I. Core Annotations

@Config

Applied to a configuration class to declare it as a config class.

java
package dev.anvilcraft.lib.v2.config;

@interface Config {
    String name();                          // Config file name (without extension)
    ModConfig.Type type() default COMMON;   // Config type: COMMON / CLIENT / SERVER
}

@Comment

Applied to fields to add human-readable comments that are written into the generated TOML file.

java
@Comment("Enable debug mode")
public boolean debugMode = false;

@BoundedDiscrete

Applied to numeric fields (int, long, float, double, etc.) to restrict the allowed value range.

java
@BoundedDiscrete(min = 1, max = 100)
public int maxCount = 10;
PropertyTypeDefaultDescription
mindoubleDouble.NEGATIVE_INFINITYMinimum (inclusive)
maxdoubleDouble.POSITIVE_INFINITYMaximum (inclusive)

@CollapsibleObject

Applied to non-primitive fields to mark them as nested configuration objects (corresponding to TOML sections). Nested object fields support all the same annotations.

java
@CollapsibleObject
public AdvancedSettings advanced = new AdvancedSettings();

II. Registering with ConfigManager

Use ConfigManager.register(modId, factory) to register your configuration. This method will:

  1. Scan the config class for the @Config annotation;
  2. Register the config with the corresponding mod's ModContainer;
  3. On the client side, automatically register a NeoForge ConfigurationScreen GUI.
java
ConfigManager.register(String modId, Supplier<T> configFactory)
ParameterTypeDescription
modIdStringThe mod ID
configFactorySupplier<T>Config class factory (usually MyConfig::new)
Return valueTThe config instance — hold a reference to it

III. Full Example

1. Define a Config Class

java
import dev.anvilcraft.lib.v2.config.BoundedDiscrete;
import dev.anvilcraft.lib.v2.config.CollapsibleObject;
import dev.anvilcraft.lib.v2.config.Comment;
import dev.anvilcraft.lib.v2.config.Config;
import net.neoforged.fml.config.ModConfig;

@Config(name = "my_mod", type = ModConfig.Type.COMMON)
public class MyModConfig {

    @Comment("Whether to enable debug mode")
    public boolean debugMode = false;

    @Comment("Maximum server connections")
    @BoundedDiscrete(min = 1, max = 256)
    public int maxConnections = 32;

    @Comment("Spawn chance (0.0 to 1.0)")
    @BoundedDiscrete(min = 0.0, max = 1.0)
    public double spawnChance = 0.5;

    @Comment("Advanced settings")
    @CollapsibleObject
    public AdvancedSettings advanced = new AdvancedSettings();

    public static class AdvancedSettings {
        @Comment("Enable experimental features")
        public boolean enableExperimental = false;

        @Comment("Cache size")
        @BoundedDiscrete(min = 64, max = 4096)
        public int cacheSize = 512;
    }
}

2. Register the Config

Register in your mod's main class and hold a reference to the returned instance:

java
import dev.anvilcraft.lib.v2.config.ConfigManager;

@Mod("my_mod")
public class MyMod {
    public static final MyModConfig CONFIG =
        ConfigManager.register("my_mod", MyModConfig::new);

    public MyMod(IEventBus modEventBus) {
        // Other initialization...
    }
}

3. Accessing the Config

java
if (MyMod.CONFIG.debugMode) {
    // Debug logic
}

int limit = MyMod.CONFIG.maxConnections;

IV. Supported Field Types

Java TypeNotes
booleanBoolean toggle
intInteger, supports @BoundedDiscrete
longLong integer, supports @BoundedDiscrete
floatSingle-precision float, supports @BoundedDiscrete
doubleDouble-precision float, supports @BoundedDiscrete
StringString value
List<T>List of primitives
Nested objectCustom types annotated with @CollapsibleObject

V. Automatic GUI

On the client side, ConfigManager automatically registers NeoForge's ConfigurationScreen as the mod's config GUI. Players can open the visual config screen directly from the mod list screen — no manual implementation required.

VI. Notes

  • Config classes must have a no-argument constructor;
  • Config fields must be public and non-final;
  • ConfigManager.register should be called inside the mod constructor (after the event bus is available);
  • Config instances are safe to read from any thread after loading, but should not be accessed before the config load event fires.

Released under the CC-BY-NC-SA 4.0 License.