Launching progress
This commit is contained in:
@@ -43,20 +43,14 @@ class DefaultDependencyManager(override val repository: DefaultGameRepository, o
|
||||
|
||||
override fun installLibraryAsync(gameVersion: String, version: Version, libraryId: String, libraryVersion: String): Task {
|
||||
if (libraryId == "forge")
|
||||
return ForgeInstallTask(this, gameVersion, version, libraryVersion) then { task ->
|
||||
val newVersion = task.result!!
|
||||
VersionJSONSaveTask(this@DefaultDependencyManager, newVersion)
|
||||
}
|
||||
return ForgeInstallTask(this, gameVersion, version, libraryVersion)
|
||||
.then { VersionJSONSaveTask(this, it["version"]) }
|
||||
else if (libraryId == "liteloader")
|
||||
return LiteLoaderInstallTask(this, gameVersion, version, libraryVersion) then { task ->
|
||||
val newVersion = task.result!!
|
||||
VersionJSONSaveTask(this@DefaultDependencyManager, newVersion)
|
||||
}
|
||||
return LiteLoaderInstallTask(this, gameVersion, version, libraryVersion)
|
||||
.then { VersionJSONSaveTask(this, it["version"]) }
|
||||
else if (libraryId == "optifine")
|
||||
return OptiFineInstallTask(this, gameVersion, version, libraryVersion) then { task ->
|
||||
val newVersion = task.result!!
|
||||
VersionJSONSaveTask(this@DefaultDependencyManager, newVersion)
|
||||
}
|
||||
return OptiFineInstallTask(this, gameVersion, version, libraryVersion)
|
||||
.then { VersionJSONSaveTask(this, it["version"]) }
|
||||
else
|
||||
throw IllegalArgumentException("Library id $libraryId is unrecognized.")
|
||||
}
|
||||
|
||||
@@ -28,53 +28,48 @@ class DefaultGameBuilder(val dependencyManager: DefaultDependencyManager): GameB
|
||||
|
||||
override fun buildAsync(): Task {
|
||||
val gameVersion = gameVersion
|
||||
return VersionJSONDownloadTask(gameVersion = gameVersion) then a@{ task ->
|
||||
var version = GSON.fromJson<Version>(task.result!!) ?: return@a null
|
||||
version = version.copy(id = name, jar = null)
|
||||
var result = ParallelTask(
|
||||
GameAssetDownloadTask(dependencyManager, version),
|
||||
GameLoggingDownloadTask(dependencyManager, version),
|
||||
GameDownloadTask(version),
|
||||
GameLibrariesTask(dependencyManager, version) // Game libraries will be downloaded for multiple times partly, this time is for vanilla libraries.
|
||||
) then VersionJSONSaveTask(dependencyManager, version)
|
||||
return VersionJSONDownloadTask(gameVersion, dependencyManager, "raw_version_json")
|
||||
.then {
|
||||
var version = GSON.fromJson<Version>(it["raw_version_json"])!!
|
||||
it["version"] = version
|
||||
version = version.copy(id = name, jar = null)
|
||||
var result = ParallelTask(
|
||||
GameAssetDownloadTask(dependencyManager, version),
|
||||
GameLoggingDownloadTask(dependencyManager, version),
|
||||
GameDownloadTask(version),
|
||||
GameLibrariesTask(dependencyManager, version) // Game libraries will be downloaded for multiple times partly, this time is for vanilla libraries.
|
||||
) then VersionJSONSaveTask(dependencyManager, version)
|
||||
|
||||
if (toolVersions.containsKey("forge"))
|
||||
result = result then libraryTaskHelper(gameVersion, version, "forge")
|
||||
if (toolVersions.containsKey("liteloader"))
|
||||
result = result then libraryTaskHelper(gameVersion, version, "liteloader")
|
||||
if (toolVersions.containsKey("optifine"))
|
||||
result = result then libraryTaskHelper(gameVersion, version, "optifine")
|
||||
result
|
||||
}
|
||||
if (toolVersions.containsKey("forge"))
|
||||
result = result then libraryTaskHelper(gameVersion, "forge")
|
||||
if (toolVersions.containsKey("liteloader"))
|
||||
result = result then libraryTaskHelper(gameVersion, "liteloader")
|
||||
if (toolVersions.containsKey("optifine"))
|
||||
result = result then libraryTaskHelper(gameVersion, "optifine")
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
private fun libraryTaskHelper(gameVersion: String, version: Version, libraryId: String): Task.(Task) -> Task = { prev ->
|
||||
var thisVersion = version
|
||||
if (prev is TaskResult<*> && prev.result is Version) {
|
||||
thisVersion = prev.result as Version
|
||||
}
|
||||
dependencyManager.installLibraryAsync(gameVersion, thisVersion, libraryId, toolVersions[libraryId]!!)
|
||||
private fun libraryTaskHelper(gameVersion: String, libraryId: String): (AutoTypingMap<String>) -> Task = {
|
||||
dependencyManager.installLibraryAsync(gameVersion, it["version"], libraryId, toolVersions[libraryId]!!)
|
||||
}
|
||||
|
||||
inner class VersionJSONDownloadTask(val gameVersion: String): Task() {
|
||||
private class VersionJSONDownloadTask(val gameVersion: String, val dependencyManager: DefaultDependencyManager, val id: String): Task() {
|
||||
override val dependents: MutableCollection<Task> = LinkedList()
|
||||
override val dependencies: MutableCollection<Task> = LinkedList()
|
||||
var httpTask: GetTask? = null
|
||||
val result: String? get() = httpTask?.result
|
||||
|
||||
val gameVersionList: VersionList<*> = dependencyManager.getVersionList("game")
|
||||
private val gameVersionList: VersionList<*> = dependencyManager.getVersionList("game")
|
||||
init {
|
||||
if (!gameVersionList.loaded)
|
||||
dependents += gameVersionList.refreshAsync(downloadProvider)
|
||||
dependents += gameVersionList.refreshAsync(dependencyManager.downloadProvider)
|
||||
}
|
||||
|
||||
override fun execute() {
|
||||
val remoteVersion = gameVersionList.getVersions(gameVersion).firstOrNull()
|
||||
?: throw Error("Cannot find specific version $gameVersion in remote repository")
|
||||
|
||||
val jsonURL = downloadProvider.injectURL(remoteVersion.url)
|
||||
httpTask = GetTask(jsonURL.toURL(), proxy = dependencyManager.proxy)
|
||||
dependencies += httpTask!!
|
||||
val jsonURL = dependencyManager.downloadProvider.injectURL(remoteVersion.url)
|
||||
dependencies += GetTask(jsonURL.toURL(), proxy = dependencyManager.proxy, id = id)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,11 +38,11 @@ class ForgeInstallTask(private val dependencyManager: DefaultDependencyManager,
|
||||
lateinit var remote: RemoteVersion<*>
|
||||
override val dependents = mutableListOf<Task>()
|
||||
override val dependencies = mutableListOf<Task>()
|
||||
override val id = ID
|
||||
override val id = "version"
|
||||
|
||||
init {
|
||||
if (!forgeVersionList.loaded)
|
||||
dependents += forgeVersionList.refreshAsync(dependencyManager.downloadProvider) then {
|
||||
dependents += forgeVersionList.refreshAsync(dependencyManager.downloadProvider).then {
|
||||
remote = forgeVersionList.getVersion(gameVersion, remoteVersion) ?: throw IllegalArgumentException("Remote forge version $gameVersion, $remoteVersion not found")
|
||||
FileDownloadTask(remote.url.toURL(), installer)
|
||||
}
|
||||
@@ -76,8 +76,4 @@ class ForgeInstallTask(private val dependencyManager: DefaultDependencyManager,
|
||||
|
||||
check(installer.delete(), { "Unable to delete installer file $installer" })
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val ID = "forge_install_task"
|
||||
}
|
||||
}
|
||||
@@ -37,11 +37,11 @@ class LiteLoaderInstallTask(private val dependencyManager: DefaultDependencyMana
|
||||
lateinit var remote: RemoteVersion<LiteLoaderRemoteVersionTag>
|
||||
override val dependents = mutableListOf<Task>()
|
||||
override val dependencies = mutableListOf<Task>()
|
||||
override val id = ID
|
||||
override val id = "version"
|
||||
|
||||
init {
|
||||
if (!liteLoaderVersionList.loaded)
|
||||
dependents += LiteLoaderVersionList.refreshAsync(dependencyManager.downloadProvider) then {
|
||||
dependents += LiteLoaderVersionList.refreshAsync(dependencyManager.downloadProvider).then {
|
||||
remote = liteLoaderVersionList.getVersion(gameVersion, remoteVersion) ?: throw IllegalArgumentException("Remote LiteLoader version $gameVersion, $remoteVersion not found")
|
||||
null
|
||||
}
|
||||
@@ -70,8 +70,4 @@ class LiteLoaderInstallTask(private val dependencyManager: DefaultDependencyMana
|
||||
)
|
||||
dependencies += GameLibrariesTask(dependencyManager, tempVersion)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val ID = "lite_loader_install_task"
|
||||
}
|
||||
}
|
||||
@@ -34,7 +34,7 @@ class OptiFineInstallTask(private val dependencyManager: DefaultDependencyManage
|
||||
lateinit var remote: RemoteVersion<*>
|
||||
override val dependents = mutableListOf<Task>()
|
||||
override val dependencies = mutableListOf<Task>()
|
||||
override val id = ID
|
||||
override val id = "version"
|
||||
|
||||
init {
|
||||
if (!optiFineVersionList.loaded)
|
||||
@@ -75,8 +75,4 @@ class OptiFineInstallTask(private val dependencyManager: DefaultDependencyManage
|
||||
result = version.copy(libraries = merge(version.libraries, libraries), mainClass = mainClass, minecraftArguments = arg)
|
||||
dependencies += GameLibrariesTask(dependencyManager, version.copy(libraries = libraries))
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val ID = "optifine_install_task"
|
||||
}
|
||||
}
|
||||
@@ -17,14 +17,16 @@
|
||||
*/
|
||||
package org.jackhuang.hmcl.task
|
||||
|
||||
internal class CoupleTask<P: Task>(private val pred: P, private val succ: Task.(P) -> Task?, override val reliant: Boolean) : Task() {
|
||||
import org.jackhuang.hmcl.util.AutoTypingMap
|
||||
|
||||
internal class CoupleTask<P: Task>(pred: P, private val succ: (AutoTypingMap<String>) -> Task?, override val reliant: Boolean) : Task() {
|
||||
override val hidden: Boolean = true
|
||||
|
||||
override val dependents: Collection<Task> = listOf(pred)
|
||||
override val dependencies: MutableCollection<Task> = mutableListOf()
|
||||
|
||||
override fun execute() {
|
||||
val task = this.succ(pred)
|
||||
val task = this.succ(variables!!)
|
||||
if (task != null)
|
||||
dependencies += task
|
||||
}
|
||||
@@ -33,9 +35,9 @@ internal class CoupleTask<P: Task>(private val pred: P, private val succ: Task.(
|
||||
/**
|
||||
* @param b A runnable that decides what to do next, You can also do something here.
|
||||
*/
|
||||
infix fun <T: Task> T.then(b: Task.(T) -> Task?): Task = CoupleTask(this, b, true)
|
||||
infix fun <T: Task> T.then(b: (AutoTypingMap<String>) -> Task?): Task = CoupleTask(this, b, true)
|
||||
|
||||
/**
|
||||
* @param b A runnable that decides what to do next, You can also do something here.
|
||||
*/
|
||||
infix fun <T: Task> T.with(b: Task.(T) -> Task?): Task = CoupleTask(this, b, false)
|
||||
infix fun <T: Task> T.with(b: (AutoTypingMap<String>) -> Task?): Task = CoupleTask(this, b, false)
|
||||
@@ -25,9 +25,8 @@ import java.net.Proxy
|
||||
import java.net.URL
|
||||
import java.nio.charset.Charset
|
||||
|
||||
class GetTask @JvmOverloads constructor(val url: URL, val encoding: Charset = Charsets.UTF_8, private val retry: Int = 5, private val proxy: Proxy = Proxy.NO_PROXY): TaskResult<String>() {
|
||||
class GetTask @JvmOverloads constructor(val url: URL, val encoding: Charset = Charsets.UTF_8, private val retry: Int = 5, private val proxy: Proxy = Proxy.NO_PROXY, override val id: String = ID): TaskResult<String>() {
|
||||
override val scheduler: Scheduler = Scheduler.IO
|
||||
override val id = ID
|
||||
|
||||
override fun execute() {
|
||||
var exception: IOException? = null
|
||||
|
||||
@@ -81,11 +81,15 @@ abstract class Task {
|
||||
protected fun updateProgress(progress: Double) {
|
||||
val now = System.currentTimeMillis()
|
||||
if (now - lastTime >= progressInterval) {
|
||||
progressPropertyImpl.updateAsync(progress, progressUpdate)
|
||||
updateProgressImmediately(progress)
|
||||
lastTime = now
|
||||
}
|
||||
}
|
||||
|
||||
protected fun updateProgressImmediately(progress: Double) {
|
||||
progressPropertyImpl.updateAsync(progress, progressUpdate)
|
||||
}
|
||||
|
||||
private val messageUpdate = AtomicReference<String>()
|
||||
private val messagePropertyImpl = ReadOnlyStringWrapper(this, "message", null)
|
||||
val messageProperty: ReadOnlyStringProperty = messagePropertyImpl.readOnlyProperty
|
||||
|
||||
@@ -49,13 +49,13 @@ class TaskExecutor() {
|
||||
* Start the subscription and run all registered tasks asynchronously.
|
||||
*/
|
||||
fun start() {
|
||||
workerQueue.add(Scheduler.Schedulers.NEW_THREAD.schedule(Callable {
|
||||
workerQueue.add(Scheduler.NEW_THREAD.schedule {
|
||||
totTask.addAndGet(taskQueue.size)
|
||||
while (!taskQueue.isEmpty()) {
|
||||
if (canceled) break
|
||||
val task = taskQueue.poll()
|
||||
if (task != null) {
|
||||
val future = task.scheduler.schedule(Callable { executeTask(task); Unit })
|
||||
val future = task.scheduler.schedule { executeTask(task) }
|
||||
try {
|
||||
future?.get()
|
||||
} catch (e: InterruptedException) {
|
||||
@@ -66,7 +66,9 @@ class TaskExecutor() {
|
||||
}
|
||||
if (canceled || Thread.interrupted())
|
||||
taskListener?.onTerminate()
|
||||
}))
|
||||
else
|
||||
taskListener?.end()
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,8 +20,9 @@ package org.jackhuang.hmcl.task
|
||||
import java.util.*
|
||||
|
||||
interface TaskListener : EventListener {
|
||||
fun onReady(task: Task)
|
||||
fun onFinished(task: Task)
|
||||
fun onFailed(task: Task)
|
||||
fun onTerminate()
|
||||
fun onReady(task: Task) {}
|
||||
fun onFinished(task: Task) {}
|
||||
fun onFailed(task: Task) {}
|
||||
fun onTerminate() {}
|
||||
fun end() {}
|
||||
}
|
||||
@@ -26,14 +26,14 @@ import java.util.logging.*
|
||||
import java.util.logging.Formatter
|
||||
|
||||
val LOG = Logger.getLogger("HMCL").apply {
|
||||
level = Level.FINEST
|
||||
level = Level.FINER
|
||||
useParentHandlers = false
|
||||
addHandler(FileHandler("hmcl.log").apply {
|
||||
level = Level.FINEST
|
||||
level = Level.FINER
|
||||
formatter = DefaultFormatter
|
||||
})
|
||||
addHandler(ConsoleHandler().apply {
|
||||
level = Level.FINEST
|
||||
level = Level.FINER
|
||||
formatter = DefaultFormatter
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user