From 4a952c82ee6d66cea86ce13fd28b7fe5559afc43 Mon Sep 17 00:00:00 2001 From: nikky Date: Sun, 31 Jan 2021 21:25:52 +0100 Subject: [PATCH] restructure json5 input format --- .../data/components/ComponentsMutable.kt | 6 +- .../kotlin/voodoo/data/components/Parts.kt | 12 +- docs/quickstart.md | 104 ++-- samples/config.json5 | 111 ++-- samples/fabricpack/152Version.voodoo.json5 | 120 ++-- samples/fabricpack/164Version.voodoo.json5 | 82 +-- samples/fabricpack/lock/0.0.3/lock.pack.json | 5 +- samples/fabricpack/old_0.0.1.voodoo.json5 | 113 ++-- samples/forgePack/v0.0.1.voodoo.json5 | 29 +- .../main/kotlin/voodoo/TestSerialization.kt | 2 +- .../voodoo/cli/GenerateSchemaCommand.kt | 2 +- .../kotlin/voodoo/cli/ImportCurseCommand.kt | 20 +- .../kotlin/voodoo/cli/init/InitPackCommand.kt | 2 +- .../kotlin/voodoo/config/Configuration.kt | 10 +- .../main/kotlin/voodoo/config/Extensions.kt | 21 +- .../main/kotlin/voodoo/pack/EntryOverride.kt | 107 +++- .../src/main/kotlin/voodoo/pack/FileEntry.kt | 512 +++++++++++++----- .../main/kotlin/voodoo/pack/VersionPack.kt | 88 +-- 18 files changed, 807 insertions(+), 539 deletions(-) diff --git a/core/src/main/kotlin/voodoo/data/components/ComponentsMutable.kt b/core/src/main/kotlin/voodoo/data/components/ComponentsMutable.kt index 83191a3d..c258505a 100644 --- a/core/src/main/kotlin/voodoo/data/components/ComponentsMutable.kt +++ b/core/src/main/kotlin/voodoo/data/components/ComponentsMutable.kt @@ -34,7 +34,11 @@ data class CommonComponent( override var validMcVersions: Set = setOf(), override var invalidMcVersions: Set = setOf(), override var enabled: Boolean = true -) : CommonMutable +) : CommonMutable { + companion object { + val DEFAULT = CommonComponent() + } +} @Serializable data class CurseComponent( diff --git a/core/src/main/kotlin/voodoo/data/components/Parts.kt b/core/src/main/kotlin/voodoo/data/components/Parts.kt index d81e37ee..29e80e88 100644 --- a/core/src/main/kotlin/voodoo/data/components/Parts.kt +++ b/core/src/main/kotlin/voodoo/data/components/Parts.kt @@ -1,6 +1,5 @@ package voodoo.data.components -import kotlinx.serialization.Transient import voodoo.data.DependencyType import voodoo.data.OptionalData import voodoo.data.Side @@ -8,7 +7,6 @@ import voodoo.data.curse.FileID import voodoo.data.curse.FileType import voodoo.data.curse.PackageType import voodoo.data.curse.ProjectID -import voodoo.data.nested.NestedEntry import voodoo.data.provider.UpdateChannel interface Common { @@ -51,14 +49,16 @@ interface CommonMutable : CommonImmutable { override var invalidMcVersions: Set override var enabled: Boolean +/* /** * utility function to configure optionalData */ - fun optional(configureOptional: OptionalData.() -> Unit) { - val optionalData = optionalData?.copy() ?: OptionalData() - optionalData.configureOptional() - this.optionalData = optionalData + fun optional(transform: (optionalData: OptionalData) -> OptionalData): OptionalData { + return transform( + optionalData?.copy() ?: OptionalData() + ) } +*/ } interface CurseImmutable { diff --git a/docs/quickstart.md b/docs/quickstart.md index 3f552249..33707414 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -35,71 +35,52 @@ run the `generateSchema` command once to make it generate a `config.json` and `. ./voodoo generateSchema ``` -now you should see `config.json5` +now you should see `config.json5` which might contain some useful defaults `/config.json5` ```json5 { - "$schema": "./schema/config.schema.json", - "curseforgeGenerators": { - }, - "forgeGenerators": { - }, - "fabricGenerators": { - }, - "overrides": { - } + "$schema": "./schema/config.schema.json", + "curseforgeGenerators": {}, + "forgeGenerators": {}, + "fabricGenerators": {}, + "overrides": {} } ``` -### gitignore - -these folders should probably be gitignored because they contain autogenerated content (lots of it) -so `init` created a gitignore file - -??? note ".gitignore" - ```gitignore - /.completions/ - /_upload/ - /reports/ - /logs/ - /docs/ - /schema/ - /wrapper/bin/ - ``` - // TODO: use https://facelessuser.github.io/pymdown-extensions/extensions/snippets/ to load actual .gitignore - ### Autocompletion Configuration we are interested in fabric and fabric mods on curseforge +so we see there is already a section that filters curseforge mods by section +and a entry that generated the fabric modloader versions `/config.json5` ```json5 { - "$schema": "./schema/config.schema.json", - "curseforgeGenerators": { - "Fabric": { - "section": "MODS", - "categories": [ - "Fabric" - ], - "mcVersions": [ - "1.16", - "1.16.1", - "1.16.2", - "1.16.3" - ] - } - }, - "forgeGenerators": { + "$schema": "./schema/config.schema.json", + "curseforgeGenerators": { + "Fabric": { + "section": "MODS", + "categories": [ + "Fabric" + ] + } + }, + "fabricGenerators": { + "Fabric": { + "requireStable": true + } + }, + "overrides": { + "side_client": { + "type": "common", + "side": "CLIENT" }, - "fabricGenerators": { - "Fabric": { - "requireStable": true - } + "side_server": { + "type": "common", + "side": "SERVER" }, - "overrides": { - } + } } ``` @@ -142,8 +123,7 @@ by default the modloader is set to `None` "modloader": { "type": "modloader.none" }, - "mods": [ - ] + "mods": {} } ``` @@ -160,8 +140,7 @@ lets replace with with fabric "type": "modloader.fabric", "intermediateMappings": "Fabric/1.16.3" }, - "mods": [ - ] + "mods": {} } ``` @@ -213,16 +192,23 @@ so lets add some mods "type": "modloader.fabric", "intermediateMappings": "Fabric/1.16.3" }, - "mods": [ + "mods": { + "": [ { - "type": "curse", - "projectName": "Fabric/appleskin" + "type": "curse" + "curse_projectName": "Fabric/campanion" + } + ], + "side_client": [ + { + "type": "curse", + "curse_projectName": "Fabric/appleskin" }, { - "type": "curse", - "projectName": "Fabric/hwyla" + "type": "curse", + "curse_projectName": "Fabric/hwyla" } - ] + ], } ``` diff --git a/samples/config.json5 b/samples/config.json5 index e3f0c5f8..150e2b29 100644 --- a/samples/config.json5 +++ b/samples/config.json5 @@ -1,68 +1,53 @@ { - "$schema": "./schema/config.schema.json", - "curseforgeGenerators": { - "Mod": { - "section": "MODS", - "mcVersions": [ - "1.12", - "1.12.1", - "1.12.2", - "1.15.2", - "1.16.4", - "1.16.5" - ] - }, - "Resource": { - "section": "RESOURCE_PACKS", - "mcVersions": [] - }, - "Fabric": { - "section": "MODS", - "categories": [ - "Fabric" - ], - "mcVersions": [ - ] - } + "$schema": "./schema/config.schema.json", + "curseforgeGenerators": { + "Mod": { + "section": "MODS" }, - "forgeGenerators": { - "Forge": {}, + "Resource": { + "section": "RESOURCE_PACKS" }, - "fabricGenerators": { - "Fabric": { - "requireStable": true - } - }, - "overrides": { - "client": { - "type": "common", - "side": "CLIENT" - }, - "server": { - "type": "common", - "side": "SERVER" - }, - "optional": { - "type": "common", - "optional": { - "selected": false - } - }, - "optionalDefault": { - "type": "common", - "optional": { - "selected": true - } - }, - "optionalStarred": { - "type": "common", - "optional": { - "recommendation": "starred" - } - }, - "163Mod": { - "type": "common", - "validMcVersions": ["1.16.3"] - } + "Fabric": { + "section": "MODS", + "categories": [ + "Fabric" + ] + } + }, + "forgeGenerators": { + "Forge": {}, + }, + "fabricGenerators": { + "Fabric": { + "requireStable": true } + }, + "overrides": { + "side_client": { + "type": "common", + "side": "CLIENT" + }, + "side_server": { + "type": "common", + "side": "SERVER" + }, + "optional": { + "type": "common", + "optional": { + "selected": false + } + }, + "optional_default": { + "type": "common", + "optional": { + "selected": true + } + }, + "optional_starred": { + "type": "common", + "optional": { + "recommendation": "starred" + } + }, + } } \ No newline at end of file diff --git a/samples/fabricpack/152Version.voodoo.json5 b/samples/fabricpack/152Version.voodoo.json5 index 29c0eec9..c35e19ee 100644 --- a/samples/fabricpack/152Version.voodoo.json5 +++ b/samples/fabricpack/152Version.voodoo.json5 @@ -7,63 +7,65 @@ "type": "modloader.fabric", "intermediateMappings": "Fabric/1.15.2" }, - "mods": [ - { - "type": "curse", - "projectName": "Fabric/fabric-api" - }, - { - "type": "curse", - "projectName": "Fabric/betternether" - }, - { - "type": "curse", - "projectName": "Fabric/tab-inventory-fabric" - }, - { - "type": "curse", - "projectName": "Fabric/campanion" - }, - { - "type": "curse", - "applyOverrides": [ - "client" - ], - "projectName": "Fabric/roughly-enough-items" - }, - { - "type": "curse", - "applyOverrides": [ - "client" - ], - "projectName": "Fabric/roughly-enough-resources" - }, - { - "type": "curse", - "applyOverrides": [ - "client" - ], - "projectName": "Fabric/modmenu" - }, - { - "type": "curse", - "applyOverrides": [ - "client", - "optionalStarred" - ], - "projectName": "Fabric/mouse-wheelie" - }, - { - "type": "curse", - "applyOverrides": [ - "client", - "optionalStarred" - ], - "projectName": "Fabric/appleskin" - }, - { - "type": "curse", - "projectName": "Fabric/hwyla" - } - ] + "mods": { + "": [ + { + "type": "curse", + "curse_projectName": "Fabric/fabric-api" + }, + { + "type": "curse", + "curse_projectName": "Fabric/betternether" + }, + { + "type": "curse", + "curse_projectName": "Fabric/tab-inventory-fabric" + }, + { + "type": "curse", + "curse_projectName": "Fabric/campanion" + }, + { + "type": "curse", + "applyOverrides": [ + "side_client" + ], + "curse_projectName": "Fabric/roughly-enough-items" + }, + { + "type": "curse", + "applyOverrides": [ + "side_client" + ], + "curse_projectName": "Fabric/roughly-enough-resources" + }, + { + "type": "curse", + "applyOverrides": [ + "side_client" + ], + "curse_projectName": "Fabric/modmenu" + }, + { + "type": "curse", + "applyOverrides": [ + "side_client", + "optional_starred" + ], + "curse_projectName": "Fabric/mouse-wheelie" + }, + { + "type": "curse", + "applyOverrides": [ + "side_client", + "optional_starred" + ], + "curse_projectName": "Fabric/appleskin" + }, + { + "type": "curse", + "curse_projectName": "Fabric/hwyla" + } + ], + } } \ No newline at end of file diff --git a/samples/fabricpack/164Version.voodoo.json5 b/samples/fabricpack/164Version.voodoo.json5 index 5f433ced..c0448d12 100644 --- a/samples/fabricpack/164Version.voodoo.json5 +++ b/samples/fabricpack/164Version.voodoo.json5 @@ -7,37 +7,55 @@ "type": "modloader.fabric", "intermediateMappings": "Fabric/1.16.4" }, - "mods": [ - "curse=Fabric/fabric-api", - "curse=Fabric/betternether", - "curse=Fabric/betternether", - // comment - { - "type": "curse", - "projectName": "Fabric/tab-inventory-fabric", - "validMcVersions": ["1.16", "1.16.1", "1.16.2", "1.16.3"] - }, - { - "type": "curse", - "projectName": "Fabric/campanion", - }, - "curse:client=Fabric/roughly-enough-items", - "curse:client=Fabric/roughly-enough-resources", - "curse:client=Fabric/modmenu", - "curse:client,optionalStarred=Fabric/mouse-wheelie", - "curse:client,optionalStarred=Fabric/appleskin", - { - "type": "curse", - "projectName": "Fabric/hwyla", - "validMcVersions": ["1.16.3"] - }, - { - "type": "local", - "folder": "", - "fileName": "_icon.png", - "localProperties": { - "fileSrc": "256.png" + "mods": { + "": [ + "curse=Fabric/fabric-api", + "curse=Fabric/betternether", + "curse=Fabric/betternether", + // comment + { + "type": "curse", + "curse_projectName": "Fabric/tab-inventory-fabric", + "validMcVersions": [ + "1.16", + "1.16.1", + "1.16.2", + "1.16.3" + ] + }, + { + "type": "curse", + "curse_projectName": "Fabric/campanion", + }, + + { + "type": "curse", + "curse_projectName": "Fabric/hwyla", + "validMcVersions": [ + "1.16.3" + ] + }, + { + "type": "local", + "folder": "", + "fileName": "_icon.png" + "local_fileSrc": "256.png" } - } - ] + ], + "side_client": [ + // "curse:client=Fabric/roughly-enough-items", + { + "type": "curse", + "curse_projectName": "Fabric/roughly-enough-items" + }, + // "curse:client=Fabric/roughly-enough-resources", + { + "type": "curse", + "curse_projectName": "Fabric/roughly-enough-resources" + }, + "curse=Fabric/modmenu", + "curse:optional_starred=Fabric/mouse-wheelie", + "curse:optional_starred=Fabric/appleskin" + ] + } } \ No newline at end of file diff --git a/samples/fabricpack/lock/0.0.3/lock.pack.json b/samples/fabricpack/lock/0.0.3/lock.pack.json index e2242bc1..d84ccb0e 100644 --- a/samples/fabricpack/lock/0.0.3/lock.pack.json +++ b/samples/fabricpack/lock/0.0.3/lock.pack.json @@ -29,8 +29,11 @@ "optionalData": { "recommendation": "starred" }, + "dependencies": { + "fabric-api": "REQUIRED" + }, "projectID": 248787, - "fileID": 3035787 + "fileID": 2987255 }, { "type": "curse", diff --git a/samples/fabricpack/old_0.0.1.voodoo.json5 b/samples/fabricpack/old_0.0.1.voodoo.json5 index 103167fe..bc1f25a5 100644 --- a/samples/fabricpack/old_0.0.1.voodoo.json5 +++ b/samples/fabricpack/old_0.0.1.voodoo.json5 @@ -7,59 +7,62 @@ "type": "modloader.fabric", "intermediateMappings": "Fabric/1.15.2" }, - "mods": [ - { - "type": "curse", - "projectName": "Fabric/fabric-api" - }, - { - "type": "curse", - "projectName": "Fabric/betternether" - }, - { - "type": "curse", - "projectName": "Fabric/tab-inventory-fabric" - }, - { - "type": "curse", - "projectName": "Fabric/campanion" - }, - { - "type": "curse", - "applyOverrides": [ - "client" - ], - "projectName": "Fabric/roughly-enough-items" - }, - { - "type": "curse", - "applyOverrides": [ - "client" - ], - "projectName": "Fabric/roughly-enough-resources" - }, - { - "type": "curse", - "applyOverrides": [ - "client" - ], - "projectName": "Fabric/modmenu" - }, - { - "type": "curse", - "applyOverrides": [ - "client", - "optionalStarred" - ], - "projectName": "Fabric/mouse-wheelie" - }, - { - "type": "curse", - "applyOverrides": [ - "client", - "optionalStarred" - ], - "projectName": "Fabric/appleskin" - } - ] + "mods": { + "": [ + { + "type": "curse", + "curse_projectName": "Fabric/fabric-api" + }, + { + "type": "curse", + "curse_projectName": "Fabric/betternether" + }, + { + "type": "curse", + "curse_projectName": "Fabric/tab-inventory-fabric" + }, + { + "type": "curse", + "curse_projectName": "Fabric/campanion" + }, + { + "type": "curse", + "applyOverrides": [ + "side_client" + ], + "curse_projectName": "Fabric/roughly-enough-items" + }, + { + "type": "curse", + "applyOverrides": [ + "side_client" + ], + "curse_projectName": "Fabric/roughly-enough-resources" + }, + { + "type": "curse", + "applyOverrides": [ + "side_client" + ], + "curse_projectName": "Fabric/modmenu" + }, + { + "type": "curse", + "applyOverrides": [ + "side_client", + "optional_starred" + ], + "curse_projectName": "Fabric/mouse-wheelie" + }, + { + "type": "curse", + "applyOverrides": [ + "side_client", + "optional_starred" + ], + "curse_projectName": "Fabric/appleskin" + } + ], + } +} } \ No newline at end of file diff --git a/samples/forgePack/v0.0.1.voodoo.json5 b/samples/forgePack/v0.0.1.voodoo.json5 index 0990bef9..45560496 100644 --- a/samples/forgePack/v0.0.1.voodoo.json5 +++ b/samples/forgePack/v0.0.1.voodoo.json5 @@ -1,16 +1,19 @@ { - "$schema": "../schema/versionPack.schema.json", - "version": "0.0.1", - "srcDir": "v0.0.1_src", - "mcVersion": "1.12.2", - "modloader": { - "type": "modloader.forge", - "version": "Forge/1.12.2/14.23.5.2854" - }, - "mods": [ - { - "type": "curse", - "projectName": "Mod/foamfix-optimization-mod" - } + "$schema": "../schema/versionPack.schema.json", + "version": "0.0.1", + "srcDir": "v0.0.1_src", + "mcVersion": "1.12.2", + "modloader": { + "type": "modloader.forge", + "version": "Forge/1.12.2/14.23.5.2854" + }, + "mods": { + "": [ + { + "type": "curse", + "curse_projectName": "Mod/foamfix-optimization-mod" + } ] + } +} } \ No newline at end of file diff --git a/voodoo/src/main/kotlin/voodoo/TestSerialization.kt b/voodoo/src/main/kotlin/voodoo/TestSerialization.kt index fc31c1e5..3aa6ba16 100644 --- a/voodoo/src/main/kotlin/voodoo/TestSerialization.kt +++ b/voodoo/src/main/kotlin/voodoo/TestSerialization.kt @@ -46,7 +46,7 @@ fun main(args: Array) { "validMcVersions": ["1.16", "1.16.1", "1.16.2", "1.16.3"] } """.trimIndent() - ) + ) as FileEntry.Curse require(decoded.validMcVersions.isNotEmpty()) { "decoding failed" diff --git a/voodoo/src/main/kotlin/voodoo/cli/GenerateSchemaCommand.kt b/voodoo/src/main/kotlin/voodoo/cli/GenerateSchemaCommand.kt index 32eb6721..2555112c 100644 --- a/voodoo/src/main/kotlin/voodoo/cli/GenerateSchemaCommand.kt +++ b/voodoo/src/main/kotlin/voodoo/cli/GenerateSchemaCommand.kt @@ -64,7 +64,7 @@ class GenerateSchemaCommand : CliktCommand( rootDir.resolve("packIdPlaceholder").resolve(VersionPack.defaultSchema).normalize().apply { absoluteFile.parentFile.mkdirs() - writeText(VersionPack.generateSchema(overridesKeys = config.overrides.keys)) + writeText(VersionPack.generateSchema(overridesKeys = setOf("") + config.overrides.keys)) } } } diff --git a/voodoo/src/main/kotlin/voodoo/cli/ImportCurseCommand.kt b/voodoo/src/main/kotlin/voodoo/cli/ImportCurseCommand.kt index 04fefec1..c8b55877 100644 --- a/voodoo/src/main/kotlin/voodoo/cli/ImportCurseCommand.kt +++ b/voodoo/src/main/kotlin/voodoo/cli/ImportCurseCommand.kt @@ -6,28 +6,22 @@ import com.eyeem.watchadoin.saveAsSvg import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.requireObject import com.github.ajalt.clikt.parameters.arguments.argument -import com.github.ajalt.clikt.parameters.arguments.multiple -import com.github.ajalt.clikt.parameters.arguments.validate import com.github.ajalt.clikt.parameters.options.flag import com.github.ajalt.clikt.parameters.options.option import com.github.ajalt.clikt.parameters.options.required import com.github.ajalt.clikt.parameters.options.validate -import com.github.ajalt.clikt.parameters.types.file import kotlinx.coroutines.* import kotlinx.coroutines.slf4j.MDCContext import kotlinx.serialization.builtins.serializer import kotlinx.serialization.json.Json import mu.KotlinLogging import mu.withLoggingContext -import voodoo.builder.Builder import voodoo.config.Autocompletions import voodoo.config.Configuration import voodoo.curse.CurseClient -import voodoo.data.components.CurseComponent import voodoo.data.curse.CurseFile import voodoo.data.curse.CurseManifest import voodoo.data.curse.FileType -import voodoo.data.curse.ProjectID import voodoo.pack.* import voodoo.poet.generator.CurseSection import voodoo.util.* @@ -163,7 +157,7 @@ class ImportCurseCommand() : CliktCommand( var hasCustomProperties = false var entry = FileEntry.Curse( - projectName = projectName, + curse_projectName = projectName, ) // // TODO: handle this properly @@ -172,18 +166,14 @@ class ImportCurseCommand() : CliktCommand( if(pinFiles) { entry = entry.copy( - curse = entry.curse.copy( - fileID = curseFileEntry.fileID - ) + curse_fileID = curseFileEntry.fileID ) hasCustomProperties = true } if(addonFile.releaseType != FileType.Release) { entry = entry.copy( - curse = entry.curse.copy( - releaseTypes = entry.curse.releaseTypes + addonFile.releaseType - ) + curse_releaseTypes = entry.curse_releaseTypes + addonFile.releaseType ) hasCustomProperties = true } @@ -206,7 +196,7 @@ class ImportCurseCommand() : CliktCommand( // fileNameRegex = "\\Q${addonFile.fileName}\\E" if(!hasCustomProperties) { - val entryString = "curse=${entry.projectName}" + val entryString = "curse=${entry.curse_projectName}" jsonPretty.encodeToJsonElement( String.serializer(), entryString @@ -230,7 +220,7 @@ class ImportCurseCommand() : CliktCommand( srcDir = srcFolder.toRelativeUnixPath(baseDir), mcVersion = manifest.minecraft.version, modloader = modloader, - mods = mods + mods = mapOf("" to mods) ).postParse(baseDir = baseDir) if(!metaPackFile.exists()) { diff --git a/voodoo/src/main/kotlin/voodoo/cli/init/InitPackCommand.kt b/voodoo/src/main/kotlin/voodoo/cli/init/InitPackCommand.kt index 0aa1b596..7a80630b 100644 --- a/voodoo/src/main/kotlin/voodoo/cli/init/InitPackCommand.kt +++ b/voodoo/src/main/kotlin/voodoo/cli/init/InitPackCommand.kt @@ -77,7 +77,7 @@ class InitPackCommand : CliktCommand( srcDir = "v${packVersion ?: "0.0.1"}_src", modloader = Modloader.None, packageConfiguration = VersionPackageConfig(), - mods = listOf( + mods = mapOf( //TODO: add mod samples there ) ).postParse(baseDir = baseDir) diff --git a/voodoo/src/main/kotlin/voodoo/config/Configuration.kt b/voodoo/src/main/kotlin/voodoo/config/Configuration.kt index 5091af93..ddf39d49 100644 --- a/voodoo/src/main/kotlin/voodoo/config/Configuration.kt +++ b/voodoo/src/main/kotlin/voodoo/config/Configuration.kt @@ -6,6 +6,7 @@ import kotlinx.serialization.Required import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import mu.KotlinLogging +import voodoo.data.Side import voodoo.pack.EntryOverride import voodoo.poet.generator.CurseSection import voodoo.util.json @@ -37,7 +38,14 @@ data class Configuration( ) ), @Required - val overrides: Map = mapOf() + val overrides: Map = mapOf( + "side_client" to EntryOverride.Common().apply { + side = Side.CLIENT + }, + "side_server" to EntryOverride.Common().apply { + side = Side.SERVER + } + ) ) { companion object { private val logger = KotlinLogging.logger {} diff --git a/voodoo/src/main/kotlin/voodoo/config/Extensions.kt b/voodoo/src/main/kotlin/voodoo/config/Extensions.kt index f6bdbf4f..ed9afb42 100644 --- a/voodoo/src/main/kotlin/voodoo/config/Extensions.kt +++ b/voodoo/src/main/kotlin/voodoo/config/Extensions.kt @@ -1,13 +1,10 @@ package voodoo.config import com.github.ricky12awesome.jss.buildJsonSchema -import com.github.ricky12awesome.jss.encodeToSchema import kotlinx.serialization.json.* import mu.KotlinLogging -import voodoo.data.nested.NestedPack import voodoo.pack.FileEntry import voodoo.pack.VersionPack -import voodoo.util.json private val logger = KotlinLogging.logger {} // @@ -36,8 +33,22 @@ fun VersionPack.Companion.generateSchema(overridesKeys: Set): String { val schema = buildJsonSchema(serializer(), generateDefinitions = true).toMutableMap() val definitions = schema["definitions"]!!.jsonObject.toMutableMap() - val fileEntryOrStringId = definitions["FileEntryList"]!!.jsonObject["items"]!!.jsonObject["\$ref"]!!.jsonPrimitive + val oldFileEntriesMap = definitions["FileEntryList"]!!.jsonObject + val fileEntryArrayId = definitions["FileEntryList"]!!.jsonObject["additionalProperties"]!!.jsonObject["\$ref"]!!.jsonPrimitive .content.substringAfter("#/definitions/") + val fileEntryOrStringId = definitions[fileEntryArrayId]!!.jsonObject["items"]!!.jsonObject["\$ref"]!!.jsonPrimitive + .content.substringAfter("#/definitions/") + + definitions["FileEntryList"] = buildJsonObject { + put("type", "object") + putJsonObject("properties") { + //TODO: add all ovverride keys here + overridesKeys.forEach { key -> + put(key, oldFileEntriesMap["additionalProperties"]!!.jsonObject) + } + } + put("additionalProperties", false) + } definitions[fileEntryOrStringId] = buildJsonObject { putJsonArray("oneOf") { @@ -68,7 +79,7 @@ fun VersionPack.Companion.generateSchema(overridesKeys: Set): String { schema["definitions"] = JsonObject(definitions) - return json.encodeToString(JsonObject.serializer(), JsonObject(schema)) + return voodoo.util.json.encodeToString(JsonObject.serializer(), JsonObject(schema)) .replace("\"replace_with_overrides\"", overridesKeys.joinToString(",") { "\"${it}\"" } ) diff --git a/voodoo/src/main/kotlin/voodoo/pack/EntryOverride.kt b/voodoo/src/main/kotlin/voodoo/pack/EntryOverride.kt index 4a1308a1..cbf74321 100644 --- a/voodoo/src/main/kotlin/voodoo/pack/EntryOverride.kt +++ b/voodoo/src/main/kotlin/voodoo/pack/EntryOverride.kt @@ -8,48 +8,105 @@ import voodoo.data.curse.PackageType @Serializable sealed class EntryOverride( - val folder: String? = null, - val description: String? = null, - val optional: OptionalOverride? = null, - val side: Side? = null, - val websiteUrl: String? = null, - val packageType: PackageType? = null, - val version: String? = null, - val fileName: String? = null, - val fileNameRegex: String? = null, - val validMcVersions: Set? = null, - val invalidMcVersions: Set? = null + var folder: String? = null, + var description: String? = null, + var optional: OptionalOverride? = null, + var side: Side? = null, + var websiteUrl: String? = null, + var packageType: PackageType? = null, + var version: String? = null, + var fileName: String? = null, + var fileNameRegex: String? = null, + var validMcVersions: Set? = null, + var invalidMcVersions: Set? = null ) { + protected fun plusCommon(other: EntryOverride) { + folder = folder ?: other.folder + description = description ?: other.description + optional = optional ?: other.optional + side = side ?: other.side + websiteUrl = websiteUrl ?: other.websiteUrl + packageType = packageType ?: other.packageType + version = version ?: other.version + fileName = fileName ?: other.fileName + fileNameRegex = fileNameRegex ?: other.fileNameRegex + validMcVersions = validMcVersions ?: other.validMcVersions + invalidMcVersions = invalidMcVersions ?: other.invalidMcVersions + } + @Serializable @SerialName("common") - open class Common: EntryOverride() + open class Common: EntryOverride() { + operator fun plus(other: Common): Common { + return apply { + plusCommon(other) + } + } + } @Serializable @SerialName("curse") data class Curse( - val releaseTypes: Set? = null, - val useOriginalUrl: Boolean? = null, - val skipFingerprintCheck: Boolean? = null, - ) : EntryOverride() + val curse_releaseTypes: Set? = null, + val curse_useOriginalUrl: Boolean? = null, + val curse_skipFingerprintCheck: Boolean? = null, + ) : EntryOverride() { + operator fun plus(other: Curse): Curse { + return copy( + curse_releaseTypes = curse_releaseTypes ?: other.curse_releaseTypes, + curse_useOriginalUrl = curse_useOriginalUrl ?: other.curse_useOriginalUrl, + curse_skipFingerprintCheck = curse_skipFingerprintCheck ?: other.curse_skipFingerprintCheck, + ).apply { + plusCommon(other) + } + } + } @Serializable @SerialName("direct") data class Direct( - val url: String? = null, - val useOriginalUrl: Boolean? = null, - ) : EntryOverride() +// val url: String? = null, + val direct_useOriginalUrl: Boolean? = null, + ) : EntryOverride() { + operator fun plus(other: Direct): Direct { + return copy( +// url = url ?: other.url, + direct_useOriginalUrl = direct_useOriginalUrl ?: other.direct_useOriginalUrl, + ).apply { + plusCommon(other) + } + } + } @Serializable @SerialName("jenkins") data class Jenkins( - val jenkinsUrl: String? = null, - val job: String? = null, - val buildNumber: Int? = null - ) : EntryOverride() + val jenkins_jenkinsUrl: String? = null, +// val job: String? = null, +// val buildNumber: Int? = null + ) : EntryOverride() { + operator fun plus(other: Jenkins): Jenkins { + return copy( + jenkins_jenkinsUrl = jenkins_jenkinsUrl ?: other.jenkins_jenkinsUrl, +// job = job ?: other.job, +// buildNumber = buildNumber ?: other.buildNumber, + ).apply { + plusCommon(other) + } + } + } @Serializable @SerialName("local") data class Local( - val fileSrc: String? = null - ) : EntryOverride() + val local_fileSrc: String? = null + ) : EntryOverride() { + operator fun plus(other: Local): Local { + return copy( + local_fileSrc = local_fileSrc ?: other.local_fileSrc, + ).apply { + plusCommon(other) + } + } + } } \ No newline at end of file diff --git a/voodoo/src/main/kotlin/voodoo/pack/FileEntry.kt b/voodoo/src/main/kotlin/voodoo/pack/FileEntry.kt index 7f3b254b..7a1b5727 100644 --- a/voodoo/src/main/kotlin/voodoo/pack/FileEntry.kt +++ b/voodoo/src/main/kotlin/voodoo/pack/FileEntry.kt @@ -3,73 +3,42 @@ package voodoo.pack import com.github.ricky12awesome.jss.JsonSchema import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable +import mu.KotlinLogging +import voodoo.config.Autocompletions import voodoo.data.Side import voodoo.data.components.* +import voodoo.data.curse.FileID +import voodoo.data.curse.FileType import voodoo.data.curse.PackageType +import voodoo.data.curse.ProjectID import voodoo.data.flat.FlatEntry @Serializable sealed class FileEntry( -// @JsonSchema.Definition("entry.applyOverrides") - @JsonSchema.StringEnum(["replace_with_overrides"]) - var applyOverrides: List = listOf(), - var id: String? = null, - var name: String? = null, - var folder: String? = null, - var description: String? = null, - var optional: Optional? = null, - var side: Side = Side.BOTH, - var websiteUrl: String = "", - var packageType: PackageType = PackageType.MOD, - var transient: Boolean = false, // this entry got added as dependency for something else, only setthis if you know what you are doing - var version: String = "", // TODO: use regex only ? - var fileName: String? = null, - var fileNameRegex: String = ".*(? = setOf(), - var invalidMcVersions: Set = setOf(), - var enabled: Boolean = true ) { - protected fun applyCommonOverride(tag: EntryOverride) { - tag.folder?.let { - folder = it - } - tag.description?.let { - description = it - } - tag.optional?.let { optionalOverride -> - val opt = this.optional ?: Optional() - opt.applyOverride(optionalOverride) - optional = opt - } - tag.side?.let { - side = it - } - tag.websiteUrl?.let { - websiteUrl = it - } - tag.packageType?.let { - packageType = it - } - tag.version?.let { - version = it - } - tag.fileName?.let { - fileName = it - } - tag.fileNameRegex?.let { - fileNameRegex = it - } - tag.validMcVersions?.let { - validMcVersions += it - } - tag.invalidMcVersions?.let { - invalidMcVersions += it - } - } + interface Common { + val applyOverrides: List + var id: String? + var name: String? + var folder: String? + var description: String? + var optional: Optional? + var side: Side + var websiteUrl: String + var packageType: PackageType + // this entry got added as dependency for something else, only setthis if you know what you are doing + var version: String // TODO: use regex only ? + var transient: Boolean + var fileName: String? + var fileNameRegex: String + var validMcVersions: Set + var invalidMcVersions: Set + + fun id(): String? + fun applyOverride(override: EntryOverride): Common - protected fun toCommonComponent(defaultId: String? = null): CommonComponent { - return CommonComponent( - id = id ?: defaultId ?: error("id must be set on $this"), + fun toCommonComponent(defaultId: String? = null): CommonComponent = CommonComponent( + id = id.takeUnless { it.isNullOrBlank() } ?: defaultId ?: error("id must be set on $this"), name = name, folder = folder, description = description, @@ -85,150 +54,425 @@ sealed class FileEntry( validMcVersions = validMcVersions, invalidMcVersions = invalidMcVersions ) + + fun applyCommonOverride(override: EntryOverride) { + override.folder?.let { folder = it } + override.description?.let { description = it } + override.optional?.let { optionalOverride -> + val opt = this.optional ?: Optional() + opt.applyOverride(optionalOverride) + optional = opt + } + override.side?.let { side = it } + override.websiteUrl?.let { websiteUrl = it } + override.packageType?.let { packageType = it } + override.version?.let { version = it } + override.fileName?.let { fileName = it } + override.fileNameRegex?.let { fileNameRegex = it } + override.validMcVersions?.let { validMcVersions += it } + override.invalidMcVersions?.let { invalidMcVersions += it } + } + + fun foldOverrides(overrides: Map): E { + val intitalEntry = this as E + val entryId = intitalEntry.id() ?: "null" + val entry = intitalEntry.applyOverrides.fold(intitalEntry) { acc: E, overrideId -> + val entryOverride = + overrides[overrideId] ?: error("$entryId: override for id $overrideId not found") + return@fold acc.applyOverride(entryOverride) as E + } + return entry as E + } } - abstract fun applyTag(tag: EntryOverride): FileEntry - abstract fun toEntry(): FlatEntry + + val logger = KotlinLogging.logger{} + fun postParse(overrideKey: String): FileEntry = when (this) { + is Curse -> { + if (curse_projectName != null) { + val addonid = Autocompletions.curseforge[curse_projectName]?.toIntOrNull() + val newName = curse_projectName.substringAfterLast('/') + require(addonid != null) { "cannot find replacement for $curse_projectName / ${Autocompletions.curseforge[curse_projectName]}" } +// logger.trace { "before transform: $validMcVersions" } + copy( +// curse_projectName = null, + applyOverrides = listOfNotNull(overrideKey.takeUnless { it.isBlank() }) + applyOverrides, + curse_projectID = ProjectID(addonid), + id = id.takeUnless { it.isNullOrBlank() } ?: newName, + name = name ?: newName + ) + } else { + this + }.copy( + applyOverrides = listOfNotNull(overrideKey.takeUnless { it.isBlank() }) + applyOverrides, + ) + } + is Direct -> copy( + applyOverrides = listOfNotNull(overrideKey.takeUnless { it.isBlank() }) + applyOverrides, + ) + is Jenkins -> copy( + applyOverrides = listOfNotNull(overrideKey.takeUnless { it.isBlank() }) + applyOverrides, + ) + is Local -> copy( + applyOverrides = listOfNotNull(overrideKey.takeUnless { it.isBlank() }) + applyOverrides, + ) + is Noop -> copy( + applyOverrides = listOfNotNull(overrideKey.takeUnless { it.isBlank() }) + applyOverrides, + ) + } + + abstract fun toEntry(overrides: Map): FlatEntry @Serializable @SerialName("curse") data class Curse( @JsonSchema.StringEnum(["replace_with_curseforge_projects"]) - val projectName: String? = null, - @SerialName("curseProperties") - val curse: CurseComponent = CurseComponent(), - ) : FileEntry() { + val curse_projectName: String? = null, + val curse_releaseTypes: Set = setOf( + FileType.Release, + FileType.Beta + ), + val curse_projectID: ProjectID = ProjectID.INVALID, + val curse_fileID: FileID = FileID.INVALID, + val curse_useOriginalUrl: Boolean = true, + val curse_skipFingerprintCheck: Boolean = false, + + @JsonSchema.Definition("entry.overridesList") + @JsonSchema.StringEnum(["replace_with_overrides"]) + override val applyOverrides: List = listOf(), - override fun applyTag(tag: EntryOverride): Curse { - return when (tag) { + override var id: String? = CommonComponent.DEFAULT.id, + override var name: String? = CommonComponent.DEFAULT.name, + override var folder: String? = CommonComponent.DEFAULT.folder, + override var description: String? = CommonComponent.DEFAULT.description, + override var optional: Optional? = null, + override var side: Side = CommonComponent.DEFAULT.side, + override var websiteUrl: String = CommonComponent.DEFAULT.websiteUrl, + override var packageType: PackageType = CommonComponent.DEFAULT.packageType, + override var transient: Boolean = CommonComponent.DEFAULT.transient, + override var version: String = CommonComponent.DEFAULT.version, + override var fileName: String? = CommonComponent.DEFAULT.fileName, + override var fileNameRegex: String =CommonComponent.DEFAULT.fileNameRegex, + override var validMcVersions: Set = CommonComponent.DEFAULT.validMcVersions, + override var invalidMcVersions: Set = CommonComponent.DEFAULT.invalidMcVersions, + ) : Common, FileEntry() { + override fun id() = id.takeUnless { it.isNullOrBlank() } ?: curse_projectName?.substringAfterLast('/') + override fun applyOverride(override: EntryOverride): Curse { + return when (override) { is EntryOverride.Curse -> copy( - curse = curse.copy( - useOriginalUrl = tag.useOriginalUrl ?: curse.useOriginalUrl, - skipFingerprintCheck = tag.skipFingerprintCheck ?: curse.skipFingerprintCheck, - ) + curse_useOriginalUrl = override.curse_useOriginalUrl ?: curse_useOriginalUrl, + curse_skipFingerprintCheck = override.curse_skipFingerprintCheck ?: curse_skipFingerprintCheck, ).apply { - applyCommonOverride(tag) + applyCommonOverride(override) } - is EntryOverride.Common -> this.apply { - applyCommonOverride(tag) + is EntryOverride.Common -> apply { + applyCommonOverride(override) } else -> this } } - override fun toEntry(): FlatEntry = FlatEntry.Curse( - common = toCommonComponent(), - curse = curse.copy() - ).apply { + override fun toEntry(overrides: Map): FlatEntry = + (foldOverrides(overrides) as Curse).let { + FlatEntry.Curse( + common = it.toCommonComponent(it.curse_projectName?.substringAfterLast('/')), + curse = it.toCurseComponent() + ) + } - } + private fun toCurseComponent() = CurseComponent( + releaseTypes = curse_releaseTypes, + projectID = curse_projectID, + fileID = curse_fileID, + useOriginalUrl = curse_useOriginalUrl, + skipFingerprintCheck = curse_skipFingerprintCheck + ) - override fun toString(): String { - return "FileEntry.Curse(projectName=$projectName,curse=$curse,validMcVersion=$validMcVersions})" - } +// override fun toString(): String { +// return "FileEntry.Curse(projectName=$projectName,curse=$curse,validMcVersion=${common.validMcVersions})" +// } } @Serializable @SerialName("direct") data class Direct( - @SerialName("directProperties") - val direct: DirectComponent = DirectComponent(), - ) : FileEntry() { - override fun applyTag(tag: EntryOverride): Direct { - return when (tag) { + val direct_url: String, // = "", + val direct_useOriginalUrl: Boolean = true, + + @JsonSchema.Definition("entry.overridesList") + @JsonSchema.StringEnum(["replace_with_overrides"]) + override val applyOverrides: List = listOf(), + + override var id: String? = CommonComponent.DEFAULT.id, + override var name: String? = CommonComponent.DEFAULT.name, + override var folder: String? = CommonComponent.DEFAULT.folder, + override var description: String? = CommonComponent.DEFAULT.description, + override var optional: Optional? = null, + override var side: Side = CommonComponent.DEFAULT.side, + override var websiteUrl: String = CommonComponent.DEFAULT.websiteUrl, + override var packageType: PackageType = CommonComponent.DEFAULT.packageType, + override var transient: Boolean = CommonComponent.DEFAULT.transient, + override var version: String = CommonComponent.DEFAULT.version, + override var fileName: String? = CommonComponent.DEFAULT.fileName, + override var fileNameRegex: String =CommonComponent.DEFAULT.fileNameRegex, + override var validMcVersions: Set = CommonComponent.DEFAULT.validMcVersions, + override var invalidMcVersions: Set = CommonComponent.DEFAULT.invalidMcVersions, + ) : Common, FileEntry() { + override fun id() = id.takeUnless { it.isNullOrBlank() } ?: direct_url.split(":|&|=".toRegex()).joinToString("_") + override fun applyOverride(override: EntryOverride): Direct { + return when (override) { is EntryOverride.Direct -> copy( - direct = direct.copy( - url = tag.url ?: direct.url, - useOriginalUrl = tag.useOriginalUrl ?: direct.useOriginalUrl - ) +// direct_url = override.url ?: direct_url, + direct_useOriginalUrl = override.direct_useOriginalUrl ?: direct_useOriginalUrl ).apply { - applyCommonOverride(tag) + applyCommonOverride(override) } - is EntryOverride.Common -> this.apply { - applyCommonOverride(tag) + is EntryOverride.Common -> apply { + applyCommonOverride(override) } else -> this } } - override fun toEntry(): FlatEntry = FlatEntry.Direct( - common = toCommonComponent(direct.url.split(":|&|=".toRegex()).joinToString("_")), - direct = direct.copy() + override fun toEntry(overrides: Map): FlatEntry = + (foldOverrides(overrides) as Direct).let { + FlatEntry.Direct( + common = it.toCommonComponent(it.id()), + direct = it.toDirectComponent() + ) + } + + private fun toDirectComponent() = DirectComponent( + url = direct_url, + useOriginalUrl = direct_useOriginalUrl, ) } @Serializable @SerialName("jenkins") data class Jenkins( - @SerialName("jenkinsProperties") - val jenkins: JenkinsComponent = JenkinsComponent(), - ) : FileEntry() { - override fun applyTag(tag: EntryOverride): Jenkins { - return when (tag) { + val jenkins_jenkinsUrl: String = "", + val jenkins_job: String, // = "", + val jenkins_buildNumber: Int = -1, + + @JsonSchema.Definition("entry.overridesList") + @JsonSchema.StringEnum(["replace_with_overrides"]) + override val applyOverrides: List = listOf(), + + override var id: String? = CommonComponent.DEFAULT.id, + override var name: String? = CommonComponent.DEFAULT.name, + override var folder: String? = CommonComponent.DEFAULT.folder, + override var description: String? = CommonComponent.DEFAULT.description, + override var optional: Optional? = null, + override var side: Side = CommonComponent.DEFAULT.side, + override var websiteUrl: String = CommonComponent.DEFAULT.websiteUrl, + override var packageType: PackageType = CommonComponent.DEFAULT.packageType, + override var transient: Boolean = CommonComponent.DEFAULT.transient, + override var version: String = CommonComponent.DEFAULT.version, + override var fileName: String? = CommonComponent.DEFAULT.fileName, + override var fileNameRegex: String =CommonComponent.DEFAULT.fileNameRegex, + override var validMcVersions: Set = CommonComponent.DEFAULT.validMcVersions, + override var invalidMcVersions: Set = CommonComponent.DEFAULT.invalidMcVersions, + ) : Common, FileEntry() { + override fun id() = id.takeUnless { it.isNullOrBlank() } ?: jenkins_job + override fun applyOverride(override: EntryOverride): Jenkins { + return when (override) { is EntryOverride.Jenkins -> copy( - jenkins = jenkins.copy( - jenkinsUrl = tag.jenkinsUrl ?: jenkins.jenkinsUrl, - job = tag.job ?: jenkins.job, - buildNumber = tag.buildNumber ?: jenkins.buildNumber - ) + jenkins_jenkinsUrl = override.jenkins_jenkinsUrl ?: jenkins_jenkinsUrl, +// jenkins_job = override.job ?: jenkins_job, +// jenkins_buildNumber = override.buildNumber ?: jenkins_buildNumber ).apply { - applyCommonOverride(tag) + applyCommonOverride(override) } - is EntryOverride.Common -> this.apply { - applyCommonOverride(tag) + is EntryOverride.Common -> apply { + applyCommonOverride(override) } else -> this } } - override fun toEntry(): FlatEntry = FlatEntry.Jenkins( - common = toCommonComponent(jenkins.job), - jenkins = jenkins.copy() + override fun toEntry(overrides: Map): FlatEntry = + (foldOverrides(overrides) as Jenkins).let { + FlatEntry.Jenkins( + common = it.toCommonComponent(it.id()), + jenkins = it.toJenkinsComponent() + ) + } + + private fun toJenkinsComponent() = JenkinsComponent( + jenkinsUrl = jenkins_jenkinsUrl, + job = jenkins_job, + buildNumber = jenkins_buildNumber ) + } @Serializable @SerialName("local") data class Local( - @SerialName("localProperties") - val local: LocalComponent = LocalComponent(), - ) : FileEntry() { - override fun applyTag(tag: EntryOverride): Local { - return when (tag) { + val local_fileSrc: String, // = "", + + @JsonSchema.Definition("entry.overridesList") + @JsonSchema.StringEnum(["replace_with_overrides"]) + override val applyOverrides: List = listOf(), + + override var id: String? = CommonComponent.DEFAULT.id, + override var name: String? = CommonComponent.DEFAULT.name, + override var folder: String? = CommonComponent.DEFAULT.folder, + override var description: String? = CommonComponent.DEFAULT.description, + override var optional: Optional? = null, + override var side: Side = CommonComponent.DEFAULT.side, + override var websiteUrl: String = CommonComponent.DEFAULT.websiteUrl, + override var packageType: PackageType = CommonComponent.DEFAULT.packageType, + override var transient: Boolean = CommonComponent.DEFAULT.transient, + override var version: String = CommonComponent.DEFAULT.version, + override var fileName: String? = CommonComponent.DEFAULT.fileName, + override var fileNameRegex: String =CommonComponent.DEFAULT.fileNameRegex, + override var validMcVersions: Set = CommonComponent.DEFAULT.validMcVersions, + override var invalidMcVersions: Set = CommonComponent.DEFAULT.invalidMcVersions, + ) : Common, FileEntry() { + override fun id() = id.takeUnless { it.isNullOrBlank() } ?: local_fileSrc + override fun applyOverride(override: EntryOverride): Local { + return when (override) { is EntryOverride.Local -> copy( - local = local.copy( - fileSrc = tag.fileSrc ?: local.fileSrc - ) + local_fileSrc = override.local_fileSrc ?: local_fileSrc, ).apply { - applyCommonOverride(tag) + applyCommonOverride(override) } - is EntryOverride.Common -> this.apply { - applyCommonOverride(tag) + is EntryOverride.Common -> apply { + applyCommonOverride(override) } else -> this } } - override fun toEntry(): FlatEntry = FlatEntry.Local( - common = toCommonComponent(local.fileSrc), - local = local.copy() + override fun toEntry(overrides: Map): FlatEntry = + (foldOverrides(overrides) as Local).let { + FlatEntry.Local( + common = it.toCommonComponent(it.id()), + local = it.toLocalComponent() + ) + } + + private fun toLocalComponent() = LocalComponent( + fileSrc = local_fileSrc ) + } @Serializable @SerialName("noop") - class Noop() : FileEntry() { - override fun applyTag(tag: EntryOverride): Noop { - return when (tag) { - is EntryOverride.Common -> this.apply { - applyCommonOverride(tag) + data class Noop( + @JsonSchema.Definition("entry.overridesList") + @JsonSchema.StringEnum(["replace_with_overrides"]) + override val applyOverrides: List = listOf(), + + override var id: String? = CommonComponent.DEFAULT.id, + override var name: String? = CommonComponent.DEFAULT.name, + override var folder: String? = CommonComponent.DEFAULT.folder, + override var description: String? = CommonComponent.DEFAULT.description, + override var optional: Optional? = null, + override var side: Side = CommonComponent.DEFAULT.side, + override var websiteUrl: String = CommonComponent.DEFAULT.websiteUrl, + override var packageType: PackageType = CommonComponent.DEFAULT.packageType, + override var transient: Boolean = CommonComponent.DEFAULT.transient, + override var version: String = CommonComponent.DEFAULT.version, + override var fileName: String? = CommonComponent.DEFAULT.fileName, + override var fileNameRegex: String =CommonComponent.DEFAULT.fileNameRegex, + override var validMcVersions: Set = CommonComponent.DEFAULT.validMcVersions, + override var invalidMcVersions: Set = CommonComponent.DEFAULT.invalidMcVersions, + ) : Common, FileEntry() { + override fun id() = id + override fun applyOverride(override: EntryOverride): Noop { + return when (override) { + is EntryOverride.Common -> apply { + applyCommonOverride(override) } else -> this } } - override fun toEntry(): FlatEntry = FlatEntry.Noop( - common = toCommonComponent() - ) + override fun toEntry(overrides: Map): FlatEntry = + (foldOverrides(overrides) as Noop).let { + FlatEntry.Noop( + common = it.toCommonComponent(it.id()), + ) + } + } + +// @Serializable +// @SerialName("nested") +// data class Nested( +// @SerialName("commonOverrides") +// val common: EntryOverride.Common? = null, +// @SerialName("curseOverrides") +// val curse: EntryOverride.Curse? = null, +// @SerialName("directOverrides") +// val direct: EntryOverride.Direct? = null, +// @SerialName("jenkinsOverrides") +// val jenkins: EntryOverride.Jenkins? = null, +// @SerialName("localOverrides") +// val local: EntryOverride.Local? = null, +// @JsonSchema.Definition("FileEntryList") +// val mods: List +// ) : FileEntry() { +// override fun getId(): String { +// return "nested_$this" +// } +// override fun applyOverride(override: EntryOverride): Nested { +// // combine with existing overrides +// +// return when (override) { +// is EntryOverride.Curse -> { +// if(curse == null) +// copy(curse = override) +// else +// copy(curse = curse + override) +// } +// is EntryOverride.Jenkins -> { +// if(jenkins == null) +// copy(jenkins = override) +// else +// copy(jenkins = jenkins + override) +// } +// is EntryOverride.Direct -> { +// if(direct == null) +// copy(direct = override) +// else +// copy(direct = direct + override) +// } +// is EntryOverride.Local -> { +// if(local == null) +// copy(local = override) +// else +// copy(local = local + override) +// } +// is EntryOverride.Common -> { +// if(common == null) +// copy(common = override) +// else +// copy( +// common = common + override +// ) +// } +// else -> error("unhanndled override type: $override") +// } +// } +// +// //TODO: return multiple entries +// override fun toEntry(overrides: Map): List = mods.flatMap { jsonElement -> +// //TODO: apply common settings to subEntry +// +// var subEntry = VersionPack.parseEntry(jsonElement).postParse() +// +// curse?.also { subEntry = subEntry.applyOverride(it) } +// jenkins?.also { subEntry = subEntry.applyOverride(it) } +// direct?.also { subEntry = subEntry.applyOverride(it) } +// local?.also { subEntry = subEntry.applyOverride(it) } +// common?.also { subEntry = subEntry.applyOverride(it) } +// +// subEntry.toEntry(overrides) +// } +// } } \ No newline at end of file diff --git a/voodoo/src/main/kotlin/voodoo/pack/VersionPack.kt b/voodoo/src/main/kotlin/voodoo/pack/VersionPack.kt index 16052f74..8caf2abd 100644 --- a/voodoo/src/main/kotlin/voodoo/pack/VersionPack.kt +++ b/voodoo/src/main/kotlin/voodoo/pack/VersionPack.kt @@ -10,12 +10,8 @@ import kotlinx.serialization.json.JsonElement import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonPrimitive import mu.KotlinLogging -import voodoo.config.Autocompletions import voodoo.data.ModloaderPattern import voodoo.data.PackOptions -import voodoo.data.components.DirectComponent -import voodoo.data.components.JenkinsComponent -import voodoo.data.curse.ProjectID import voodoo.data.flat.FlatModPack import voodoo.util.json import java.io.File @@ -35,12 +31,14 @@ data class VersionPack( val mcVersion: String, val modloader: Modloader, val packageConfiguration: VersionPackageConfig = VersionPackageConfig(), -// val overrides: Map = mapOf(), @JsonSchema.Definition("FileEntryList") - val mods: List, + val mods: Map>, +// @JsonSchema.Definition("FileEntryList") +// val mods: List, ) { @Transient lateinit var baseDir: File + @Transient lateinit var modEntries: List @@ -50,34 +48,33 @@ data class VersionPack( const val defaultSchema = "../schema/versionPack.schema.json" fun parseEntry(jsonElement: JsonElement): FileEntry { - return when(jsonElement) { + return when (jsonElement) { is JsonPrimitive -> { require(jsonElement.isString) { "element $jsonElement is not a string" } val str = jsonElement.content - val overrides = str.substringBefore("=").takeIf { it.contains(":") }?.substringAfter(":")?.split(",") ?: listOf() + val overrides = + str.substringBefore("=").takeIf { it.contains(":") }?.substringAfter(":")?.split(",") + ?: listOf() when { str.startsWith("curse") -> { FileEntry.Curse( - projectName = str.substringAfter(":").substringAfter("=") + applyOverrides = overrides, + curse_projectName = str.substringAfter(":").substringAfter("=") ) } str.startsWith("jenkins:") -> { FileEntry.Jenkins( - jenkins = JenkinsComponent( - job = str.substringAfter(":").substringAfter("=") - ) + applyOverrides = overrides, + jenkins_job = str.substringAfter(":").substringAfter("=") ) } str.startsWith("direct:") -> { FileEntry.Direct( - direct = DirectComponent( - url = str.substringAfter(":").substringAfter("=") - ) + applyOverrides = overrides, + direct_url = str.substringAfter(":").substringAfter("=") ) } else -> error("unknown prefix: ${str.substringBefore(":")}") - }.apply { - applyOverrides = overrides } } is JsonObject -> { @@ -115,43 +112,6 @@ data class VersionPack( } } - private fun transformFileEntry(entry: FileEntry): FileEntry = when (entry) { - is FileEntry.Curse -> { - if (entry.projectName != null) { - val addonid = Autocompletions.curseforge[entry.projectName]?.toIntOrNull() - val newName = entry.projectName.substringAfterLast('/') - require(addonid != null) { "cannot find replacement for ${entry.projectName} / ${Autocompletions.curseforge[entry.projectName]}" } - logger.trace { "before transform: ${entry.validMcVersions}" } - entry.copy( - projectName = null, - curse = entry.curse.copy( - projectID = ProjectID(addonid) - ) - ).apply { - applyOverrides = entry.applyOverrides - id = entry.id ?: newName - name = entry.name ?: newName - folder = entry.folder - description = entry.description - optional = entry.optional - side = entry.side - websiteUrl = entry.websiteUrl - packageType = entry.packageType - transient = entry.transient - version = entry.version - fileName = entry.fileName - fileNameRegex = entry.fileNameRegex - validMcVersions = entry.validMcVersions - invalidMcVersions = entry.invalidMcVersions - enabled = entry.enabled - logger.trace { "after transform: $validMcVersions" } - } - } else { - entry - } - } - else -> entry - } } @@ -160,10 +120,12 @@ data class VersionPack( copy( modloader = modloader.replaceAutoCompletes(), ).apply { - modEntries = mods.map { element -> - parseEntry(element) - }.map { entry -> - transformFileEntry(entry) + modEntries = mods.flatMap { (overrideKey, modsList) -> + modsList.map { element -> + parseEntry(element) + }.map { entry -> + entry.postParse(overrideKey) + } } } }.apply { @@ -200,15 +162,7 @@ data class VersionPack( ) ), entrySet = modEntries.map { intitalEntry -> - val entryId = intitalEntry.id - val entry = intitalEntry.applyOverrides.fold(intitalEntry) { acc, overrideId -> - val entryOverride = - overrides[overrideId] ?: error("$entryId: override for id $overrideId not found") - return@fold acc.applyTag(entryOverride) - } - entry.toEntry().also { - logger.trace { "toEntry() ${it.id} ${entry.validMcVersions} -> $it" } - } + intitalEntry.toEntry(overrides) }.toMutableSet() ).apply {