feat: allow to pass in relative paths for input files and add assets file

This commit is contained in:
Cody Adam
2026-01-13 18:48:52 +01:00
committed by GitHub
parent 4f7cabf1d1
commit b7b84b47ba
2 changed files with 66 additions and 31 deletions

View File

@@ -28,9 +28,8 @@ dependencies {
// Configure server testing // Configure server testing
runHytale { runHytale {
// TODO: Update this URL when Hytale server is available jarUrl = "./HytaleServer.jar"
// Using Paper server as placeholder for testing the runServer functionality assetsPath = "./Assets.zip"
jarUrl = "https://fill-data.papermc.io/v1/objects/d5f47f6393aa647759f101f02231fa8200e5bccd36081a3ee8b6a5fd96739057/paper-1.21.10-115.jar"
} }
tasks { tasks {

View File

@@ -5,6 +5,7 @@ import org.gradle.api.tasks.Input
import org.gradle.api.tasks.TaskAction import org.gradle.api.tasks.TaskAction
import org.gradle.api.tasks.TaskProvider import org.gradle.api.tasks.TaskProvider
import java.io.File import java.io.File
import java.io.InputStream
import java.net.URI import java.net.URI
import java.security.MessageDigest import java.security.MessageDigest
@@ -14,30 +15,24 @@ import java.security.MessageDigest
* Usage: * Usage:
* runHytale { * runHytale {
* jarUrl = "https://example.com/hytale-server.jar" * jarUrl = "https://example.com/hytale-server.jar"
* assetsPath = "Assets.zip"
* } * }
* *
* ./gradlew runServer * ./gradlew runServer
*/ */
open class RunHytalePlugin : Plugin<Project> { open class RunHytalePlugin : Plugin<Project> {
override fun apply(project: Project) { override fun apply(project: Project) {
// Create extension for configuration
val extension = project.extensions.create("runHytale", RunHytaleExtension::class.java) val extension = project.extensions.create("runHytale", RunHytaleExtension::class.java)
// Register the runServer task val runTask = project.tasks.register("runServer", RunServerTask::class.java) {
val runTask: TaskProvider<RunServerTask> = project.tasks.register(
"runServer",
RunServerTask::class.java
) {
jarUrl.set(extension.jarUrl) jarUrl.set(extension.jarUrl)
extension.assetsPath?.let { assetsPath.set(it) }
group = "hytale" group = "hytale"
description = "Downloads and runs the Hytale server with your plugin" description = "Downloads and runs the Hytale server with your plugin"
} }
// Make runServer depend on shadowJar (build plugin first)
project.tasks.findByName("shadowJar")?.let { project.tasks.findByName("shadowJar")?.let {
runTask.configure { runTask.configure { dependsOn(it) }
dependsOn(it)
}
} }
} }
} }
@@ -47,6 +42,7 @@ open class RunHytalePlugin : Plugin<Project> {
*/ */
open class RunHytaleExtension { open class RunHytaleExtension {
var jarUrl: String = "https://example.com/hytale-server.jar" var jarUrl: String = "https://example.com/hytale-server.jar"
var assetsPath: String? = null
} }
/** /**
@@ -57,6 +53,9 @@ open class RunServerTask : DefaultTask() {
@Input @Input
val jarUrl = project.objects.property(String::class.java) val jarUrl = project.objects.property(String::class.java)
@Input
val assetsPath = project.objects.property(String::class.java)
@TaskAction @TaskAction
fun run() { fun run() {
// Create directories // Create directories
@@ -70,17 +69,26 @@ open class RunServerTask : DefaultTask() {
"hytale-cache" "hytale-cache"
).apply { mkdirs() } ).apply { mkdirs() }
// Compute hash of URL for caching // Normalize jarUrl to URI
val jarUrlStr = jarUrl.get()
val jarUri = when {
jarUrlStr.startsWith("file://") -> URI.create(jarUrlStr)
jarUrlStr.startsWith("http://") || jarUrlStr.startsWith("https://") -> URI.create(jarUrlStr)
File(jarUrlStr).isAbsolute -> File(jarUrlStr).toURI()
else -> File(project.projectDir, jarUrlStr).toURI()
}
// Compute hash of URI for caching
val urlHash = MessageDigest.getInstance("SHA-256") val urlHash = MessageDigest.getInstance("SHA-256")
.digest(jarUrl.get().toByteArray()) .digest(jarUri.toString().toByteArray())
.joinToString("") { "%02x".format(it) } .joinToString("") { "%02x".format(it) }
val cachedJar = File(cacheDir, "$urlHash.jar") val cachedJar = File(cacheDir, "$urlHash.jar")
// Download server JAR if not cached // Download server JAR if not cached
if (!cachedJar.exists()) { if (!cachedJar.exists()) {
println("Downloading Hytale server from ${jarUrl.get()}") println("Downloading Hytale server from ${jarUri}")
try { try {
URI.create(jarUrl.get()).toURL().openStream().use { input -> jarUri.toURL().openStream().use { input ->
cachedJar.outputStream().use { output -> cachedJar.outputStream().use { output ->
input.copyTo(output) input.copyTo(output)
} }
@@ -108,6 +116,29 @@ open class RunServerTask : DefaultTask() {
println("WARNING: Could not find shadowJar output") println("WARNING: Could not find shadowJar output")
} }
// Copy assets file (mandatory)
val assetsPathStr = assetsPath.orNull
?: throw IllegalStateException(
"assetsPath is required but not set. " +
"Please configure it in build.gradle.kts: runHytale { assetsPath = \"Assets.zip\" }"
)
val sourceAssets = when {
assetsPathStr.startsWith("file://") -> File(URI.create(assetsPathStr))
File(assetsPathStr).isAbsolute -> File(assetsPathStr)
else -> File(project.projectDir, assetsPathStr)
}
if (!sourceAssets.exists()) {
throw IllegalStateException(
"Assets file not found: ${sourceAssets.absolutePath}. " +
"Please ensure assetsPath is correctly configured in build.gradle.kts"
)
}
val assetsFile = File(runDir, sourceAssets.name)
sourceAssets.copyTo(assetsFile, overwrite = true)
println("Assets copied to: ${assetsFile.absolutePath}")
println("Starting Hytale server...") println("Starting Hytale server...")
println("Press Ctrl+C to stop the server") println("Press Ctrl+C to stop the server")
@@ -122,6 +153,10 @@ open class RunServerTask : DefaultTask() {
javaArgs.addAll(listOf("-jar", jarFile.name)) javaArgs.addAll(listOf("-jar", jarFile.name))
// Add assets argument (mandatory)
javaArgs.add("--assets")
javaArgs.add(assetsFile.name)
// Start the server process // Start the server process
val process = ProcessBuilder("java", *javaArgs.toTypedArray()) val process = ProcessBuilder("java", *javaArgs.toTypedArray())
.directory(runDir) .directory(runDir)
@@ -135,19 +170,9 @@ open class RunServerTask : DefaultTask() {
} }
} }
// Forward stdout to console // Forward process streams to console
Thread { forwardStream(process.inputStream) { println(it) }
process.inputStream.bufferedReader().useLines { lines -> forwardStream(process.errorStream) { System.err.println(it) }
lines.forEach { println(it) }
}
}.start()
// Forward stderr to console
Thread {
process.errorStream.bufferedReader().useLines { lines ->
lines.forEach { System.err.println(it) }
}
}.start()
// Forward stdin to server (for commands) // Forward stdin to server (for commands)
Thread { Thread {
@@ -163,4 +188,15 @@ open class RunServerTask : DefaultTask() {
val exitCode = process.waitFor() val exitCode = process.waitFor()
println("Server exited with code $exitCode") println("Server exited with code $exitCode")
} }
/**
* Forwards an input stream to a consumer in a background thread.
*/
private fun forwardStream(inputStream: InputStream, consumer: (String) -> Unit) {
Thread {
inputStream.bufferedReader().useLines { lines ->
lines.forEach(consumer)
}
}.start()
}
} }