1
0
mirror of https://github.com/SKCraft/Launcher.git synced 2025-02-15 01:31:22 +01:00

Add instance settings dialog

This commit is contained in:
Henry Le Grys 2021-09-02 01:59:15 +01:00
parent e12eec29b5
commit faa1bc9a38
7 changed files with 240 additions and 49 deletions

View File

@ -5,26 +5,10 @@ import com.skcraft.launcher.launch.JavaRuntime;
import com.skcraft.launcher.launch.MemorySettings;
import lombok.Data;
import java.util.Optional;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class InstanceSettings {
private JavaRuntime runtime;
private MemorySettings memorySettings;
private String customJvmArgs;
/**
* @return Empty optional if there is no custom runtime set, present optional if there is.
*/
public Optional<JavaRuntime> getRuntime() {
return Optional.ofNullable(runtime);
}
/**
* @return Empty optional if there are no custom memory settings, present optional if there are.
*/
public Optional<MemorySettings> getMemorySettings() {
return Optional.ofNullable(memorySettings);
}
}

View File

@ -0,0 +1,153 @@
package com.skcraft.launcher.dialog;
import com.skcraft.launcher.Instance;
import com.skcraft.launcher.InstanceSettings;
import com.skcraft.launcher.dialog.component.BetterComboBox;
import com.skcraft.launcher.launch.JavaRuntime;
import com.skcraft.launcher.launch.JavaRuntimeFinder;
import com.skcraft.launcher.launch.MemorySettings;
import com.skcraft.launcher.persistence.Persistence;
import com.skcraft.launcher.swing.FormPanel;
import com.skcraft.launcher.swing.LinedBoxPanel;
import com.skcraft.launcher.util.SharedLocale;
import lombok.extern.java.Log;
import javax.swing.*;
import java.awt.*;
@Log
public class InstanceSettingsDialog extends JDialog {
private final InstanceSettings settings;
private final LinedBoxPanel formsPanel = new LinedBoxPanel(false);
private final FormPanel memorySettingsPanel = new FormPanel();
private final JCheckBox enableMemorySettings = new JCheckBox(SharedLocale.tr("instance.options.customMemory"));
private final JSpinner minMemorySpinner = new JSpinner();
private final JSpinner maxMemorySpinner = new JSpinner();
private final JCheckBox enableCustomRuntime = new JCheckBox(SharedLocale.tr("instance.options.customJava"));
private final FormPanel runtimePanel = new FormPanel();
private final JComboBox<JavaRuntime> javaRuntimeBox = new BetterComboBox<>();
private final JTextField javaArgsBox = new JTextField();
private final LinedBoxPanel buttonsPanel = new LinedBoxPanel(true);
private final JButton okButton = new JButton(SharedLocale.tr("button.save"));
private final JButton cancelButton = new JButton(SharedLocale.tr("button.cancel"));
private boolean saved = false;
public InstanceSettingsDialog(Window owner, InstanceSettings settings) {
super(owner);
this.settings = settings;
setTitle(SharedLocale.tr("instance.options.title"));
setModalityType(DEFAULT_MODALITY_TYPE);
initComponents();
setSize(new Dimension(400, 500));
setLocationRelativeTo(owner);
}
private void initComponents() {
memorySettingsPanel.addRow(enableMemorySettings);
memorySettingsPanel.addRow(new JLabel(SharedLocale.tr("options.minMemory")), minMemorySpinner);
memorySettingsPanel.addRow(new JLabel(SharedLocale.tr("options.maxMemory")), maxMemorySpinner);
// TODO: Do we keep this list centrally somewhere? Or is actively refreshing good?
JavaRuntime[] javaRuntimes = JavaRuntimeFinder.getAvailableRuntimes().toArray(new JavaRuntime[0]);
javaRuntimeBox.setModel(new DefaultComboBoxModel<>(javaRuntimes));
runtimePanel.addRow(enableCustomRuntime);
runtimePanel.addRow(new JLabel(SharedLocale.tr("options.jvmPath")), javaRuntimeBox);
runtimePanel.addRow(new JLabel(SharedLocale.tr("options.jvmArguments")), javaArgsBox);
okButton.setMargin(new Insets(0, 10, 0, 10));
buttonsPanel.addGlue();
buttonsPanel.addElement(okButton);
buttonsPanel.addElement(cancelButton);
enableMemorySettings.addActionListener(e -> {
if (enableMemorySettings.isSelected()) {
settings.setMemorySettings(new MemorySettings());
} else {
settings.setMemorySettings(null);
}
updateComponents();
});
enableCustomRuntime.addActionListener(e -> {
runtimePanel.setEnabled(enableCustomRuntime.isSelected());
});
okButton.addActionListener(e -> {
save();
dispose();
});
cancelButton.addActionListener(e -> dispose());
formsPanel.addElement(memorySettingsPanel);
formsPanel.addElement(runtimePanel);
add(formsPanel, BorderLayout.NORTH);
add(buttonsPanel, BorderLayout.SOUTH);
updateComponents();
}
private void updateComponents() {
if (settings.getMemorySettings() != null) {
memorySettingsPanel.setEnabled(true);
enableMemorySettings.setSelected(true);
minMemorySpinner.setValue(settings.getMemorySettings().getMinMemory());
maxMemorySpinner.setValue(settings.getMemorySettings().getMaxMemory());
} else {
memorySettingsPanel.setEnabled(false);
enableMemorySettings.setSelected(false);
}
if (settings.getRuntime() != null) {
runtimePanel.setEnabled(true);
enableCustomRuntime.setSelected(true);
} else {
runtimePanel.setEnabled(false);
enableCustomRuntime.setSelected(false);
}
javaRuntimeBox.setSelectedItem(settings.getRuntime());
javaArgsBox.setText(settings.getCustomJvmArgs());
}
private void save() {
if (enableMemorySettings.isSelected()) {
MemorySettings memorySettings = settings.getMemorySettings();
memorySettings.setMinMemory((int) minMemorySpinner.getValue());
memorySettings.setMaxMemory((int) maxMemorySpinner.getValue());
} else {
settings.setMemorySettings(null);
}
if (enableCustomRuntime.isSelected()) {
settings.setRuntime((JavaRuntime) javaRuntimeBox.getSelectedItem());
settings.setCustomJvmArgs(javaArgsBox.getText());
} else {
settings.setRuntime(null);
settings.setCustomJvmArgs(null);
}
saved = true;
}
public static boolean open(Window parent, Instance instance) {
InstanceSettingsDialog dialog = new InstanceSettingsDialog(parent, instance.getSettings());
dialog.setVisible(true);
if (dialog.saved) {
Persistence.commitAndForget(instance);
}
return dialog.saved;
}
}

View File

@ -241,6 +241,12 @@ public class LauncherFrame extends JFrame {
});
popup.add(menuItem);
menuItem = new JMenuItem(SharedLocale.tr("instance.openSettings"));
menuItem.addActionListener(e -> {
InstanceSettingsDialog.open(this, selected);
});
popup.add(menuItem);
popup.addSeparator();
if (!selected.isUpdatePending()) {

View File

@ -1,5 +1,9 @@
package com.skcraft.launcher.launch;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonValue;
import com.google.common.base.Objects;
import lombok.Data;
import java.io.File;
@ -9,11 +13,22 @@ public class JavaRuntime implements Comparable<JavaRuntime> {
private final File dir;
private final String version;
private final boolean is64Bit;
private boolean isMinecraftBundled = false;
private boolean isMinecraftBundled = false; // Used only in list sorting & not serialized.
@JsonValue
public File getDir() {
return dir;
}
@JsonCreator
public static JavaRuntime fromDir(String dir) {
return JavaRuntimeFinder.getRuntimeFromPath(dir);
}
@JsonIgnore
public int getMajorVersion() {
if (version == null) {
return 0; //
return 0; // uhh make this an error?
}
String[] parts = version.split("\\.");
@ -29,6 +44,19 @@ public class JavaRuntime implements Comparable<JavaRuntime> {
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
JavaRuntime that = (JavaRuntime) o;
return Objects.equal(dir, that.dir);
}
@Override
public int hashCode() {
return Objects.hashCode(dir);
}
@Override
public int compareTo(JavaRuntime o) {
if (isMinecraftBundled && !o.isMinecraftBundled) {

View File

@ -45,7 +45,6 @@ public final class JavaRuntimeFinder {
getEntriesFromRegistry(entries, "SOFTWARE\\JavaSoft\\Java Development Kit");
} catch (Throwable ignored) {
}
Collections.sort(entries);
} else if (env.getPlatform() == Platform.LINUX) {
launcherDir = new File(System.getenv("HOME"), ".minecraft");
@ -68,40 +67,39 @@ public final class JavaRuntimeFinder {
return Collections.emptyList();
}
if (!launcherDir.isDirectory()) {
return entries;
}
File runtimes = new File(launcherDir, "runtime");
File[] runtimeList = runtimes.listFiles();
if (runtimeList == null) {
return entries;
}
if (runtimeList != null) {
for (File potential : runtimeList) {
if (potential.getName().startsWith("jre-x")) {
boolean is64Bit = potential.getName().equals("jre-x64");
for (File potential : runtimeList) {
if (potential.getName().startsWith("jre-x")) {
boolean is64Bit = potential.getName().equals("jre-x64");
JavaRuntime runtime = new JavaRuntime(potential.getAbsoluteFile(), readVersionFromRelease(potential), is64Bit);
runtime.setMinecraftBundled(true);
entries.add(runtime);
} else {
String runtimeName = potential.getName();
entries.add(new JavaRuntime(potential.getAbsoluteFile(), readVersionFromRelease(potential), is64Bit));
} else {
String runtimeName = potential.getName();
String[] children = potential.list();
if (children == null || children.length == 0) continue;
String platformName = children[0];
String[] children = potential.list();
if (children == null || children.length == 0) continue;
String platformName = children[0];
String[] parts = platformName.split("-");
if (parts.length < 2) continue;
String[] parts = platformName.split("-");
if (parts.length < 2) continue;
String arch = parts[1];
boolean is64Bit = arch.equals("x64");
String arch = parts[1];
boolean is64Bit = arch.equals("x64");
File javaDir = new File(potential, String.format("%s/%s", platformName, runtimeName));
JavaRuntime runtime = new JavaRuntime(javaDir.getAbsoluteFile(), readVersionFromRelease(javaDir), is64Bit);
runtime.setMinecraftBundled(true);
File javaDir = new File(potential, String.format("%s/%s", platformName, runtimeName));
entries.add(new JavaRuntime(javaDir.getAbsoluteFile(), readVersionFromRelease(javaDir), is64Bit));
entries.add(runtime);
}
}
}
Collections.sort(entries);
return entries;
}
@ -127,8 +125,18 @@ public final class JavaRuntimeFinder {
.findFirst();
}
public static Optional<JavaRuntime> findAnyJavaRuntime() {
return getAvailableRuntimes().stream().sorted().findFirst();
}
public static JavaRuntime getRuntimeFromPath(String path) {
File target = new File(path);
if (target.isFile()) {
// Probably referring directly to bin/java, back up two levels
target = target.getParentFile().getParentFile();
}
{
File jre = new File(target, "jre/release");
if (jre.isFile()) {

View File

@ -212,12 +212,14 @@ public class Runner implements Callable<Process>, ProgressObservable {
*
* @throws IOException on I/O error
*/
private void addJvmArgs() throws IOException {
int minMemory = instance.getSettings().getMemorySettings()
private void addJvmArgs() throws IOException, LauncherException {
Optional<MemorySettings> memorySettings = Optional.ofNullable(instance.getSettings().getMemorySettings());
int minMemory = memorySettings
.map(MemorySettings::getMinMemory)
.orElse(config.getMinMemory());
int maxMemory = instance.getSettings().getMemorySettings()
int maxMemory = memorySettings
.map(MemorySettings::getMaxMemory)
.orElse(config.getMaxMemory());
@ -247,14 +249,18 @@ public class Runner implements Callable<Process>, ProgressObservable {
builder.setMaxMemory(maxMemory);
builder.setPermGen(permGen);
JavaRuntime selectedRuntime = instance.getSettings().getRuntime()
JavaRuntime selectedRuntime = Optional.ofNullable(instance.getSettings().getRuntime())
.orElseGet(() -> Optional.ofNullable(versionManifest.getJavaVersion())
.flatMap(JavaRuntimeFinder::findBestJavaRuntime)
.orElse(config.getJavaRuntime())
);
String rawJvmPath = selectedRuntime.getDir().getAbsolutePath();
if (!Strings.isNullOrEmpty(rawJvmPath)) {
builder.tryJvmPath(new File(rawJvmPath));
// Builder defaults to a found runtime or just the PATH `java` otherwise
if (selectedRuntime != null) {
String rawJvmPath = selectedRuntime.getDir().getAbsolutePath();
if (!Strings.isNullOrEmpty(rawJvmPath)) {
builder.tryJvmPath(new File(rawJvmPath));
}
}
List<String> flags = builder.getFlags();

View File

@ -22,6 +22,7 @@ errors.selfUpdateCheckError=Checking for an update to the launcher has failed.
button.cancel=Cancel
button.ok=OK
button.save=Save
options.title = Options
options.useProxyCheck = Use following proxy in Minecraft
@ -52,6 +53,7 @@ instance.openSaves=View saves
instance.openResourcePacks=View resource packs
instance.openScreenshots=View screenshots
instance.copyAsPath=Copy as path
instance.openSettings=Settings...
instance.forceUpdate=Force update
instance.hardForceUpdate=Hard force update...
instance.deleteFiles=Delete files...
@ -62,6 +64,10 @@ instance.confirmHardUpdate=A hard force update will delete the contents of confi
instance.resettingTitle=Resetting instance...
instance.resettingStatus=Resetting ''{0}''...
instance.options.title=Instance Settings
instance.options.customJava=Use a custom Java runtime
instance.options.customMemory=Use custom memory settings
launcher.launch=Launch...
launcher.checkForUpdates=Check for updates
launcher.options=Options...