diff --git a/TestProjectKt/build.gradle.kts b/TestProjectKt/build.gradle.kts index b78da81..4658eb3 100644 --- a/TestProjectKt/build.gradle.kts +++ b/TestProjectKt/build.gradle.kts @@ -98,11 +98,14 @@ runMindustry { official(version = "v146") putDataAt(file = buildDir.resolve("customDataDir")) } - addClient("default data dir"){ + addClient("default data dir") { official(version = "v146") modpack = null useDefaultDataDir() } + addClient("from url") { + url("https://github.com/Anuken/Mindustry/releases/download/v146/Mindustry.jar") + } addClient("debugging") { official(version = "v146") useModpack(name = "for debugging 2") diff --git a/main/src/dsl/FileSystem.kt b/main/src/dsl/FileSystem.kt index 19c3c8e..8da103f 100644 --- a/main/src/dsl/FileSystem.kt +++ b/main/src/dsl/FileSystem.kt @@ -23,6 +23,7 @@ fun InputStream.copyToTmpAndMove(file: File) { this.use { it.copyTo(tmp) } + file.ensureParentDir() tmp.renameTo(file) // ignore the error when deleting the temp file runCatching { diff --git a/main/src/run/model/GameSide.kt b/main/src/run/model/GameSide.kt index b0e8ef3..46693cf 100644 --- a/main/src/run/model/GameSide.kt +++ b/main/src/run/model/GameSide.kt @@ -7,6 +7,7 @@ import io.github.liplum.mindustry.LocalProperties.local import org.gradle.api.Action import org.gradle.api.Project import java.io.File +import java.net.URL enum class GameSideType { Client, Server @@ -225,8 +226,16 @@ abstract class AddGameSideSpec { } } + fun url(url: URL) { + UrlGameLoc(url).checkAndSet() + } + + fun url(url: String) { + this.url(URL(url)) + } + fun localFile(path: String) { - LocalGameLoc(File(path)).checkAndSet() + this.localFile(File(path)) } fun localFile(file: File) { diff --git a/main/src/run/model/Games.kt b/main/src/run/model/Games.kt index 67bc289..e030249 100644 --- a/main/src/run/model/Games.kt +++ b/main/src/run/model/Games.kt @@ -24,6 +24,18 @@ sealed interface IDownloadableGameLoc : IGameLoc { sealed interface ILatestDownloadableGameLoc : IDownloadableGameLoc +data class UrlGameLoc( + val url: URL +) : IDownloadableGameLoc { + override fun resolveDownloadSrc(): URL = url + + override val fileName4Local: String = "${url.resolve4FileName()}.jar" + + override fun resolveCacheFile(): File { + return SharedCache.gamesDir.resolve("url").resolve(fileName4Local) + } +} + data class GitHubGameLoc( val user: String, val repo: String, diff --git a/main/src/run/model/Mods.kt b/main/src/run/model/Mods.kt index 196faf6..0f5c32a 100644 --- a/main/src/run/model/Mods.kt +++ b/main/src/run/model/Mods.kt @@ -52,18 +52,10 @@ data class UrlMod( ) : IMod { constructor(url: String) : this(URL(url)) - override val fileName4Local: String = run { - val path: String = url.path - val last = path.substring(path.lastIndexOf('/') + 1) - if (last.endsWith(".zip")) last else "$last.zip" - } + override val fileName4Local: String = "${url.resolve4FileName()}.zip" override fun resolveCacheFile(): File { - val urlInBytes = MessageDigest - .getInstance("SHA-1") - .digest(url.toString().toByteArray()) - val urlHashed = urlInBytes.toString() - return SharedCache.modsDir.resolve("url").resolve(urlHashed) + return SharedCache.modsDir.resolve("url").resolve(fileName4Local) } } diff --git a/main/src/run/model/Utils.kt b/main/src/run/model/Utils.kt new file mode 100644 index 0000000..3f473e1 --- /dev/null +++ b/main/src/run/model/Utils.kt @@ -0,0 +1,18 @@ +package io.github.liplum.mindustry + +import java.net.URL +import java.security.MessageDigest + +fun URL.resolve4FileName(): String { + val urlInBytes = MessageDigest + .getInstance("SHA-1") + .digest(this.toString().toByteArray()) + + // Convert the byte array to a hexadecimal string + val hexString = StringBuilder() + for (byte in urlInBytes) { + hexString.append(String.format("%02x", byte)) + } + + return hexString.toString() +} \ No newline at end of file