@@ -8,18 +8,28 @@ import dev.slne.surf.api.core.config.migration.ConfigMigration
88import dev.slne.surf.api.core.config.migration.ConfigMigrationBuilder
99import dev.slne.surf.api.core.config.serializer.surfSpongeConfigSerializers
1010import dev.slne.surf.api.core.util.logger
11+ import io.leangen.geantyref.GenericTypeReflector
12+ import org.spongepowered.configurate.CommentedConfigurationNodeIntermediary
1113import org.spongepowered.configurate.ConfigurateException
1214import org.spongepowered.configurate.ConfigurationNode
1315import org.spongepowered.configurate.ScopedConfigurationNode
1416import org.spongepowered.configurate.jackson.JacksonConfigurationLoader
17+ import org.spongepowered.configurate.kotlin.dataClassFieldDiscoverer
1518import org.spongepowered.configurate.loader.AbstractConfigurationLoader
1619import org.spongepowered.configurate.loader.ConfigurationLoader
20+ import org.spongepowered.configurate.objectmapping.ObjectMapper
21+ import org.spongepowered.configurate.objectmapping.meta.Constraint
22+ import org.spongepowered.configurate.objectmapping.meta.NodeResolver
1723import org.spongepowered.configurate.serialize.SerializationException
24+ import org.spongepowered.configurate.serialize.TypeSerializerCollection
1825import org.spongepowered.configurate.yaml.NodeStyle
1926import org.spongepowered.configurate.yaml.YamlConfigurationLoader
2027import java.io.Serial
2128import java.io.UncheckedIOException
2229import java.nio.file.Path
30+ import java.text.MessageFormat
31+ import java.util.*
32+ import java.util.regex.Pattern
2333
2434/* *
2535 * Manages configurations using Sponge's Configurate library, including loading, saving, and reloading configurations.
@@ -186,7 +196,7 @@ class SpongeConfigManager<C> private constructor(
186196 migrations : ConfigMigrationBuilder = ConfigMigrationBuilder ()
187197 ): SpongeConfigManager <C > = buildConfigManager(
188198 " https://yamlchecker.com/" ,
189- YamlConfigurationLoader .builder().nodeStyle(NodeStyle .BLOCK ),
199+ YamlConfigurationLoader .builder().nodeStyle(NodeStyle .BLOCK ).commentsEnabled( true ) ,
190200 configClass,
191201 configFolder,
192202 configFileName,
@@ -229,8 +239,16 @@ class SpongeConfigManager<C> private constructor(
229239 ): SpongeConfigManager <C > {
230240 val loader = builder.path(configFolder.resolve(configFileName))
231241 .defaultOptions {
232- it.serializers(surfSpongeConfigSerializers.buildSerializersModule())
233- .shouldCopyDefaults(true )
242+ it.serializers { serializers ->
243+ surfSpongeConfigSerializers.buildSerializersModule().accept(serializers)
244+
245+ try {
246+ OldSpongeReflections .OLD_CONFIG_SERIALIZABLE_ANNOTATION // If this throws an exception, there are no non-relocated annotations, no need to register — most likely the standalone version
247+ serializers.registerBackwardsCompatibleSerializers()
248+ } catch (_: Throwable ) {
249+ // no non-relocated annotations, no need to register
250+ }
251+ }.shouldCopyDefaults(true )
234252 }
235253 .build()
236254
@@ -268,6 +286,75 @@ class SpongeConfigManager<C> private constructor(
268286 throw LoadConfigException (e)
269287 }
270288 }
289+
290+ private fun TypeSerializerCollection.Builder.registerBackwardsCompatibleSerializers () {
291+ register(
292+ { type ->
293+ GenericTypeReflector .annotate(type)
294+ .isAnnotationPresent(OldSpongeReflections .OLD_CONFIG_SERIALIZABLE_ANNOTATION )
295+ },
296+ ObjectMapper .factoryBuilder()
297+ .addDiscoverer(dataClassFieldDiscoverer())
298+ .addProcessor(OldSpongeReflections .OLD_COMMENT_ANNOTATION ) { data, _ ->
299+ { _, destination ->
300+ if (destination is CommentedConfigurationNodeIntermediary <* >) {
301+ if (OldSpongeReflections .isCommentOverride(data)) {
302+ destination.comment(OldSpongeReflections .getCommentValue(data))
303+ } else {
304+ destination.commentIfAbsent(OldSpongeReflections .getCommentValue(data))
305+ }
306+ }
307+ }
308+ }
309+ .addConstraint(
310+ OldSpongeReflections .OLD_MATCHES_ANNOTATION ,
311+ String ::class .java
312+ ) { data, _ ->
313+ val value = OldSpongeReflections .getMatchesValue(data)
314+ val flags = OldSpongeReflections .getMatchesFlags(data)
315+ val failureMessage = OldSpongeReflections .getMatchesFailureMessage(data)
316+
317+ val test = Pattern .compile(value, flags)
318+ val format = MessageFormat (failureMessage, Locale .getDefault())
319+
320+ Constraint { toValidate ->
321+ if (toValidate != null ) {
322+ val match = test.matcher(toValidate)
323+ if (! match.matches()) {
324+ throw SerializationException (format.format(arrayOf(toValidate, value)))
325+ }
326+ }
327+ }
328+ }
329+ .addConstraint(OldSpongeReflections .OLD_REQUIRED_ANNOTATION , Constraint .required())
330+ .addNodeResolver(fun (name, element): NodeResolver ? {
331+ if (element.isAnnotationPresent(OldSpongeReflections .OLD_SETTING_ANNOTATION )) {
332+ val annotation =
333+ element.getAnnotation(OldSpongeReflections .OLD_SETTING_ANNOTATION )
334+ val key = OldSpongeReflections .getSettingValue(annotation)
335+ if (key.isNotEmpty()) {
336+ return { node -> node.node(key) }
337+ }
338+ }
339+
340+ return null
341+ })
342+ .addNodeResolver(fun (name, element): NodeResolver ? {
343+ if (element.isAnnotationPresent(OldSpongeReflections .OLD_SETTING_ANNOTATION )) {
344+ val annotation =
345+ element.getAnnotation(OldSpongeReflections .OLD_SETTING_ANNOTATION )
346+ val nodeFromParent = OldSpongeReflections .isSettingNodeFromParent(annotation)
347+ if (nodeFromParent) {
348+ return { node -> node }
349+ }
350+ }
351+
352+ return null
353+ })
354+ .build()
355+ .asTypeSerializer()
356+ )
357+ }
271358 }
272359}
273360
0 commit comments