Convert buildSrc from gradle/groovy to kts/kotlin

This commit is contained in:
2026-07-05 14:14:04 +02:00
parent 6fd3e6f690
commit 9e7311934f
7 changed files with 412 additions and 372 deletions
-8
View File
@@ -19,7 +19,6 @@
plugins {
`kotlin-dsl`
`groovy-gradle-plugin`
}
repositories {
@@ -27,13 +26,6 @@ repositories {
gradlePluginPortal()
}
sourceSets {
main {
groovy.srcDirs("src/main/groovy")
kotlin.srcDirs("src/main/kotlin")
}
}
dependencies {
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:2.2.21")
}
@@ -1,348 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2026 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import java.security.MessageDigest
import java.util.stream.Collectors
plugins {
}
class DevServer extends DefaultTask {
@Input
boolean debug = false
@Input
String template = null
@Input
@Optional
String plugins = null
@Input
@Optional
Integer port = null
@Input
@Optional
String jar = null
@Input
@Optional
Map<String, String> dParams = new HashMap<>()
@Input
@Optional
String jvmArgs = null
@Input
@Optional
String checkpointFolder = null
@Input
@Optional
Boolean profile = null
@Input
@Optional
Boolean forceUpgrade = null
@Input
@Optional
String worldName = null
DevServer() {
super()
doFirst {
if (checkpointFolder != null) dParams.put("checkpoint", checkpointFolder)
List<Project> projects = []
projects.add(project)
while (projects.first.parent != null) {
projects.add(0, projects.first.parent)
}
def properties = new Properties()
projects.forEach {
def file = new File(it.projectDir, "steamwar.properties")
if (file.exists()) {
properties.load(new FileInputStream(file))
}
}
if (template.startsWith("Bau")) {
if (properties.containsKey("worldName")) {
worldName = properties.get("worldName")
} else {
throw new GradleException("Please supply the 'worldName' in a 'steamwar.properties' files either in this project dir or any parent project!")
}
}
host = properties.get("host")
debugPort = new Random().nextInt(5001, 10000)
if (host == null) {
throw new GradleException("Please supply the 'host' in a 'steamwar.properties' files either in this project dir or any parent project!")
}
}
doLast {
setupTemplate(template)
uploadDependencies()
if (debug) startDebugPort()
startDevServer()
}
finalizedBy(new Finalizer())
}
@Internal
BufferedWriter processInput
@Internal
String host
@Internal
int debugPort
@Internal
Boolean running = true
class Finalizer extends DefaultTask {
Finalizer() {
super()
doLast {
if (processInput != null) {
processInput.write(template.endsWith("Velocity") ? "end\n" : "stop\n")
processInput.flush()
}
running = false
}
}
}
private Process run(String... args) {
List<String> arguments = new ArrayList<>();
arguments.add("ssh")
arguments.add(host)
arguments.add("-T")
arguments.addAll(Arrays.asList(args))
def process = new ProcessBuilder(arguments).start()
process.waitFor()
return process
}
private boolean checkFileOnRemote(String path) {
def process = run("[ -e \"$path\" ] && echo \"true\"")
process.errorStream.close()
process.outputStream.close()
try (def reader = new BufferedReader(new InputStreamReader(process.inputStream))) {
return reader.lines().count() > 0
}
}
private static void closeProcess(Process process) {
process.outputStream.close()
process.inputStream.close()
process.errorStream.close()
}
void setupTemplate(String template) {
if (checkFileOnRemote("$template")) return
if (checkFileOnRemote("/configs/GameModes/${template}.yml")) {
println("GameMode Config exists")
def process = run("cat /configs/GameModes/${template}.yml | grep \"Folder: \"")
String serverTemplateName = new BufferedReader(new InputStreamReader(process.inputStream)).lines().collect(Collectors.joining("\n"))
.trim()
.substring("Folder: ".length())
DevServer.closeProcess(process)
setupTemplate(serverTemplateName)
run("ln -s $serverTemplateName $template")
return
}
if (!checkFileOnRemote("/servers/$template")) {
throw new GradleException("Used template ($template) is not in /servers/ directory of the given host $host")
}
DevServer.closeProcess(run("cp -r /servers/$template $template"))
DevServer.closeProcess(run("chmod u+w $template"))
DevServer.closeProcess(run("rm -r $template/plugins/*WorldEdit/"))
DevServer.closeProcess(run("rm $template/log4j2.xml"))
}
void uploadDependencies() {
def base = plugins == null ? "$template/plugins" : plugins
println("Uploading to ~/$base")
this.dependsOn.forEach {
Project resolved
AbstractArchiveTask archiveTask
if (it instanceof String) {
resolved = project.findProject(it.substring(0, it.lastIndexOf(':')))
archiveTask = (AbstractArchiveTask) resolved.tasks.findByName(it.substring(it.lastIndexOf(':') + 1))
} else {
throw new GradleException("Illegal argument for uploading dependencies")
}
def archive = archiveTask.archiveFile.get().asFile
Process process = new ProcessBuilder("ssh", host, "-T", "sha1sum $base/${archive.name.replace("-all", "")}").start()
byte[] bytes = MessageDigest.getInstance("sha1").digest(archive.bytes)
StringBuilder sb = new StringBuilder()
for (byte b : bytes) {
sb.append(String.format("%02X", b))
}
boolean same = false
process.inputStream.readLines().forEach {
same |= it.startsWith(sb.toString().toLowerCase())
}
DevServer.closeProcess(process)
if (same) {
println("Skipping $archive")
return
}
println("Uploading $archive")
process = new ProcessBuilder("ssh", host, "-T", "rm $base/${archive.name.replace("-all", "")}").start()
process.waitFor()
DevServer.closeProcess(process)
process = new ProcessBuilder("scp", archive.absolutePath, "$host:~/$base/${archive.name.replace("-all", "")}").start();
process.waitFor()
DevServer.closeProcess(process)
println("Uploaded $archive")
}
}
void startDebugPort() {
def process = new ProcessBuilder("ssh", host, "-L", "5005:localhost:$debugPort").start()
def processOutput = new BufferedReader(new InputStreamReader(process.inputStream))
new Thread({
while (running) {
}
processOutput.close()
process.errorStream.close()
}).start()
}
void startDevServer() {
def devPy = new StringBuilder().append("sw dev")
if (port != null) devPy.append(" --port $port")
if (worldName != null) devPy.append(" -w $template/$worldName")
if (plugins != null) devPy.append(" -p $plugins")
if (profile != null) devPy.append(" --profile")
if (forceUpgrade != null) devPy.append(" --forceUpgrade")
if (jar != null) devPy.append(" --jar $jar")
devPy.append(" $template")
for (Map.Entry<String, String> dParam : dParams.entrySet()) {
devPy.append(" -D${dParam.key}=${dParam.value}")
}
devPy.append(" -Dpaper.disablePluginRemapping=true")
if (debug) devPy.append(" -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:$debugPort")
devPy.append(" -javaagent:/jars/AccessWidener.jar=start")
if (jvmArgs != null) devPy.append(" $jvmArgs")
println("Starting $template with command ${devPy.toString()}")
def process = new ProcessBuilder("ssh", host, "-T", devPy.toString()).start()
def processOutput = new BufferedReader(new InputStreamReader(process.inputStream))
new Thread({
while (running) {
if (processOutput.ready()) {
println(processOutput.readLine())
}
}
processOutput.close()
process.errorStream.close()
}).start()
processInput = new BufferedWriter(new OutputStreamWriter(process.outputStream))
def input = new BufferedReader(new InputStreamReader(System.in))
new Thread({
while (running) {
def text = input.readLine()
if (text == null) break
processInput.write(text)
processInput.newLine()
processInput.flush()
}
}).start()
process.waitFor()
if (processInput != null) {
processInput.close()
}
processInput = null
running = false
}
}
class VelocityServer extends DevServer {
@Input
@Optional
Boolean packetDecodeLogging = false
VelocityServer() {
super()
doFirst {
if (packetDecodeLogging) dParams.put("velocity.packet-decode-logging", "true")
}
}
}
class FightServer extends DevServer {
@Input
@Optional
Integer checkSchemID = 0
@Input
@Optional
Integer prepareSchemID = 0
@Input
@Optional
Integer replay = 0
@Input
@Optional
String config = null
@Input
@Optional
// Property: fightID
Integer eventKampfID = 0
@Input
@Optional
UUID blueLeader = null
@Input
@Optional
UUID redLeader = null
FightServer() {
super()
doFirst {
if (checkSchemID != 0) dParams.put("checkSchemID", "$checkSchemID")
if (prepareSchemID != 0) dParams.put("prepareSchemID", "$prepareSchemID")
if (replay != 0) dParams.put("replay", "$replay")
if (eventKampfID != 0) dParams.put("fightID", "$eventKampfID")
if (blueLeader != null) dParams.put("blueLeader", blueLeader.toString())
if (redLeader != null) dParams.put("redLeader", redLeader.toString())
if (config != null) dParams.put("config", config)
}
}
}
+290
View File
@@ -0,0 +1,290 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2026 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import org.gradle.api.DefaultTask
import org.gradle.api.GradleException
import org.gradle.api.Project
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.bundling.AbstractArchiveTask
import java.io.BufferedReader
import java.io.BufferedWriter
import java.io.File
import java.io.FileInputStream
import java.io.InputStreamReader
import java.io.OutputStreamWriter
import java.security.MessageDigest
import java.util.Properties
import java.util.Random
import java.util.stream.Collectors
open class DevServer : DefaultTask() {
@get:Input
var debug: Boolean = false
@get:Input
var template: String? = null
@get:Input
@get:Optional
var plugins: String? = null
@get:Input
@get:Optional
var port: Int? = null
@get:Input
@get:Optional
var jar: String? = null
@get:Input
@get:Optional
var dParams: MutableMap<String, String> = HashMap()
@get:Input
@get:Optional
var jvmArgs: String? = null
@get:Input
@get:Optional
var checkpointFolder: String? = null
@get:Input
@get:Optional
var profile: Boolean? = null
@get:Input
@get:Optional
var forceUpgrade: Boolean? = null
@get:Input
@get:Optional
var worldName: String? = null
@get:Internal
var processInput: BufferedWriter? = null
@get:Internal
var host: String? = null
@get:Internal
var debugPort: Int = 0
@get:Internal
var running: Boolean = true
init {
doFirst {
checkpointFolder?.let { dParams.put("checkpoint", it) }
val projects = mutableListOf<Project>()
projects.add(project)
while (projects[0].parent != null) {
projects.add(0, projects[0].parent!!)
}
val properties = Properties()
projects.forEach {
val file = File(it.projectDir, "steamwar.properties")
if (file.exists()) {
FileInputStream(file).use { input -> properties.load(input) }
}
}
if (template!!.startsWith("Bau")) {
if (properties.containsKey("worldName")) {
worldName = properties.getProperty("worldName")
} else {
throw GradleException("Please supply the 'worldName' in a 'steamwar.properties' files either in this project dir or any parent project!")
}
}
host = properties.getProperty("host")
debugPort = Random().nextInt(5001, 10000)
if (host == null) {
throw GradleException("Please supply the 'host' in a 'steamwar.properties' files either in this project dir or any parent project!")
}
}
doLast {
setupTemplate(template!!)
uploadDependencies()
if (debug) startDebugPort()
startDevServer()
}
finalizedBy(Finalizer())
}
inner class Finalizer : DefaultTask() {
init {
doLast {
processInput?.let {
it.write(if (template!!.endsWith("Velocity")) "end\n" else "stop\n")
it.flush()
}
running = false
}
}
}
private fun run(vararg args: String): Process {
val arguments = mutableListOf("ssh", host, "-T")
arguments.addAll(args)
val process = ProcessBuilder(arguments).start()
process.waitFor()
return process
}
private fun checkFileOnRemote(path: String): Boolean {
val process = run("[ -e \"$path\" ] && echo \"true\"")
process.errorStream.close()
process.outputStream.close()
return BufferedReader(InputStreamReader(process.inputStream)).use { reader ->
reader.lines().count() > 0
}
}
private fun closeProcess(process: Process) {
process.outputStream.close()
process.inputStream.close()
process.errorStream.close()
}
fun setupTemplate(template: String) {
if (checkFileOnRemote(template)) return
if (checkFileOnRemote("/configs/GameModes/$template.yml")) {
println("GameMode Config exists")
val process = run("cat /configs/GameModes/$template.yml | grep \"Folder: \"")
val serverTemplateName = BufferedReader(InputStreamReader(process.inputStream)).lines()
.collect(Collectors.joining("\n"))
.trim()
.substring("Folder: ".length)
closeProcess(process)
setupTemplate(serverTemplateName)
run("ln -s $serverTemplateName $template")
return
}
if (!checkFileOnRemote("/servers/$template")) {
throw GradleException("Used template ($template) is not in /servers/ directory of the given host $host")
}
closeProcess(run("cp -r /servers/$template $template"))
closeProcess(run("chmod u+w $template"))
closeProcess(run("rm -r $template/plugins/*WorldEdit/"))
closeProcess(run("rm $template/log4j2.xml"))
}
fun uploadDependencies() {
val base = if (plugins == null) "$template/plugins" else plugins
println("Uploading to ~/$base")
this.dependsOn.forEach {
if (it !is String) {
throw GradleException("Illegal argument for uploading dependencies")
}
val resolved = project.findProject(it.substring(0, it.lastIndexOf(':')))!!
val archiveTask = resolved.tasks.findByName(it.substring(it.lastIndexOf(':') + 1)) as AbstractArchiveTask
val archive = archiveTask.archiveFile.get().asFile
var process = ProcessBuilder("ssh", host, "-T", "sha1sum $base/${archive.name.replace("-all", "")}").start()
val bytes = MessageDigest.getInstance("sha1").digest(archive.readBytes())
val sb = StringBuilder()
for (b in bytes) {
sb.append(String.format("%02X", b))
}
var same = false
process.inputStream.bufferedReader().readLines().forEach { line ->
same = same || line.startsWith(sb.toString().lowercase())
}
closeProcess(process)
if (same) {
println("Skipping $archive")
return@forEach
}
println("Uploading $archive")
process = ProcessBuilder("ssh", host, "-T", "rm $base/${archive.name.replace("-all", "")}").start()
process.waitFor()
closeProcess(process)
process = ProcessBuilder("scp", archive.absolutePath, "$host:~/$base/${archive.name.replace("-all", "")}").start()
process.waitFor()
closeProcess(process)
println("Uploaded $archive")
}
}
fun startDebugPort() {
val process = ProcessBuilder("ssh", host, "-L", "5005:localhost:$debugPort").start()
val processOutput = BufferedReader(InputStreamReader(process.inputStream))
Thread {
while (running) {
}
processOutput.close()
process.errorStream.close()
}.start()
}
fun startDevServer() {
val devPy = StringBuilder().append("sw dev")
if (port != null) devPy.append(" --port $port")
if (worldName != null) devPy.append(" -w $template/$worldName")
if (plugins != null) devPy.append(" -p $plugins")
if (profile != null) devPy.append(" --profile")
if (forceUpgrade != null) devPy.append(" --forceUpgrade")
if (jar != null) devPy.append(" --jar $jar")
devPy.append(" $template")
for ((key, value) in dParams) {
devPy.append(" -D$key=$value")
}
devPy.append(" -Dpaper.disablePluginRemapping=true")
if (debug) devPy.append(" -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:$debugPort")
devPy.append(" -javaagent:/jars/AccessWidener.jar=start")
if (jvmArgs != null) devPy.append(" $jvmArgs")
println("Starting $template with command $devPy")
val process = ProcessBuilder("ssh", host, "-T", devPy.toString()).start()
val processOutput = BufferedReader(InputStreamReader(process.inputStream))
Thread {
while (running) {
if (processOutput.ready()) {
println(processOutput.readLine())
}
}
processOutput.close()
process.errorStream.close()
}.start()
processInput = BufferedWriter(OutputStreamWriter(process.outputStream))
val input = BufferedReader(InputStreamReader(System.`in`))
Thread {
while (running) {
val text = input.readLine() ?: break
processInput?.write(text)
processInput?.newLine()
processInput?.flush()
}
}.start()
process.waitFor()
processInput?.close()
processInput = null
running = false
}
}
+66
View File
@@ -0,0 +1,66 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2026 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Optional
import java.util.UUID
open class FightServer : DevServer() {
@get:Input
@get:Optional
var checkSchemID: Int = 0
@get:Input
@get:Optional
var prepareSchemID: Int = 0
@get:Input
@get:Optional
var replay: Int = 0
@get:Input
@get:Optional
var config: String? = null
// Property: fightID
@get:Input
@get:Optional
var eventKampfID: Int = 0
@get:Input
@get:Optional
var blueLeader: UUID? = null
@get:Input
@get:Optional
var redLeader: UUID? = null
init {
doFirst {
if (checkSchemID != 0) dParams.put("checkSchemID", "$checkSchemID")
if (prepareSchemID != 0) dParams.put("prepareSchemID", "$prepareSchemID")
if (replay != 0) dParams.put("replay", "$replay")
if (eventKampfID != 0) dParams.put("fightID", "$eventKampfID")
blueLeader?.let { dParams.put("blueLeader", it.toString()) }
redLeader?.let { dParams.put("redLeader", it.toString()) }
config?.let { dParams.put("config", it) }
}
}
}
@@ -0,0 +1,34 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2026 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Optional
open class VelocityServer : DevServer() {
@get:Input
@get:Optional
var packetDecodeLogging: Boolean = false
init {
doFirst {
if (packetDecodeLogging) dParams.put("velocity.packet-decode-logging", "true")
}
}
}
@@ -18,16 +18,18 @@
*/
plugins {
id 'java-library'
`java-library`
}
val libs = the<VersionCatalogsExtension>().named("libs")
java {
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
}
tasks.compileJava {
options.encoding "UTF-8"
options.encoding = "UTF-8"
}
sourceSets {
@@ -54,8 +56,9 @@ sourceSets {
}
dependencies {
annotationProcessor libs.lombok
compileOnly libs.lombok
testCompileOnly libs.lombok
testAnnotationProcessor libs.lombok
val lombok = libs.findLibrary("lombok").get()
annotationProcessor(lombok)
compileOnly(lombok)
testCompileOnly(lombok)
testAnnotationProcessor(lombok)
}
@@ -1,7 +1,7 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
* Copyright (C) 2026 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -18,10 +18,12 @@
*/
plugins {
id 'java-library'
id "org.jetbrains.kotlin.jvm"
`java-library`
id("org.jetbrains.kotlin.jvm")
}
val libs = the<VersionCatalogsExtension>().named("libs")
kotlin {
jvmToolchain(21)
}
@@ -32,7 +34,7 @@ java {
}
tasks.compileJava {
options.encoding "UTF-8"
options.encoding = "UTF-8"
}
sourceSets {
@@ -67,8 +69,9 @@ sourceSets {
}
dependencies {
annotationProcessor libs.lombok
compileOnly libs.lombok
testCompileOnly libs.lombok
testAnnotationProcessor libs.lombok
val lombok = libs.findLibrary("lombok").get()
annotationProcessor(lombok)
compileOnly(lombok)
testCompileOnly(lombok)
testAnnotationProcessor(lombok)
}