Configs¶
Nova uses YAML as its configuration format, reading it via kotlinx.serialization.
Configs are read as JSON
Nova converts YAML to JSON internally, then uses kotlinx.serialization for deserialization. This is because kotlinx.serialization does not support YAML natively. Additionally, this allows you to use JSON-specific serializers like JsonTransformingSerializer. The config files themselves stay in YAML format.
Config Extraction¶
Nova will automatically extract all YAML files from resources/configs/ on startup to plugins/<addon name>/configs/<name>.yml, preserving the capitalization of the addon name. New or changed keys will automatically be added / updated on the server as well, unless they have been modified on the server.
Accessing Configs¶
You can access a config in two ways:
CONFIGS["<namespace>:<name>"]:plugins/<addon name>/configs/<name>.yml(extracted fromresources/configs/<name>.yml)
ItemType.config/BlockType.config:- By default, this is the same as
CONFIGS["<namespace>:<name>"], but a custom config path can be set in the item/block builder.
- By default, this is the same as
Ultimately, the type you'll get is ConfigProvider1, which is a Provider<JsonElement> with additional functions like entry and optionalEntry that you can use like this:
val exampleValue1: Int by Items.EXAMPLE_ITEM.config.entry<Int>(1, "example_value") // (1)!
val exampleValue2: Int? by Items.EXAMPLE_ITEM.config.optionalEntry<Int>("optional_value") // (2)!
- Delegating to the
Provider<Int>will cause this field automatically change every time the config is reloaded. - Using
ConfigProvider#optionalEntry, you can get aProvider<Int?>, where the value is null if the key is not present in the config.
Built-In Serializers¶
Nova offers lots of built-in serializers under xyz.xenondevs.nova.serialization.kotlinx. Most notably, this covers all registry-related types such as ItemType, RegistryEntry.Paper<ItemType>, RegistryEntrySet.Paper<ItemType>, and more.
Prefer Nova's registry types
Prefer using Nova's RegistryEntry.Paper<T> over T and RegistryEntrySet.Paper<T> over RegistryKeySet<T>. Nova's types can be deserialized during bootstrap phase, Paper's types cannot.
Nova also ships with serializable type aliases to reduce verbosity:
@Serializable
data class ItemsMenuTab(
val icon: ItemTypeEntry /*(1)!*/ = ItemTypeEntries.AIR,
val name: ComponentAsMiniMessage /*(2)!*/ = Component.empty(),
val description: ValueOrList<ComponentAsMiniMessage> /*(3)!*/ = emptyList(),
val items: ItemTypeEntrySet /*(4)!*/ = emptyRegistryEntrySet(RegistryKey.ITEM)
)
@Serializable(ItemTypeEntrySerializer::class) RegistryEntry.Paper<ItemType>@Serializable(ComponentAsMiniMessageSerializer::class) Component@Serializable(ValueOrListSerializer::class) List<@Serializable(ComponentAsMiniMessageSerializer::class) Component>@Serializable(ItemTypeEntrySetSerializer::class) RegistryEntrySet.Paper<ItemType>
Custom Serializers¶
Nova's config system uses kotlinx.serialization, so every @Serializable can immediately be used as a config value. You can also register additional serializers SerializersModule via CONFIGS.setSerializers(addon, serializersModule).
Limitations of SerializersModules
Due to the nature of kotlinx.serialization, your custom serializers are only queried for the immediate type requested by ConfigProvider.entry<T>(...) (or for properties annotated with @Contextual). For serializable classes, prefer annotating the relevant properties with @Serializable(with = SerializerClass::class) directly instead of relying on the SerializersModule to provide the serializer (see code example above).
-
Or
Provider<ConfigProvider>if you got it from e.g.ItemType.config, because registry reloading could change the config path. This should not matter to you though, since there are equivalent extension functions forProvider<ConfigProvider>. ↩