Skip to content

Commit

Permalink
Migrate to configurate for configs
Browse files Browse the repository at this point in the history
  • Loading branch information
NichtStudioCode committed Jul 24, 2023
1 parent 4d18189 commit b805b3f
Show file tree
Hide file tree
Showing 78 changed files with 1,135 additions and 732 deletions.
3 changes: 2 additions & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ kotlin = "1.9.0"
ktor = "2.3.1"
paper = "1.20.1-R0.1-SNAPSHOT"
paperweight = "1.5.5"
xenondevs-commons = "1.3"
xenondevs-commons = "1.4"

[libraries]
adventure-api = { group = "net.kyori", name = "adventure-api", version = "4.12.0" }
Expand All @@ -23,6 +23,7 @@ commons-collections = { group = "xyz.xenondevs.commons", name = "commons-collect
commons-gson = { group = "xyz.xenondevs.commons", name = "commons-gson", version.ref = "xenondevs-commons" }
commons-provider = { group = "xyz.xenondevs.commons", name = "commons-provider", version.ref = "xenondevs-commons" }
commons-reflection = { group = "xyz.xenondevs.commons", name = "commons-reflection", version.ref = "xenondevs-commons" }
configurate-kotlin = { group = "org.spongepowered", name = "configurate-extra-kotlin", version = "4.1.2"}
cosmic-binary-format = { group = "xyz.xenondevs.cbf", name = "cosmic-binary-format", version.ref = "cbf" }
cosmic-binary-format-netty-adapter = { group = "xyz.xenondevs.cbf", name = "cosmic-binary-format-netty-adapter", version.ref = "cbf" }
fuzzywuzzy = { group = "me.xdrop", name = "fuzzywuzzy", version = "1.4.0" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package xyz.xenondevs.nova.hook.impl.oraxen

import io.th0rgal.oraxen.config.Settings
import io.th0rgal.oraxen.pack.upload.hosts.Polymath
import org.bukkit.configuration.ConfigurationSection
import org.spongepowered.configurate.ConfigurationNode
import xyz.xenondevs.nova.data.resources.upload.UploadService
import xyz.xenondevs.nova.integration.Hook
import java.io.File
Expand All @@ -18,7 +18,7 @@ internal object OraxenUploadService : UploadService {
return polymath.minecraftPackURL
}

override fun loadConfig(cfg: ConfigurationSection) = Unit
override fun loadConfig(cfg: ConfigurationNode) = Unit

override fun disable() = Unit

Expand Down
1 change: 1 addition & 0 deletions nova/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ dependencies {
novaLoaderApi(libs.bundles.cbf)
novaLoaderApi(libs.bundles.xenondevs.commons)
novaLoaderApi(libs.invui.kotlin)
novaLoaderApi(libs.configurate.kotlin)

// internal dependencies
compileOnly(project(":nova-api"))
Expand Down
4 changes: 2 additions & 2 deletions nova/src/main/kotlin/xyz/xenondevs/nova/addon/AddonManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import xyz.xenondevs.nova.LOGGER
import xyz.xenondevs.nova.NOVA
import xyz.xenondevs.nova.addon.loader.AddonLoader
import xyz.xenondevs.nova.addon.loader.LibraryLoaderPools
import xyz.xenondevs.nova.data.config.NovaConfig
import xyz.xenondevs.nova.data.config.Configs
import xyz.xenondevs.nova.initialize.Init
import xyz.xenondevs.nova.initialize.InitFun
import xyz.xenondevs.nova.initialize.InitializableClass
Expand Down Expand Up @@ -74,7 +74,7 @@ internal object AddonsLoader {
*/
@InternalInit(
stage = InternalInitStage.PRE_WORLD,
dependsOn = [NovaConfig::class, Patcher::class]
dependsOn = [Configs::class, Patcher::class]
)
internal object AddonsInitializer {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package xyz.xenondevs.nova.addon.registry

import xyz.xenondevs.commons.provider.immutable.provider
import xyz.xenondevs.nova.data.config.NovaConfig
import xyz.xenondevs.nova.data.config.configReloadable
import xyz.xenondevs.nova.data.config.Configs
import xyz.xenondevs.nova.data.config.entry
import xyz.xenondevs.nova.item.tool.ToolTier
import xyz.xenondevs.nova.registry.HardcodedProperties
import xyz.xenondevs.nova.registry.NovaRegistries
Expand All @@ -14,10 +14,8 @@ interface ToolTierRegistry: AddonGetter {

fun registerToolTier(name: String): ToolTier {
val id = ResourceLocation(addon, name)
val tier = ToolTier(id, configReloadable {
NovaConfig["${id.namespace}:tool_levels"].getDouble(id.name)
})

val tier = ToolTier(id, Configs["${id.namespace}:tool_levels"].entry(id.name))

NovaRegistries.TOOL_TIER[id] = tier
return tier
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import xyz.xenondevs.nova.command.requiresPlayer
import xyz.xenondevs.nova.command.requiresPlayerPermission
import xyz.xenondevs.nova.command.sendFailure
import xyz.xenondevs.nova.command.sendSuccess
import xyz.xenondevs.nova.data.config.NovaConfig
import xyz.xenondevs.nova.data.config.Configs
import xyz.xenondevs.nova.data.recipe.RecipeManager
import xyz.xenondevs.nova.data.resources.ResourceGeneration
import xyz.xenondevs.nova.data.resources.builder.ResourcePackBuilder
Expand Down Expand Up @@ -175,7 +175,7 @@ internal object NovaCommand : Command("nova") {

private fun reloadConfigs(ctx: CommandContext<CommandSourceStack>) {
ctx.source.sendSuccess(Component.translatable("command.nova.reload_configs.start", NamedTextColor.GRAY))
NovaConfig.reload()
Configs.reload()
ctx.source.sendSuccess(Component.translatable("command.nova.reload_configs.success", NamedTextColor.GRAY))
}

Expand Down

This file was deleted.

117 changes: 55 additions & 62 deletions nova/src/main/kotlin/xyz/xenondevs/nova/data/config/ConfigExtractor.kt
Original file line number Diff line number Diff line change
@@ -1,90 +1,83 @@
package xyz.xenondevs.nova.data.config

import org.bukkit.configuration.ConfigurationSection
import org.bukkit.configuration.file.YamlConfiguration
import xyz.xenondevs.commons.collections.contentEquals
import xyz.xenondevs.nova.NOVA
import xyz.xenondevs.nova.util.data.copy
import java.io.ByteArrayInputStream
import java.io.File
import org.spongepowered.configurate.CommentedConfigurationNode
import xyz.xenondevs.nova.util.data.walk
import java.nio.file.Path
import kotlin.io.path.exists

internal object ConfigExtractor {

private val storedConfigs: HashMap<String, YamlConfiguration> = PermanentStorage.retrieve("storedConfigs", ::HashMap)
private val storedConfigs: MutableMap<String, CommentedConfigurationNode> = loadStoredConfigs()

fun extract(configPath: String, data: ByteArray): YamlConfiguration {
val file = File(NOVA.dataFolder, configPath)
val internalCfg = YamlConfiguration.loadConfiguration(ByteArrayInputStream(data).reader())
fun extract(configPath: String, destFile: Path, fileInZip: Path): CommentedConfigurationNode {
val internalCfg = Configs.createLoader(fileInZip).load()
val storedCfg = storedConfigs[configPath]

val cfg: YamlConfiguration
if (!file.exists() || storedCfg == null) {
val loader = Configs.createLoader(destFile)
val cfg: CommentedConfigurationNode
if (!destFile.exists() || storedCfg == null) {
cfg = internalCfg.copy()
storedConfigs[configPath] = internalCfg.copy()
} else cfg = updateExistingConfig(file, storedCfg, internalCfg)

cfg.save(file)
cfg.setDefaults(internalCfg)
} else cfg = updateExistingConfig(loader.load(), storedCfg, internalCfg)

loader.save(cfg)
return cfg
}

private fun updateExistingConfig(file: File, storedCfg: YamlConfiguration, internalCfg: YamlConfiguration): YamlConfiguration {
val cfg = YamlConfiguration.loadConfiguration(file)

// add keys that are new
internalCfg.getKeys(true).filterNot(cfg::isSet).forEach { path ->
val internalValue = internalCfg.get(path)
cfg.set(path, internalValue)
cfg.setComments(path, internalCfg.getComments(path))
cfg.setInlineComments(path, internalCfg.getInlineComments(path))
storedCfg.set(path, internalValue)
private fun updateExistingConfig(
cfg: CommentedConfigurationNode,
storedCfg: CommentedConfigurationNode,
internalCfg: CommentedConfigurationNode
): CommentedConfigurationNode {
internalCfg.walk().forEach { internalNode ->
val path = internalNode.path()
val configuredNode = cfg.node(path)

val internalValue = internalNode.raw()
if (configuredNode.virtual()) {
// add new key
configuredNode.raw(internalValue)
storedCfg.node(path).set(internalValue)
} else {
// update value if unchanged by user
if (internalNode.childrenMap().isNotEmpty()) // update only terminal nodes
return@forEach

val storedNode = storedCfg.node(path)
if (internalNode != configuredNode && storedNode == configuredNode) {
configuredNode.raw(internalValue)
storedNode.raw(internalValue)
}
}

// reset comments
configuredNode.comment(internalNode.comment())
}

// remove keys that were once extracted but are no longer in the internal config
cfg.getKeys(true)
.filter { !internalCfg.isSet(it) && storedCfg.isSet(it) }
.forEach { path ->
cfg.set(path, null)
storedCfg.set(path, null)
}

internalCfg.getKeys(true).forEach { path ->
// reset comments
cfg.setComments(path, internalCfg.getComments(path))
cfg.setInlineComments(path, internalCfg.getInlineComments(path))

// update keys that were unchanged by the user
val internalValue = internalCfg.get(path)
if (internalValue is ConfigurationSection)
return@forEach

val storedValue = storedCfg.get(path)
val configuredValue = cfg.get(path)

if (checkNoUserChanges(internalValue, configuredValue, storedValue)) {
cfg.set(path, internalValue)
storedCfg.set(path, internalValue)
cfg.walk().forEach { node ->
val path = node.path()
if (internalCfg.node(path).virtual() && !storedCfg.node(path).virtual()) {
cfg.removeChild(path)
storedCfg.removeChild(path)
}
}

return cfg
}

/**
* Checks if the [configuredValue] differs from the [internalValue] but was not changed by the user by cross-referencing it with [storedValue].
*/
private fun checkNoUserChanges(internalValue: Any?, configuredValue: Any?, storedValue: Any?): Boolean =
internalValue != configuredValue && checkEquality(storedValue, configuredValue)

/**
* Checks if [value1] and [value2] are equal or if they're lists and have the same content.
*/
private fun checkEquality(value1: Any?, value2: Any?): Boolean =
value1 == value2 || (value1 is List<*> && value2 is List<*> && value1.contentEquals(value2))
private fun loadStoredConfigs(): MutableMap<String, CommentedConfigurationNode> {
return PermanentStorage.retrieve<HashMap<String, String>>("storedConfigs", ::HashMap)
.mapValuesTo(HashMap()) { (_, cfgStr) ->
Configs.createBuilder().buildAndLoadString(cfgStr) as CommentedConfigurationNode
}
}

internal fun saveStoredConfigs() {
PermanentStorage.store("storedConfigs", storedConfigs)
PermanentStorage.store(
"storedConfigs",
storedConfigs.mapValues { (_, cfg) -> Configs.createBuilder().buildAndSaveString(cfg) }
)
}

}
Loading

0 comments on commit b805b3f

Please sign in to comment.