mirror of
https://github.com/SKCraft/Launcher.git
synced 2024-11-28 12:57:07 +01:00
Update launcher settings dialog with new runtime selection dropdown
This commit is contained in:
parent
2ff147fc10
commit
e12eec29b5
@ -62,6 +62,8 @@ public class Configuration {
|
|||||||
* Backwards compatibility for old configs with jvmPaths
|
* Backwards compatibility for old configs with jvmPaths
|
||||||
*/
|
*/
|
||||||
public void setJvmPath(String jvmPath) {
|
public void setJvmPath(String jvmPath) {
|
||||||
|
if (jvmPath != null) {
|
||||||
this.javaRuntime = JavaRuntimeFinder.getRuntimeFromPath(jvmPath);
|
this.javaRuntime = JavaRuntimeFinder.getRuntimeFromPath(jvmPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@ -8,6 +8,9 @@ package com.skcraft.launcher.dialog;
|
|||||||
|
|
||||||
import com.skcraft.launcher.Configuration;
|
import com.skcraft.launcher.Configuration;
|
||||||
import com.skcraft.launcher.Launcher;
|
import com.skcraft.launcher.Launcher;
|
||||||
|
import com.skcraft.launcher.dialog.component.BetterComboBox;
|
||||||
|
import com.skcraft.launcher.launch.JavaRuntime;
|
||||||
|
import com.skcraft.launcher.launch.JavaRuntimeFinder;
|
||||||
import com.skcraft.launcher.persistence.Persistence;
|
import com.skcraft.launcher.persistence.Persistence;
|
||||||
import com.skcraft.launcher.swing.*;
|
import com.skcraft.launcher.swing.*;
|
||||||
import com.skcraft.launcher.util.SharedLocale;
|
import com.skcraft.launcher.util.SharedLocale;
|
||||||
@ -29,7 +32,7 @@ public class ConfigurationDialog extends JDialog {
|
|||||||
private final JPanel tabContainer = new JPanel(new BorderLayout());
|
private final JPanel tabContainer = new JPanel(new BorderLayout());
|
||||||
private final JTabbedPane tabbedPane = new JTabbedPane();
|
private final JTabbedPane tabbedPane = new JTabbedPane();
|
||||||
private final FormPanel javaSettingsPanel = new FormPanel();
|
private final FormPanel javaSettingsPanel = new FormPanel();
|
||||||
private final JTextField jvmPathText = new JTextField();
|
private final JComboBox<JavaRuntime> jvmRuntime = new BetterComboBox<>();
|
||||||
private final JTextField jvmArgsText = new JTextField();
|
private final JTextField jvmArgsText = new JTextField();
|
||||||
private final JSpinner minMemorySpinner = new JSpinner();
|
private final JSpinner minMemorySpinner = new JSpinner();
|
||||||
private final JSpinner maxMemorySpinner = new JSpinner();
|
private final JSpinner maxMemorySpinner = new JSpinner();
|
||||||
@ -70,7 +73,10 @@ public class ConfigurationDialog extends JDialog {
|
|||||||
setResizable(false);
|
setResizable(false);
|
||||||
setLocationRelativeTo(owner);
|
setLocationRelativeTo(owner);
|
||||||
|
|
||||||
mapper.map(jvmPathText, "jvmPath");
|
JavaRuntime[] javaRuntimes = JavaRuntimeFinder.getAvailableRuntimes().toArray(new JavaRuntime[0]);
|
||||||
|
jvmRuntime.setModel(new DefaultComboBoxModel<>(javaRuntimes));
|
||||||
|
jvmRuntime.setSelectedItem(config.getJavaRuntime());
|
||||||
|
|
||||||
mapper.map(jvmArgsText, "jvmArgs");
|
mapper.map(jvmArgsText, "jvmArgs");
|
||||||
mapper.map(minMemorySpinner, "minMemory");
|
mapper.map(minMemorySpinner, "minMemory");
|
||||||
mapper.map(maxMemorySpinner, "maxMemory");
|
mapper.map(maxMemorySpinner, "maxMemory");
|
||||||
@ -88,7 +94,7 @@ public class ConfigurationDialog extends JDialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void initComponents() {
|
private void initComponents() {
|
||||||
javaSettingsPanel.addRow(new JLabel(SharedLocale.tr("options.jvmPath")), jvmPathText);
|
javaSettingsPanel.addRow(new JLabel(SharedLocale.tr("options.jvmPath")), jvmRuntime);
|
||||||
javaSettingsPanel.addRow(new JLabel(SharedLocale.tr("options.jvmArguments")), jvmArgsText);
|
javaSettingsPanel.addRow(new JLabel(SharedLocale.tr("options.jvmArguments")), jvmArgsText);
|
||||||
javaSettingsPanel.addRow(Box.createVerticalStrut(15));
|
javaSettingsPanel.addRow(Box.createVerticalStrut(15));
|
||||||
javaSettingsPanel.addRow(new JLabel(SharedLocale.tr("options.64BitJavaWarning")));
|
javaSettingsPanel.addRow(new JLabel(SharedLocale.tr("options.64BitJavaWarning")));
|
||||||
@ -157,6 +163,8 @@ public class ConfigurationDialog extends JDialog {
|
|||||||
*/
|
*/
|
||||||
public void save() {
|
public void save() {
|
||||||
mapper.copyFromSwing();
|
mapper.copyFromSwing();
|
||||||
|
config.setJavaRuntime((JavaRuntime) jvmRuntime.getSelectedItem());
|
||||||
|
|
||||||
Persistence.commitAndForget(config);
|
Persistence.commitAndForget(config);
|
||||||
dispose();
|
dispose();
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
package com.skcraft.launcher.dialog.component;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.plaf.basic.BasicComboBoxUI;
|
||||||
|
import javax.swing.plaf.basic.BasicComboPopup;
|
||||||
|
import javax.swing.plaf.basic.ComboPopup;
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
|
public class BetterComboBox<E> extends JComboBox<E> {
|
||||||
|
public BetterComboBox() {
|
||||||
|
setUI(new BetterComboBoxUI());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class BetterComboBoxUI extends BasicComboBoxUI {
|
||||||
|
@Override
|
||||||
|
protected ComboPopup createPopup() {
|
||||||
|
BasicComboPopup popup = new BasicComboPopup(comboBox) {
|
||||||
|
@Override
|
||||||
|
protected Rectangle computePopupBounds(int px, int py, int pw, int ph) {
|
||||||
|
return super.computePopupBounds(px, py, Math.max(comboBox.getPreferredSize().width, pw), ph);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
popup.getAccessibleContext().setAccessibleParent(comboBox);
|
||||||
|
return popup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -12,6 +12,10 @@ public class JavaRuntime implements Comparable<JavaRuntime> {
|
|||||||
private boolean isMinecraftBundled = false;
|
private boolean isMinecraftBundled = false;
|
||||||
|
|
||||||
public int getMajorVersion() {
|
public int getMajorVersion() {
|
||||||
|
if (version == null) {
|
||||||
|
return 0; //
|
||||||
|
}
|
||||||
|
|
||||||
String[] parts = version.split("\\.");
|
String[] parts = version.split("\\.");
|
||||||
|
|
||||||
if (parts.length < 2) {
|
if (parts.length < 2) {
|
||||||
@ -39,6 +43,12 @@ public class JavaRuntime implements Comparable<JavaRuntime> {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (version == null) {
|
||||||
|
return 1;
|
||||||
|
} else if (o.version == null) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
String[] a = version.split("[\\._]");
|
String[] a = version.split("[\\._]");
|
||||||
String[] b = o.version.split("[\\._]");
|
String[] b = o.version.split("[\\._]");
|
||||||
int min = Math.min(a.length, b.length);
|
int min = Math.min(a.length, b.length);
|
||||||
|
@ -48,6 +48,22 @@ public final class JavaRuntimeFinder {
|
|||||||
Collections.sort(entries);
|
Collections.sort(entries);
|
||||||
} else if (env.getPlatform() == Platform.LINUX) {
|
} else if (env.getPlatform() == Platform.LINUX) {
|
||||||
launcherDir = new File(System.getenv("HOME"), ".minecraft");
|
launcherDir = new File(System.getenv("HOME"), ".minecraft");
|
||||||
|
|
||||||
|
String javaHome = System.getenv("JAVA_HOME");
|
||||||
|
if (javaHome != null) {
|
||||||
|
entries.add(getRuntimeFromPath(javaHome));
|
||||||
|
}
|
||||||
|
|
||||||
|
File[] runtimesList = new File("/usr/lib/jvm").listFiles();
|
||||||
|
if (runtimesList != null) {
|
||||||
|
Arrays.stream(runtimesList).map(file -> {
|
||||||
|
try {
|
||||||
|
return file.getCanonicalFile();
|
||||||
|
} catch (IOException exception) {
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
}).distinct().forEach(file -> entries.add(getRuntimeFromPath(file.getAbsolutePath())));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
@ -57,7 +73,12 @@ public final class JavaRuntimeFinder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
File runtimes = new File(launcherDir, "runtime");
|
File runtimes = new File(launcherDir, "runtime");
|
||||||
for (File potential : Objects.requireNonNull(runtimes.listFiles())) {
|
File[] runtimeList = runtimes.listFiles();
|
||||||
|
if (runtimeList == null) {
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (File potential : runtimeList) {
|
||||||
if (potential.getName().startsWith("jre-x")) {
|
if (potential.getName().startsWith("jre-x")) {
|
||||||
boolean is64Bit = potential.getName().equals("jre-x64");
|
boolean is64Bit = potential.getName().equals("jre-x64");
|
||||||
|
|
||||||
@ -108,6 +129,12 @@ public final class JavaRuntimeFinder {
|
|||||||
|
|
||||||
public static JavaRuntime getRuntimeFromPath(String path) {
|
public static JavaRuntime getRuntimeFromPath(String path) {
|
||||||
File target = new File(path);
|
File target = new File(path);
|
||||||
|
{
|
||||||
|
File jre = new File(target, "jre/release");
|
||||||
|
if (jre.isFile()) {
|
||||||
|
target = jre.getParentFile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return new JavaRuntime(target, readVersionFromRelease(target), guessIf64Bit(target));
|
return new JavaRuntime(target, readVersionFromRelease(target), guessIf64Bit(target));
|
||||||
}
|
}
|
||||||
@ -150,7 +177,8 @@ public final class JavaRuntimeFinder {
|
|||||||
Map<String, String> releaseDetails = EnvironmentParser.parse(releaseFile);
|
Map<String, String> releaseDetails = EnvironmentParser.parse(releaseFile);
|
||||||
|
|
||||||
return releaseDetails.get("JAVA_VERSION");
|
return releaseDetails.get("JAVA_VERSION");
|
||||||
} catch (IOException ignored) {
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Failed to read release file", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,27 +1,139 @@
|
|||||||
package com.skcraft.launcher.util;
|
package com.skcraft.launcher.util;
|
||||||
|
|
||||||
import com.google.common.base.Splitter;
|
|
||||||
import com.google.common.io.CharSource;
|
import com.google.common.io.CharSource;
|
||||||
import com.google.common.io.Files;
|
import com.google.common.io.Files;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.EOFException;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses dotenv-style files.
|
* Parses dotenv-style files.
|
||||||
*/
|
*/
|
||||||
|
@RequiredArgsConstructor
|
||||||
public class EnvironmentParser {
|
public class EnvironmentParser {
|
||||||
|
private final BufferedReader reader;
|
||||||
|
|
||||||
|
private char read() throws IOException {
|
||||||
|
int c = reader.read();
|
||||||
|
|
||||||
|
if (c == -1) {
|
||||||
|
throw new EOFException("End of stream reached unexpectedly!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return (char) c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> parse() throws IOException {
|
||||||
|
HashMap<String, String> result = new HashMap<>();
|
||||||
|
|
||||||
|
while (reader.ready()) {
|
||||||
|
KeyValue entry = parseLine();
|
||||||
|
|
||||||
|
result.put(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public KeyValue parseLine() throws IOException {
|
||||||
|
String key = parseKey();
|
||||||
|
String value = parseValue();
|
||||||
|
|
||||||
|
try {
|
||||||
|
reader.mark(1);
|
||||||
|
char newline = read();
|
||||||
|
if (newline == '\r') {
|
||||||
|
reader.mark(1);
|
||||||
|
if (read() != '\n') {
|
||||||
|
throw new IOException("Expected CRLF but only got CR");
|
||||||
|
}
|
||||||
|
reader.reset();
|
||||||
|
} else if (newline != '\n') {
|
||||||
|
reader.reset();
|
||||||
|
}
|
||||||
|
} catch (EOFException ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
|
return new KeyValue(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String parseKey() throws IOException {
|
||||||
|
StringBuilder buffer = new StringBuilder();
|
||||||
|
|
||||||
|
// Very lenient key parsing.
|
||||||
|
while (true) {
|
||||||
|
char c = read();
|
||||||
|
|
||||||
|
switch (c) {
|
||||||
|
case '=':
|
||||||
|
case '\r':
|
||||||
|
case '\n':
|
||||||
|
return buffer.toString();
|
||||||
|
default:
|
||||||
|
buffer.append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String parseValue() throws IOException {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
char c = read();
|
||||||
|
|
||||||
|
switch (c) {
|
||||||
|
case '\r':
|
||||||
|
case '\n':
|
||||||
|
return buffer.toString();
|
||||||
|
case '"':
|
||||||
|
buffer.append(parseQuotedPhrase());
|
||||||
|
break;
|
||||||
|
case '\\':
|
||||||
|
char next = read();
|
||||||
|
buffer.append(next);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
buffer.append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String parseQuotedPhrase() throws IOException {
|
||||||
|
StringBuilder buffer = new StringBuilder();
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
char c = read();
|
||||||
|
|
||||||
|
switch (c) {
|
||||||
|
case '"':
|
||||||
|
return buffer.toString();
|
||||||
|
case '\\':
|
||||||
|
char next = read();
|
||||||
|
buffer.append(next);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
buffer.append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static Map<String, String> parse(File target) throws IOException {
|
public static Map<String, String> parse(File target) throws IOException {
|
||||||
CharSource charSource = Files.asCharSource(target, StandardCharsets.UTF_8);
|
CharSource charSource = Files.asCharSource(target, StandardCharsets.UTF_8);
|
||||||
Map<String, String> values = Splitter.onPattern("\r?\n").withKeyValueSeparator('=')
|
|
||||||
.split(charSource.read());
|
|
||||||
|
|
||||||
// Remove quotes
|
EnvironmentParser parser = new EnvironmentParser(charSource.openBufferedStream());
|
||||||
// TODO do this better. it works fine for the release file, though
|
return parser.parse();
|
||||||
values.replaceAll((key, value) -> value.substring(1, value.length() - 1));
|
}
|
||||||
|
|
||||||
return values;
|
@Data
|
||||||
|
private static class KeyValue {
|
||||||
|
private final String key;
|
||||||
|
private final String value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ button.ok=OK
|
|||||||
|
|
||||||
options.title = Options
|
options.title = Options
|
||||||
options.useProxyCheck = Use following proxy in Minecraft
|
options.useProxyCheck = Use following proxy in Minecraft
|
||||||
options.jvmPath=JVM path\:
|
options.jvmPath=Java Runtime\:
|
||||||
options.jvmArguments=JVM arguments\:
|
options.jvmArguments=JVM arguments\:
|
||||||
options.64BitJavaWarning=<html>Make sure to have <strong>64-bit Java installed</strong> if you are planning to set the memory limits higher.
|
options.64BitJavaWarning=<html>Make sure to have <strong>64-bit Java installed</strong> if you are planning to set the memory limits higher.
|
||||||
options.minMemory=Minimum memory (MB)\:
|
options.minMemory=Minimum memory (MB)\:
|
||||||
|
Loading…
Reference in New Issue
Block a user