Skip to content

CustomConfig

MrLetsplay edited this page Aug 10, 2020 · 24 revisions

This page is currently outdated and needs updating

For users

Properties

Normal properties

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 & Booleans

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

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

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

Complex objects & Lists of them

// TODO

Comments

The header comment (at the very top of the config) has to be prefixed with ## , normal comments need to be prefixed with #

For developers

Setting up the CustomConfig

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.

Adding defaults

1. Using another CustomConfig instance

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

2. Setting defaults manually

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

Other features

getKeys()

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.

OUTDATED CONTENT AHEAD

The section below needs to be updated

Object Mappers (me.mrletsplay.mrcore.config.mapper.ObjectMapper)

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)