Skip to content

Repository files navigation

Logo

A class-based config API and in-game config screen for Minecraft mods.

EasyConfig makes it easy to create, modify, and share config files for your mod. With an easily accessible in-game config screen, users can adjust settings on the fly without having to manually edit config files.

EasyConfig naturally integrates with NeoForge, not replacing their configs, but giving a cleaner alternative. For Fabric, EasyConfig integrates with ModMenu for in-game config access, while still remaining an optional dependency.

What It Provides

  • One config API for Fabric and NeoForge.
  • In-game config screens for mods that use EasyConfig.
  • Tabs for mods with more than one config.
  • Fabric Mod Menu integration.
  • Lower-level APIs for custom config loading, saving, and metadata.

For Developers

Add the Maven repository:

repositories {
    maven {
        name = "iso2t"
        url = "https://maven.iso2t.com/releases"
    }
}

Fabric:

dependencies {
    modImplementation "com.iso2t.easyconfig:easyconfig-fabric-26.2:26.1.0.3"
}

NeoForge:

dependencies {
    implementation "com.iso2t.easyconfig:easyconfig-neoforge-26.2:26.1.0.3"
}

API only:

dependencies {
    implementation "com.iso2t.easyconfig:api:1.1.3"
}

The Fabric and NeoForge artifacts include the API classes in the built mod jar. Use the standalone api artifact only when you want the Java config API without EasyConfig's Minecraft mod implementation or in-game screens.

Creating a Config

import com.iso2t.easyconfig.api.Side;
import com.iso2t.easyconfig.api.annotations.Comment;
import com.iso2t.easyconfig.api.annotations.Ignore;
import com.iso2t.easyconfig.api.annotations.Config;
import com.iso2t.easyconfig.api.value.wrappers.BooleanValue;
import com.iso2t.easyconfig.api.value.wrappers.EnumValue;
import com.iso2t.easyconfig.api.value.wrappers.IntegerValue;

@Config(name = "example", side = Side.COMMON)
public class ExampleConfig {
    @Comment(value = "Enable the feature", values = false)
    public BooleanValue enabled = BooleanValue.of(true);

    @Comment("Maximum entries to process")
    public IntegerValue maxEntries = IntegerValue.of(64, 1, 256);
	
    @Ignore // Ignored by the config builder
    public IntegerValue maxAttempts = IntegerValue.of(10);

    @Comment("Feature mode")
    public EnumValue<Mode> mode = EnumValue.of(Mode.NORMAL);

    public enum Mode {
        QUIET,
        NORMAL,
        AGGRESSIVE
    }
}

Build the config during mod initialization:

import com.iso2t.easyconfig.api.ConfigBuilder;

public final class ExampleMod {
    public static final String MOD_ID = "examplemod";
    public static ExampleConfig CONFIG;

    public static void init() {
        CONFIG = ConfigBuilder.build(ExampleConfig.class, MOD_ID);
    }
}

This loads the config, writes missing values, and saves comments. When using the Fabric or NeoForge artifact, it also registers the config screen.

Screen registration is handled by the EasyConfig mod artifacts. If you use the standalone Java API outside Minecraft, configure the config directory through ConfigPlatform.

import com.iso2t.easyconfig.api.ConfigPlatform;
import java.nio.file.Path;

ConfigPlatform.configure(Path.of("config"), modId -> {});

Config Files

Config file names come from @Config.

@Config(name = "example", side = Side.CLIENT)

generates:

example-client.json5

Side suffixes:

  • Side.COMMON: no suffix
  • Side.CLIENT: -client
  • Side.SERVER: -server

JSON5 is the default format:

ConfigBuilder.build(ExampleConfig.class, MOD_ID);

You can pass a file type explicitly:

import com.iso2t.easyconfig.api.files.FileTypes;

ConfigBuilder.build(ExampleConfig.class, MOD_ID, FileTypes.JSON5);
ConfigBuilder.build(ExampleConfig.class, MOD_ID, FileTypes.TOML);

Nested Sections

Nested classes become sections when they are config-like objects with a no-argument constructor.

@Comment("Debug options")
public Debug debug = new Debug();

public static class Debug {
    @Comment(value = "Show debug output", values = false)
    public BooleanValue enabled = BooleanValue.of(false);
}

@Comment can be used on fields and nested sections.

Config Screens

Configs created through ConfigBuilder are registered for screen support by default.

Config screens are part of the Minecraft implementation, not the standalone Java API.

Disable screen registration:

import com.iso2t.easyconfig.api.ConfigBuildOptions;

ConfigBuilder.build(
    ExampleConfig.class,
    MOD_ID,
    ConfigBuildOptions.unregistered()
);

Set a custom tab title:

ConfigBuilder.build(
    ExampleConfig.class,
    MOD_ID,
    ConfigBuildOptions.defaults().screenTitle("Gameplay")
);

Multiple configs registered under the same mod id appear as tabs.

NeoForge uses the native mod-list config button. Fabric uses Mod Menu when it is installed.

Manual Control

Use ConfigManager directly when you need a custom path or lifecycle:

import com.iso2t.easyconfig.api.files.FileTypes;
import com.iso2t.easyconfig.api.manager.ConfigManager;

ConfigManager<ExampleConfig> manager = new ConfigManager<>(
    ExampleConfig.class,
    configPath,
    FileTypes.JSON5
);

ExampleConfig config = manager.loadAndSave();
manager.save(config);

Useful methods:

  • load()
  • loadAndSave()
  • save(config)
  • loadInto(config)
  • loadAndSaveInto(config)
  • schema(config)

License

EasyConfig is licensed under LGPL v3.0. See LICENSE.md.

About

Class based annotation processing for mods with a separate API for Java.

Resources

Stars

Watchers

Forks

Releases

Contributors

Languages