-
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: 1Multiple properties combined under a single "super-property" are called sections
this-is-a-section:
property-one: "Yay!"
property-two: 2Numbers 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.45Strings 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 availableIf 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 defaultsThe 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 defaultsgetKeys() 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)