mirror of
https://github.com/SKCraft/Launcher.git
synced 2024-11-24 12:16:28 +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
|
||||
*/
|
||||
public void setJvmPath(String jvmPath) {
|
||||
this.javaRuntime = JavaRuntimeFinder.getRuntimeFromPath(jvmPath);
|
||||
if (jvmPath != null) {
|
||||
this.javaRuntime = JavaRuntimeFinder.getRuntimeFromPath(jvmPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,9 @@ package com.skcraft.launcher.dialog;
|
||||
|
||||
import com.skcraft.launcher.Configuration;
|
||||
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.swing.*;
|
||||
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 JTabbedPane tabbedPane = new JTabbedPane();
|
||||
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 JSpinner minMemorySpinner = new JSpinner();
|
||||
private final JSpinner maxMemorySpinner = new JSpinner();
|
||||
@ -70,7 +73,10 @@ public class ConfigurationDialog extends JDialog {
|
||||
setResizable(false);
|
||||
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(minMemorySpinner, "minMemory");
|
||||
mapper.map(maxMemorySpinner, "maxMemory");
|
||||
@ -88,7 +94,7 @@ public class ConfigurationDialog extends JDialog {
|
||||
}
|
||||
|
||||
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(Box.createVerticalStrut(15));
|
||||
javaSettingsPanel.addRow(new JLabel(SharedLocale.tr("options.64BitJavaWarning")));
|
||||
@ -157,6 +163,8 @@ public class ConfigurationDialog extends JDialog {
|
||||
*/
|
||||
public void save() {
|
||||
mapper.copyFromSwing();
|
||||
config.setJavaRuntime((JavaRuntime) jvmRuntime.getSelectedItem());
|
||||
|
||||
Persistence.commitAndForget(config);
|
||||
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;
|
||||
|
||||
public int getMajorVersion() {
|
||||
if (version == null) {
|
||||
return 0; //
|
||||
}
|
||||
|
||||
String[] parts = version.split("\\.");
|
||||
|
||||
if (parts.length < 2) {
|
||||
@ -39,6 +43,12 @@ public class JavaRuntime implements Comparable<JavaRuntime> {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (version == null) {
|
||||
return 1;
|
||||
} else if (o.version == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
String[] a = version.split("[\\._]");
|
||||
String[] b = o.version.split("[\\._]");
|
||||
int min = Math.min(a.length, b.length);
|
||||
|
@ -48,6 +48,22 @@ public final class JavaRuntimeFinder {
|
||||
Collections.sort(entries);
|
||||
} else if (env.getPlatform() == Platform.LINUX) {
|
||||
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 {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
@ -57,7 +73,12 @@ public final class JavaRuntimeFinder {
|
||||
}
|
||||
|
||||
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")) {
|
||||
boolean is64Bit = potential.getName().equals("jre-x64");
|
||||
|
||||
@ -108,6 +129,12 @@ public final class JavaRuntimeFinder {
|
||||
|
||||
public static JavaRuntime getRuntimeFromPath(String 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));
|
||||
}
|
||||
@ -150,7 +177,8 @@ public final class JavaRuntimeFinder {
|
||||
Map<String, String> releaseDetails = EnvironmentParser.parse(releaseFile);
|
||||
|
||||
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;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.io.CharSource;
|
||||
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.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Parses dotenv-style files.
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
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 {
|
||||
CharSource charSource = Files.asCharSource(target, StandardCharsets.UTF_8);
|
||||
Map<String, String> values = Splitter.onPattern("\r?\n").withKeyValueSeparator('=')
|
||||
.split(charSource.read());
|
||||
|
||||
// Remove quotes
|
||||
// TODO do this better. it works fine for the release file, though
|
||||
values.replaceAll((key, value) -> value.substring(1, value.length() - 1));
|
||||
EnvironmentParser parser = new EnvironmentParser(charSource.openBufferedStream());
|
||||
return parser.parse();
|
||||
}
|
||||
|
||||
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.useProxyCheck = Use following proxy in Minecraft
|
||||
options.jvmPath=JVM path\:
|
||||
options.jvmPath=Java Runtime\:
|
||||
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.minMemory=Minimum memory (MB)\:
|
||||
|
Loading…
Reference in New Issue
Block a user