big ol' refactor of the Gradle Factorio Mod

- handle launching in multiple OSes
- specific tasks for specific mod operations
- extension object for settings
- ground work for multiple mods
This commit is contained in:
Adam 2022-12-18 01:40:40 +01:00
parent 2c9c442595
commit 9f2b9cbd5c
33 changed files with 1098 additions and 244 deletions

View file

@ -7,7 +7,7 @@ import dev.adamko.gradle.factorio.typescriptAttributes
plugins {
id("kafkatorio.conventions.lang.kotlin-multiplatform")
id("dev.adamko.factorio-mod") apply false // only needed for 'attributes' - need to split up the plugin?
id("dev.adamko.factorio-mod-library") // only needed for 'attributes' - need to split up the plugin?
kotlin("plugin.serialization")
distribution
}

View file

@ -1,38 +1,40 @@
import dev.adamko.gradle.factorio.mod_portal.FactorioModPublishTask
import dev.adamko.gradle.factorio.typescriptAttributes
import dev.adamko.gradle.factorio.factorioModAttributes
import kafkatorio.tasks.TypescriptToLuaTask
import kafkatorio.tasks.TypeScriptToLuaTask
import kotlinx.serialization.json.put
import kotlinx.serialization.json.putJsonObject
import net.swiftzer.semver.SemVer
import org.apache.tools.ant.filters.ReplaceTokens
import org.gradle.plugins.ide.idea.model.Module as IdeaImlModule
import org.gradle.plugins.ide.idea.model.Path as IdeaImlPath
plugins {
id("kafkatorio.conventions.lang.node")
id("dev.adamko.factorio-mod")
distribution
idea
}
description = "Sends in-game information to a server over the internet (requires additional setup)"
factorioMod {
modName.set("kafkatorio-events")
modTitle.set("Kafkatorio Events")
modAuthor.set("adam@adamko.dev")
factorioCompatibility.set(libs.versions.factorio.map { it.substringBeforeLast(".") })
}
// Factorio required format is:
// - filename: `mod-name_version.zip`
// - zip contains one directory, `mod-name`
//val modName: String by extra { "${rootProject.name}-events" }
extra.set("modName", "kafkatorio-events")
val modName = extra.get("modName") as String
//extra.set("modName", "kafkatorio-events")
//val modName = extra.get("modName") as String
val modDescription: String by project.extra { project.description ?: "" }
val distributionZipName: String by extra { "${modName}_${rootProject.version}.zip" }
//val modDescription: String by project.extra { project.description ?: "" }
// version of Factorio that the mod is compatible with (must only be "major.minor" - patch causes error)
val modFactorioCompatibility: Provider<String> =
libs.versions.factorio.map { SemVer.parse(it).run { "$major.$minor" } }
//val modFactorioCompatibility: Provider<String> =
// libs.versions.factorio.map { SemVer.parse(it).run { "$major.$minor" } }
//rootProject.layout.projectDirectory.file("LICENSE")
val licenseFile: RegularFile by rootProject.extra
@Suppress("UNCHECKED_CAST")
@ -42,13 +44,13 @@ val projectTokens: MapProperty<String, String> =
//val projectTokens: MapProperty<String, String> by rootProject.extra
val projectTokensX1 = projectTokens.apply {
put("mod.name", modName)
put("mod.title", "Kafkatorio Events")
put("mod.description", modDescription)
put("factorio.version", modFactorioCompatibility)
put("mod.name", factorioMod.modName)
put("mod.title", factorioMod.modTitle)
put("mod.description", factorioMod.modDescription)
put("factorio.version", factorioMod.factorioCompatibility)
}
val tsSrcDir: Directory = layout.projectDirectory.dir("src/main/typescript")
//val tsSrcDir: Directory = layout.projectDirectory.dir("src/main/typescript")
node {
@ -68,7 +70,7 @@ dependencies {
}
val typescriptToLua by tasks.registering(TypescriptToLuaTask::class) {
val typescriptToLua by tasks.registering(TypeScriptToLuaTask::class) {
dependsOn(
tasks.npmInstall,
installEventsTsSchema,
@ -77,21 +79,18 @@ val typescriptToLua by tasks.registering(TypescriptToLuaTask::class) {
inputs.file(tasks.updatePackageJson.map { it.packageJsonFile })
sourceFiles.set(tsSrcDir)
sourceFiles.from(factorioMod.mainSources.typescript.sourceDirectories)
outputDirectory.set(layout.projectDirectory.dir("src/generated/lua"))
outputDirectory.set(factorioMod.mainSources.typescript.destinationDirectory)
}
val installEventsTsSchema by tasks.registering(Sync::class) {
description = "Fetch the latest shared data-model"
description = "Fetch the latest shared TypeScript data-model"
group = project.name
dependsOn(typescriptEventsSchema)
val outputDir = layout.projectDirectory.dir("src/main/typescript/generated/")
outputs.dir(outputDir)
from(
provider { typescriptEventsSchema }
.map { eventsSchema ->
@ -107,73 +106,80 @@ val installEventsTsSchema by tasks.registering(Sync::class) {
// eachFile { relativePath = dropDirectory() }
includeEmptyDirs = false
}
into(outputDir)
into(layout.projectDirectory.dir("src/main/typescript/generated"))
}
val zipNameProvider = provider { distributionZipName }
//val zipNameProvider = provider { distributionZipName }
tasks.distZip {
val projectTokensXX22 = projectTokensX1
// val projectTokensXX22 = projectTokensX1
inputs.property("zipNameProvider", zipNameProvider)
inputs.property("projectTokens", projectTokensXX22)
archiveFileName.set(zipNameProvider)
// inputs.property("zipNameProvider", zipNameProvider)
// inputs.property("projectTokens", projectTokensXX22)
val distributionZipName = factorioMod.distributionZipName
archiveFileName.set(distributionZipName)
}
val publishModToPortal by tasks.registering(FactorioModPublishTask::class) {
dependsOn(tasks.check)
distributionZip.set(tasks.distZip.flatMap { it.archiveFile })
val projectModName = project.extra.get("modName") as String
modName.set(projectModName)
modVersion.set(project.version.toString())
// val projectModName = project.extra.get("modName") as String
modName.set(factorioMod.modName)
modVersion.set(factorioMod.modVersion)
// modVersion.set(project.version.toString())
}
distributions {
main {
distributionBaseName.set(modName)
val tokens333: MutableMap<String, String> = projectTokensX1.get()
contents {
from(layout.projectDirectory.dir("src/main/resources/mod-data")) {
include("**/**")
}
from(licenseFile)
from(typescriptToLua.map { it.outputDirectory })
filesNotMatching("**/*.png") {
// maybe make a bug report for projectTokensX1 causing null$null$null error?
// val tokens333: MutableMap<String, String> = projectTokensX1.get()
filter<ReplaceTokens>("tokens" to tokens333)
}
includeEmptyDirs = false
exclude {
// exclude empty files
it.file.run {
isFile && useLines { lines -> lines.all { line -> line.isBlank() } }
}
}
}
tasks.assembleFactorioModContents {
modFiles.apply {
from(typescriptToLua.map { it.outputDirectory })
from(licenseFile)
}
}
//distributions {
// main {
//
//// distributionBaseName.set(factorioMod.modName)
// val tokens333: MutableMap<String, String> = projectTokensX1.get()
//
// contents {
//// from(factorioMod.mainSources.resources) {
//// include("**/**")
//// }
// from(licenseFile)
// from(typescriptToLua.map { it.outputDirectory })
// filesNotMatching("**/*.png") {
// // maybe make a bug report for projectTokensX1 causing null$null$null error?
// // val tokens333: MutableMap<String, String> = projectTokensX1.get()
// filter<ReplaceTokens>("tokens" to tokens333)
// }
//// includeEmptyDirs = false
//// exclude {
//// // exclude empty files
//// it.file.run {
//// isFile && useLines { lines -> lines.all { line -> line.isBlank() } }
//// }
//// }
// }
// }
//}
tasks.withType<Zip>().configureEach {
val projectTokensXX444 = projectTokensX1
inputs.property("projectTokens", projectTokensXX444)
}
val factorioModProvider by configurations.registering {
asProvider()
factorioModAttributes(objects)
outgoing.artifact(tasks.distZip.flatMap { it.archiveFile })
}
//val factorioModProvider by configurations.registering {
// asProvider()
// factorioModAttributes(objects)
// outgoing.artifact(tasks.distZip.flatMap { it.archiveFile })
//}
val projectPackageJsonName: Provider<String> =
@ -202,49 +208,51 @@ tasks.updatePackageJson {
tasks.assemble { dependsOn(installEventsTsSchema, tasks.updatePackageJson) }
val typescriptSrcDir: File = file("src/main/typescript")
val luaSrcDir: File = file("src/generated/lua")
val resourcesDir: File = file("src/main/resources")
val typescriptTestSrcDir: File = file("src/test/typescript")
val generatedSrcDir: File = file("src/generated")
idea {
module {
sourceDirs.plusAssign(
listOf(
typescriptSrcDir,
luaSrcDir,
)
)
// sourceDirs = sourceDirs + file("src/main/lua")
resourceDirs = resourceDirs + resourcesDir
testSourceDirs = testSourceDirs + typescriptTestSrcDir
generatedSourceDirs = generatedSourceDirs + generatedSrcDir
// excludeDirs = excludeDirs + generatedSrcDir
iml {
whenMerged {
require(this is IdeaImlModule)
sourceDirs.plusAssign(
listOf(
typescriptSrcDir,
luaSrcDir,
)
)
generatedSourceFolders.plusAssign(
IdeaImlPath(luaSrcDir.toURI().toString())
)
resourceDirs = resourceDirs + resourcesDir
testSourceDirs = testSourceDirs + typescriptTestSrcDir
// excludeDirs = excludeDirs + generatedSrcDir
}
}
}
}
//val typescriptSrcDir: File = file("src/main/typescript")
//val luaSrcDir: File = file("src/generated/lua")
//val resourcesDir: File = file("src/main/resources")
//val typescriptTestSrcDir: File = file("src/test/typescript")
//val generatedSrcDir: File = file("src/generated")
//
//
//idea {
// module {
// sourceDirs.plusAssign(
// listOf(
// typescriptSrcDir,
// luaSrcDir,
// )
// )
//// sourceDirs = sourceDirs + file("src/main/lua")
// resourceDirs = resourceDirs + resourcesDir
// testSources.from(typescriptTestSrcDir)
//// testSourceDirs = testSourceDirs + typescriptTestSrcDir
//
// generatedSourceDirs = generatedSourceDirs + generatedSrcDir
//// excludeDirs = excludeDirs + generatedSrcDir
//
// iml {
// whenMerged {
// require(this is IdeaImlModule)
//
// sourceDirs.plusAssign(
// listOf(
// typescriptSrcDir,
// luaSrcDir,
// )
// )
//
// generatedSourceFolders.plusAssign(
// IdeaImlPath(luaSrcDir.toURI().toString())
// )
// resourceDirs = resourceDirs + resourcesDir
// testSources.from(typescriptTestSrcDir)
//// testSourceDirs = testSourceDirs + typescriptTestSrcDir
//// excludeDirs = excludeDirs + generatedSrcDir
// }
// }
// }
//}
// trying to get Gradle+idea to recognise the ts-src...

View file

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 8 KiB

After

Width:  |  Height:  |  Size: 8 KiB

Before After
Before After

View file

@ -18,6 +18,7 @@ dependencies {
implementation(platform(projects.modules.versionsPlatform))
implementation(libs.kafka.streams)
implementation(kotlin("reflect"))
testImplementation(libs.kafka.streamsTestUtils)

View file

@ -18,13 +18,13 @@ val clientModsDirectory: DirectoryProperty = objects.directoryProperty().apply {
set(modDir)
}
}
val factorioGameId = "427520"
val steamExe: RegularFileProperty = objects.fileProperty().apply {
val steam = File("""C:\Program Files (x86)\Steam\steam.exe""")
if (steam.exists()) {
set(steam)
}
}
//val factorioGameId = "427520"
//val steamExe: RegularFileProperty = objects.fileProperty().apply {
// val steam = File("""C:\Program Files (x86)\Steam\steam.exe""")
// if (steam.exists()) {
// set(steam)
// }
//}
//val factorioMod: Configuration by configurations.creating {
// asConsumer()
@ -37,21 +37,21 @@ dependencies {
//<editor-fold desc="Mod deployment tasks">
val deployModToLocalClient by tasks.registering(Copy::class) {
description = "Copy the mod to the Factorio client"
group = FactorioModPlugin.TASK_GROUP
val clientModsDirectory123 = clientModsDirectory
onlyIf { clientModsDirectory123.orNull?.asFile?.exists() == true }
from(configurations.factorioMod.map { it.incoming.artifactView { lenient(true) }.files })
into(clientModsDirectory)
doLast {
logger.lifecycle("Copying mod from ${source.files} to $destinationDir")
}
}
//val deployModToLocalClient by tasks.registering(Copy::class) {
// description = "Copy the mod to the Factorio client"
// group = FactorioModPlugin.TASK_GROUP
//
// val clientModsDirectory123 = clientModsDirectory
//
// onlyIf { clientModsDirectory123.orNull?.asFile?.exists() == true }
//
// from(configurations.factorioMod.map { it.incoming.artifactView { lenient(true) }.files })
// into(clientModsDirectory)
//
// doLast {
// logger.lifecycle("Copying mod from ${source.files} to $destinationDir")
// }
//}
//</editor-fold>
@ -59,27 +59,27 @@ val deployModToLocalClient by tasks.registering(Copy::class) {
fun ExecOperations.isFactorioRunning(): Spec<Task> = ProcessRunningSpec(this, "factorio.exe")
val clientLaunch by tasks.registering(Exec::class) {
description = "Run local Factorio Steam game client"
group = FactorioModPlugin.TASK_GROUP
val steamExe123 = steamExe
val clientModsDirectory444 = clientModsDirectory
onlyIf(!serviceOf<ExecOperations>().isFactorioRunning())
onlyIf { steamExe123.orNull?.asFile?.exists() == true }
onlyIf { clientModsDirectory444.orNull?.asFile?.exists() == true }
dependsOn(deployModToLocalClient)
mustRunAfter(clientKill, ":modules:infra-factorio-server:processRun")
commandLine = parseSpaceSeparatedArgs(
// """explorer "steam://rungameid/$factorioGameId// --mp-connect localhost/" """ // not working
// """explorer "steam://run/$factorioGameId//--mp-connect localhost/" """ // works! But has annoying pop-up
""" ${steamExe.asFile.orNull?.canonicalPath} -applaunch $factorioGameId --mp-connect localhost --mod-directory ${clientModsDirectory.asFile.orNull?.canonicalPath} """
)
doFirst { logger.lifecycle("Launching factorio.exe") }
}
//val clientLaunch by tasks.registering(Exec::class) {
// description = "Run local Factorio Steam game client"
// group = FactorioModPlugin.TASK_GROUP
//
// val steamExe123 = steamExe
// val clientModsDirectory444 = clientModsDirectory
//
// onlyIf(!serviceOf<ExecOperations>().isFactorioRunning())
// onlyIf { steamExe123.orNull?.asFile?.exists() == true }
// onlyIf { clientModsDirectory444.orNull?.asFile?.exists() == true }
//
// dependsOn(deployModToLocalClient)
// mustRunAfter(clientKill, ":modules:infra-factorio-server:processRun")
//
// commandLine = parseSpaceSeparatedArgs(
//// """explorer "steam://rungameid/$factorioGameId// --mp-connect localhost/" """ // not working
//// """explorer "steam://run/$factorioGameId//--mp-connect localhost/" """ // works! But has annoying pop-up
// """ ${steamExe.asFile.orNull?.canonicalPath} -applaunch $factorioGameId --mp-connect localhost --mod-directory ${clientModsDirectory.asFile.orNull?.canonicalPath} """
// )
// doFirst { logger.lifecycle("Launching factorio.exe") }
//}
val clientKill by tasks.registering(Exec::class) {
description = "Stop the local Factorio Steam game client"
@ -95,14 +95,14 @@ val clientKill by tasks.registering(Exec::class) {
tasks.register(FactorioModPlugin.PUBLISH_MOD_LOCAL_TASK_NAME) {
group = FactorioModPlugin.TASK_GROUP
dependsOn(deployModToLocalClient)
// dependsOn(deployModToLocalClient)
}
tasks.processRun {
dependsOn(
deployModToLocalClient,
clientLaunch,
// deployModToLocalClient,
tasks.launchFactorioClient,
)
}

View file

@ -3,7 +3,7 @@ import dev.adamko.gradle.factorio.FactorioModPlugin
plugins {
id("kafkatorio.conventions.base")
id("dev.adamko.geedeecee")
id("dev.adamko.factorio-mod")
id("dev.adamko.factorio-mod-library")
idea
}