Java Selection
This commit is contained in:
@@ -36,8 +36,9 @@ class ForgeInstallTask(private val dependencyManager: DefaultDependencyManager,
|
||||
private val forgeVersionList = dependencyManager.getVersionList("forge")
|
||||
private val installer: File = File("forge-installer.jar").absoluteFile
|
||||
lateinit var remote: RemoteVersion<*>
|
||||
override val dependents: MutableCollection<Task> = mutableListOf()
|
||||
override val dependencies: MutableCollection<Task> = mutableListOf()
|
||||
override val dependents = mutableListOf<Task>()
|
||||
override val dependencies = mutableListOf<Task>()
|
||||
override val id = ID
|
||||
|
||||
init {
|
||||
if (!forgeVersionList.loaded)
|
||||
@@ -76,5 +77,7 @@ class ForgeInstallTask(private val dependencyManager: DefaultDependencyManager,
|
||||
check(installer.delete(), { "Unable to delete installer file $installer" })
|
||||
}
|
||||
|
||||
|
||||
companion object {
|
||||
const val ID = "forge_install_task"
|
||||
}
|
||||
}
|
||||
@@ -37,7 +37,7 @@ import java.util.logging.Level
|
||||
* @param resolvedVersion the <b>resolved</b> version
|
||||
*/
|
||||
class GameLibrariesTask(private val dependencyManager: DefaultDependencyManager, private val resolvedVersion: Version): Task() {
|
||||
override val dependencies: MutableCollection<Task> = LinkedList()
|
||||
override val dependencies = LinkedList<Task>()
|
||||
override fun execute() {
|
||||
for (library in resolvedVersion.libraries)
|
||||
if (library.appliesToCurrentEnvironment) {
|
||||
@@ -50,7 +50,7 @@ class GameLibrariesTask(private val dependencyManager: DefaultDependencyManager,
|
||||
}
|
||||
|
||||
class GameLoggingDownloadTask(private val dependencyManager: DefaultDependencyManager, private val version: Version) : Task() {
|
||||
override val dependencies: MutableCollection<Task> = LinkedList()
|
||||
override val dependencies = LinkedList<Task>()
|
||||
override fun execute() {
|
||||
val logging = version.logging?.get(DownloadType.CLIENT) ?: return
|
||||
val file = dependencyManager.repository.getLoggingObject(version.id, version.actualAssetIndex.id, logging)
|
||||
@@ -60,7 +60,7 @@ class GameLoggingDownloadTask(private val dependencyManager: DefaultDependencyMa
|
||||
}
|
||||
|
||||
class GameAssetIndexDownloadTask(private val dependencyManager: DefaultDependencyManager, private val version: Version) : Task() {
|
||||
override val dependencies: MutableCollection<Task> = LinkedList()
|
||||
override val dependencies = LinkedList<Task>()
|
||||
override fun execute() {
|
||||
val assetIndexInfo = version.actualAssetIndex
|
||||
val assetDir = dependencyManager.repository.getAssetDirectory(version.id, assetIndexInfo.id)
|
||||
@@ -76,7 +76,8 @@ class GameAssetRefreshTask(private val dependencyManager: DefaultDependencyManag
|
||||
private val assetIndexTask = GameAssetIndexDownloadTask(dependencyManager, version)
|
||||
private val assetIndexInfo = version.actualAssetIndex
|
||||
private val assetIndexFile = dependencyManager.repository.getIndexFile(version.id, assetIndexInfo.id)
|
||||
override val dependents: MutableCollection<Task> = LinkedList()
|
||||
override val dependents = LinkedList<Task>()
|
||||
override val id = ID
|
||||
|
||||
init {
|
||||
if (!assetIndexFile.exists())
|
||||
@@ -93,12 +94,16 @@ class GameAssetRefreshTask(private val dependencyManager: DefaultDependencyManag
|
||||
}
|
||||
result = res
|
||||
}
|
||||
|
||||
companion object {
|
||||
val ID = "game_asset_refresh_task"
|
||||
}
|
||||
}
|
||||
|
||||
class GameAssetDownloadTask(private val dependencyManager: DefaultDependencyManager, private val version: Version) : Task() {
|
||||
private val refreshTask = GameAssetRefreshTask(dependencyManager, version)
|
||||
override val dependents: Collection<Task> = listOf(refreshTask)
|
||||
override val dependencies: MutableCollection<Task> = LinkedList()
|
||||
override val dependents = listOf(refreshTask)
|
||||
override val dependencies = LinkedList<Task>()
|
||||
override fun execute() {
|
||||
val size = refreshTask.result?.size ?: 0
|
||||
refreshTask.result?.forEach single@{ (file, assetObject) ->
|
||||
|
||||
@@ -35,8 +35,9 @@ class LiteLoaderInstallTask(private val dependencyManager: DefaultDependencyMana
|
||||
private val remoteVersion: String): TaskResult<Version>() {
|
||||
private val liteLoaderVersionList = dependencyManager.getVersionList("liteloader") as LiteLoaderVersionList
|
||||
lateinit var remote: RemoteVersion<LiteLoaderRemoteVersionTag>
|
||||
override val dependents: MutableCollection<Task> = mutableListOf()
|
||||
override val dependencies: MutableCollection<Task> = mutableListOf()
|
||||
override val dependents = mutableListOf<Task>()
|
||||
override val dependencies = mutableListOf<Task>()
|
||||
override val id = ID
|
||||
|
||||
init {
|
||||
if (!liteLoaderVersionList.loaded)
|
||||
@@ -70,4 +71,7 @@ class LiteLoaderInstallTask(private val dependencyManager: DefaultDependencyMana
|
||||
dependencies += GameLibrariesTask(dependencyManager, tempVersion)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val ID = "lite_loader_install_task"
|
||||
}
|
||||
}
|
||||
@@ -32,8 +32,9 @@ class OptiFineInstallTask(private val dependencyManager: DefaultDependencyManage
|
||||
private val remoteVersion: String): TaskResult<Version>() {
|
||||
private val optiFineVersionList = dependencyManager.getVersionList("optifine")
|
||||
lateinit var remote: RemoteVersion<*>
|
||||
override val dependents: MutableCollection<Task> = mutableListOf()
|
||||
override val dependencies: MutableCollection<Task> = mutableListOf()
|
||||
override val dependents = mutableListOf<Task>()
|
||||
override val dependencies = mutableListOf<Task>()
|
||||
override val id = ID
|
||||
|
||||
init {
|
||||
if (!optiFineVersionList.loaded)
|
||||
@@ -45,6 +46,7 @@ class OptiFineInstallTask(private val dependencyManager: DefaultDependencyManage
|
||||
remote = optiFineVersionList.getVersion(gameVersion, remoteVersion) ?: throw IllegalArgumentException("Remote OptiFine version $gameVersion-$remoteVersion not found")
|
||||
}
|
||||
}
|
||||
|
||||
override fun execute() {
|
||||
val library = Library(
|
||||
groupId = "net.optifine",
|
||||
@@ -73,4 +75,8 @@ 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"
|
||||
}
|
||||
}
|
||||
@@ -68,7 +68,7 @@ open class DefaultLauncher(repository: GameRepository, versionId: String, accoun
|
||||
|
||||
if (OS.CURRENT_OS == OS.OSX) {
|
||||
res.add("-Xdock:name=Minecraft ${version.id}")
|
||||
res.add("-Xdock:icon=" + repository.getAssetObject(version.id, version.actualAssetIndex.id, "icons/minecraft.icns").absolutePath);
|
||||
res.add("-Xdock:icon=" + repository.getAssetObject(version.id, version.actualAssetIndex.id, "icons/minecraft.icns").absolutePath)
|
||||
}
|
||||
|
||||
val logging = version.logging
|
||||
@@ -107,8 +107,8 @@ open class DefaultLauncher(repository: GameRepository, versionId: String, accoun
|
||||
if (options.minMemory != null && options.minMemory > 0)
|
||||
res.add("-Xms${options.minMemory}m")
|
||||
|
||||
res.add("-Dfml.ignoreInvalidMinecraftCertificates=true");
|
||||
res.add("-Dfml.ignorePatchDiscrepancies=true");
|
||||
res.add("-Dfml.ignoreInvalidMinecraftCertificates=true")
|
||||
res.add("-Dfml.ignorePatchDiscrepancies=true")
|
||||
}
|
||||
|
||||
// Classpath
|
||||
@@ -161,9 +161,9 @@ open class DefaultLauncher(repository: GameRepository, versionId: String, accoun
|
||||
|
||||
// Optional Minecraft arguments
|
||||
if (options.height != null && options.width != null) {
|
||||
res.add("--height");
|
||||
res.add("--height")
|
||||
res.add(options.height.toString())
|
||||
res.add("--width");
|
||||
res.add("--width")
|
||||
res.add(options.width.toString())
|
||||
}
|
||||
|
||||
@@ -180,16 +180,16 @@ open class DefaultLauncher(repository: GameRepository, versionId: String, accoun
|
||||
|
||||
if (options.proxyHost != null && options.proxyHost.isNotBlank() &&
|
||||
options.proxyPort != null && options.proxyPort.isNotBlank()) {
|
||||
res.add("--proxyHost");
|
||||
res.add("--proxyHost")
|
||||
res.add(options.proxyHost)
|
||||
res.add("--proxyPort");
|
||||
res.add("--proxyPort")
|
||||
res.add(options.proxyPort)
|
||||
if (options.proxyUser != null && options.proxyUser.isNotBlank() &&
|
||||
options.proxyPass != null && options.proxyPass.isNotBlank()) {
|
||||
res.add("--proxyUser");
|
||||
res.add(options.proxyUser);
|
||||
res.add("--proxyPass");
|
||||
res.add(options.proxyPass);
|
||||
res.add("--proxyUser")
|
||||
res.add(options.proxyUser)
|
||||
res.add("--proxyPass")
|
||||
res.add(options.proxyPass)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,6 +246,7 @@ open class DefaultLauncher(repository: GameRepository, versionId: String, accoun
|
||||
|
||||
fun launchAsync(): TaskResult<JavaProcess> {
|
||||
return object : TaskResult<JavaProcess>() {
|
||||
override val id = LAUNCH_ASYNC_ID
|
||||
override fun execute() {
|
||||
result = launch()
|
||||
}
|
||||
@@ -259,11 +260,11 @@ open class DefaultLauncher(repository: GameRepository, versionId: String, accoun
|
||||
throw IOException("Script file: $scriptFile cannot be created.")
|
||||
scriptFile.bufferedWriter().use { writer ->
|
||||
if (isWindows) {
|
||||
writer.write("@echo off");
|
||||
writer.write("@echo off")
|
||||
writer.newLine()
|
||||
writer.write("set APPDATA=" + options.gameDir.parent);
|
||||
writer.write("set APPDATA=" + options.gameDir.parent)
|
||||
writer.newLine()
|
||||
writer.write("cd /D %APPDATA%");
|
||||
writer.write("cd /D %APPDATA%")
|
||||
writer.newLine()
|
||||
}
|
||||
if (options.precalledCommand != null && options.precalledCommand.isNotBlank()) {
|
||||
@@ -287,4 +288,8 @@ open class DefaultLauncher(repository: GameRepository, versionId: String, accoun
|
||||
thread(name = "stderr-pump", isDaemon = isDaemon, block = StreamPump(javaProcess.process.errorStream, processListener::onErrorLog)::run)
|
||||
thread(name = "exit-waiter", isDaemon = isDaemon, block = ExitWaiter(javaProcess.process, processListener::onExit)::run)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val LAUNCH_ASYNC_ID = "process"
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ 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>() {
|
||||
override val scheduler: Scheduler = Scheduler.IO_THREAD
|
||||
override val id = ID
|
||||
|
||||
override fun execute() {
|
||||
var exception: IOException? = null
|
||||
@@ -63,4 +64,8 @@ class GetTask @JvmOverloads constructor(val url: URL, val encoding: Charset = Ch
|
||||
if (exception != null)
|
||||
throw exception
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val ID = "http_get"
|
||||
}
|
||||
}
|
||||
@@ -17,8 +17,10 @@
|
||||
*/
|
||||
package org.jackhuang.hmcl.task
|
||||
|
||||
internal class SimpleTask @JvmOverloads constructor(private val runnable: () -> Unit, override val scheduler: Scheduler = Scheduler.DEFAULT) : Task() {
|
||||
import org.jackhuang.hmcl.util.AutoTypingMap
|
||||
|
||||
internal class SimpleTask @JvmOverloads constructor(private val runnable: (AutoTypingMap<String>) -> Unit, override val scheduler: Scheduler = Scheduler.DEFAULT) : Task() {
|
||||
override fun execute() {
|
||||
runnable()
|
||||
runnable(variables!!)
|
||||
}
|
||||
}
|
||||
@@ -49,6 +49,8 @@ abstract class Task {
|
||||
|
||||
var title: String = this.javaClass.toString()
|
||||
|
||||
var variables: AutoTypingMap<String>? = null
|
||||
|
||||
/**
|
||||
* @see Thread.isInterrupted
|
||||
* @throws InterruptedException if current thread is interrupted
|
||||
@@ -119,12 +121,13 @@ abstract class Task {
|
||||
submit(subscriber).start()
|
||||
}
|
||||
|
||||
fun subscribe(scheduler: Scheduler = Scheduler.DEFAULT, closure: () -> Unit) = subscribe(task(scheduler, closure))
|
||||
fun subscribe(scheduler: Scheduler = Scheduler.DEFAULT, closure: (AutoTypingMap<String>) -> Unit) = subscribe(task(scheduler, closure))
|
||||
|
||||
override fun toString(): String {
|
||||
return title
|
||||
}
|
||||
}
|
||||
|
||||
fun task(scheduler: Scheduler = Scheduler.DEFAULT, closure: () -> Unit): Task = SimpleTask(closure, scheduler)
|
||||
fun <V> task(callable: Callable<V>): TaskResult<V> = TaskCallable(callable)
|
||||
fun task(scheduler: Scheduler = Scheduler.DEFAULT, closure: (AutoTypingMap<String>) -> Unit): Task = SimpleTask(closure, scheduler)
|
||||
fun <V> taskResult(id: String, callable: Callable<V>): TaskResult<V> = TaskCallable(id, callable)
|
||||
fun <V> taskResult(id: String, callable: (AutoTypingMap<String>) -> V): TaskResult<V> = TaskCallable2(id, callable)
|
||||
@@ -17,10 +17,17 @@
|
||||
*/
|
||||
package org.jackhuang.hmcl.task
|
||||
|
||||
import org.jackhuang.hmcl.util.AutoTypingMap
|
||||
import java.util.concurrent.Callable
|
||||
|
||||
internal class TaskCallable<V>(private val callable: Callable<V>) : TaskResult<V>() {
|
||||
internal class TaskCallable<V>(override val id: String, private val callable: Callable<V>) : TaskResult<V>() {
|
||||
override fun execute() {
|
||||
result = callable.call()
|
||||
}
|
||||
}
|
||||
|
||||
internal class TaskCallable2<V>(override val id: String, private val callable: (AutoTypingMap<String>) -> V) : TaskResult<V>() {
|
||||
override fun execute() {
|
||||
result = callable(variables!!)
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
package org.jackhuang.hmcl.task
|
||||
|
||||
import org.jackhuang.hmcl.util.AutoTypingMap
|
||||
import org.jackhuang.hmcl.util.LOG
|
||||
import java.util.concurrent.*
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
@@ -30,6 +31,7 @@ class TaskExecutor() {
|
||||
var canceled = false
|
||||
private set
|
||||
val totTask = AtomicInteger(0)
|
||||
val variables = AutoTypingMap<String>(mutableMapOf())
|
||||
private val taskQueue = ConcurrentLinkedQueue<Task>()
|
||||
private val workerQueue = ConcurrentLinkedQueue<Future<*>>()
|
||||
|
||||
@@ -119,7 +121,10 @@ class TaskExecutor() {
|
||||
if (!doDependentsSucceeded && t.reliant || canceled)
|
||||
throw SilentException()
|
||||
|
||||
t.variables = variables
|
||||
t.execute()
|
||||
if (t is TaskResult<*>)
|
||||
variables[t.id] = t.result
|
||||
flag = true
|
||||
if (!t.hidden)
|
||||
LOG.finer("Task finished: ${t.title}")
|
||||
@@ -142,6 +147,8 @@ class TaskExecutor() {
|
||||
t.onDone(TaskEvent(source = this, task = t, failed = true))
|
||||
taskListener?.onFailed(t)
|
||||
}
|
||||
} finally {
|
||||
t.variables = null
|
||||
}
|
||||
return flag
|
||||
}
|
||||
|
||||
@@ -19,4 +19,9 @@ package org.jackhuang.hmcl.task
|
||||
|
||||
abstract class TaskResult<V> : Task() {
|
||||
open var result: V? = null
|
||||
|
||||
/**
|
||||
* The task id, will be stored as key of [variables]
|
||||
*/
|
||||
abstract val id: String
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Hello Minecraft! Launcher.
|
||||
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
*/
|
||||
package org.jackhuang.hmcl.util
|
||||
|
||||
class AutoTypingMap<K>(private val impl: MutableMap<K, Any>) {
|
||||
|
||||
fun clear() = impl.clear()
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
operator fun <V> get(key: K): V = impl[key] as V
|
||||
operator fun set(key: K, value: Any?) {
|
||||
if (value != null)
|
||||
impl.set(key, value)
|
||||
}
|
||||
val values get() = impl.values
|
||||
val keys get() = impl.keys
|
||||
|
||||
fun containsKey(key: K) = impl.containsKey(key)
|
||||
fun remove(key: K) = impl.remove(key)
|
||||
}
|
||||
@@ -21,17 +21,22 @@ import com.google.gson.annotations.SerializedName
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.io.Serializable
|
||||
import java.util.*
|
||||
import java.util.regex.Pattern
|
||||
|
||||
data class JavaVersion internal constructor(
|
||||
@SerializedName("location")
|
||||
val binary: File,
|
||||
val version: Int,
|
||||
val longVersion: String,
|
||||
val platform: Platform) : Serializable
|
||||
{
|
||||
val version = parseVersion(longVersion)
|
||||
|
||||
companion object {
|
||||
private val regex = Pattern.compile("java version \"(?<version>[1-9]*\\.[1-9]*\\.[0-9]*(.*?))\"")
|
||||
|
||||
val JAVAS: Map<String, JavaVersion>
|
||||
|
||||
val UNKNOWN: Int = -1
|
||||
val JAVA_5: Int = 50
|
||||
val JAVA_6: Int = 60
|
||||
@@ -54,12 +59,15 @@ data class JavaVersion internal constructor(
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun fromExecutable(file: File): JavaVersion {
|
||||
var actualFile = file
|
||||
var platform = Platform.BIT_32
|
||||
var version: String? = null
|
||||
if (actualFile.nameWithoutExtension == "javaw") // javaw will not output version information
|
||||
actualFile = actualFile.absoluteFile.parentFile.resolve("java")
|
||||
try {
|
||||
val process = ProcessBuilder(file.absolutePath, "-version").start()
|
||||
val process = ProcessBuilder(actualFile.absolutePath, "-version").start()
|
||||
process.waitFor()
|
||||
process.inputStream.bufferedReader().forEachLine { line ->
|
||||
process.errorStream.bufferedReader().forEachLine { line ->
|
||||
val m = regex.matcher(line)
|
||||
if (m.find())
|
||||
version = m.group("version")
|
||||
@@ -74,10 +82,26 @@ data class JavaVersion internal constructor(
|
||||
val parsedVersion = parseVersion(thisVersion)
|
||||
if (parsedVersion == UNKNOWN)
|
||||
throw IOException("Java version '$thisVersion' can not be recognized")
|
||||
return JavaVersion(file.parentFile, parsedVersion, platform)
|
||||
return JavaVersion(file.parentFile, thisVersion, platform)
|
||||
}
|
||||
|
||||
fun getJavaFile(home: File): File {
|
||||
private fun fromExecutable(file: File, version: String) =
|
||||
JavaVersion (
|
||||
binary = file,
|
||||
longVersion = version,
|
||||
platform = Platform.UNKNOWN
|
||||
)
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun fromJavaHome(home: File): JavaVersion {
|
||||
return fromExecutable(getJavaFile(home))
|
||||
}
|
||||
|
||||
private fun fromJavaHome(home: File, version: String): JavaVersion {
|
||||
return fromExecutable(getJavaFile(home), version)
|
||||
}
|
||||
|
||||
private fun getJavaFile(home: File): File {
|
||||
val path = home.resolve("bin")
|
||||
val javaw = path.resolve("javaw.exe")
|
||||
if (OS.CURRENT_OS === OS.WINDOWS && javaw.isFile)
|
||||
@@ -86,11 +110,80 @@ data class JavaVersion internal constructor(
|
||||
return path.resolve("java")
|
||||
}
|
||||
|
||||
fun fromCurrentEnvironment(): JavaVersion {
|
||||
return JavaVersion(
|
||||
binary = getJavaFile(File(System.getProperty("java.home"))),
|
||||
version = parseVersion(System.getProperty("java.version")),
|
||||
platform = Platform.PLATFORM)
|
||||
private val currentJava: JavaVersion = JavaVersion(
|
||||
binary = getJavaFile(File(System.getProperty("java.home"))),
|
||||
longVersion = System.getProperty("java.version"),
|
||||
platform = Platform.PLATFORM)
|
||||
fun fromCurrentEnvironment() = currentJava
|
||||
|
||||
init {
|
||||
val temp = mutableMapOf<String, JavaVersion>()
|
||||
(when (OS.CURRENT_OS) {
|
||||
OS.WINDOWS -> queryWindows()
|
||||
OS.OSX -> queryMacintosh()
|
||||
else -> emptyList<JavaVersion>() /* Cannot detect Java in linux. */
|
||||
}).forEach { javaVersion ->
|
||||
temp.put(javaVersion.longVersion, javaVersion)
|
||||
}
|
||||
JAVAS = temp
|
||||
}
|
||||
|
||||
private fun queryMacintosh() = LinkedList<JavaVersion>().apply {
|
||||
val currentJRE = File("/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home")
|
||||
if (currentJRE.exists())
|
||||
this += fromJavaHome(currentJRE)
|
||||
File("/Library/Java/JavaVirtualMachines/").listFiles()?.forEach { file ->
|
||||
this += fromJavaHome(file.resolve("Contents/Home"))
|
||||
}
|
||||
}
|
||||
|
||||
private fun queryWindows() = LinkedList<JavaVersion>().apply {
|
||||
ignoreException { this += queryRegisterKey("HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment\\") }
|
||||
ignoreException { this += queryRegisterKey("HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\") }
|
||||
}
|
||||
|
||||
private fun queryRegisterKey(location: String) = LinkedList<JavaVersion>().apply {
|
||||
querySubFolders(location).forEach { java ->
|
||||
val s = java.count { it == '.' }
|
||||
if (s > 1) {
|
||||
val home = queryRegisterValue(java, "JavaHome")
|
||||
if (home != null)
|
||||
this += fromJavaHome(File(home))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun querySubFolders(location: String) = LinkedList<String>().apply {
|
||||
val cmd = arrayOf("cmd", "/c", "reg", "query", location)
|
||||
val process = Runtime.getRuntime().exec(cmd)
|
||||
process.waitFor()
|
||||
process.inputStream.bufferedReader().readLines().forEach { s ->
|
||||
if (s.startsWith(location) && s != location)
|
||||
this += s
|
||||
}
|
||||
}
|
||||
|
||||
private fun queryRegisterValue(location: String, name: String): String? {
|
||||
val cmd = arrayOf("cmd", "/c", "reg", "query", location, "/v", name)
|
||||
var last = false
|
||||
val process = Runtime.getRuntime().exec(cmd)
|
||||
process.waitFor()
|
||||
process.inputStream.bufferedReader().readLines().forEach { s ->
|
||||
if (s.isNotBlank()) {
|
||||
if (last && s.trim().startsWith(name)) {
|
||||
var begins = s.indexOf(name)
|
||||
if (begins > 0) {
|
||||
val s2 = s.substring(begins + name.length)
|
||||
begins = s2.indexOf("REG_SZ")
|
||||
if (begins > 0)
|
||||
return s2.substring(begins + "REG_SZ".length).trim()
|
||||
}
|
||||
}
|
||||
if (s.trim() == location)
|
||||
last = true
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@
|
||||
package org.jackhuang.hmcl.util.property
|
||||
|
||||
import javafx.beans.property.*
|
||||
import javafx.beans.value.ChangeListener
|
||||
import javafx.beans.value.ObservableValue
|
||||
|
||||
open class ImmediateStringProperty(bean: Any, name: String, initialValue: String): SimpleStringProperty(bean, name, initialValue) {
|
||||
@@ -27,10 +28,6 @@ open class ImmediateStringProperty(bean: Any, name: String, initialValue: String
|
||||
super.set(newValue)
|
||||
}
|
||||
|
||||
protected fun superSet(newValue: String) {
|
||||
super.set(newValue)
|
||||
}
|
||||
|
||||
override fun bind(newObservable: ObservableValue<out String>) {
|
||||
super.get()
|
||||
super.bind(newObservable)
|
||||
@@ -41,30 +38,17 @@ open class ImmediateStringProperty(bean: Any, name: String, initialValue: String
|
||||
super.unbind()
|
||||
}
|
||||
|
||||
public override fun fireValueChangedEvent() {
|
||||
super.fireValueChangedEvent()
|
||||
}
|
||||
}
|
||||
|
||||
open class ImmediateNullableStringProperty(bean: Any, name: String, initialValue: String?): SimpleStringProperty(bean, name, initialValue) {
|
||||
|
||||
override fun set(newValue: String?) {
|
||||
super.get()
|
||||
super.set(newValue)
|
||||
private var myListener: (String) -> Unit = {}
|
||||
private val changeListener = ChangeListener<String> { _, _, newValue ->
|
||||
myListener(newValue)
|
||||
}
|
||||
|
||||
protected fun superSet(newValue: String?) {
|
||||
super.set(newValue)
|
||||
fun setChangedListener(listener: (String) -> Unit) {
|
||||
myListener = listener
|
||||
}
|
||||
|
||||
override fun bind(newObservable: ObservableValue<out String?>) {
|
||||
super.get()
|
||||
super.bind(newObservable)
|
||||
}
|
||||
|
||||
override fun unbind() {
|
||||
super.get()
|
||||
super.unbind()
|
||||
init {
|
||||
addListener(changeListener)
|
||||
}
|
||||
|
||||
public override fun fireValueChangedEvent() {
|
||||
@@ -79,10 +63,6 @@ open class ImmediateBooleanProperty(bean: Any, name: String, initialValue: Boole
|
||||
super.set(newValue)
|
||||
}
|
||||
|
||||
protected fun superSet(newValue: Boolean) {
|
||||
super.set(newValue)
|
||||
}
|
||||
|
||||
override fun bind(rawObservable: ObservableValue<out Boolean>?) {
|
||||
super.get()
|
||||
super.bind(rawObservable)
|
||||
@@ -93,6 +73,19 @@ open class ImmediateBooleanProperty(bean: Any, name: String, initialValue: Boole
|
||||
super.unbind()
|
||||
}
|
||||
|
||||
private var myListener: (Boolean) -> Unit = {}
|
||||
private val changeListener = ChangeListener<Boolean> { _, _, newValue ->
|
||||
myListener(newValue)
|
||||
}
|
||||
|
||||
fun setChangedListener(listener: (Boolean) -> Unit) {
|
||||
myListener = listener
|
||||
}
|
||||
|
||||
init {
|
||||
addListener(changeListener)
|
||||
}
|
||||
|
||||
public override fun fireValueChangedEvent() {
|
||||
super.fireValueChangedEvent()
|
||||
}
|
||||
@@ -105,10 +98,6 @@ open class ImmediateIntegerProperty(bean: Any, name: String, initialValue: Int):
|
||||
super.set(newValue)
|
||||
}
|
||||
|
||||
protected fun superSet(newValue: Int) {
|
||||
super.set(newValue)
|
||||
}
|
||||
|
||||
override fun bind(rawObservable: ObservableValue<out Number>) {
|
||||
super.get()
|
||||
super.bind(rawObservable)
|
||||
@@ -119,6 +108,19 @@ open class ImmediateIntegerProperty(bean: Any, name: String, initialValue: Int):
|
||||
super.unbind()
|
||||
}
|
||||
|
||||
private var myListener: (Int) -> Unit = {}
|
||||
private val changeListener = ChangeListener<Number> { _, _, newValue ->
|
||||
myListener(newValue.toInt())
|
||||
}
|
||||
|
||||
fun setChangedListener(listener: (Int) -> Unit) {
|
||||
myListener = listener
|
||||
}
|
||||
|
||||
init {
|
||||
addListener(changeListener)
|
||||
}
|
||||
|
||||
public override fun fireValueChangedEvent() {
|
||||
super.fireValueChangedEvent()
|
||||
}
|
||||
@@ -131,10 +133,6 @@ open class ImmediateDoubleProperty(bean: Any, name: String, initialValue: Double
|
||||
super.set(newValue)
|
||||
}
|
||||
|
||||
protected fun superSet(newValue: Double) {
|
||||
super.set(newValue)
|
||||
}
|
||||
|
||||
override fun bind(rawObservable: ObservableValue<out Number>) {
|
||||
super.get()
|
||||
super.bind(rawObservable)
|
||||
@@ -145,6 +143,19 @@ open class ImmediateDoubleProperty(bean: Any, name: String, initialValue: Double
|
||||
super.unbind()
|
||||
}
|
||||
|
||||
private var myListener: (Double) -> Unit = {}
|
||||
private val changeListener = ChangeListener<Number> { _, _, newValue ->
|
||||
myListener(newValue.toDouble())
|
||||
}
|
||||
|
||||
fun setChangedListener(listener: (Double) -> Unit) {
|
||||
myListener = listener
|
||||
}
|
||||
|
||||
init {
|
||||
addListener(changeListener)
|
||||
}
|
||||
|
||||
public override fun fireValueChangedEvent() {
|
||||
super.fireValueChangedEvent()
|
||||
}
|
||||
@@ -167,6 +178,19 @@ open class ImmediateObjectProperty<T>(bean: Any, name: String, initialValue: T):
|
||||
super.unbind()
|
||||
}
|
||||
|
||||
private var myListener: (T) -> Unit = {}
|
||||
private val changeListener = ChangeListener<T> { _, _, newValue ->
|
||||
myListener(newValue)
|
||||
}
|
||||
|
||||
fun setChangedListener(listener: (T) -> Unit) {
|
||||
myListener = listener
|
||||
}
|
||||
|
||||
init {
|
||||
addListener(changeListener)
|
||||
}
|
||||
|
||||
public override fun fireValueChangedEvent() {
|
||||
super.fireValueChangedEvent()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user