Advanced Entry Types
Besides Basic Entry Types, Simple Config provide a few useful composite entry types you can build on top.
- Lists
- Sets
- Maps
- Pair Lists (non-unique maps)
- Pairs & Triples
- Bean Entries (Java) / Data Class Entries (Kotlin)
- Captioned Entries
Additionally, you may be interested in how you could define your own Custom Entry Types.
Lists are the most simple composite type. In Simple Config, list entries can contain any other entry type, including other lists.
-
list(entry)
creates a list of the type passed asentry
, and defaults to an empty list -
list(entry, defaultValue)
likewise, but with an explicit default value
Players will be able to easily insert/delete/drag list elements around.
For example, to create a list of colors, defaulting to [Color.RED, Color.GREEN, Color.BLUE]
you could use list(color(Color.GRAY), asList(Color.RED, Color.GREEN, Color.BLUE))
. New elements added to the list will default to Color.GRAY
, as specified for the inner entry.
As another example, to create a list of lists of sliders between 0 and 1, you could use list(list(number(0F).range(0, 10).slider(), asList(0F, 1F)), asList(asList(0F, 0.1F), asList(0.2F, 0.3F)))
. In this case, there are multiple default values. The outer is the default value for the entry itself, the second is the default value for new lists added to the entry, and the first is the default value for sliders added to inner lists.
There are also some legacy type-specific list types, but you should always prefer general lists
stringList(defaultValue)
byteList(defaultValue)
shortList(defaultValue)
intList(defaultValue)
longList(defaultValue)
floatList(defaultValue)
doubleList(defaultValue)
These type-specific list types won't let you modify the internal entries to your liking, as you could with general lists, for instance, to limit string width as in list(string("").maxLength(20), asList("a", "b", "c"))
, so you're encouraged to always use general lists.
Set entries are identical to list entries, just using sets. This means the order is not necessarily preserved, and entries cannot be duplicated.
-
set(entry)
creates a set of the type passed asentry
, and defaults to an empty set -
set(entry, defaultValue)
likewise, but with an explicit default value
Unlike with lists, there are no legacy type-specific set entries, for the better.
Map entries depend on two types of entries, key entries and value entries. They represent a map from the key entries' type to the value entries' one.
-
map(keyEntry, valueEntry)
creates a map from the type ofkeyEntry
tovalueEntry
, and defaults to an empty map -
map(keyEntry, valueEntry, defaultValue)
likewise, but with an explicit default value -
map(entry)
defaults tostring("")
keys, and an empty default value -
map(entry, defaultValue)
defaults tostring("")
keys, with an explicit default value
Maps have an additional restriction on key entry types, they must implement AtomicEntryBuilder
. This only excludes other collection types, that is, you cannot use lists/sets/maps/pair lists as keys in map entries, since there'd be no easy way to display this in a graphical interface. This limitation doesn't apply to value entry types, for example, you can create nested maps.
By default, maps do not necessarily preserve their order, but you may request that they do by using the linked
method on them, so they use LinkedHashMap
s instead and serialize to YAML sorted maps.
Pair lists are exactly like maps, but allowing duplicate keys, and preserving their order. They have as type List<Pair<K, V>>
.
-
pairList(keyEntry, valueEntry)
creates a pair list with types ofkeyEntry
andvalueEntry
, and defaults to an empty list -
pairList(keyEntry, valueEntry, defaultValue)
likewise, but with an explicit default value
As in maps, key entry types must implement AtomicEntryBuilder
, that is, they can't be collection entries.
Another form of composite type are pair and triple entries:
-
pair(left, right)
creates a pair entry with the types ofleft
andright
, and defaults to a pair of the default values of these entries -
pair(left, right, defaultValue)
likewise, but with an explicit default value -
triple(left, middle, right)
creates a triple entry with the types ofleft
,middle
andright
, and defaults to a triple of their defaults -
triple(left, middle, right, defaultValue)
likewise, but with an explicit default value
As with maps, all inner entry types must implement AtomicEntryBuilder
, so pairs or triples cannot contain collection types.
The Pair
and Triple
classes used are from the org.apache.commons.lang3.tuple
package, although the Kotlin API does some effort to translate them to Kotlin types under the hood, when used from Kotlin.
If you're using Kotlin, see data class entries
Bean entries let you create your own compound groups of entries. This is specially powerful if you use them inside collection entries, such as lists/maps of beans. To define a bean entry, use the bean
factory method:
-
bean(defaultValue)
creates a bean entry
However, you'll now need to use the add
methods of the returned builder to map bean properties to entries. This behaves just as if you were defining a config group.
If you're using Java, see bean entries
Data class entries let you create your own compound groups of entries. This is specially powerful if you use them inside collection entries, such as lists/maps of data class entries. To define a data class entry, use the data
factory method:
-
data(defaultValue, binding)
create a data class entry with the given default value and applying thebinding
lambda to configure the entries
Inside the binding
lambda, you'll need to call the bind
method (until Kotlin supports multiple context receivers), inside which you can bind property references from your data class to entry builders. For example, you could have
data class Data(val name: String, val age: Int)
val data = data(Data("Steve", 20)) { bind {
::name caption string()
::age by number()
}}
This is safer than bean entries, as you cannot misspell or bind the wrong entry type to data class properties.
It is possible to attach a caption entry to all collection (list/set/map/pair list) and bean/data class entries, by using the caption
factory method, or the caption
method of bean/data class entry builders.
Caption entries are displayed in the title of the host entry, to make use of the physical space left. As such, they need to implement the AtomicEntryBuilder
interface.
In collection entries, attaching a caption to the entry will produce an entry of type Pair<CaptionType, EntryType>
where CaptionType
is the type of the entry added as caption, and EntryType
is the type of the original entry.
In the Java API, it's possible to define separate backing fields for the caption and the collection entry, by using the captionField
/collectionField
methods of the entry builder. With the Kotlin API, you can simply define a baked
property for them instead.
For bean/data class entries, the caption entry is just one more of the subentries, and it'll be bound with the property you provide to the caption
method.
This is only intended for entries for which there's a natural meaning for the caption entry, such as a master volume slider as the caption of a map of volume sliders, or the name/ID of a bean entry. Do not abuse it in situations where players will have doubts of what the caption does.
If you have any doubts, feel free to drop by the official Discord Server.