Auto-installing
This commit is contained in:
@@ -76,7 +76,7 @@ class HMCLModpackInstallTask(profile: Profile, private val zipFile: File, privat
|
|||||||
version = version.copy(jar = null)
|
version = version.copy(jar = null)
|
||||||
dependents += dependency.gameBuilder().name(name).gameVersion(modpack.gameVersion!!).buildAsync()
|
dependents += dependency.gameBuilder().name(name).gameVersion(modpack.gameVersion!!).buildAsync()
|
||||||
dependencies += dependency.checkGameCompletionAsync(version)
|
dependencies += dependency.checkGameCompletionAsync(version)
|
||||||
dependencies += VersionJSONSaveTask(dependency, version)
|
dependencies += VersionJSONSaveTask(repository, version)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val run = repository.getRunDirectory(name)
|
private val run = repository.getRunDirectory(name)
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* 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.ui
|
||||||
|
|
||||||
|
import javafx.fxml.FXML
|
||||||
|
import javafx.scene.control.ScrollPane
|
||||||
|
import javafx.scene.layout.VBox
|
||||||
|
import org.jackhuang.hmcl.download.game.VersionJSONSaveTask
|
||||||
|
import org.jackhuang.hmcl.game.Version
|
||||||
|
import org.jackhuang.hmcl.game.minecraftVersion
|
||||||
|
import org.jackhuang.hmcl.setting.Profile
|
||||||
|
import org.jackhuang.hmcl.task.Scheduler
|
||||||
|
import org.jackhuang.hmcl.task.task
|
||||||
|
import org.jackhuang.hmcl.ui.download.InstallWizardProvider
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class InstallerController {
|
||||||
|
private lateinit var profile: Profile
|
||||||
|
private lateinit var versionId: String
|
||||||
|
private lateinit var version: Version
|
||||||
|
|
||||||
|
@FXML lateinit var scrollPane: ScrollPane
|
||||||
|
@FXML lateinit var contentPane: VBox
|
||||||
|
|
||||||
|
private var forge: String? = null
|
||||||
|
private var liteloader: String? = null
|
||||||
|
private var optifine: String? = null
|
||||||
|
|
||||||
|
fun initialize() {
|
||||||
|
scrollPane.smoothScrolling()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun loadVersion(profile: Profile, versionId: String) {
|
||||||
|
this.profile = profile
|
||||||
|
this.versionId = versionId
|
||||||
|
this.version = profile.repository.getVersion(versionId).resolve(profile.repository)
|
||||||
|
|
||||||
|
contentPane.children.clear()
|
||||||
|
forge = null
|
||||||
|
liteloader = null
|
||||||
|
optifine = null
|
||||||
|
|
||||||
|
for (library in version.libraries) {
|
||||||
|
val removeAction = { _: InstallerItem ->
|
||||||
|
val newList = LinkedList(version.libraries)
|
||||||
|
newList.remove(library)
|
||||||
|
VersionJSONSaveTask(profile.repository, version.copy(libraries = newList))
|
||||||
|
.with(task { profile.repository.refreshVersions() })
|
||||||
|
.with(task(Scheduler.JAVAFX) { loadVersion(this.profile, this.versionId) })
|
||||||
|
.start()
|
||||||
|
}
|
||||||
|
if (library.groupId.equals("net.minecraftforge", ignoreCase = true) && library.artifactId.equals("forge", ignoreCase = true)) {
|
||||||
|
contentPane.children += InstallerItem("Forge", library.version, removeAction)
|
||||||
|
forge = library.version
|
||||||
|
} else if (library.groupId.equals("com.mumfrey", ignoreCase = true) && library.artifactId.equals("liteloader", ignoreCase = true)) {
|
||||||
|
contentPane.children += InstallerItem("LiteLoader", library.version, removeAction)
|
||||||
|
liteloader = library.version
|
||||||
|
} else if ((library.groupId.equals("net.optifine", ignoreCase = true) || library.groupId.equals("optifine", ignoreCase = true)) && library.artifactId.equals("optifine", ignoreCase = true)) {
|
||||||
|
contentPane.children += InstallerItem("OptiFine", library.version, removeAction)
|
||||||
|
optifine = library.version
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onAdd() {
|
||||||
|
// TODO: if minecraftVersion returns null.
|
||||||
|
val gameVersion = minecraftVersion(profile.repository.getVersionJar(version)) ?: return
|
||||||
|
|
||||||
|
Controllers.decorator.startWizard(InstallWizardProvider(profile, gameVersion, version, forge, liteloader, optifine))
|
||||||
|
}
|
||||||
|
}
|
||||||
24
HMCL/src/main/kotlin/org/jackhuang/hmcl/ui/InstallerItem.kt
Normal file
24
HMCL/src/main/kotlin/org/jackhuang/hmcl/ui/InstallerItem.kt
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package org.jackhuang.hmcl.ui
|
||||||
|
|
||||||
|
import com.jfoenix.effects.JFXDepthManager
|
||||||
|
import javafx.fxml.FXML
|
||||||
|
import javafx.scene.control.Label
|
||||||
|
import javafx.scene.layout.BorderPane
|
||||||
|
|
||||||
|
class InstallerItem(artifact: String, version: String, private val deleteCallback: (InstallerItem) -> Unit) : BorderPane() {
|
||||||
|
@FXML lateinit var lblInstallerArtifact: Label
|
||||||
|
@FXML lateinit var lblInstallerVersion: Label
|
||||||
|
|
||||||
|
init {
|
||||||
|
loadFXML("/assets/fxml/version/installer-item.fxml")
|
||||||
|
|
||||||
|
style = "-fx-background-radius: 2; -fx-background-color: white; -fx-padding: 8;"
|
||||||
|
JFXDepthManager.setDepth(this, 1)
|
||||||
|
lblInstallerArtifact.text = artifact
|
||||||
|
lblInstallerVersion.text = version
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onDelete() {
|
||||||
|
deleteCallback(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -69,9 +69,6 @@ class ModController {
|
|||||||
modManager.removeMods(versionId, modInfo)
|
modManager.removeMods(versionId, modInfo)
|
||||||
loadMods(modManager, versionId)
|
loadMods(modManager, versionId)
|
||||||
}.apply {
|
}.apply {
|
||||||
JFXDepthManager.setDepth(this, 1)
|
|
||||||
style += "-fx-background-radius: 2; -fx-background-color: white; -fx-padding: 8;"
|
|
||||||
|
|
||||||
modInfo.activeProperty.onChange {
|
modInfo.activeProperty.onChange {
|
||||||
if (it)
|
if (it)
|
||||||
styleClass -= "disabled"
|
styleClass -= "disabled"
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
package org.jackhuang.hmcl.ui
|
package org.jackhuang.hmcl.ui
|
||||||
|
|
||||||
import com.jfoenix.controls.JFXCheckBox
|
import com.jfoenix.controls.JFXCheckBox
|
||||||
|
import com.jfoenix.effects.JFXDepthManager
|
||||||
import javafx.fxml.FXML
|
import javafx.fxml.FXML
|
||||||
import javafx.scene.control.Label
|
import javafx.scene.control.Label
|
||||||
import javafx.scene.layout.BorderPane
|
import javafx.scene.layout.BorderPane
|
||||||
@@ -30,8 +31,10 @@ class ModItem(info: ModInfo, private val deleteCallback: (ModItem) -> Unit) : Bo
|
|||||||
@FXML lateinit var chkEnabled: JFXCheckBox
|
@FXML lateinit var chkEnabled: JFXCheckBox
|
||||||
|
|
||||||
init {
|
init {
|
||||||
loadFXML("/assets/fxml/mod-item.fxml")
|
loadFXML("/assets/fxml/version/mod-item.fxml")
|
||||||
|
|
||||||
|
style = "-fx-background-radius: 2; -fx-background-color: white; -fx-padding: 8;"
|
||||||
|
JFXDepthManager.setDepth(this, 1)
|
||||||
lblModFileName.text = info.fileName
|
lblModFileName.text = info.fileName
|
||||||
lblModAuthor.text = "${info.name}, Version: ${info.version}, Game Version: ${info.mcversion}, Authors: ${info.authors}"
|
lblModAuthor.text = "${info.name}, Version: ${info.version}, Game Version: ${info.mcversion}, Authors: ${info.authors}"
|
||||||
chkEnabled.isSelected = info.isActive
|
chkEnabled.isSelected = info.isActive
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ class VersionPage : StackPane(), DecoratorPage {
|
|||||||
|
|
||||||
@FXML lateinit var versionSettingsController: VersionSettingsController
|
@FXML lateinit var versionSettingsController: VersionSettingsController
|
||||||
@FXML lateinit var modController: ModController
|
@FXML lateinit var modController: ModController
|
||||||
|
@FXML lateinit var installerController: InstallerController
|
||||||
|
|
||||||
@FXML lateinit var browseList: JFXListView<*>
|
@FXML lateinit var browseList: JFXListView<*>
|
||||||
@FXML lateinit var managementList: JFXListView<*>
|
@FXML lateinit var managementList: JFXListView<*>
|
||||||
@FXML lateinit var btnBrowseMenu: JFXButton
|
@FXML lateinit var btnBrowseMenu: JFXButton
|
||||||
@@ -48,7 +50,7 @@ class VersionPage : StackPane(), DecoratorPage {
|
|||||||
lateinit var version: String
|
lateinit var version: String
|
||||||
|
|
||||||
init {
|
init {
|
||||||
loadFXML("/assets/fxml/version.fxml")
|
loadFXML("/assets/fxml/version/version.fxml")
|
||||||
|
|
||||||
children -= browseList
|
children -= browseList
|
||||||
children -= managementList
|
children -= managementList
|
||||||
@@ -68,6 +70,7 @@ class VersionPage : StackPane(), DecoratorPage {
|
|||||||
|
|
||||||
versionSettingsController.loadVersionSetting(profile.getVersionSetting(id))
|
versionSettingsController.loadVersionSetting(profile.getVersionSetting(id))
|
||||||
modController.loadMods(profile.modManager, id)
|
modController.loadMods(profile.modManager, id)
|
||||||
|
installerController.loadVersion(profile, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onBrowseMenu() {
|
fun onBrowseMenu() {
|
||||||
|
|||||||
@@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* 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.ui.download
|
||||||
|
|
||||||
|
import com.jfoenix.controls.JFXButton
|
||||||
|
import com.jfoenix.controls.JFXListView
|
||||||
|
import javafx.fxml.FXML
|
||||||
|
import javafx.scene.control.Label
|
||||||
|
import javafx.scene.layout.StackPane
|
||||||
|
import javafx.scene.layout.VBox
|
||||||
|
import org.jackhuang.hmcl.download.DownloadProvider
|
||||||
|
import org.jackhuang.hmcl.game.GameRepository
|
||||||
|
import org.jackhuang.hmcl.ui.loadFXML
|
||||||
|
import org.jackhuang.hmcl.ui.wizard.WizardController
|
||||||
|
import org.jackhuang.hmcl.ui.wizard.WizardPage
|
||||||
|
|
||||||
|
class AdditionalInstallersPage(private val provider: InstallWizardProvider, private val controller: WizardController, private val repository: GameRepository, private val downloadProvider: DownloadProvider): StackPane(), WizardPage {
|
||||||
|
|
||||||
|
@FXML lateinit var list: VBox
|
||||||
|
@FXML lateinit var btnForge: JFXButton
|
||||||
|
@FXML lateinit var btnLiteLoader: JFXButton
|
||||||
|
@FXML lateinit var btnOptiFine: JFXButton
|
||||||
|
@FXML lateinit var lblGameVersion: Label
|
||||||
|
@FXML lateinit var lblVersionName: Label
|
||||||
|
@FXML lateinit var lblForge: Label
|
||||||
|
@FXML lateinit var lblLiteLoader: Label
|
||||||
|
@FXML lateinit var lblOptiFine: Label
|
||||||
|
@FXML lateinit var btnInstall: JFXButton
|
||||||
|
|
||||||
|
init {
|
||||||
|
loadFXML("/assets/fxml/download/additional-installers.fxml")
|
||||||
|
|
||||||
|
lblGameVersion.text = provider.gameVersion
|
||||||
|
lblVersionName.text = provider.version.id
|
||||||
|
|
||||||
|
btnForge.setOnMouseClicked {
|
||||||
|
controller.settings[INSTALLER_TYPE] = 0
|
||||||
|
controller.onNext(VersionsPage(controller, provider.gameVersion, downloadProvider, "forge") { controller.onPrev(false) })
|
||||||
|
}
|
||||||
|
|
||||||
|
btnLiteLoader.setOnMouseClicked {
|
||||||
|
controller.settings[INSTALLER_TYPE] = 1
|
||||||
|
controller.onNext(VersionsPage(controller, provider.gameVersion, downloadProvider, "liteloader") { controller.onPrev(false) })
|
||||||
|
}
|
||||||
|
|
||||||
|
btnOptiFine.setOnMouseClicked {
|
||||||
|
controller.settings[INSTALLER_TYPE] = 2
|
||||||
|
controller.onNext(VersionsPage(controller, provider.gameVersion, downloadProvider, "optifine") { controller.onPrev(false) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override val title: String
|
||||||
|
get() = "Choose a game version"
|
||||||
|
|
||||||
|
override fun onNavigate(settings: MutableMap<String, Any>) {
|
||||||
|
lblGameVersion.text = "Current Game Version: ${provider.gameVersion}"
|
||||||
|
btnForge.isDisable = provider.forge != null
|
||||||
|
if (provider.forge != null || controller.settings.containsKey("forge"))
|
||||||
|
lblForge.text = "Forge Versoin: ${provider.forge ?: controller.settings["forge"]}"
|
||||||
|
else
|
||||||
|
lblForge.text = "Forge not installed"
|
||||||
|
|
||||||
|
btnLiteLoader.isDisable = provider.liteloader != null
|
||||||
|
if (provider.liteloader != null || controller.settings.containsKey("liteloader"))
|
||||||
|
lblLiteLoader.text = "LiteLoader Versoin: ${provider.liteloader ?: controller.settings["liteloader"]}"
|
||||||
|
else
|
||||||
|
lblLiteLoader.text = "LiteLoader not installed"
|
||||||
|
|
||||||
|
btnOptiFine.isDisable = provider.optifine != null
|
||||||
|
if (provider.optifine != null || controller.settings.containsKey("optifine"))
|
||||||
|
lblOptiFine.text = "OptiFine Versoin: ${provider.optifine ?: controller.settings["optifine"]}"
|
||||||
|
else
|
||||||
|
lblOptiFine.text = "OptiFine not installed"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun cleanup(settings: MutableMap<String, Any>) {
|
||||||
|
settings.remove(INSTALLER_TYPE)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onInstall() {
|
||||||
|
controller.onFinish()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val INSTALLER_TYPE = "INSTALLER_TYPE"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -95,10 +95,11 @@ class DownloadWizardProvider(): WizardProvider() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun createPage(controller: WizardController, step: Int, settings: MutableMap<String, Any>): Node {
|
override fun createPage(controller: WizardController, step: Int, settings: MutableMap<String, Any>): Node {
|
||||||
|
val provider = profile.dependency.downloadProvider
|
||||||
return when (step) {
|
return when (step) {
|
||||||
0 -> InstallTypePage(controller)
|
0 -> InstallTypePage(controller)
|
||||||
1 -> when (settings[InstallTypePage.INSTALL_TYPE]) {
|
1 -> when (settings[InstallTypePage.INSTALL_TYPE]) {
|
||||||
0 -> VersionsPage(controller, "", BMCLAPIDownloadProvider, "game") { controller.onNext(InstallersPage(controller, profile.repository, BMCLAPIDownloadProvider)) }
|
0 -> VersionsPage(controller, "", provider, "game") { controller.onNext(InstallersPage(controller, profile.repository, provider)) }
|
||||||
1 -> ModpackPage(controller)
|
1 -> ModpackPage(controller)
|
||||||
else -> throw Error()
|
else -> throw Error()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package org.jackhuang.hmcl.ui.download
|
||||||
|
|
||||||
|
import javafx.scene.Node
|
||||||
|
import org.jackhuang.hmcl.download.BMCLAPIDownloadProvider
|
||||||
|
import org.jackhuang.hmcl.game.HMCLModpackInstallTask
|
||||||
|
import org.jackhuang.hmcl.game.HMCLModpackManifest
|
||||||
|
import org.jackhuang.hmcl.game.Version
|
||||||
|
import org.jackhuang.hmcl.mod.CurseForgeModpackInstallTask
|
||||||
|
import org.jackhuang.hmcl.mod.CurseForgeModpackManifest
|
||||||
|
import org.jackhuang.hmcl.mod.Modpack
|
||||||
|
import org.jackhuang.hmcl.setting.EnumGameDirectory
|
||||||
|
import org.jackhuang.hmcl.setting.Profile
|
||||||
|
import org.jackhuang.hmcl.setting.Settings
|
||||||
|
import org.jackhuang.hmcl.task.Scheduler
|
||||||
|
import org.jackhuang.hmcl.task.Task
|
||||||
|
import org.jackhuang.hmcl.task.task
|
||||||
|
import org.jackhuang.hmcl.ui.wizard.WizardController
|
||||||
|
import org.jackhuang.hmcl.ui.wizard.WizardProvider
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class InstallWizardProvider(val profile: Profile, val gameVersion: String, val version: Version, val forge: String? = null, val liteloader: String? = null, val optifine: String? = null): WizardProvider() {
|
||||||
|
|
||||||
|
override fun start(settings: MutableMap<String, Any>) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun finish(settings: MutableMap<String, Any>): Any? {
|
||||||
|
var ret = task {}
|
||||||
|
|
||||||
|
if (settings.containsKey("forge"))
|
||||||
|
ret = ret with profile.dependency.installLibraryAsync(gameVersion, version, "forge", settings["forge"] as String)
|
||||||
|
|
||||||
|
if (settings.containsKey("liteloader"))
|
||||||
|
ret = ret with profile.dependency.installLibraryAsync(gameVersion, version, "liteloader", settings["liteloader"] as String)
|
||||||
|
|
||||||
|
if (settings.containsKey("optifine"))
|
||||||
|
ret = ret with profile.dependency.installLibraryAsync(gameVersion, version, "optifine", settings["optifine"] as String)
|
||||||
|
|
||||||
|
return ret with task(Scheduler.JAVAFX) { profile.repository.refreshVersions() }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createPage(controller: WizardController, step: Int, settings: MutableMap<String, Any>): Node {
|
||||||
|
return when (step) {
|
||||||
|
0 -> AdditionalInstallersPage(this, controller, profile.repository, BMCLAPIDownloadProvider)
|
||||||
|
else -> throw IllegalStateException()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun cancel(): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -23,6 +23,7 @@ import com.jfoenix.controls.JFXTextField
|
|||||||
import javafx.fxml.FXML
|
import javafx.fxml.FXML
|
||||||
import javafx.scene.control.Label
|
import javafx.scene.control.Label
|
||||||
import javafx.scene.layout.StackPane
|
import javafx.scene.layout.StackPane
|
||||||
|
import javafx.scene.layout.VBox
|
||||||
import org.jackhuang.hmcl.download.DownloadProvider
|
import org.jackhuang.hmcl.download.DownloadProvider
|
||||||
import org.jackhuang.hmcl.game.GameRepository
|
import org.jackhuang.hmcl.game.GameRepository
|
||||||
import org.jackhuang.hmcl.i18n
|
import org.jackhuang.hmcl.i18n
|
||||||
@@ -30,11 +31,13 @@ import org.jackhuang.hmcl.ui.construct.Validator
|
|||||||
import org.jackhuang.hmcl.ui.loadFXML
|
import org.jackhuang.hmcl.ui.loadFXML
|
||||||
import org.jackhuang.hmcl.ui.wizard.WizardController
|
import org.jackhuang.hmcl.ui.wizard.WizardController
|
||||||
import org.jackhuang.hmcl.ui.wizard.WizardPage
|
import org.jackhuang.hmcl.ui.wizard.WizardPage
|
||||||
import org.jackhuang.hmcl.util.onChange
|
|
||||||
|
|
||||||
class InstallersPage(private val controller: WizardController, private val repository: GameRepository, private val downloadProvider: DownloadProvider): StackPane(), WizardPage {
|
class InstallersPage(private val controller: WizardController, private val repository: GameRepository, private val downloadProvider: DownloadProvider): StackPane(), WizardPage {
|
||||||
|
|
||||||
@FXML lateinit var list: JFXListView<VersionsPageItem>
|
@FXML lateinit var list: VBox
|
||||||
|
@FXML lateinit var btnForge: JFXButton
|
||||||
|
@FXML lateinit var btnLiteLoader: JFXButton
|
||||||
|
@FXML lateinit var btnOptiFine: JFXButton
|
||||||
@FXML lateinit var lblGameVersion: Label
|
@FXML lateinit var lblGameVersion: Label
|
||||||
@FXML lateinit var lblForge: Label
|
@FXML lateinit var lblForge: Label
|
||||||
@FXML lateinit var lblLiteLoader: Label
|
@FXML lateinit var lblLiteLoader: Label
|
||||||
@@ -52,14 +55,19 @@ class InstallersPage(private val controller: WizardController, private val repos
|
|||||||
}
|
}
|
||||||
txtName.text = gameVersion
|
txtName.text = gameVersion
|
||||||
|
|
||||||
list.selectionModel.selectedIndexProperty().onChange {
|
btnForge.setOnMouseClicked {
|
||||||
controller.settings[INSTALLER_TYPE] = it
|
controller.settings[INSTALLER_TYPE] = 0
|
||||||
controller.onNext(when (it){
|
controller.onNext(VersionsPage(controller, gameVersion, downloadProvider, "forge") { controller.onPrev(false) })
|
||||||
0 -> VersionsPage(controller, gameVersion, downloadProvider, "forge") { controller.onPrev(false) }
|
}
|
||||||
1 -> VersionsPage(controller, gameVersion, downloadProvider, "liteloader") { controller.onPrev(false) }
|
|
||||||
2 -> VersionsPage(controller, gameVersion, downloadProvider, "optifine") { controller.onPrev(false) }
|
btnLiteLoader.setOnMouseClicked {
|
||||||
else -> throw IllegalStateException()
|
controller.settings[INSTALLER_TYPE] = 1
|
||||||
})
|
controller.onNext(VersionsPage(controller, gameVersion, downloadProvider, "liteloader") { controller.onPrev(false) })
|
||||||
|
}
|
||||||
|
|
||||||
|
btnOptiFine.setOnMouseClicked {
|
||||||
|
controller.settings[INSTALLER_TYPE] = 2
|
||||||
|
controller.onNext(VersionsPage(controller, gameVersion, downloadProvider, "optifine") { controller.onPrev(false) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,10 +28,15 @@ class WizardController(protected val displayer: WizardDisplayer) : Navigation {
|
|||||||
|
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
settings.clear()
|
settings.clear()
|
||||||
|
provider.start(settings)
|
||||||
|
|
||||||
pages.clear()
|
pages.clear()
|
||||||
val page = navigatingTo(0)
|
val page = navigatingTo(0)
|
||||||
pages.push(page)
|
pages.push(page)
|
||||||
provider.start(settings)
|
|
||||||
|
if (page is WizardPage)
|
||||||
|
page.onNavigate(settings)
|
||||||
|
|
||||||
displayer.onStart()
|
displayer.onStart()
|
||||||
displayer.navigateTo(page, Navigation.NavigationDirection.START)
|
displayer.navigateTo(page, Navigation.NavigationDirection.START)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<?import com.jfoenix.controls.*?>
|
||||||
|
<?import javafx.scene.control.Label?>
|
||||||
|
<?import javafx.scene.layout.*?>
|
||||||
|
<fx:root xmlns="http://javafx.com/javafx"
|
||||||
|
xmlns:fx="http://javafx.com/fxml"
|
||||||
|
type="StackPane" style="-fx-padding: 16;">
|
||||||
|
<BorderPane>
|
||||||
|
<top>
|
||||||
|
<VBox alignment="CENTER" style="-fx-padding: 40px;" spacing="20">
|
||||||
|
<Label fx:id="lblGameVersion" alignment="CENTER"/>
|
||||||
|
<Label fx:id="lblVersionName" alignment="CENTER"/>
|
||||||
|
</VBox>
|
||||||
|
</top>
|
||||||
|
<center>
|
||||||
|
<VBox fx:id="list" styleClass="jfx-list-view" maxHeight="150" maxWidth="300">
|
||||||
|
<JFXButton fx:id="btnForge" prefWidth="${list.width}">
|
||||||
|
<graphic>
|
||||||
|
<BorderPane mouseTransparent="true">
|
||||||
|
<left>
|
||||||
|
<Label fx:id="lblForge">Install Forge</Label>
|
||||||
|
</left>
|
||||||
|
<right>
|
||||||
|
<fx:include source="/assets/svg/arrow-right.fxml"/>
|
||||||
|
</right>
|
||||||
|
</BorderPane>
|
||||||
|
</graphic>
|
||||||
|
</JFXButton>
|
||||||
|
<JFXButton fx:id="btnLiteLoader" prefWidth="${list.width}">
|
||||||
|
<graphic>
|
||||||
|
<BorderPane mouseTransparent="true">
|
||||||
|
<left>
|
||||||
|
<Label fx:id="lblLiteLoader">Install LiteLoader</Label>
|
||||||
|
</left>
|
||||||
|
<right>
|
||||||
|
<fx:include source="/assets/svg/arrow-right.fxml"/>
|
||||||
|
</right>
|
||||||
|
</BorderPane>
|
||||||
|
</graphic>
|
||||||
|
</JFXButton>
|
||||||
|
<JFXButton fx:id="btnOptiFine" prefWidth="${list.width}">
|
||||||
|
<graphic>
|
||||||
|
<BorderPane mouseTransparent="true">
|
||||||
|
<left>
|
||||||
|
<Label fx:id="lblOptiFine">Install OptiFine</Label>
|
||||||
|
</left>
|
||||||
|
<right>
|
||||||
|
<fx:include source="/assets/svg/arrow-right.fxml"/>
|
||||||
|
</right>
|
||||||
|
</BorderPane>
|
||||||
|
</graphic>
|
||||||
|
</JFXButton>
|
||||||
|
</VBox>
|
||||||
|
</center>
|
||||||
|
<bottom>
|
||||||
|
<HBox alignment="CENTER">
|
||||||
|
<JFXButton fx:id="btnInstall" onMouseClicked="#onInstall" prefWidth="100" prefHeight="40"
|
||||||
|
buttonType="RAISED" text="%ui.button.install" styleClass="jfx-button-raised"/>
|
||||||
|
</HBox>
|
||||||
|
</bottom>
|
||||||
|
</BorderPane>
|
||||||
|
</fx:root>
|
||||||
@@ -1,54 +1,62 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
<?import com.jfoenix.controls.JFXListView?>
|
<?import com.jfoenix.controls.*?>
|
||||||
<?import javafx.scene.layout.StackPane?>
|
|
||||||
<?import javafx.scene.layout.VBox?>
|
|
||||||
<?import javafx.scene.control.Label?>
|
<?import javafx.scene.control.Label?>
|
||||||
<?import javafx.scene.layout.BorderPane?>
|
<?import javafx.scene.layout.*?>
|
||||||
<?import com.jfoenix.controls.JFXButton?>
|
|
||||||
<?import javafx.scene.layout.HBox?>
|
|
||||||
<?import com.jfoenix.controls.JFXTextField?>
|
|
||||||
<fx:root xmlns="http://javafx.com/javafx"
|
<fx:root xmlns="http://javafx.com/javafx"
|
||||||
xmlns:fx="http://javafx.com/fxml"
|
xmlns:fx="http://javafx.com/fxml"
|
||||||
type="StackPane">
|
type="StackPane" style="-fx-padding: 16;">
|
||||||
<BorderPane>
|
<BorderPane>
|
||||||
<top>
|
<top>
|
||||||
<VBox alignment="CENTER" style="-fx-padding: 40px;" spacing="20">
|
<VBox alignment="CENTER" style="-fx-padding: 40px;" spacing="20">
|
||||||
<Label fx:id="lblGameVersion" alignment="CENTER" />
|
<Label fx:id="lblGameVersion" alignment="CENTER"/>
|
||||||
<JFXTextField fx:id="txtName" labelFloat="true" promptText="%modpack.enter_name" maxWidth="300" />
|
<JFXTextField fx:id="txtName" labelFloat="true" promptText="%modpack.enter_name" maxWidth="300"/>
|
||||||
</VBox>
|
</VBox>
|
||||||
</top>
|
</top>
|
||||||
<center>
|
<center>
|
||||||
<JFXListView fx:id="list" styleClass="jfx-list-view" maxHeight="150" maxWidth="300">
|
<VBox fx:id="list" styleClass="jfx-list-view" maxHeight="150" maxWidth="300">
|
||||||
<BorderPane mouseTransparent="true">
|
<JFXButton fx:id="btnForge" prefWidth="${list.width}">
|
||||||
<left>
|
<graphic>
|
||||||
<Label fx:id="lblForge">Install Forge</Label>
|
<BorderPane mouseTransparent="true">
|
||||||
</left>
|
<left>
|
||||||
<right>
|
<Label fx:id="lblForge">Install Forge</Label>
|
||||||
<fx:include source="/assets/svg/arrow-right.fxml"/>
|
</left>
|
||||||
</right>
|
<right>
|
||||||
</BorderPane>
|
<fx:include source="/assets/svg/arrow-right.fxml"/>
|
||||||
<BorderPane mouseTransparent="true">
|
</right>
|
||||||
<left>
|
</BorderPane>
|
||||||
<Label fx:id="lblLiteLoader">Install LiteLoader</Label>
|
</graphic>
|
||||||
</left>
|
</JFXButton>
|
||||||
<right>
|
<JFXButton fx:id="btnLiteLoader" prefWidth="${list.width}">
|
||||||
<fx:include source="/assets/svg/arrow-right.fxml"/>
|
<graphic>
|
||||||
</right>
|
<BorderPane mouseTransparent="true">
|
||||||
</BorderPane>
|
<left>
|
||||||
<BorderPane mouseTransparent="true">
|
<Label fx:id="lblLiteLoader">Install LiteLoader</Label>
|
||||||
<left>
|
</left>
|
||||||
<Label fx:id="lblOptiFine">Install OptiFine</Label>
|
<right>
|
||||||
</left>
|
<fx:include source="/assets/svg/arrow-right.fxml"/>
|
||||||
<right>
|
</right>
|
||||||
<fx:include source="/assets/svg/arrow-right.fxml"/>
|
</BorderPane>
|
||||||
</right>
|
</graphic>
|
||||||
</BorderPane>
|
</JFXButton>
|
||||||
</JFXListView>
|
<JFXButton fx:id="btnOptiFine" prefWidth="${list.width}">
|
||||||
|
<graphic>
|
||||||
|
<BorderPane mouseTransparent="true">
|
||||||
|
<left>
|
||||||
|
<Label fx:id="lblOptiFine">Install OptiFine</Label>
|
||||||
|
</left>
|
||||||
|
<right>
|
||||||
|
<fx:include source="/assets/svg/arrow-right.fxml"/>
|
||||||
|
</right>
|
||||||
|
</BorderPane>
|
||||||
|
</graphic>
|
||||||
|
</JFXButton>
|
||||||
|
</VBox>
|
||||||
</center>
|
</center>
|
||||||
<bottom>
|
<bottom>
|
||||||
<HBox alignment="CENTER">
|
<HBox alignment="CENTER">
|
||||||
<JFXButton fx:id="btnInstall" onMouseClicked="#onInstall" prefWidth="100" prefHeight="40" buttonType="RAISED" text="%ui.button.install" styleClass="jfx-button-raised" />
|
<JFXButton fx:id="btnInstall" onMouseClicked="#onInstall" prefWidth="100" prefHeight="40"
|
||||||
|
buttonType="RAISED" text="%ui.button.install" styleClass="jfx-button-raised"/>
|
||||||
</HBox>
|
</HBox>
|
||||||
</bottom>
|
</bottom>
|
||||||
</BorderPane>
|
</BorderPane>
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<?import javafx.scene.control.*?>
|
||||||
|
<?import javafx.scene.layout.*?>
|
||||||
|
<?import com.jfoenix.controls.JFXButton?>
|
||||||
|
|
||||||
|
<fx:root xmlns="http://javafx.com/javafx"
|
||||||
|
xmlns:fx="http://javafx.com/fxml"
|
||||||
|
type="BorderPane">
|
||||||
|
<center>
|
||||||
|
<VBox BorderPane.alignment="CENTER">
|
||||||
|
<Label fx:id="lblInstallerArtifact" style="-fx-font-size: 15;" />
|
||||||
|
<Label fx:id="lblInstallerVersion" style="-fx-font-size: 10;" />
|
||||||
|
</VBox>
|
||||||
|
</center>
|
||||||
|
<right>
|
||||||
|
<JFXButton onMouseClicked="#onDelete" styleClass="toggle-icon4" BorderPane.alignment="CENTER">
|
||||||
|
<graphic>
|
||||||
|
<fx:include source="/assets/svg/close-black.fxml"/>
|
||||||
|
</graphic>
|
||||||
|
</JFXButton>
|
||||||
|
</right>
|
||||||
|
</fx:root>
|
||||||
23
HMCL/src/main/resources/assets/fxml/version/installer.fxml
Normal file
23
HMCL/src/main/resources/assets/fxml/version/installer.fxml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<?import javafx.scene.layout.*?>
|
||||||
|
|
||||||
|
<?import com.jfoenix.controls.JFXButton?>
|
||||||
|
<?import javafx.scene.control.ScrollPane?>
|
||||||
|
<StackPane xmlns="http://javafx.com/javafx"
|
||||||
|
xmlns:fx="http://javafx.com/fxml"
|
||||||
|
fx:controller="org.jackhuang.hmcl.ui.InstallerController">
|
||||||
|
<ScrollPane fx:id="scrollPane" fitToWidth="true" fitToHeight="true">
|
||||||
|
<VBox fx:id="contentPane" spacing="10" style="-fx-padding: 20;">
|
||||||
|
|
||||||
|
</VBox>
|
||||||
|
</ScrollPane>
|
||||||
|
<VBox style="-fx-padding: 15;" spacing="15" pickOnBounds="false" alignment="BOTTOM_RIGHT">
|
||||||
|
<JFXButton prefWidth="40" prefHeight="40" buttonType="RAISED" onMouseClicked="#onAdd"
|
||||||
|
style="-fx-background-color:#5264AE;-fx-background-radius: 50px;">
|
||||||
|
<graphic>
|
||||||
|
<fx:include source="/assets/svg/plus.fxml" />
|
||||||
|
</graphic>
|
||||||
|
</JFXButton>
|
||||||
|
</VBox>
|
||||||
|
</StackPane>
|
||||||
@@ -13,6 +13,9 @@
|
|||||||
<Tab text="%mods">
|
<Tab text="%mods">
|
||||||
<fx:include source="mod.fxml" fx:id="mod" />
|
<fx:include source="mod.fxml" fx:id="mod" />
|
||||||
</Tab>
|
</Tab>
|
||||||
|
<Tab text="%settings.tabs.installers">
|
||||||
|
<fx:include source="installer.fxml" fx:id="installer" />
|
||||||
|
</Tab>
|
||||||
</JFXTabPane>
|
</JFXTabPane>
|
||||||
|
|
||||||
<HBox alignment="TOP_RIGHT" style="-fx-padding: 3px;" pickOnBounds="false">
|
<HBox alignment="TOP_RIGHT" style="-fx-padding: 3px;" pickOnBounds="false">
|
||||||
@@ -51,13 +51,13 @@ class DefaultDependencyManager(override val repository: DefaultGameRepository, o
|
|||||||
override fun installLibraryAsync(gameVersion: String, version: Version, libraryId: String, libraryVersion: String): Task {
|
override fun installLibraryAsync(gameVersion: String, version: Version, libraryId: String, libraryVersion: String): Task {
|
||||||
if (libraryId == "forge")
|
if (libraryId == "forge")
|
||||||
return ForgeInstallTask(this, gameVersion, version, libraryVersion)
|
return ForgeInstallTask(this, gameVersion, version, libraryVersion)
|
||||||
.then { VersionJSONSaveTask(this, it["version"]) }
|
.then { VersionJSONSaveTask(repository, it["version"]) }
|
||||||
else if (libraryId == "liteloader")
|
else if (libraryId == "liteloader")
|
||||||
return LiteLoaderInstallTask(this, gameVersion, version, libraryVersion)
|
return LiteLoaderInstallTask(this, gameVersion, version, libraryVersion)
|
||||||
.then { VersionJSONSaveTask(this, it["version"]) }
|
.then { VersionJSONSaveTask(repository, it["version"]) }
|
||||||
else if (libraryId == "optifine")
|
else if (libraryId == "optifine")
|
||||||
return OptiFineInstallTask(this, gameVersion, version, libraryVersion)
|
return OptiFineInstallTask(this, gameVersion, version, libraryVersion)
|
||||||
.then { VersionJSONSaveTask(this, it["version"]) }
|
.then { VersionJSONSaveTask(repository, it["version"]) }
|
||||||
else
|
else
|
||||||
throw IllegalArgumentException("Library id $libraryId is unrecognized.")
|
throw IllegalArgumentException("Library id $libraryId is unrecognized.")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ class DefaultGameBuilder(val dependencyManager: DefaultDependencyManager): GameB
|
|||||||
GameLoggingDownloadTask(dependencyManager, version),
|
GameLoggingDownloadTask(dependencyManager, version),
|
||||||
GameDownloadTask(version),
|
GameDownloadTask(version),
|
||||||
GameLibrariesTask(dependencyManager, version) // Game libraries will be downloaded for multiple times partly, this time is for vanilla libraries.
|
GameLibrariesTask(dependencyManager, version) // Game libraries will be downloaded for multiple times partly, this time is for vanilla libraries.
|
||||||
) then VersionJSONSaveTask(dependencyManager, version)
|
) then VersionJSONSaveTask(dependencyManager.repository, version)
|
||||||
|
|
||||||
if (toolVersions.containsKey("forge"))
|
if (toolVersions.containsKey("forge"))
|
||||||
result = result then libraryTaskHelper(gameVersion, "forge")
|
result = result then libraryTaskHelper(gameVersion, "forge")
|
||||||
|
|||||||
@@ -20,10 +20,7 @@ package org.jackhuang.hmcl.download.game
|
|||||||
import org.jackhuang.hmcl.download.AbstractDependencyManager
|
import org.jackhuang.hmcl.download.AbstractDependencyManager
|
||||||
import org.jackhuang.hmcl.download.DefaultDependencyManager
|
import org.jackhuang.hmcl.download.DefaultDependencyManager
|
||||||
import org.jackhuang.hmcl.download.DependencyManager
|
import org.jackhuang.hmcl.download.DependencyManager
|
||||||
import org.jackhuang.hmcl.game.AssetIndex
|
import org.jackhuang.hmcl.game.*
|
||||||
import org.jackhuang.hmcl.game.AssetObject
|
|
||||||
import org.jackhuang.hmcl.game.DownloadType
|
|
||||||
import org.jackhuang.hmcl.game.Version
|
|
||||||
import org.jackhuang.hmcl.task.FileDownloadTask
|
import org.jackhuang.hmcl.task.FileDownloadTask
|
||||||
import org.jackhuang.hmcl.task.Task
|
import org.jackhuang.hmcl.task.Task
|
||||||
import org.jackhuang.hmcl.task.TaskResult
|
import org.jackhuang.hmcl.task.TaskResult
|
||||||
@@ -164,12 +161,12 @@ class GameAssetDownloadTask(private val dependencyManager: DefaultDependencyMana
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This task is to save the version json.
|
* This task is to save the version json.
|
||||||
* @param dependencyManager the dependency manager that can provides proxy settings and [GameRepository]
|
* @param repository the game repository
|
||||||
* @param version the **resolved** version
|
* @param version the **resolved** version
|
||||||
*/
|
*/
|
||||||
class VersionJSONSaveTask(private val dependencyManager: DefaultDependencyManager, private val version: Version): Task() {
|
class VersionJSONSaveTask(private val repository: DefaultGameRepository, private val version: Version): Task() {
|
||||||
override fun execute() {
|
override fun execute() {
|
||||||
val json = dependencyManager.repository.getVersionJson(version.id).absoluteFile
|
val json = repository.getVersionJson(version.id).absoluteFile
|
||||||
if (!json.makeFile())
|
if (!json.makeFile())
|
||||||
throw IOException("Cannot create file $json")
|
throw IOException("Cannot create file $json")
|
||||||
json.writeText(GSON.toJson(version))
|
json.writeText(GSON.toJson(version))
|
||||||
|
|||||||
@@ -74,12 +74,13 @@ open class Library(
|
|||||||
companion object LibrarySerializer : JsonDeserializer<Library>, JsonSerializer<Library> {
|
companion object LibrarySerializer : JsonDeserializer<Library>, JsonSerializer<Library> {
|
||||||
fun fromName(name: String, url: String? = null, downloads: LibrariesDownloadInfo? = null, extract: ExtractRules? = null, natives: Map<OS, String>? = null, rules: List<CompatibilityRule>? = null): Library {
|
fun fromName(name: String, url: String? = null, downloads: LibrariesDownloadInfo? = null, extract: ExtractRules? = null, natives: Map<OS, String>? = null, rules: List<CompatibilityRule>? = null): Library {
|
||||||
val arr = name.split(":".toRegex(), 3)
|
val arr = name.split(":".toRegex(), 3)
|
||||||
if (arr.size != 3)
|
if (arr.size != 3 && arr.size != 4)
|
||||||
throw IllegalArgumentException("Library name is malformed. Correct example: group:artifact:version.")
|
throw IllegalArgumentException("Library name is malformed. Correct example: group:artifact:version.")
|
||||||
return Library(
|
return Library(
|
||||||
groupId = arr[0].replace("\\", "/"),
|
groupId = arr[0].replace("\\", "/"),
|
||||||
artifactId = arr[1],
|
artifactId = arr[1],
|
||||||
version = arr[2],
|
version = arr[2],
|
||||||
|
classifier_ = arr.getOrNull(3),
|
||||||
url = url,
|
url = url,
|
||||||
downloads = downloads,
|
downloads = downloads,
|
||||||
extract = extract,
|
extract = extract,
|
||||||
|
|||||||
@@ -65,6 +65,10 @@ class GetTask @JvmOverloads constructor(val url: URL, val encoding: Charset = Ch
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (size > 0 && size != read) {
|
||||||
|
throw IllegalStateException("Not completed! Readed: $read, Size: $size")
|
||||||
|
}
|
||||||
|
|
||||||
result = baos.toString(encoding.name())
|
result = baos.toString(encoding.name())
|
||||||
return
|
return
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ abstract class Task {
|
|||||||
*/
|
*/
|
||||||
open val reliant: Boolean = true
|
open val reliant: Boolean = true
|
||||||
|
|
||||||
var title: String = this.javaClass.toString()
|
open var title: String = this.javaClass.toString()
|
||||||
|
|
||||||
var variables: AutoTypingMap<String>? = null
|
var variables: AutoTypingMap<String>? = null
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user