Ctrl+K

Configuration

All configuration uses TOML exclusively. INI support has been removed. Every config file maps to one Java class that reads it.

Loader Pipeline

MultiFormatLoader.load(path)
    └─► TomlConfigLoader.INSTANCE.load(path)
            ├─ Jackson TomlMapper.readTree(file) → JsonNode
            ├─ flatten(root, props)   // strips section names, keeps leaf keys
            └─ return PropertiesParser(props, filePath)

TOML sections ([server], [database]) are for human readability only. The loader flattens the entire tree — only leaf key names are retained. This means key names must be unique within a file.

MultiFormatLoader API

// Returns PropertiesParser — extends Properties, adds typed getters
PropertiesParser pp = MultiFormatLoader.load("./config/main/Rates.toml");
int xp = pp.getInteger("RateXp", 1);

// Backward-compatible bridge for classes using raw Properties
Properties raw = MultiFormatLoader.loadProperties("./config/l2jdrmods/PremiumService.toml");

AbstractConfigs Pattern

Every config class extends AbstractConfigs and holds typed public static fields.

public class PremiumServiceConfigs extends AbstractConfigs {

    private static final String FILE = "./config/l2jdrmods/PremiumService.toml";

    public static boolean USE_PREMIUM_SERVICE;
    public static float   PREMIUM_RATE_XP;
    public static float   PREMIUM_RATE_SP;
    public static String  PREMIUM_NAME_PREFIX;

    @Override
    public void loadConfigs() {
        Properties p = MultiFormatLoader.loadProperties(FILE);
        USE_PREMIUM_SERVICE  = Boolean.parseBoolean(p.getProperty("UsePremiumServices", "false"));
        PREMIUM_RATE_XP      = Float.parseFloat(p.getProperty("PremiumRateXp", "1.0"));
        PREMIUM_RATE_SP      = Float.parseFloat(p.getProperty("PremiumRateSp", "1.0"));
        PREMIUM_NAME_PREFIX  = p.getProperty("PremiumNamePrefix", "[VIP]");
    }
}

TOML File Format

# config/l2jdrmods/PremiumService.toml

[service]
UsePremiumServices   = true
PremiumRateXp        = 2.0
PremiumRateSp        = 2.0
PremiumRateDropItems = 2.0

[display]
PremiumNamePrefix    = "[VIP]"
PremiumChatPrefix    = ""
The section headers [service] and [display] are stripped during loading. Java code accesses keys as getProperty("UsePremiumServices") — no section prefix needed.

ConfigsController

All module configs are registered in ConfigsController.loadAll(), called during GameServer startup after Config.load():

public class ConfigsController {
    public static void loadAll() {
        new PremiumServiceConfigs().loadConfigs();
        new SecuritySystemConfigs().loadConfigs();
        new AioItemsConfigs().loadConfigs();
        new BackupManagerConfigs().loadConfigs();
        // ... all engine modules
    }
}

Adding a New Config File

  1. Create config/l2jdrmods/MyFeature.toml with all keys and inline comments.
  2. Create MyFeatureConfigs.java extending AbstractConfigs. Declare public static fields. Implement loadConfigs().
  3. Register with new MyFeatureConfigs().loadConfigs(); in ConfigsController.loadAll().
# config/l2jdrmods/MyFeature.toml
[feature]
Enable   = false
MaxValue = 10
public class MyFeatureConfigs extends AbstractConfigs {
    private static final String FILE = "./config/l2jdrmods/MyFeature.toml";
    public static boolean ENABLE;
    public static int     MAX_VALUE;

    @Override
    public void loadConfigs() {
        Properties p = MultiFormatLoader.loadProperties(FILE);
        ENABLE    = Boolean.parseBoolean(p.getProperty("Enable",   "false"));
        MAX_VALUE = Integer.parseInt(p.getProperty("MaxValue", "10"));
    }
}