-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add YmlConfigWrapper for managing YAML configuration files #169
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
a9fbf6c
a2c6024
19911ab
0ec3503
7a43d27
679b6f1
9078904
d092db0
8c1506f
e099e77
c7f04d8
83b47b1
65d54d1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| package dev.slne.surf.surfapi.bukkit.test.config | ||
|
|
||
| import dev.slne.surf.surfapi.bukkit.test.BukkitPluginMain | ||
| import dev.slne.surf.surfapi.core.api.config.SpongeYmlConfigClass | ||
| import org.spongepowered.configurate.objectmapping.ConfigSerializable | ||
|
|
||
| @ConfigSerializable | ||
| data class ModernTestConfig( | ||
| var message: String = "Hello from Modern Config!", | ||
| var number: Int = 42, | ||
| var enabled: Boolean = true | ||
| ) { | ||
| companion object : SpongeYmlConfigClass<ModernTestConfig>( | ||
| ModernTestConfig::class.java, | ||
| BukkitPluginMain.getInstance().dataPath, | ||
| "modern-test-config.yml" | ||
| ) { | ||
| fun randomise() = edit { | ||
| message = "Random Message ${Math.random()}" | ||
| number = (Math.random() * 100).toInt() | ||
| enabled = Math.random() > 0.5 | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| package dev.slne.surf.surfapi.core.api.config | ||
|
|
||
| import dev.slne.surf.surfapi.core.api.config.manager.SpongeConfigManager | ||
| import java.nio.file.Path | ||
|
|
||
| /** | ||
| * Base convenience wrapper around a [SpongeConfigManager] for a specific config type [C]. | ||
| * | ||
| * This class is intended to be extended by companion objects of config data classes. | ||
| * It provides a simple, type-safe API to: | ||
| * - access the current config instance via [getConfig] | ||
| * - persist changes via [save] | ||
| * - reload the config from disk via [reloadFromFile] | ||
| * - perform in-place mutations via [edit] | ||
| * | ||
| * The actual manager instance is provided by subclasses and typically created by | ||
| * a central configuration API (e.g. [surfConfigApi]). | ||
| * | ||
| * @param C the type of the configuration data object. | ||
| * @param configClass the Java class of [C], used by underlying config frameworks | ||
| * to create and map configuration instances. | ||
| */ | ||
| sealed class SpongeConfigClass<C>( | ||
| configClass: Class<C>, | ||
| /** | ||
| * Folder where the configuration file is stored. | ||
| * | ||
| * Implementations should point this to a plugin- or module-specific config directory. | ||
| */ | ||
| protected val configFolder: Path, | ||
| /** | ||
| * The name of the configuration file, including its extension | ||
| * (for example `settings.yml` or `settings.json`). | ||
| */ | ||
| protected val fileName: String | ||
| ) { | ||
|
|
||
| /** | ||
| * The underlying configuration manager responsible for loading, saving, | ||
| * and tracking the config instance of type [C]. | ||
| */ | ||
| abstract val manager: SpongeConfigManager<C> | ||
|
|
||
| /** | ||
| * Persists the current configuration to disk. | ||
| * | ||
| * Delegates to [SpongeConfigManager.save]. | ||
| */ | ||
| fun save() = manager.save() | ||
|
|
||
| /** | ||
| * Reloads the configuration from disk and replaces the current in-memory instance. | ||
| * | ||
| * Delegates to [SpongeConfigManager.reloadFromFile]. | ||
| * Use this when external changes to the config file should be picked up at runtime. | ||
| */ | ||
| fun reloadFromFile() = manager.reloadFromFile() | ||
|
|
||
| /** | ||
| * Applies mutations to the current config instance in a safe way. | ||
| * | ||
| * The [block] receives the current config instance as receiver and can freely | ||
| * modify its properties. After the block completes, the config will be saved | ||
| * automatically if [save] is `true`. | ||
| * | ||
| * Example: | ||
| * ```kotlin | ||
| * MyConfig.edit { | ||
| * someField = "new value" | ||
| * } | ||
| * ``` | ||
| * | ||
| * @param save whether to persist the config to disk after applying [block]. Defaults to `true`. | ||
| * @param block mutation block executed on the current config instance. | ||
| */ | ||
| inline fun edit(save: Boolean = true, block: C.() -> Unit) = manager.edit(save, block) | ||
|
|
||
| /** | ||
| * Returns the current in-memory configuration instance. | ||
| * | ||
| * The returned object is managed by the underlying [SpongeConfigManager] and | ||
| * will be replaced when [reloadFromFile] is called. | ||
| */ | ||
| fun getConfig(): C = manager.config | ||
|
|
||
| /** | ||
| * Dummy initializer to force class loading and companion object initialization. | ||
| * | ||
| * This is useful in plugin entry points (e.g. `onLoad`) to ensure that: | ||
| * - the config manager is constructed | ||
| * - the configuration is loaded before first access via [getConfig] | ||
| * | ||
| * This method is a no-op and can be safely called multiple times. | ||
| */ | ||
| fun init() = Unit | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| package dev.slne.surf.surfapi.core.api.config | ||
|
|
||
| import java.nio.file.Path | ||
|
|
||
| /** | ||
| * Convenience base class for JSON-backed Sponge configuration classes. | ||
| * | ||
| * This class wires the common configuration metadata ([configFolder], [fileName]) | ||
| * to a JSON-based [dev.slne.surf.surfapi.core.api.config.manager.SpongeConfigManager] instance created by [surfConfigApi]. | ||
| * | ||
| * Typical usage is via a companion object on a `@ConfigSerializable` data class: | ||
| * ```kotlin | ||
| * @ConfigSerializable | ||
| * data class MyJsonConfig( | ||
| * var someField: String = "value" | ||
| * ) { | ||
| * companion object : SpongeJsonConfigClass<MyJsonConfig>( | ||
| * MyJsonConfig::class.java, | ||
| * Path("config/my-plugin"), | ||
| * "my-config.json" | ||
| * ) { | ||
| * } | ||
| * } | ||
| * ``` | ||
| * | ||
| * @param C the type of the configuration data object. | ||
| * @param configClass the Java class of [C], used by the underlying config framework. | ||
| */ | ||
| abstract class SpongeJsonConfigClass<C>( | ||
| configClass: Class<C>, configFolder: Path, fileName: String | ||
| ) : SpongeConfigClass<C>(configClass, configFolder, fileName) { | ||
|
|
||
| /** | ||
| * JSON-backed configuration manager for this config type. | ||
| * | ||
| * The manager is created using [SurfConfigApi.createSpongeJsonConfigManager] | ||
| * with [configClass], [configFolder] and [fileName]. | ||
| */ | ||
| override val manager = | ||
| surfConfigApi.createSpongeJsonConfigManager(configClass, configFolder, fileName) | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,41 @@ | ||||||||||||
| package dev.slne.surf.surfapi.core.api.config | ||||||||||||
|
|
||||||||||||
| import java.nio.file.Path | ||||||||||||
|
|
||||||||||||
| /** | ||||||||||||
| * Convenience base class for YAML-backed Sponge configuration classes. | ||||||||||||
| * | ||||||||||||
| * This class wires the common configuration metadata ([configFolder], [fileName]) | ||||||||||||
| * to a YAML-based [dev.slne.surf.surfapi.core.api.config.manager.SpongeConfigManager] instance created by [surfConfigApi]. | ||||||||||||
| * | ||||||||||||
| * Typical usage is via a companion object on a `@ConfigSerializable` data class: | ||||||||||||
| * ```kotlin | ||||||||||||
| * @ConfigSerializable | ||||||||||||
| * data class MyConfig( | ||||||||||||
| * var someField: String = "value" | ||||||||||||
| * ) { | ||||||||||||
| * companion object : SpongeYmlConfigClass<MyConfig>( | ||||||||||||
| * MyConfig::class.java, | ||||||||||||
| * Path("config/my-plugin"), | ||||||||||||
| * "my-config.yml" | ||||||||||||
| * ) { | ||||||||||||
| * } | ||||||||||||
| * } | ||||||||||||
| * ``` | ||||||||||||
| * | ||||||||||||
| * @param C the type of the configuration data object. | ||||||||||||
| * @param configClass the Java class of [C], used by the underlying config framework. | ||||||||||||
| */ | ||||||||||||
| abstract class SpongeYmlConfigClass<C>( | ||||||||||||
| configClass: Class<C>, configFolder: Path, fileName: String | ||||||||||||
| ) : SpongeConfigClass<C>(configClass, configFolder, fileName) { | ||||||||||||
|
|
||||||||||||
| /** | ||||||||||||
| * YAML-backed configuration manager for this config type. | ||||||||||||
| * | ||||||||||||
| * The manager is created using [SurfConfigApi.createSpongeYmlConfigManager] | ||||||||||||
| * with [configClass], [configFolder] and [fileName]. | ||||||||||||
| */ | ||||||||||||
| override val manager = | ||||||||||||
| surfConfigApi.createSpongeYmlConfigManager(configClass, configFolder, fileName) | ||||||||||||
|
Comment on lines
+39
to
+40
|
||||||||||||
| override val manager = | |
| surfConfigApi.createSpongeYmlConfigManager(configClass, configFolder, fileName) | |
| override val manager by lazy { | |
| surfConfigApi.createSpongeYmlConfigManager(configClass, configFolder, fileName) | |
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Property initialization order issue:
manageris initialized before subclass properties. Themanagerproperty initialization accessesconfigFolderandfileName, which are abstract properties that won't be initialized until after the superclass constructor completes. This will cause a runtime error.Consider making
managera lazy property or use a different initialization pattern: