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.I18n import io.gitlab.jfronny.inceptum.gtk.util.Memory import io.gitlab.jfronny.inceptum.gtk.util.markup import io.gitlab.jfronny.inceptum.gtk.util.toTypedArray 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(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? = 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) { Utils.LOGGER.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())) } }