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
- Create
config/l2jdrmods/MyFeature.tomlwith all keys and inline comments. - Create
MyFeatureConfigs.javaextendingAbstractConfigs. Declarepublic staticfields. ImplementloadConfigs(). - Register with
new MyFeatureConfigs().loadConfigs();inConfigsController.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"));
}
}