-
Notifications
You must be signed in to change notification settings - Fork 2
CustomConfig
This page is currently outdated and needs updating
A property consists of a key and a value (e.g. this-is-a-key: <value>
). Sub-properties (property.sub-property
) are indented using 2 spaces.
this-is-a-key: "This is a value"
property:
sub-property: 1
Multiple properties combined under a single "super-property" are called sections
this-is-a-section:
property-one: "Yay!"
property-two: 2
Numbers and Booleans are just the plain values written after the key. They don't need to be formatted in any special way
my-boolean: true
my-integer: 1234
my-double: 123.45
Strings need to be wrapped in quotes ("
) to be recognized as such, otherwise the config parser will throw an error
Escaping works very similar to string escaping in JSON
string-stuff:
test: "This is a string. Special characters can be escaped using backslashes: \" is a quote, \\ is a backslash"
unicode: "Unicode escapes work very similar to JSON too. \u263A is a smiley face. This is not required to be escaped though ☺"
Lists need to be indented 2 spaces from their declaring key and every entry is prefixed with -
.
my-string-list:
- "Some entry"
- "Some other entry"
an-integer-list:
- 1
- 2
// TODO
The header comment (at the very top of the config) has to be prefixed with ##
, normal comments need to be prefixed with #
CustomConfigs can be loaded using the handy ConfigLoader (me.mrletsplay.mrcore.config.ConfigLoader) class
FileCustomConfig fileConfig = ConfigLoader.loadFileConfig(myConfigFile); // This will load a FileCustomConfig from the given file
CustomConfig streamConfig = ConfigLoader.loadStreamConfig(anInputStream, true); // This will load a CustomConfig from the given InputStream. This config will not have the #saveToFile() method available
If you're very fancy (or are just using another implementation, such as the BukkitCustomConfig), you can use custom types as well
BukkitCustomConfig aBukkitConfig = ConfigLoader.loadConfigFromFile(new BukkitCustomConfig(configFile), configFile, false);
The false
at the end is for auto-conversion of the config to the newest version. The API is currently not available though and that parameter will most likely be removed in a future update. Just leave it to false
for now.
To load defaults from another CustomConfig instance, you can do something like this:
CustomConfigs myDefaults = // ... load the config from somewhere else
config.addDefaults(myDefaults); // This will add all of the properties in `myDefaults` as defaults to `config`
config.applyDefaults(); // Apply the defaults
The second parameter is set to false
, so it doesn't override the existing properties if they are already set
You can also set each of the default properties manually
config.addDefault("something.my-property", true);
config.addDefault("something.another-property", "Very cool default value");
config.applyDefaults(); // Apply the defaults
getKeys()
returns a list of keys, either from the top layer or from some specific path
Example usage:
config.getKeys();
This will list all the top layer keys, so in a config like this:
abc:
cde: "Something"
xyz: "test"
def:
ghi: "Something else"
it would return [abc, def]
, while
config.getKeys(true, true); // Deep/Recursive & full keys (Full keys is irrelevant in this case because we're on the top layer anyway)
would produce [abc, abc.cde, abc.xyz, def, def.ghi]
Another example:
config.getKeys("abc", false, true);
If run with our config from above, this would produce [abc.cde, abc.xyz]
. The false
in this case is the same as above. If you changed the true
to another false
, it would chop off the abc.
bit.
Note: Bukkit classes that implement ConfigSerializable are not yet handled by the CustomConfig, though that is planned for a future update
Object mappers can be used to save and retrieve complex objects in a CustomConfig.
To use them, you first need to register them to yout ExpandableCustomConfig instance
In this example i'll use a simple class called "SomeClass"
public class SomeClass {
public String someString;
public int someInt;
public SomeClass(String someString, int someInt) {
this.someString = someString;
this.someInt = someInt;
}
}
To register a mapper for this class, you need to call the ExpandableCustomConfig#registerMapper(ObjectMapper) function
ObjectMapper<SomeClass> mapper = new ObjectMapper<SomeClass>() {
@Override
public Map<String, Object> mapObject(SomeClass obj) {
Map<String, Object> map = new HashMap<>();
map.put("some-string", obj.someString);
map.put("some-int", obj.someInt);
return map;
}
@Override
public SomeClass constructObject(Map<String, Object> map) {
if(!requireKeys("some-string", "some-int")) return null; // This is optional, like this the method will return null instead of throwing a InvalidTypeException if a key is missing
String someString = (String) map.get("some-string"); // This can be safely done due to the CustomConfig type specifications
Integer someInt = castGeneric(map.get("some-int"), Integer.class);
return new SomeClass(someString, someInt);
}
}
The ObjectMapper thus needs to define a method to convert the Object into a Map<String, Object> as well as a method to convert it back into an Object instance.
To now save/load objects (or even lists of these objects) in your config you can call
SomeClass obj = new SomeClass("This is some String", 10);
config.set("some-key", obj);
and to retrieve it
SomeClass loadedObj = config.getMappable("some-key", SomeClass.class);
System.out.println(loadedObj.someString + " / " + loadedObj.someInt); // Will give "This is some String / 10"
Or to save/load a list of these Objects
config.set("some-classes", oldSomeClassList);
List<SomeClass> someClassList = config.getMappableList("some-classes");
(The BukkitCustomConfig also extends ExpandableCustomConfig and defines default object mappers for ItemStack and Location)