package fr.username404.snowygui.config import com.typesafe.config.* import com.typesafe.config.ConfigFactory.* import fr.username404.snowygui.ClickGui import fr.username404.snowygui.Snowy import fr.username404.snowygui.gui.elements.ClickBox import fr.username404.snowygui.gui.feature.Category import fr.username404.snowygui.gui.feature.Macro import fr.username404.snowygui.gui.feature.riskyCheatsEnabled import io.github.config4k.extract import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import kotlinx.serialization.decodeFromString import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json import net.minecraft.client.Minecraft import java.io.File import java.util.function.Supplier object Configuration { val ModifiableValues = mutableMapOf>( "enabledFeatures" to Supplier { ConfigValueFactory.fromMap(enabledFeatures) }, "riskyCheats" to Supplier { ConfigValueFactory.fromAnyRef(riskyCheatsEnabled) }, "macros" to Supplier { ConfigValueFactory.fromIterable((ClickGui.components.find { it is ClickBox && it.isCategory(Category.MACROS) } as ClickBox).buttons.map { Json.encodeToString(it as Macro) }) } ); inline fun setConfigValue(s: String, crossinline value: () -> Any) = ModifiableValues.put(s, Supplier { ConfigValueFactory.fromAnyRef(value.invoke()) }) private fun Config.withFullModifiableValues() = ModifiableValues.entries.fold(this) { previous, entry -> previous.withValue(entry.key, entry.value.get()) } private val configDirectory: String = (Minecraft.getInstance().gameDirectory.absolutePath + File.separator + "config").also { File(it).mkdir() } private val file: File = File(configDirectory + File.separator + "snowy.conf") private suspend fun writeConfig(c: Config) = coroutineScope { launch { file.writeText( """ |Snowy { |${ c.root().render( ConfigRenderOptions.defaults() .setFormatted(true) .setJson(false) .setOriginComments(false) ).prependIndent(" ").trimEnd() } |} """.trimMargin() ) } } val obtained: Config by lazy { var result: Config = empty() with(file) { if (!exists()) { createNewFile() setWritable(true) setReadable(true) } else try { result = parseFile(file) } catch (e: ConfigException) { Snowy.logs.warn("Could not parse the snowy configuration file, the default configuration will be used instead.") } } load(result).withFallback( parseString( """ |Snowy { | displayInitMessage = false | macros = [] | riskyCheats = false |} """.trimMargin() ) ).extract("Snowy") }.also { runBlocking { writeConfig(it.value) } } val enabledFeatures = mutableMapOf().apply { if (obtained.hasPath("enabledFeatures")) { putAll(obtained.extract("enabledFeatures")) } } val foundMacros: Set = run { obtained.getStringList("macros").map { Json.decodeFromString(it) }.toSet() } init { Runtime.getRuntime().addShutdownHook( Thread { runBlocking { ClickGui.boxContext { enabledFeatures.putAll( buttons.map { it.run { title to toggled } } ) } writeConfig(obtained.withFullModifiableValues()).join() } } ) } }