Inceptum/launcher-gtk/src/main/kotlin/io/gitlab/jfronny/inceptum/gtk/window/settings/instance/GeneralTab.kt

244 lines
12 KiB
Kotlin

package io.gitlab.jfronny.inceptum.gtk.window.settings.instance
import io.github.jwharm.javagi.base.GErrorException
import io.gitlab.jfronny.commons.ArgumentsTokenizer
import io.gitlab.jfronny.commons.io.JFiles
import io.gitlab.jfronny.inceptum.common.InceptumConfig
import io.gitlab.jfronny.inceptum.common.MetaHolder
import io.gitlab.jfronny.inceptum.common.Utils
import io.gitlab.jfronny.inceptum.gtk.control.ILabel
import io.gitlab.jfronny.inceptum.gtk.control.settings.SectionedSettingsTab
import io.gitlab.jfronny.inceptum.gtk.util.*
import io.gitlab.jfronny.inceptum.launcher.api.FabricMetaApi
import io.gitlab.jfronny.inceptum.launcher.api.McApi
import io.gitlab.jfronny.inceptum.launcher.system.instance.InstanceList
import io.gitlab.jfronny.inceptum.launcher.system.instance.InstanceNameTool
import io.gitlab.jfronny.inceptum.launcher.util.GameVersionParser
import org.gnome.gio.File
import org.gnome.gobject.BindingFlags
import org.gnome.gtk.*
import java.io.IOException
import java.nio.file.Files
import java.nio.file.Path
import java.util.*
class GeneralTab(window: InstanceSettingsWindow) : SectionedSettingsTab<InstanceSettingsWindow>(window) {
companion object {
private val VERSIONS = McApi.getVersions()
}
init {
val instance = window.instance
section(null) {
row("instance.settings.general.name", "instance.settings.general.name.placeholder") {
val apply = Button.newWithLabel(I18n["instance.settings.apply"])
val entry = setEntry(instance.name) { s: String -> apply.sensitive = s != instance.name }
entry.placeholderText = I18n["instance.settings.general.name.placeholder"]
apply.valign = Align.CENTER
apply.onClicked {
try {
val newPath = MetaHolder.INSTANCE_DIR.resolve(InstanceNameTool.getNextValid(entry.text))
Files.move(instance.path, newPath)
window.close()
InstanceSettingsWindow(window.application, InstanceList.read(newPath)).show()
} catch (e: IOException) {
showError("Could not rename", e)
}
}
apply.sensitive = false
append(apply)
}
}
section("instance.settings.general.game") {
run {
var fabricEnabled: Switch? = null
var versionChanged: (() -> Unit)? = null
var fabricVersion: DropDown? = null
var defaultFabric: String? = null
var fabricVersions: Array<String>? = null
val versions = VERSIONS.versions.stream()
.filter { InceptumConfig.snapshots || it.type == "release" }
.map { it.id }
.toTypedArray()
val def = versions.withIndex().firstOrNull { it.value == instance.gameVersion }?.index ?: 0
row("instance.settings.general.game.version", "instance.settings.general.game.version.subtitle") {
setDropdown(versions, def) { i ->
instance.meta.gameVersion = if (instance.isFabric) GameVersionParser.createVersionWithFabric(
versions[i], instance.loaderVersion
) else versions[i]
instance.writeMeta()
versionChanged!!()
}.enableSearch = true
}
val fabricRow = row("instance.settings.general.game.fabric.enabled", "instance.settings.general.game.fabric.enabled.subtitle")
val loaderRow = row("instance.settings.general.game.fabric.version", "instance.settings.general.game.fabric.version.subtitle")
loaderRow.visible = instance.isFabric
fabricEnabled = fabricRow.setSwitch(instance.isFabric) { bl: Boolean ->
if (bl) {
if (fabricVersions != null && fabricVersions!!.isNotEmpty() && defaultFabric != null) {
instance.meta.gameVersion =
GameVersionParser.createVersionWithFabric(instance.gameVersion, defaultFabric)
instance.writeMeta()
} else {
fabricEnabled!!.active = false
}
} else {
instance.meta.gameVersion = instance.gameVersion
instance.writeMeta()
}
}
fabricEnabled.bindProperty("active", loaderRow, "visible", BindingFlags.DEFAULT)
versionChanged = {
val ver = VERSIONS.versions.stream()
.filter { it.id == instance.gameVersion }
.findFirst()
.map { FabricMetaApi.getLoaderVersions(it) }
.map { it.toTypedArray() }
defaultFabric = if (instance.isFabric) instance.loaderVersion else ver
.map { Arrays.stream(it) }
.map { it.filter { l -> l.loader.stable } }
.flatMap { it.findFirst() }
.map { it.loader.version }
.orElse(null)
fabricVersions = ver.map { Arrays.stream(it) }
.map { it.map { l -> l.loader.version }.toTypedArray() }
.orElse(null)
if (fabricVersions == null || fabricVersions!!.isEmpty()) {
fabricEnabled.active = false
} else if (fabricVersion != null) fabricVersion!!.model = StringList(fabricVersions)
}
versionChanged()
fabricVersion =
loaderRow.setDropdown(fabricVersions!!, fabricVersions!!.indexOf(defaultFabric)) { i: Int ->
instance.meta.gameVersion =
if (i == -1) instance.gameVersion
else GameVersionParser.createVersionWithFabric(instance.gameVersion, fabricVersions!![i])
instance.writeMeta()
}
fabricVersion.enableSearch = true
}
row("instance.settings.general.game.java", "instance.settings.general.game.java.subtitle") {
val entry = setEntry(instance.meta.java) { s: String ->
instance.meta.java = s.ifBlank { null }
instance.writeMeta()
}
val btn = Button.newFromIconName("folder-symbolic")
btn.valign = Align.CENTER
btn.onClicked {
val dialog = FileChooserNative(
I18n["instance.settings.general.game.java"],
window,
FileChooserAction.OPEN,
"_" + I18n["select"],
"_" + I18n["cancel"]
)
if (instance.meta.java != null && Files.exists(Path.of(instance.meta.java))) {
try {
dialog.setFile(File.newForPath(instance.meta.java))
} catch (e: GErrorException) {
Log.error("Could not set starting point", e)
}
}
dialog.onResponse { responseId: Int ->
if (responseId == ResponseType.ACCEPT.value) {
val file = dialog.file!!.path
if (file != null) entry.text = file
}
}
dialog.show()
}
append(btn)
}
row("instance.settings.general.game.memory.min", "instance.settings.general.game.memory.min.subtitle") {
setSpinButton(
(if (instance.meta.minMem == null) 512 else instance.meta.minMem / Memory.MB).toDouble(),
512.0,
Memory.maxMBForInstance.toDouble(),
128.0
) { v: Double ->
instance.meta.minMem = (v * Memory.MB).toLong()
if (instance.meta.minMem == Memory.GB / 2) instance.meta.minMem = null
instance.writeMeta()
}
}
row("instance.settings.general.game.memory.max", "instance.settings.general.game.memory.max.subtitle") {
setSpinButton(
(if (instance.meta.maxMem == null) 1024 else instance.meta.maxMem / Memory.MB).toDouble(),
1024.0,
Memory.maxMBForInstance.toDouble(),
128.0
) { v: Double ->
instance.meta.maxMem = (v * Memory.MB).toLong()
if (instance.meta.maxMem == Memory.GB) instance.meta.maxMem = null
instance.writeMeta()
}
}
}
section("instance.settings.general.args") {
instance.meta.checkArguments()
row("instance.settings.general.args.jvm", "instance.settings.general.args.jvm.subtitle") {
setEntry(ArgumentsTokenizer.join(instance.meta.arguments.jvm.toTypedArray())) {
instance.meta.arguments = instance.meta.arguments.withJvm(listOf(*ArgumentsTokenizer.tokenize(it)))
instance.writeMeta()
}
}
row("instance.settings.general.args.client", "instance.settings.general.args.client.subtitle") {
setEntry(ArgumentsTokenizer.join(instance.meta.arguments.client.toTypedArray())) {
instance.meta.arguments = instance.meta.arguments.withClient(listOf(*ArgumentsTokenizer.tokenize(it)))
instance.writeMeta()
}
}
row("instance.settings.general.args.server", "instance.settings.general.args.server.subtitle") {
setEntry(ArgumentsTokenizer.join(instance.meta.arguments.server.toTypedArray())) {
instance.meta.arguments = instance.meta.arguments.withServer(listOf(*ArgumentsTokenizer.tokenize(it)))
instance.writeMeta()
}
}
}
section("instance.settings.general.manage") {
row("instance.delete", "instance.delete.subtitle") {
setButton("instance.delete") {
val dialog = MessageDialog(
window,
DialogFlags.MODAL.or(DialogFlags.DESTROY_WITH_PARENT),
MessageType.WARNING,
ButtonsType.OK_CANCEL,
null
)
dialog.markup = I18n["instance.delete.confirm"]
dialog.title = I18n["instance.delete.confirm.title"]
dialog.onResponse { responseId: Int ->
when (ResponseType.of(responseId)) {
ResponseType.OK -> {
try {
JFiles.deleteRecursive(instance.path)
dialog.close()
window.close()
} catch (e: IOException) {
showError(I18n["instance.delete.fail"], e)
}
dialog.close()
}
ResponseType.CLOSE, ResponseType.CANCEL -> dialog.close()
ResponseType.DELETE_EVENT -> dialog.destroy()
else -> {}
}
}
dialog.show()
}
}
row("instance.directory", "instance.directory.subtitle") {
setButton("instance.directory") { Utils.openFile(instance.path.toFile()) }
}
}
val timestamp = if (instance.meta.lastLaunched == null) 0 else instance.meta.lastLaunched
append(ILabel("instance.settings.general.last-launched", ILabel.Mode.SUBTITLE, Date(timestamp * 1000).toString()))
}
}