Skip to content

Commit 6e09127

Browse files
authored
feat: add YmlConfigWrapper for managing YAML configuration files (#169)
2 parents 176919f + 65d54d1 commit 6e09127

File tree

13 files changed

+385
-13
lines changed

13 files changed

+385
-13
lines changed

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled
77
javaVersion=21
88
mcVersion=1.21.10
99
group=dev.slne.surf
10-
version=1.21.10-2.42.4
10+
version=1.21.10-2.43.0
1111
relocationPrefix=dev.slne.surf.surfapi.libs
1212
snapshot=false

surf-api-bukkit/surf-api-bukkit-api/api/surf-api-bukkit-api.api

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5974,11 +5974,36 @@ public final class dev/slne/surf/surfapi/core/api/command/exception/WrapperComma
59745974
public abstract interface annotation class dev/slne/surf/surfapi/core/api/config/JsonConfigFileNamePattern : java/lang/annotation/Annotation {
59755975
}
59765976

5977+
public abstract class dev/slne/surf/surfapi/core/api/config/SpongeConfigClass {
5978+
public synthetic fun <init> (Ljava/lang/Class;Ljava/nio/file/Path;Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
5979+
public final fun edit (ZLkotlin/jvm/functions/Function1;)V
5980+
public static synthetic fun edit$default (Ldev/slne/surf/surfapi/core/api/config/SpongeConfigClass;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
5981+
public final fun getConfig ()Ljava/lang/Object;
5982+
protected final fun getConfigFolder ()Ljava/nio/file/Path;
5983+
protected final fun getFileName ()Ljava/lang/String;
5984+
public abstract fun getManager ()Ldev/slne/surf/surfapi/core/api/config/manager/SpongeConfigManager;
5985+
public final fun init ()V
5986+
public final fun reloadFromFile ()Ljava/lang/Object;
5987+
public final fun save ()V
5988+
}
5989+
5990+
public abstract class dev/slne/surf/surfapi/core/api/config/SpongeJsonConfigClass : dev/slne/surf/surfapi/core/api/config/SpongeConfigClass {
5991+
public fun <init> (Ljava/lang/Class;Ljava/nio/file/Path;Ljava/lang/String;)V
5992+
public fun getManager ()Ldev/slne/surf/surfapi/core/api/config/manager/SpongeConfigManager;
5993+
}
5994+
5995+
public abstract class dev/slne/surf/surfapi/core/api/config/SpongeYmlConfigClass : dev/slne/surf/surfapi/core/api/config/SpongeConfigClass {
5996+
public fun <init> (Ljava/lang/Class;Ljava/nio/file/Path;Ljava/lang/String;)V
5997+
public fun getManager ()Ldev/slne/surf/surfapi/core/api/config/manager/SpongeConfigManager;
5998+
}
5999+
59776000
public abstract interface class dev/slne/surf/surfapi/core/api/config/SurfConfigApi {
59786001
public static final field Companion Ldev/slne/surf/surfapi/core/api/config/SurfConfigApi$Companion;
59796002
public abstract fun createDazzlConfig (Ljava/lang/Class;Ljava/nio/file/Path;Ljava/lang/String;)Ljava/lang/Object;
59806003
public abstract fun createSpongeJsonConfig (Ljava/lang/Class;Ljava/nio/file/Path;Ljava/lang/String;)Ljava/lang/Object;
6004+
public abstract fun createSpongeJsonConfigManager (Ljava/lang/Class;Ljava/nio/file/Path;Ljava/lang/String;)Ldev/slne/surf/surfapi/core/api/config/manager/SpongeConfigManager;
59816005
public abstract fun createSpongeYmlConfig (Ljava/lang/Class;Ljava/nio/file/Path;Ljava/lang/String;)Ljava/lang/Object;
6006+
public abstract fun createSpongeYmlConfigManager (Ljava/lang/Class;Ljava/nio/file/Path;Ljava/lang/String;)Ldev/slne/surf/surfapi/core/api/config/manager/SpongeConfigManager;
59826007
public abstract fun getDazzlConfig (Ljava/lang/Class;)Ljava/lang/Object;
59836008
public abstract fun getSpongeConfig (Ljava/lang/Class;)Ljava/lang/Object;
59846009
public abstract fun getSpongeConfigManagerForConfig (Ljava/lang/Class;)Ldev/slne/surf/surfapi/core/api/config/manager/SpongeConfigManager;
@@ -6034,6 +6059,8 @@ public final class dev/slne/surf/surfapi/core/api/config/manager/SpongeConfigMan
60346059
public static final field Companion Ldev/slne/surf/surfapi/core/api/config/manager/SpongeConfigManager$Companion;
60356060
public field config Ljava/lang/Object;
60366061
public synthetic fun <init> (Ljava/lang/Class;Ljava/lang/Object;Lorg/spongepowered/configurate/loader/ConfigurationLoader;Lorg/spongepowered/configurate/ConfigurationNode;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
6062+
public final fun edit (ZLkotlin/jvm/functions/Function1;)V
6063+
public static synthetic fun edit$default (Ldev/slne/surf/surfapi/core/api/config/manager/SpongeConfigManager;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
60376064
public final fun reloadFromFile ()Ljava/lang/Object;
60386065
public final fun save ()V
60396066
}

surf-api-bukkit/surf-api-bukkit-plugin-test/src/main/java/dev/slne/surf/surfapi/bukkit/test/BukkitPluginMain.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import dev.slne.surf.surfapi.bukkit.test.command.SurfApiTestCommand;
77
import dev.slne.surf.surfapi.bukkit.test.command.subcommands.inventory.TestInventoryView;
88
import dev.slne.surf.surfapi.bukkit.test.command.subcommands.reflection.Reflection;
9+
import dev.slne.surf.surfapi.bukkit.test.config.ModernTestConfig;
910
import dev.slne.surf.surfapi.bukkit.test.listener.ChatListener;
1011
import org.bukkit.plugin.java.JavaPlugin;
1112
import org.jetbrains.annotations.NotNull;
@@ -19,6 +20,9 @@ public class BukkitPluginMain extends JavaPlugin {
1920

2021
@Override
2122
public void onLoad() {
23+
ModernTestConfig.Companion.init();
24+
ModernTestConfig.Companion.randomise();
25+
2226
SurfBukkitPacketListenerApi.Companion.getInstance().registerListeners(new ChatListener());
2327
InventoryFrameworkExtensions.register(TestInventoryView.INSTANCE);
2428
// TestConfig config = SurfCore#Api.getCore()
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package dev.slne.surf.surfapi.bukkit.test.config
2+
3+
import dev.slne.surf.surfapi.bukkit.test.BukkitPluginMain
4+
import dev.slne.surf.surfapi.core.api.config.SpongeYmlConfigClass
5+
import org.spongepowered.configurate.objectmapping.ConfigSerializable
6+
7+
@ConfigSerializable
8+
data class ModernTestConfig(
9+
var message: String = "Hello from Modern Config!",
10+
var number: Int = 42,
11+
var enabled: Boolean = true
12+
) {
13+
companion object : SpongeYmlConfigClass<ModernTestConfig>(
14+
ModernTestConfig::class.java,
15+
BukkitPluginMain.getInstance().dataPath,
16+
"modern-test-config.yml"
17+
) {
18+
fun randomise() = edit {
19+
message = "Random Message ${Math.random()}"
20+
number = (Math.random() * 100).toInt()
21+
enabled = Math.random() > 0.5
22+
}
23+
}
24+
}

surf-api-core/surf-api-core-api/api/surf-api-core-api.api

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,11 +601,36 @@ public final class dev/slne/surf/surfapi/core/api/command/exception/WrapperComma
601601
public abstract interface annotation class dev/slne/surf/surfapi/core/api/config/JsonConfigFileNamePattern : java/lang/annotation/Annotation {
602602
}
603603

604+
public abstract class dev/slne/surf/surfapi/core/api/config/SpongeConfigClass {
605+
public synthetic fun <init> (Ljava/lang/Class;Ljava/nio/file/Path;Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
606+
public final fun edit (ZLkotlin/jvm/functions/Function1;)V
607+
public static synthetic fun edit$default (Ldev/slne/surf/surfapi/core/api/config/SpongeConfigClass;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
608+
public final fun getConfig ()Ljava/lang/Object;
609+
protected final fun getConfigFolder ()Ljava/nio/file/Path;
610+
protected final fun getFileName ()Ljava/lang/String;
611+
public abstract fun getManager ()Ldev/slne/surf/surfapi/core/api/config/manager/SpongeConfigManager;
612+
public final fun init ()V
613+
public final fun reloadFromFile ()Ljava/lang/Object;
614+
public final fun save ()V
615+
}
616+
617+
public abstract class dev/slne/surf/surfapi/core/api/config/SpongeJsonConfigClass : dev/slne/surf/surfapi/core/api/config/SpongeConfigClass {
618+
public fun <init> (Ljava/lang/Class;Ljava/nio/file/Path;Ljava/lang/String;)V
619+
public fun getManager ()Ldev/slne/surf/surfapi/core/api/config/manager/SpongeConfigManager;
620+
}
621+
622+
public abstract class dev/slne/surf/surfapi/core/api/config/SpongeYmlConfigClass : dev/slne/surf/surfapi/core/api/config/SpongeConfigClass {
623+
public fun <init> (Ljava/lang/Class;Ljava/nio/file/Path;Ljava/lang/String;)V
624+
public fun getManager ()Ldev/slne/surf/surfapi/core/api/config/manager/SpongeConfigManager;
625+
}
626+
604627
public abstract interface class dev/slne/surf/surfapi/core/api/config/SurfConfigApi {
605628
public static final field Companion Ldev/slne/surf/surfapi/core/api/config/SurfConfigApi$Companion;
606629
public abstract fun createDazzlConfig (Ljava/lang/Class;Ljava/nio/file/Path;Ljava/lang/String;)Ljava/lang/Object;
607630
public abstract fun createSpongeJsonConfig (Ljava/lang/Class;Ljava/nio/file/Path;Ljava/lang/String;)Ljava/lang/Object;
631+
public abstract fun createSpongeJsonConfigManager (Ljava/lang/Class;Ljava/nio/file/Path;Ljava/lang/String;)Ldev/slne/surf/surfapi/core/api/config/manager/SpongeConfigManager;
608632
public abstract fun createSpongeYmlConfig (Ljava/lang/Class;Ljava/nio/file/Path;Ljava/lang/String;)Ljava/lang/Object;
633+
public abstract fun createSpongeYmlConfigManager (Ljava/lang/Class;Ljava/nio/file/Path;Ljava/lang/String;)Ldev/slne/surf/surfapi/core/api/config/manager/SpongeConfigManager;
609634
public abstract fun getDazzlConfig (Ljava/lang/Class;)Ljava/lang/Object;
610635
public abstract fun getSpongeConfig (Ljava/lang/Class;)Ljava/lang/Object;
611636
public abstract fun getSpongeConfigManagerForConfig (Ljava/lang/Class;)Ldev/slne/surf/surfapi/core/api/config/manager/SpongeConfigManager;
@@ -661,6 +686,8 @@ public final class dev/slne/surf/surfapi/core/api/config/manager/SpongeConfigMan
661686
public static final field Companion Ldev/slne/surf/surfapi/core/api/config/manager/SpongeConfigManager$Companion;
662687
public field config Ljava/lang/Object;
663688
public synthetic fun <init> (Ljava/lang/Class;Ljava/lang/Object;Lorg/spongepowered/configurate/loader/ConfigurationLoader;Lorg/spongepowered/configurate/ConfigurationNode;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
689+
public final fun edit (ZLkotlin/jvm/functions/Function1;)V
690+
public static synthetic fun edit$default (Ldev/slne/surf/surfapi/core/api/config/manager/SpongeConfigManager;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
664691
public final fun reloadFromFile ()Ljava/lang/Object;
665692
public final fun save ()V
666693
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package dev.slne.surf.surfapi.core.api.config
2+
3+
import dev.slne.surf.surfapi.core.api.config.manager.SpongeConfigManager
4+
import java.nio.file.Path
5+
6+
/**
7+
* Base convenience wrapper around a [SpongeConfigManager] for a specific config type [C].
8+
*
9+
* This class is intended to be extended by companion objects of config data classes.
10+
* It provides a simple, type-safe API to:
11+
* - access the current config instance via [getConfig]
12+
* - persist changes via [save]
13+
* - reload the config from disk via [reloadFromFile]
14+
* - perform in-place mutations via [edit]
15+
*
16+
* The actual manager instance is provided by subclasses and typically created by
17+
* a central configuration API (e.g. [surfConfigApi]).
18+
*
19+
* @param C the type of the configuration data object.
20+
* @param configClass the Java class of [C], used by underlying config frameworks
21+
* to create and map configuration instances.
22+
*/
23+
sealed class SpongeConfigClass<C>(
24+
configClass: Class<C>,
25+
/**
26+
* Folder where the configuration file is stored.
27+
*
28+
* Implementations should point this to a plugin- or module-specific config directory.
29+
*/
30+
protected val configFolder: Path,
31+
/**
32+
* The name of the configuration file, including its extension
33+
* (for example `settings.yml` or `settings.json`).
34+
*/
35+
protected val fileName: String
36+
) {
37+
38+
/**
39+
* The underlying configuration manager responsible for loading, saving,
40+
* and tracking the config instance of type [C].
41+
*/
42+
abstract val manager: SpongeConfigManager<C>
43+
44+
/**
45+
* Persists the current configuration to disk.
46+
*
47+
* Delegates to [SpongeConfigManager.save].
48+
*/
49+
fun save() = manager.save()
50+
51+
/**
52+
* Reloads the configuration from disk and replaces the current in-memory instance.
53+
*
54+
* Delegates to [SpongeConfigManager.reloadFromFile].
55+
* Use this when external changes to the config file should be picked up at runtime.
56+
*/
57+
fun reloadFromFile() = manager.reloadFromFile()
58+
59+
/**
60+
* Applies mutations to the current config instance in a safe way.
61+
*
62+
* The [block] receives the current config instance as receiver and can freely
63+
* modify its properties. After the block completes, the config will be saved
64+
* automatically if [save] is `true`.
65+
*
66+
* Example:
67+
* ```kotlin
68+
* MyConfig.edit {
69+
* someField = "new value"
70+
* }
71+
* ```
72+
*
73+
* @param save whether to persist the config to disk after applying [block]. Defaults to `true`.
74+
* @param block mutation block executed on the current config instance.
75+
*/
76+
inline fun edit(save: Boolean = true, block: C.() -> Unit) = manager.edit(save, block)
77+
78+
/**
79+
* Returns the current in-memory configuration instance.
80+
*
81+
* The returned object is managed by the underlying [SpongeConfigManager] and
82+
* will be replaced when [reloadFromFile] is called.
83+
*/
84+
fun getConfig(): C = manager.config
85+
86+
/**
87+
* Dummy initializer to force class loading and companion object initialization.
88+
*
89+
* This is useful in plugin entry points (e.g. `onLoad`) to ensure that:
90+
* - the config manager is constructed
91+
* - the configuration is loaded before first access via [getConfig]
92+
*
93+
* This method is a no-op and can be safely called multiple times.
94+
*/
95+
fun init() = Unit
96+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package dev.slne.surf.surfapi.core.api.config
2+
3+
import java.nio.file.Path
4+
5+
/**
6+
* Convenience base class for JSON-backed Sponge configuration classes.
7+
*
8+
* This class wires the common configuration metadata ([configFolder], [fileName])
9+
* to a JSON-based [dev.slne.surf.surfapi.core.api.config.manager.SpongeConfigManager] instance created by [surfConfigApi].
10+
*
11+
* Typical usage is via a companion object on a `@ConfigSerializable` data class:
12+
* ```kotlin
13+
* @ConfigSerializable
14+
* data class MyJsonConfig(
15+
* var someField: String = "value"
16+
* ) {
17+
* companion object : SpongeJsonConfigClass<MyJsonConfig>(
18+
* MyJsonConfig::class.java,
19+
* Path("config/my-plugin"),
20+
* "my-config.json"
21+
* ) {
22+
* }
23+
* }
24+
* ```
25+
*
26+
* @param C the type of the configuration data object.
27+
* @param configClass the Java class of [C], used by the underlying config framework.
28+
*/
29+
abstract class SpongeJsonConfigClass<C>(
30+
configClass: Class<C>, configFolder: Path, fileName: String
31+
) : SpongeConfigClass<C>(configClass, configFolder, fileName) {
32+
33+
/**
34+
* JSON-backed configuration manager for this config type.
35+
*
36+
* The manager is created using [SurfConfigApi.createSpongeJsonConfigManager]
37+
* with [configClass], [configFolder] and [fileName].
38+
*/
39+
override val manager =
40+
surfConfigApi.createSpongeJsonConfigManager(configClass, configFolder, fileName)
41+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package dev.slne.surf.surfapi.core.api.config
2+
3+
import java.nio.file.Path
4+
5+
/**
6+
* Convenience base class for YAML-backed Sponge configuration classes.
7+
*
8+
* This class wires the common configuration metadata ([configFolder], [fileName])
9+
* to a YAML-based [dev.slne.surf.surfapi.core.api.config.manager.SpongeConfigManager] instance created by [surfConfigApi].
10+
*
11+
* Typical usage is via a companion object on a `@ConfigSerializable` data class:
12+
* ```kotlin
13+
* @ConfigSerializable
14+
* data class MyConfig(
15+
* var someField: String = "value"
16+
* ) {
17+
* companion object : SpongeYmlConfigClass<MyConfig>(
18+
* MyConfig::class.java,
19+
* Path("config/my-plugin"),
20+
* "my-config.yml"
21+
* ) {
22+
* }
23+
* }
24+
* ```
25+
*
26+
* @param C the type of the configuration data object.
27+
* @param configClass the Java class of [C], used by the underlying config framework.
28+
*/
29+
abstract class SpongeYmlConfigClass<C>(
30+
configClass: Class<C>, configFolder: Path, fileName: String
31+
) : SpongeConfigClass<C>(configClass, configFolder, fileName) {
32+
33+
/**
34+
* YAML-backed configuration manager for this config type.
35+
*
36+
* The manager is created using [SurfConfigApi.createSpongeYmlConfigManager]
37+
* with [configClass], [configFolder] and [fileName].
38+
*/
39+
override val manager =
40+
surfConfigApi.createSpongeYmlConfigManager(configClass, configFolder, fileName)
41+
}

0 commit comments

Comments
 (0)