feat: allow to pass in relative paths for input files and add assets file
This commit is contained in:
@@ -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 {
|
||||||
|
|||||||
@@ -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()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user