Compare commits

...
13 Commits
Author SHA1 Message Date
Glavo af36a0ac2a Bump Gradle to 8.0.1 (#2158) 2023-03-01 23:32:24 +08:00
Glavo 7356335106 添加环境变量设置 (#2157)
* Remove unused methods

* 添加环境变量设置

* update

* update
2023-02-26 23:46:00 +08:00
Glavo d8c96769ea Bump dependencies (#2149) 2023-02-24 04:31:45 +08:00
Glavo d71815aa3d 清理编译警告 (#2148) 2023-02-24 04:14:23 +08:00
Glavo 9a4286620f 简化 JFXHyperlink 用法 (#2147)
* 简化 JFXHyperlink 用法

* fix checkstyle
2023-02-24 03:49:13 +08:00
Glavo 0eac7b5d12 Use MESA_LOADER_DRIVER_OVERRIDE on Linux (#2146) 2023-02-24 01:56:01 +08:00
Glavo af63c3aa3a 添加渲染器设置 (#2145)
close #2143
2023-02-24 01:32:15 +08:00
Glavo 72a8199453 将版本高级设置拆分至单独页面中 (#2142)
* update

* update

* update

* update
2023-02-22 20:37:27 +08:00
Glavo 090b83bf9c fix #2129: Fix computePerfHeight of ComponentList (#2139)
* update

* update style

* update

* update

* update

* update
2023-02-19 19:22:01 +08:00
Glavo 6f70da51f9 Use computeIfAbsent in EventBus (#2138) 2023-02-19 13:25:20 +08:00
Glavo ed0a4c8cf4 fix #2131: Hide feedbackTextFlow from gameDirPane if possible (#2136)
* Add scroll bar to GameCrashWindow

* Hide feedbackTextFlow when it is not visible

* fix checkstyle

* update I18N

* update I18N
2023-02-19 12:36:35 +08:00
Glavo 5fa066de6b fix crash (#2124) 2023-02-15 23:27:59 +08:00
zkitefly 1454ea8358 添加提示 (#2108)
* 添加提示

* Update I18N_zh_CN.properties
2023-02-15 17:45:25 +08:00
32 changed files with 599 additions and 536 deletions

No files matched your search

@@ -48,11 +48,13 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.logging.Level;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.jackhuang.hmcl.setting.ConfigHolder.config;
import static org.jackhuang.hmcl.ui.FXUtils.newImage;
import static org.jackhuang.hmcl.util.Logging.LOG;
import static org.jackhuang.hmcl.util.Pair.pair;
public class HMCLGameRepository extends DefaultGameRepository {
private final Profile profile;
@@ -335,6 +337,16 @@ public class HMCLGameRepository extends DefaultGameRepository {
) / 1024 / 1024))
.setMinMemory(vs.getMinMemory())
.setMetaspace(Lang.toIntOrNull(vs.getPermSize()))
.setEnvironmentVariables(
Lang.mapOf(StringUtils.tokenize(vs.getEnvironmentVariables())
.stream()
.map(it -> {
int idx = it.indexOf('=');
return idx >= 0 ? pair(it.substring(0, idx), it.substring(idx + 1)) : pair(it, "");
})
.collect(Collectors.toList())
)
)
.setWidth(vs.getWidth())
.setHeight(vs.getHeight())
.setFullscreen(vs.isFullscreen())
@@ -346,7 +358,7 @@ public class HMCLGameRepository extends DefaultGameRepository {
.setNativesDirType(vs.getNativesDirType())
.setNativesDir(vs.getNativesDir())
.setProcessPriority(vs.getProcessPriority())
.setUseSoftwareRenderer(vs.isUseSoftwareRenderer())
.setRenderer(vs.getRenderer())
.setUseNativeGLFW(vs.isUseNativeGLFW())
.setUseNativeOpenAL(vs.isUseNativeOpenAL())
.setDaemon(!makeLaunchScript && vs.getLauncherVisibility().isDaemon())
@@ -150,8 +150,9 @@ public final class LauncherHelper {
}
}),
Task.composeAsync(() -> {
if (setting.isUseSoftwareRenderer() && OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS) {
Library lib = NativePatcher.getSoftwareRendererLoader(javaVersion);
Renderer renderer = setting.getRenderer();
if (renderer != Renderer.DEFAULT && OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS) {
Library lib = NativePatcher.getMesaLoader(javaVersion, renderer);
if (lib == null)
return null;
File file = dependencyManager.getGameRepository().getLibraryFile(version.get(), lib);
@@ -160,11 +161,13 @@ public final class LauncherHelper {
return null;
}
String agent = file.getAbsolutePath() + "=" + renderer.name().toLowerCase(Locale.ROOT);
if (GameLibrariesTask.shouldDownloadLibrary(repository, version.get(), lib, integrityCheck)) {
return new LibraryDownloadTask(dependencyManager, file, lib)
.thenRunAsync(() -> javaAgents.add(file.getAbsolutePath()));
.thenRunAsync(() -> javaAgents.add(agent));
} else {
javaAgents.add(file.getAbsolutePath());
javaAgents.add(agent);
return null;
}
} else {
@@ -38,6 +38,7 @@ import java.lang.reflect.Type;
import java.nio.file.InvalidPathException;
import java.nio.file.Paths;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.concurrent.CancellationException;
import java.util.stream.Collectors;
@@ -340,6 +341,20 @@ public final class VersionSetting implements Cloneable {
minecraftArgsProperty.set(minecraftArgs);
}
private final StringProperty environmentVariablesProperty = new SimpleStringProperty(this, "environmentVariables", "");
public StringProperty environmentVariablesProperty() {
return environmentVariablesProperty;
}
public String getEnvironmentVariables() {
return environmentVariablesProperty.get();
}
public void setEnvironmentVariables(String env) {
environmentVariablesProperty.set(env);
}
private final BooleanProperty noJVMArgsProperty = new SimpleBooleanProperty(this, "noJVMArgs", false);
public BooleanProperty noJVMArgsProperty() {
@@ -482,7 +497,6 @@ public final class VersionSetting implements Cloneable {
widthProperty.set(width);
}
private final IntegerProperty heightProperty = new SimpleIntegerProperty(this, "height", 480);
public IntegerProperty heightProperty() {
@@ -553,18 +567,18 @@ public final class VersionSetting implements Cloneable {
processPriorityProperty.set(processPriority);
}
private final BooleanProperty useSoftwareRenderer = new SimpleBooleanProperty(this, "softwareRenderer", false);
private final ObjectProperty<Renderer> rendererProperty = new SimpleObjectProperty<>(this, "renderer", Renderer.DEFAULT);
public boolean isUseSoftwareRenderer() {
return useSoftwareRenderer.get();
public Renderer getRenderer() {
return rendererProperty.get();
}
public BooleanProperty useSoftwareRendererProperty() {
return useSoftwareRenderer;
public ObjectProperty<Renderer> rendererProperty() {
return rendererProperty;
}
public void setUseSoftwareRenderer(boolean useSoftwareRenderer) {
this.useSoftwareRenderer.set(useSoftwareRenderer);
public void setRenderer(Renderer renderer) {
this.rendererProperty.set(renderer);
}
private final BooleanProperty useNativeGLFW = new SimpleBooleanProperty(this, "nativeGLFW", false);
@@ -692,6 +706,7 @@ public final class VersionSetting implements Cloneable {
postExitCommand.addListener(listener);
javaArgsProperty.addListener(listener);
minecraftArgsProperty.addListener(listener);
environmentVariablesProperty.addListener(listener);
noJVMArgsProperty.addListener(listener);
notCheckGameProperty.addListener(listener);
notCheckJVMProperty.addListener(listener);
@@ -704,7 +719,7 @@ public final class VersionSetting implements Cloneable {
gameDirTypeProperty.addListener(listener);
gameDirProperty.addListener(listener);
processPriorityProperty.addListener(listener);
useSoftwareRenderer.addListener(listener);
rendererProperty.addListener(listener);
useNativeGLFW.addListener(listener);
useNativeOpenAL.addListener(listener);
launcherVisibilityProperty.addListener(listener);
@@ -730,6 +745,7 @@ public final class VersionSetting implements Cloneable {
versionSetting.setPostExitCommand(getPostExitCommand());
versionSetting.setJavaArgs(getJavaArgs());
versionSetting.setMinecraftArgs(getMinecraftArgs());
versionSetting.setEnvironmentVariables(getEnvironmentVariables());
versionSetting.setNoJVMArgs(isNoJVMArgs());
versionSetting.setNotCheckGame(isNotCheckGame());
versionSetting.setNotCheckJVM(isNotCheckJVM());
@@ -742,7 +758,7 @@ public final class VersionSetting implements Cloneable {
versionSetting.setGameDirType(getGameDirType());
versionSetting.setGameDir(getGameDir());
versionSetting.setProcessPriority(getProcessPriority());
versionSetting.setUseSoftwareRenderer(isUseSoftwareRenderer());
versionSetting.setRenderer(getRenderer());
versionSetting.setUseNativeGLFW(isUseNativeGLFW());
versionSetting.setUseNativeOpenAL(isUseNativeOpenAL());
versionSetting.setLauncherVisibility(getLauncherVisibility());
@@ -760,6 +776,7 @@ public final class VersionSetting implements Cloneable {
obj.addProperty("usesGlobal", src.isUsesGlobal());
obj.addProperty("javaArgs", src.getJavaArgs());
obj.addProperty("minecraftArgs", src.getMinecraftArgs());
obj.addProperty("environmentVariables", src.getEnvironmentVariables());
obj.addProperty("maxMemory", src.getMaxMemory() <= 0 ? OperatingSystem.SUGGESTED_MEMORY : src.getMaxMemory());
obj.addProperty("minMemory", src.getMinMemory());
obj.addProperty("autoMemory", src.isAutoMemory());
@@ -781,7 +798,6 @@ public final class VersionSetting implements Cloneable {
obj.addProperty("gameDir", src.getGameDir());
obj.addProperty("launcherVisibility", src.getLauncherVisibility().ordinal());
obj.addProperty("processPriority", src.getProcessPriority().ordinal());
obj.addProperty("useSoftwareRenderer", src.isUseSoftwareRenderer());
obj.addProperty("useNativeGLFW", src.isUseNativeGLFW());
obj.addProperty("useNativeOpenAL", src.isUseNativeOpenAL());
obj.addProperty("gameDirType", src.getGameDirType().ordinal());
@@ -790,6 +806,10 @@ public final class VersionSetting implements Cloneable {
obj.addProperty("nativesDirType", src.getNativesDirType().ordinal());
obj.addProperty("versionIcon", src.getVersionIcon().ordinal());
obj.addProperty("renderer", src.getRenderer().name());
if (src.getRenderer() == Renderer.LLVMPIPE)
obj.addProperty("useSoftwareRenderer", true);
return obj;
}
@@ -815,6 +835,7 @@ public final class VersionSetting implements Cloneable {
vs.setUsesGlobal(Optional.ofNullable(obj.get("usesGlobal")).map(JsonElement::getAsBoolean).orElse(false));
vs.setJavaArgs(Optional.ofNullable(obj.get("javaArgs")).map(JsonElement::getAsString).orElse(""));
vs.setMinecraftArgs(Optional.ofNullable(obj.get("minecraftArgs")).map(JsonElement::getAsString).orElse(""));
vs.setEnvironmentVariables(Optional.ofNullable(obj.get("environmentVariables")).map(JsonElement::getAsString).orElse(""));
vs.setMaxMemory(maxMemoryN);
vs.setMinMemory(Optional.ofNullable(obj.get("minMemory")).map(JsonElement::getAsInt).orElse(null));
vs.setAutoMemory(Optional.ofNullable(obj.get("autoMemory")).map(JsonElement::getAsBoolean).orElse(true));
@@ -836,7 +857,6 @@ public final class VersionSetting implements Cloneable {
vs.setShowLogs(Optional.ofNullable(obj.get("showLogs")).map(JsonElement::getAsBoolean).orElse(false));
vs.setLauncherVisibility(getOrDefault(LauncherVisibility.values(), obj.get("launcherVisibility"), LauncherVisibility.HIDE));
vs.setProcessPriority(getOrDefault(ProcessPriority.values(), obj.get("processPriority"), ProcessPriority.NORMAL));
vs.setUseSoftwareRenderer(Optional.ofNullable(obj.get("useSoftwareRenderer")).map(JsonElement::getAsBoolean).orElse(false));
vs.setUseNativeGLFW(Optional.ofNullable(obj.get("useNativeGLFW")).map(JsonElement::getAsBoolean).orElse(false));
vs.setUseNativeOpenAL(Optional.ofNullable(obj.get("useNativeOpenAL")).map(JsonElement::getAsBoolean).orElse(false));
vs.setGameDirType(getOrDefault(GameDirectoryType.values(), obj.get("gameDirType"), GameDirectoryType.ROOT_FOLDER));
@@ -844,6 +864,18 @@ public final class VersionSetting implements Cloneable {
vs.setNativesDirType(getOrDefault(NativesDirectoryType.values(), obj.get("nativesDirType"), NativesDirectoryType.VERSION_FOLDER));
vs.setVersionIcon(getOrDefault(VersionIconType.values(), obj.get("versionIcon"), VersionIconType.DEFAULT));
vs.setRenderer(Optional.ofNullable(obj.get("renderer")).map(JsonElement::getAsString)
.flatMap(name -> {
try {
return Optional.of(Renderer.valueOf(name.toUpperCase(Locale.ROOT)));
} catch (IllegalArgumentException ignored) {
return Optional.empty();
}
}).orElseGet(() -> {
boolean useSoftwareRenderer = Optional.ofNullable(obj.get("useSoftwareRenderer")).map(JsonElement::getAsBoolean).orElse(false);
return useSoftwareRenderer ? Renderer.LLVMPIPE : Renderer.DEFAULT;
}));
return vs;
}
@@ -227,7 +227,7 @@ public final class Controllers {
agreementPane.setHeading(new Label(i18n("launcher.agreement")));
agreementPane.setBody(new Label(i18n("launcher.agreement.hint")));
JFXHyperlink agreementLink = new JFXHyperlink(i18n("launcher.agreement"));
agreementLink.setOnAction(e -> FXUtils.openLink(Metadata.EULA_URL));
agreementLink.setExternalLink(Metadata.EULA_URL);
JFXButton yesButton = new JFXButton(i18n("launcher.agreement.accept"));
yesButton.getStyleClass().add("dialog-accept");
yesButton.setOnAction(e -> {
@@ -236,9 +236,7 @@ public final class Controllers {
});
JFXButton noButton = new JFXButton(i18n("launcher.agreement.decline"));
noButton.getStyleClass().add("dialog-cancel");
noButton.setOnAction(e -> {
System.exit(1);
});
noButton.setOnAction(e -> System.exit(1));
agreementPane.setActions(agreementLink, yesButton, noButton);
Controllers.dialog(agreementPane);
}
@@ -625,16 +625,17 @@ public final class FXUtils {
* @param comboBox the combo box being bound with {@code property}.
* @param property the property being bound with {@code combo box}.
* @see #unbindEnum(JFXComboBox)
* @deprecated Use {@link ExtendedProperties#selectedItemPropertyFor(ComboBox)}
* @see ExtendedProperties#selectedItemPropertyFor(ComboBox)
*/
@SuppressWarnings("unchecked")
@Deprecated
public static void bindEnum(JFXComboBox<?> comboBox, Property<? extends Enum<?>> property) {
public static <T extends Enum<T>> void bindEnum(JFXComboBox<T> comboBox, Property<T> property) {
unbindEnum(comboBox);
@SuppressWarnings("rawtypes")
ChangeListener<Number> listener = (a, b, newValue) ->
((Property) property).setValue(property.getValue().getClass().getEnumConstants()[newValue.intValue()]);
comboBox.getSelectionModel().select(property.getValue().ordinal());
T currentValue = property.getValue();
@SuppressWarnings("unchecked")
T[] enumConstants = (T[]) currentValue.getClass().getEnumConstants();
ChangeListener<Number> listener = (a, b, newValue) -> property.setValue(enumConstants[newValue.intValue()]);
comboBox.getSelectionModel().select(currentValue.ordinal());
comboBox.getProperties().put("FXUtils.bindEnum.listener", listener);
comboBox.getSelectionModel().selectedIndexProperty().addListener(listener);
}
@@ -645,15 +646,13 @@ public final class FXUtils {
*
* @param comboBox the combo box being bound with the property which can be inferred by {@code bindEnum}.
* @see #bindEnum(JFXComboBox, Property)
* @deprecated Use {@link ExtendedProperties#selectedItemPropertyFor(ComboBox)}
* @see ExtendedProperties#selectedItemPropertyFor(ComboBox)
*/
@SuppressWarnings("unchecked")
@Deprecated
public static void unbindEnum(JFXComboBox<?> comboBox) {
@SuppressWarnings("rawtypes")
ChangeListener listener = tryCast(comboBox.getProperties().get("FXUtils.bindEnum.listener"), ChangeListener.class).orElse(null);
if (listener == null) return;
comboBox.getSelectionModel().selectedIndexProperty().removeListener(listener);
public static void unbindEnum(JFXComboBox<? extends Enum<?>> comboBox) {
@SuppressWarnings("unchecked")
ChangeListener<Number> listener = (ChangeListener<Number>) comboBox.getProperties().remove("FXUtils.bindEnum.listener");
if (listener != null)
comboBox.getSelectionModel().selectedIndexProperty().removeListener(listener);
}
/**
@@ -28,6 +28,7 @@ import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
@@ -347,9 +348,20 @@ public class GameCrashWindow extends Stage {
Label reasonTitle = new Label(i18n("game.crash.reason"));
reasonTitle.getStyleClass().add("two-line-item-second-large-title");
ScrollPane reasonPane = new ScrollPane(reasonTextFlow);
reasonPane.setFitToWidth(true);
reasonPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
reasonPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
gameDirPane.setPadding(new Insets(8));
VBox.setVgrow(gameDirPane, Priority.ALWAYS);
gameDirPane.getChildren().setAll(gameDir, javaDir, new VBox(reasonTitle, reasonTextFlow, feedbackTextFlow));
FXUtils.onChangeAndOperate(feedbackTextFlow.visibleProperty(), visible -> {
if (visible) {
gameDirPane.getChildren().setAll(gameDir, javaDir, new VBox(reasonTitle, reasonPane, feedbackTextFlow));
} else {
gameDirPane.getChildren().setAll(gameDir, javaDir, new VBox(reasonTitle, reasonPane));
}
});
}
HBox toolBar = new HBox();
@@ -36,7 +36,6 @@ import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilService;
import org.jackhuang.hmcl.setting.Accounts;
import org.jackhuang.hmcl.task.Schedulers;
import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.ui.FXUtils;
import org.jackhuang.hmcl.ui.construct.DialogCloseEvent;
import org.jackhuang.hmcl.ui.construct.JFXHyperlink;
import org.jackhuang.hmcl.ui.construct.RequiredValidator;
@@ -91,10 +90,10 @@ public class ClassicAccountLoginDialog extends StackPane {
body.getChildren().add(linkPane);
JFXHyperlink migrationLink = new JFXHyperlink(i18n("account.methods.yggdrasil.migration"));
migrationLink.setOnAction(e -> FXUtils.openLink(YggdrasilService.PROFILE_URL));
migrationLink.setExternalLink(YggdrasilService.PROFILE_URL);
JFXHyperlink migrationHowLink = new JFXHyperlink(i18n("account.methods.yggdrasil.migration.how"));
migrationHowLink.setOnAction(e -> FXUtils.openLink(YggdrasilService.MIGRATION_FAQ_URL));
migrationHowLink.setExternalLink(YggdrasilService.MIGRATION_FAQ_URL);
linkPane.getChildren().setAll(migrationLink, migrationHowLink);
}
@@ -512,13 +512,13 @@ public class CreateAccountPane extends JFXDialogLayout implements DialogAware {
GridPane.setColumnSpan(box, 2);
JFXHyperlink migrationLink = new JFXHyperlink(i18n("account.methods.yggdrasil.migration"));
migrationLink.setOnAction(e -> FXUtils.openLink("https://aka.ms/MinecraftMigration"));
migrationLink.setExternalLink("https://aka.ms/MinecraftMigration");
JFXHyperlink migrationHowLink = new JFXHyperlink(i18n("account.methods.yggdrasil.migration.how"));
migrationHowLink.setOnAction(e -> FXUtils.openLink("https://help.minecraft.net/hc/articles/4411173197709"));
migrationHowLink.setExternalLink("https://help.minecraft.net/hc/articles/4411173197709");
JFXHyperlink purchaseLink = new JFXHyperlink(i18n("account.methods.yggdrasil.purchase"));
purchaseLink.setOnAction(e -> FXUtils.openLink(YggdrasilService.PURCHASE_URL));
purchaseLink.setExternalLink(YggdrasilService.PURCHASE_URL);
box.getChildren().setAll(migrationLink, migrationHowLink, purchaseLink);
add(box, 0, rowIndex);
@@ -530,7 +530,7 @@ public class CreateAccountPane extends JFXDialogLayout implements DialogAware {
txtUsername.setPromptText(i18n("account.methods.offline.name.special_characters"));
JFXHyperlink purchaseLink = new JFXHyperlink(i18n("account.methods.yggdrasil.purchase"));
purchaseLink.setOnAction(e -> FXUtils.openLink(YggdrasilService.PURCHASE_URL));
purchaseLink.setExternalLink(YggdrasilService.PURCHASE_URL);
HBox linkPane = new HBox(purchaseLink);
GridPane.setColumnSpan(linkPane, 2);
add(linkPane, 0, rowIndex);
@@ -38,7 +38,8 @@ import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import org.jackhuang.hmcl.util.javafx.MappedObservableList;
import java.util.function.Consumer;
import java.util.List;
import java.util.function.Supplier;
@DefaultProperty("content")
public class ComponentList extends Control {
@@ -47,13 +48,17 @@ public class ComponentList extends Control {
private final IntegerProperty depth = new SimpleIntegerProperty(this, "depth", 0);
private boolean hasSubtitle = false;
public final ObservableList<Node> content = FXCollections.observableArrayList();
private boolean expanded = false;
private Consumer<ComponentList> lazyInitializer;
private Supplier<List<? extends Node>> lazyInitializer;
public ComponentList() {
getStyleClass().add("options-list");
}
public ComponentList(Supplier<List<? extends Node>> lazyInitializer) {
this();
this.lazyInitializer = lazyInitializer;
}
public String getTitle() {
return title.get();
}
@@ -102,17 +107,12 @@ public class ComponentList extends Control {
return content;
}
public void setLazyInitializer(Consumer<ComponentList> lazyInitializer) {
this.lazyInitializer = lazyInitializer;
}
public void onExpand() {
if (!expanded && lazyInitializer != null) {
lazyInitializer.accept(this);
void doLazyInit() {
if (lazyInitializer != null) {
this.getContent().setAll(lazyInitializer.get());
setNeedsLayout(true);
lazyInitializer = null;
}
expanded = true;
}
@Override
@@ -125,7 +125,7 @@ public class ComponentList extends Control {
return new Skin(this);
}
protected static class Skin extends ControlSkinBase<ComponentList> {
private static final class Skin extends ControlSkinBase<ComponentList> {
private static final PseudoClass PSEUDO_CLASS_FIRST = PseudoClass.getPseudoClass("first");
private static final PseudoClass PSEUDO_CLASS_LAST = PseudoClass.getPseudoClass("last");
@@ -133,7 +133,7 @@ public class ComponentList extends Control {
private final ObjectBinding<Node> firstItem;
private final ObjectBinding<Node> lastItem;
protected Skin(ComponentList control) {
Skin(ComponentList control) {
super(control);
list = MappedObservableList.create(control.getContent(), node -> {
@@ -43,7 +43,7 @@ import org.jackhuang.hmcl.ui.animation.AnimationUtils;
/**
* @author huangyuhui
*/
class ComponentListCell extends StackPane {
final class ComponentListCell extends StackPane {
private final Node content;
private Animation expandAnimation;
private Rectangle clipRect;
@@ -139,69 +139,53 @@ class ComponentListCell extends StackPane {
container.getChildren().setAll(content);
groupNode.getChildren().add(container);
EventHandler<Event> onExpand;
if (AnimationUtils.isAnimationEnabled()) {
onExpand = e -> {
if (expandAnimation != null && expandAnimation.getStatus() == Animation.Status.RUNNING) {
expandAnimation.stop();
EventHandler<Event> onExpand = e -> {
if (expandAnimation != null && expandAnimation.getStatus() == Animation.Status.RUNNING) {
expandAnimation.stop();
}
boolean expanded = !isExpanded();
setExpanded(expanded);
if (expanded) {
list.doLazyInit();
list.layout();
}
Platform.runLater(() -> {
double newAnimatedHeight = (list.prefHeight(-1) + 8 + 10) * (expanded ? 1 : -1);
double newHeight = expanded ? getHeight() + newAnimatedHeight : prefHeight(-1);
double contentHeight = expanded ? newAnimatedHeight : 0;
if (expanded) {
updateClip(newHeight);
}
setExpanded(!isExpanded());
if (isExpanded()) {
list.onExpand();
list.layout();
}
Platform.runLater(() -> {
double newAnimatedHeight = (content.prefHeight(-1) + 8 + 10) * (isExpanded() ? 1 : -1);
double newHeight = isExpanded() ? getHeight() + newAnimatedHeight : prefHeight(-1);
double contentHeight = isExpanded() ? newAnimatedHeight : 0;
if (isExpanded()) {
updateClip(newHeight);
}
if (AnimationUtils.isAnimationEnabled()) {
expandAnimation = new Timeline(new KeyFrame(new Duration(320.0),
new KeyValue(container.minHeightProperty(), contentHeight, FXUtils.SINE),
new KeyValue(container.maxHeightProperty(), contentHeight, FXUtils.SINE)
));
if (!isExpanded()) {
if (!expanded) {
expandAnimation.setOnFinished(e2 -> updateClip(newHeight));
}
expandAnimation.play();
});
};
} else {
onExpand = e -> {
setExpanded(!isExpanded());
} else {
container.setMinHeight(contentHeight);
container.setMaxHeight(contentHeight);
double newAnimatedHeight = (content.prefHeight(-1) + 8 + 10) * (isExpanded() ? 1 : -1);
double newHeight = isExpanded() ? getHeight() + newAnimatedHeight : prefHeight(-1);
double contentHeight = isExpanded() ? newAnimatedHeight : 0;
if (isExpanded()) {
list.onExpand();
list.layout();
updateClip(newHeight);
if (!expanded) {
updateClip(newHeight);
}
}
container.setMinHeight(contentHeight);
container.setMaxHeight(contentHeight);
if (!isExpanded()) {
updateClip(newHeight);
}
};
}
});
};
headerRippler.setOnMouseClicked(onExpand);
expandButton.setOnAction((EventHandler<ActionEvent>) (Object) onExpand);
expandedProperty().addListener((a, b, newValue) ->
expandIcon.setRotate(newValue ? 180 : 0));
expandedProperty().addListener((a, b, newValue) -> expandIcon.setRotate(newValue ? 180 : 0));
getChildren().setAll(groupNode);
} else {
@@ -157,7 +157,7 @@ public class RootPage extends DecoratorAnimatedPage implements DecoratorPage {
multiplayerItem.setActionButtonVisible(false);
multiplayerItem.setTitle(i18n("multiplayer"));
JFXHyperlink link = new JFXHyperlink(i18n("multiplayer.hint.details"));
link.setOnAction(e -> FXUtils.openLink("https://hmcl.huangyuhui.net/api/redirect/multiplayer-migrate"));
link.setExternalLink("https://hmcl.huangyuhui.net/api/redirect/multiplayer-migrate");
multiplayerItem.setOnAction(e -> Controllers.dialog(
new MessageDialogPane.Builder(i18n("multiplayer.hint"), null, MessageDialogPane.MessageType.INFO)
.addAction(link)
@@ -0,0 +1,258 @@
package org.jackhuang.hmcl.ui.versions;
import com.jfoenix.controls.JFXComboBox;
import com.jfoenix.controls.JFXTextField;
import javafx.beans.binding.Bindings;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.geometry.Pos;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.*;
import org.jackhuang.hmcl.game.NativesDirectoryType;
import org.jackhuang.hmcl.setting.Profile;
import org.jackhuang.hmcl.game.Renderer;
import org.jackhuang.hmcl.setting.VersionSetting;
import org.jackhuang.hmcl.ui.FXUtils;
import org.jackhuang.hmcl.ui.construct.*;
import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Locale;
import static org.jackhuang.hmcl.ui.FXUtils.stringConverter;
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
public final class AdvancedVersionSettingPage extends StackPane implements DecoratorPage {
private final ObjectProperty<State> stateProperty;
private final Profile profile;
private final String versionId;
private final VersionSetting versionSetting;
private final JFXTextField txtJVMArgs;
private final JFXTextField txtGameArgs;
private final JFXTextField txtEnvironmentVariables;
private final JFXTextField txtMetaspace;
private final JFXTextField txtWrapper;
private final JFXTextField txtPreLaunchCommand;
private final JFXTextField txtPostExitCommand;
private final OptionToggleButton noJVMArgsPane;
private final OptionToggleButton noGameCheckPane;
private final OptionToggleButton noJVMCheckPane;
private final OptionToggleButton noNativesPatchPane;
private final OptionToggleButton useNativeGLFWPane;
private final OptionToggleButton useNativeOpenALPane;
private final ComponentSublist nativesDirSublist;
private final MultiFileItem<NativesDirectoryType> nativesDirItem;
private final MultiFileItem.FileOption<NativesDirectoryType> nativesDirCustomOption;
private final JFXComboBox<Renderer> cboRenderer;
public AdvancedVersionSettingPage(Profile profile, String versionId, VersionSetting versionSetting) {
this.profile = profile;
this.versionId = versionId;
this.versionSetting = versionSetting;
this.stateProperty = new SimpleObjectProperty<>(State.fromTitle(
versionId == null ? i18n("settings.advanced") : i18n("settings.advanced.title", versionId)
));
ScrollPane scrollPane = new ScrollPane();
scrollPane.setFitToHeight(true);
scrollPane.setFitToWidth(true);
scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED);
getChildren().setAll(scrollPane);
VBox rootPane = new VBox();
rootPane.setFillWidth(true);
scrollPane.setContent(rootPane);
FXUtils.smoothScrolling(scrollPane);
rootPane.getStyleClass().add("card-list");
ComponentList customCommandsPane = new ComponentList();
{
GridPane pane = new GridPane();
pane.setHgap(16);
pane.setVgap(8);
pane.getColumnConstraints().setAll(new ColumnConstraints(), FXUtils.getColumnHgrowing());
txtGameArgs = new JFXTextField();
txtGameArgs.setPromptText(i18n("settings.advanced.minecraft_arguments.prompt"));
txtGameArgs.getStyleClass().add("fit-width");
pane.addRow(0, new Label(i18n("settings.advanced.minecraft_arguments")), txtGameArgs);
txtPreLaunchCommand = new JFXTextField();
txtPreLaunchCommand.setPromptText(i18n("settings.advanced.precall_command.prompt"));
txtPreLaunchCommand.getStyleClass().add("fit-width");
pane.addRow(1, new Label(i18n("settings.advanced.precall_command")), txtPreLaunchCommand);
txtWrapper = new JFXTextField();
txtWrapper.setPromptText(i18n("settings.advanced.wrapper_launcher.prompt"));
txtWrapper.getStyleClass().add("fit-width");
pane.addRow(2, new Label(i18n("settings.advanced.wrapper_launcher")), txtWrapper);
txtPostExitCommand = new JFXTextField();
txtPostExitCommand.setPromptText(i18n("settings.advanced.post_exit_command.prompt"));
txtPostExitCommand.getStyleClass().add("fit-width");
pane.addRow(3, new Label(i18n("settings.advanced.post_exit_command")), txtPostExitCommand);
HintPane hintPane = new HintPane();
hintPane.setText(i18n("settings.advanced.custom_commands.hint"));
GridPane.setColumnSpan(hintPane, 2);
pane.addRow(4, hintPane);
customCommandsPane.getContent().setAll(pane);
}
ComponentList jvmPane = new ComponentList();
{
GridPane pane = new GridPane();
ColumnConstraints title = new ColumnConstraints();
ColumnConstraints value = new ColumnConstraints();
value.setFillWidth(true);
value.setHgrow(Priority.ALWAYS);
pane.setHgap(16);
pane.setVgap(8);
pane.getColumnConstraints().setAll(title, value);
txtJVMArgs = new JFXTextField();
txtJVMArgs.getStyleClass().add("fit-width");
pane.addRow(0, new Label(i18n("settings.advanced.jvm_args")), txtJVMArgs);
HintPane hintPane = new HintPane();
hintPane.setText(i18n("settings.advanced.jvm_args.prompt"));
GridPane.setColumnSpan(hintPane, 2);
pane.addRow(4, hintPane);
txtMetaspace = new JFXTextField();
txtMetaspace.setPromptText(i18n("settings.advanced.java_permanent_generation_space.prompt"));
txtMetaspace.getStyleClass().add("fit-width");
FXUtils.setValidateWhileTextChanged(txtMetaspace, true);
txtMetaspace.setValidators(new NumberValidator(i18n("input.number"), true));
pane.addRow(1, new Label(i18n("settings.advanced.java_permanent_generation_space")), txtMetaspace);
txtEnvironmentVariables = new JFXTextField();
txtEnvironmentVariables.getStyleClass().add("fit-width");
pane.addRow(2, new Label(i18n("settings.advanced.environment_variables")), txtEnvironmentVariables);
jvmPane.getContent().setAll(pane);
}
ComponentList workaroundPane = new ComponentList();
HintPane workaroundWarning = new HintPane(MessageDialogPane.MessageType.WARNING);
workaroundWarning.setText(i18n("settings.advanced.workaround.warning"));
{
nativesDirItem = new MultiFileItem<>();
nativesDirSublist = new ComponentSublist();
nativesDirSublist.getContent().add(nativesDirItem);
nativesDirSublist.setTitle(i18n("settings.advanced.natives_directory"));
nativesDirSublist.setHasSubtitle(true);
nativesDirCustomOption = new MultiFileItem.FileOption<>(i18n("settings.advanced.natives_directory.custom"), NativesDirectoryType.CUSTOM)
.setChooserTitle(i18n("settings.advanced.natives_directory.choose"))
.setDirectory(true);
nativesDirItem.loadChildren(Arrays.asList(
new MultiFileItem.Option<>(i18n("settings.advanced.natives_directory.default"), NativesDirectoryType.VERSION_FOLDER),
nativesDirCustomOption
));
HintPane nativesDirHint = new HintPane(MessageDialogPane.MessageType.WARNING);
nativesDirHint.setText(i18n("settings.advanced.natives_directory.hint"));
nativesDirItem.getChildren().add(nativesDirHint);
BorderPane rendererPane = new BorderPane();
{
Label label = new Label(i18n("settings.advanced.renderer"));
rendererPane.setLeft(label);
BorderPane.setAlignment(label, Pos.CENTER_LEFT);
cboRenderer = new JFXComboBox<>();
cboRenderer.getItems().setAll(Renderer.values());
cboRenderer.setConverter(stringConverter(e -> i18n("settings.advanced.renderer." + e.name().toLowerCase(Locale.ROOT))));
rendererPane.setRight(cboRenderer);
BorderPane.setAlignment(cboRenderer, Pos.CENTER_RIGHT);
FXUtils.setLimitWidth(cboRenderer, 300);
}
noJVMArgsPane = new OptionToggleButton();
noJVMArgsPane.setTitle(i18n("settings.advanced.no_jvm_args"));
noGameCheckPane = new OptionToggleButton();
noGameCheckPane.setTitle(i18n("settings.advanced.dont_check_game_completeness"));
noJVMCheckPane = new OptionToggleButton();
noJVMCheckPane.setTitle(i18n("settings.advanced.dont_check_jvm_validity"));
noNativesPatchPane = new OptionToggleButton();
noNativesPatchPane.setTitle(i18n("settings.advanced.dont_patch_natives"));
useNativeGLFWPane = new OptionToggleButton();
useNativeGLFWPane.setTitle(i18n("settings.advanced.use_native_glfw"));
useNativeOpenALPane = new OptionToggleButton();
useNativeOpenALPane.setTitle(i18n("settings.advanced.use_native_openal"));
workaroundPane.getContent().setAll(
nativesDirSublist, rendererPane,
noJVMArgsPane, noGameCheckPane, noJVMCheckPane, noNativesPatchPane,
useNativeGLFWPane, useNativeOpenALPane);
}
rootPane.getChildren().addAll(
ComponentList.createComponentListTitle(i18n("settings.advanced.custom_commands")), customCommandsPane,
ComponentList.createComponentListTitle(i18n("settings.advanced.jvm")), jvmPane,
ComponentList.createComponentListTitle(i18n("settings.advanced.workaround")), workaroundWarning, workaroundPane
);
bindProperties();
}
void bindProperties() {
nativesDirCustomOption.bindBidirectional(versionSetting.nativesDirProperty());
FXUtils.bindString(txtJVMArgs, versionSetting.javaArgsProperty());
FXUtils.bindString(txtGameArgs, versionSetting.minecraftArgsProperty());
FXUtils.bindString(txtMetaspace, versionSetting.permSizeProperty());
FXUtils.bindString(txtEnvironmentVariables, versionSetting.environmentVariablesProperty());
FXUtils.bindString(txtWrapper, versionSetting.wrapperProperty());
FXUtils.bindString(txtPreLaunchCommand, versionSetting.preLaunchCommandProperty());
FXUtils.bindEnum(cboRenderer, versionSetting.rendererProperty());
noGameCheckPane.selectedProperty().bindBidirectional(versionSetting.notCheckGameProperty());
noJVMCheckPane.selectedProperty().bindBidirectional(versionSetting.notCheckJVMProperty());
noJVMArgsPane.selectedProperty().bindBidirectional(versionSetting.noJVMArgsProperty());
noNativesPatchPane.selectedProperty().bindBidirectional(versionSetting.notPatchNativesProperty());
useNativeGLFWPane.selectedProperty().bindBidirectional(versionSetting.useNativeGLFWProperty());
useNativeOpenALPane.selectedProperty().bindBidirectional(versionSetting.useNativeOpenALProperty());
nativesDirItem.selectedDataProperty().bindBidirectional(versionSetting.nativesDirTypeProperty());
nativesDirSublist.subtitleProperty().bind(Bindings.createStringBinding(() -> Paths.get(profile.getRepository().getRunDirectory(versionId).getAbsolutePath() + "/natives").normalize().toString(),
versionSetting.nativesDirProperty(), versionSetting.nativesDirTypeProperty()));
}
void unbindProperties() {
nativesDirCustomOption.valueProperty().unbindBidirectional(versionSetting.nativesDirProperty());
FXUtils.unbind(txtJVMArgs, versionSetting.javaArgsProperty());
FXUtils.unbind(txtGameArgs, versionSetting.minecraftArgsProperty());
FXUtils.unbind(txtMetaspace, versionSetting.permSizeProperty());
FXUtils.unbind(txtEnvironmentVariables, versionSetting.environmentVariablesProperty());
FXUtils.unbind(txtWrapper, versionSetting.wrapperProperty());
FXUtils.unbind(txtPreLaunchCommand, versionSetting.preLaunchCommandProperty());
FXUtils.unbind(txtPostExitCommand, versionSetting.postExitCommandProperty());
FXUtils.unbindEnum(cboRenderer);
noGameCheckPane.selectedProperty().unbindBidirectional(versionSetting.notCheckGameProperty());
noJVMCheckPane.selectedProperty().unbindBidirectional(versionSetting.notCheckJVMProperty());
noJVMArgsPane.selectedProperty().unbindBidirectional(versionSetting.noJVMArgsProperty());
noNativesPatchPane.selectedProperty().unbindBidirectional(versionSetting.notPatchNativesProperty());
useNativeGLFWPane.selectedProperty().unbindBidirectional(versionSetting.useNativeGLFWProperty());
useNativeOpenALPane.selectedProperty().unbindBidirectional(versionSetting.useNativeOpenALProperty());
nativesDirItem.selectedDataProperty().unbindBidirectional(versionSetting.nativesDirTypeProperty());
nativesDirSublist.subtitleProperty().unbind();
}
@Override
public ReadOnlyObjectProperty<State> stateProperty() {
return stateProperty;
}
}
@@ -260,18 +260,18 @@ public class DownloadPage extends Control implements DecoratorPage {
if (getSkinnable().mod != null) {
JFXHyperlink openMcmodButton = new JFXHyperlink(i18n("mods.mcmod"));
openMcmodButton.setOnAction(e -> FXUtils.openLink(getSkinnable().translations.getMcmodUrl(getSkinnable().mod)));
openMcmodButton.setExternalLink(getSkinnable().translations.getMcmodUrl(getSkinnable().mod));
descriptionPane.getChildren().add(openMcmodButton);
if (StringUtils.isNotBlank(getSkinnable().mod.getMcbbs())) {
JFXHyperlink openMcbbsButton = new JFXHyperlink(i18n("mods.mcbbs"));
openMcbbsButton.setOnAction(e -> FXUtils.openLink(ModManager.getMcbbsUrl(getSkinnable().mod.getMcbbs())));
openMcbbsButton.setExternalLink(ModManager.getMcbbsUrl(getSkinnable().mod.getMcbbs()));
descriptionPane.getChildren().add(openMcbbsButton);
}
}
JFXHyperlink openUrlButton = new JFXHyperlink(control.page.getLocalizedOfficialPage());
openUrlButton.setOnAction(e -> FXUtils.openLink(getSkinnable().addon.getPageUrl()));
openUrlButton.setExternalLink(getSkinnable().addon.getPageUrl());
descriptionPane.getChildren().add(openUrlButton);
}
@@ -322,12 +322,10 @@ public class DownloadPage extends Control implements DecoratorPage {
for (String gameVersion : control.versions.keys().stream()
.sorted(VersionNumber.VERSION_COMPARATOR.reversed())
.collect(Collectors.toList())) {
ComponentList sublist = new ComponentList();
sublist.setLazyInitializer(self -> {
self.getContent().setAll(control.versions.get(gameVersion).stream()
.map(version -> new ModItem(version, control))
.collect(Collectors.toList()));
});
ComponentList sublist = new ComponentList(() ->
control.versions.get(gameVersion).stream()
.map(version -> new ModItem(version, control))
.collect(Collectors.toList()));
sublist.getStyleClass().add("no-padding");
sublist.setTitle(gameVersion);
@@ -369,6 +367,7 @@ public class DownloadPage extends Control implements DecoratorPage {
}
private static final class ModItem extends StackPane {
ModItem(RemoteMod.Version dataItem, DownloadPage selfPage) {
HBox pane = new HBox(8);
pane.setPadding(new Insets(8));
@@ -378,9 +377,7 @@ public class DownloadPage extends Control implements DecoratorPage {
JFXButton saveAsButton = new JFXButton();
RipplerContainer container = new RipplerContainer(pane);
container.setOnMouseClicked(e -> {
selfPage.download(dataItem);
});
container.setOnMouseClicked(e -> selfPage.download(dataItem));
getChildren().setAll(container);
saveAsButton.getStyleClass().add("toggle-icon4");
@@ -391,7 +388,7 @@ public class DownloadPage extends Control implements DecoratorPage {
content.setTitle(dataItem.getName());
content.setSubtitle(FORMATTER.format(dataItem.getDatePublished().toInstant()));
saveAsButton.setOnMouseClicked(e -> selfPage.saveAs(dataItem));
saveAsButton.setOnAction(e -> selfPage.saveAs(dataItem));
switch (dataItem.getVersionType()) {
case Release:
@@ -407,6 +404,9 @@ public class DownloadPage extends Control implements DecoratorPage {
content.getTags().add(i18n("version.game.snapshot"));
break;
}
// Workaround for https://github.com/huanghongxun/HMCL/issues/2129
this.setMinHeight(50);
}
}
@@ -17,6 +17,7 @@
*/
package org.jackhuang.hmcl.ui.versions;
import com.google.gson.JsonParseException;
import javafx.application.Platform;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
@@ -82,8 +83,8 @@ public class GameItem extends Control {
ModpackConfiguration<?> config = profile.getRepository().readModpackConfiguration(version);
if (config == null) return;
tag.set(config.getVersion());
} catch (IOException e) {
LOG.log(Level.WARNING, "Failed to read modpack configuration from ", e);
} catch (IOException | JsonParseException e) {
LOG.log(Level.WARNING, "Failed to read modpack configuration from " + version, e);
}
}, Platform::runLater)
.exceptionally(handleUncaught);
@@ -308,8 +308,7 @@ class ModListPageSkin extends SkinBase<ModListPage> {
setBody(description);
if (StringUtils.isNotBlank(modInfo.getModInfo().getUrl())) {
JFXHyperlink officialPageButton = new JFXHyperlink();
officialPageButton.setText(i18n("mods.url"));
JFXHyperlink officialPageButton = new JFXHyperlink(i18n("mods.url"));
officialPageButton.setOnAction(e -> {
fireEvent(new DialogCloseEvent());
FXUtils.openLink(modInfo.getModInfo().getUrl());
@@ -319,8 +318,7 @@ class ModListPageSkin extends SkinBase<ModListPage> {
}
if (modInfo.getMod() != null && StringUtils.isNotBlank(modInfo.getMod().getMcbbs())) {
JFXHyperlink mcbbsButton = new JFXHyperlink();
mcbbsButton.setText(i18n("mods.mcbbs"));
JFXHyperlink mcbbsButton = new JFXHyperlink(i18n("mods.mcbbs"));
mcbbsButton.setOnAction(e -> {
fireEvent(new DialogCloseEvent());
FXUtils.openLink(ModManager.getMcbbsUrl(modInfo.getMod().getMcbbs()));
@@ -329,8 +327,7 @@ class ModListPageSkin extends SkinBase<ModListPage> {
}
if (modInfo.getMod() == null || StringUtils.isBlank(modInfo.getMod().getMcmod())) {
JFXHyperlink searchButton = new JFXHyperlink();
searchButton.setText(i18n("mods.mcmod.search"));
JFXHyperlink searchButton = new JFXHyperlink(i18n("mods.mcmod.search"));
searchButton.setOnAction(e -> {
fireEvent(new DialogCloseEvent());
FXUtils.openLink(NetworkUtils.withQuery("https://search.mcmod.cn/s", mapOf(
@@ -341,8 +338,7 @@ class ModListPageSkin extends SkinBase<ModListPage> {
});
getActions().add(searchButton);
} else {
JFXHyperlink mcmodButton = new JFXHyperlink();
mcmodButton.setText(i18n("mods.mcmod.page"));
JFXHyperlink mcmodButton = new JFXHyperlink(i18n("mods.mcmod.page"));
mcmodButton.setOnAction(e -> {
fireEvent(new DialogCloseEvent());
FXUtils.openLink(ModTranslations.MOD.getMcmodUrl(modInfo.getMod()));
@@ -66,7 +66,7 @@ import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
public final class VersionSettingsPage extends StackPane implements DecoratorPage, VersionPage.VersionLoadable, PageAware {
private final ReadOnlyObjectWrapper<State> state = new ReadOnlyObjectWrapper<>(new State("", null, false, false, false));
private final boolean globalSetting;
private AdvancedVersionSettingPage advancedVersionSettingPage;
private VersionSetting lastVersionSetting = null;
private Profile profile;
@@ -77,24 +77,11 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
private final VBox rootPane;
private final JFXTextField txtWidth;
private final JFXTextField txtHeight;
private final JFXTextField txtJVMArgs;
private final JFXTextField txtGameArgs;
private final JFXTextField txtMetaspace;
private final JFXTextField txtWrapper;
private final JFXTextField txtPreLaunchCommand;
private final JFXTextField txtPostExitCommand;
private final JFXTextField txtServerIP;
private final ComponentList componentList;
private final JFXComboBox<LauncherVisibility> cboLauncherVisibility;
private final JFXCheckBox chkAutoAllocate;
private final JFXCheckBox chkFullscreen;
private final OptionToggleButton noJVMArgsPane;
private final OptionToggleButton noGameCheckPane;
private final OptionToggleButton noJVMCheckPane;
private final OptionToggleButton noNativesPatchPane;
private final OptionToggleButton useSoftwareRenderer;
private final OptionToggleButton useNativeGLFWPane;
private final OptionToggleButton useNativeOpenALPane;
private final ComponentSublist javaSublist;
private final MultiFileItem<Pair<JavaVersionType, JavaVersion>> javaItem;
private final MultiFileItem.Option<Pair<JavaVersionType, JavaVersion>> javaAutoDeterminedOption;
@@ -102,12 +89,9 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
private final ComponentSublist gameDirSublist;
private final MultiFileItem<GameDirectoryType> gameDirItem;
private final MultiFileItem.FileOption<GameDirectoryType> gameDirCustomOption;
private final ComponentSublist nativesDirSublist;
private final MultiFileItem<NativesDirectoryType> nativesDirItem;
private final MultiFileItem.FileOption<NativesDirectoryType> nativesDirCustomOption;
private final JFXComboBox<ProcessPriority> cboProcessPriority;
private final OptionToggleButton showLogsPane;
private ImagePickerItem iconPickerItem;
private final ImagePickerItem iconPickerItem;
private final InvalidationListener specificSettingsListener;
@@ -121,8 +105,6 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
private final BooleanProperty modpack = new SimpleBooleanProperty();
public VersionSettingsPage(boolean globalSetting) {
this.globalSetting = globalSetting;
ScrollPane scrollPane = new ScrollPane();
scrollPane.setFitToHeight(true);
scrollPane.setFitToWidth(true);
@@ -145,18 +127,17 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
text.textProperty().bind(BindingMapping.of(selectedVersion)
.map(selectedVersion -> i18n("settings.type.special.edit.hint", selectedVersion)));
JFXHyperlink specificSettingsLink = new JFXHyperlink();
specificSettingsLink.setText(i18n("settings.type.special.edit"));
specificSettingsLink.setOnMouseClicked(e -> editSpecificSettings());
JFXHyperlink specificSettingsLink = new JFXHyperlink(i18n("settings.type.special.edit"));
specificSettingsLink.setOnAction(e -> editSpecificSettings());
specificSettingsHint.setChildren(text, specificSettingsLink);
specificSettingsHint.managedProperty().bind(navigateToSpecificSettings);
specificSettingsHint.visibleProperty().bind(navigateToSpecificSettings);
rootPane.getChildren().addAll(specificSettingsHint);
}
iconPickerItem = null;
if (!globalSetting) {
rootPane.getChildren().addAll(specificSettingsHint);
} else {
HintPane gameDirHint = new HintPane(MessageDialogPane.MessageType.INFO);
gameDirHint.setText(i18n("settings.game.working_directory.hint"));
rootPane.getChildren().add(gameDirHint);
@@ -171,7 +152,6 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
iconPickerItem.setOnDeleteButtonClicked(e -> onDeleteIcon());
iconPickerItemWrapper.getContent().setAll(iconPickerItem);
BorderPane settingsTypePane = new BorderPane();
settingsTypePane.disableProperty().bind(modpack);
rootPane.getChildren().add(settingsTypePane);
@@ -186,7 +166,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
settingsTypePane.setRight(editGlobalSettingsButton);
editGlobalSettingsButton.disableProperty().bind(enableSpecificCheckBox.selectedProperty());
BorderPane.setAlignment(editGlobalSettingsButton, Pos.CENTER_RIGHT);
editGlobalSettingsButton.setOnMouseClicked(e -> editGlobalSettings());
editGlobalSettingsButton.setOnAction(e -> editGlobalSettings());
}
{
@@ -401,146 +381,43 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
serverPane.addRow(0, new Label(i18n("settings.advanced.server_ip")), txtServerIP);
}
componentList.getContent().setAll(javaSublist, gameDirSublist, maxMemoryPane, launcherVisibilityPane, dimensionPane, showLogsPane, processPriorityPane, serverPane);
BorderPane showAdvancedSettingPane = new BorderPane();
{
Label label = new Label(i18n("settings.advanced"));
showAdvancedSettingPane.setLeft(label);
BorderPane.setAlignment(label, Pos.CENTER_LEFT);
JFXButton button = new JFXButton(i18n("settings.advanced.modify"));
button.setOnAction(e -> {
if (lastVersionSetting != null) {
if (advancedVersionSettingPage == null)
advancedVersionSettingPage = new AdvancedVersionSettingPage(profile, versionId, lastVersionSetting);
Controllers.navigate(advancedVersionSettingPage);
}
});
button.getStyleClass().add("jfx-button-border");
showAdvancedSettingPane.setRight(button);
}
componentList.getContent().setAll(
javaSublist,
gameDirSublist,
maxMemoryPane,
launcherVisibilityPane,
dimensionPane,
showLogsPane,
processPriorityPane,
serverPane,
showAdvancedSettingPane
);
}
HBox advancedHintPane = new HBox();
advancedHintPane.setAlignment(Pos.CENTER);
advancedHintPane.setPadding(new Insets(16, 0, 8, 0));
{
Label advanced = new Label(i18n("settings.advanced"));
advanced.setStyle("-fx-font-size: 12px;");
advancedHintPane.getChildren().setAll(advanced);
}
ComponentList customCommandsPane = new ComponentList();
customCommandsPane.disableProperty().bind(enableSpecificSettings.not());
{
GridPane pane = new GridPane();
pane.setHgap(16);
pane.setVgap(8);
pane.getColumnConstraints().setAll(new ColumnConstraints(), FXUtils.getColumnHgrowing());
txtGameArgs = new JFXTextField();
txtGameArgs.setPromptText(i18n("settings.advanced.minecraft_arguments.prompt"));
txtGameArgs.getStyleClass().add("fit-width");
pane.addRow(0, new Label(i18n("settings.advanced.minecraft_arguments")), txtGameArgs);
txtPreLaunchCommand = new JFXTextField();
txtPreLaunchCommand.setPromptText(i18n("settings.advanced.precall_command.prompt"));
txtPreLaunchCommand.getStyleClass().add("fit-width");
pane.addRow(1, new Label(i18n("settings.advanced.precall_command")), txtPreLaunchCommand);
txtWrapper = new JFXTextField();
txtWrapper.setPromptText(i18n("settings.advanced.wrapper_launcher.prompt"));
txtWrapper.getStyleClass().add("fit-width");
pane.addRow(2, new Label(i18n("settings.advanced.wrapper_launcher")), txtWrapper);
txtPostExitCommand = new JFXTextField();
txtPostExitCommand.setPromptText(i18n("settings.advanced.post_exit_command.prompt"));
txtPostExitCommand.getStyleClass().add("fit-width");
pane.addRow(3, new Label(i18n("settings.advanced.post_exit_command")), txtPostExitCommand);
HintPane hintPane = new HintPane();
hintPane.setText(i18n("settings.advanced.custom_commands.hint"));
GridPane.setColumnSpan(hintPane, 2);
pane.addRow(4, hintPane);
customCommandsPane.getContent().setAll(pane);
}
ComponentList jvmPane = new ComponentList();
jvmPane.disableProperty().bind(enableSpecificSettings.not());
{
GridPane pane = new GridPane();
ColumnConstraints title = new ColumnConstraints();
ColumnConstraints value = new ColumnConstraints();
value.setFillWidth(true);
value.setHgrow(Priority.ALWAYS);
pane.setHgap(16);
pane.setVgap(8);
pane.getColumnConstraints().setAll(title, value);
txtJVMArgs = new JFXTextField();
txtJVMArgs.getStyleClass().add("fit-width");
pane.addRow(0, new Label(i18n("settings.advanced.jvm_args")), txtJVMArgs);
HintPane hintPane = new HintPane();
hintPane.setText(i18n("settings.advanced.jvm_args.prompt"));
GridPane.setColumnSpan(hintPane, 2);
pane.addRow(4, hintPane);
txtMetaspace = new JFXTextField();
txtMetaspace.setPromptText(i18n("settings.advanced.java_permanent_generation_space.prompt"));
txtMetaspace.getStyleClass().add("fit-width");
FXUtils.setValidateWhileTextChanged(txtMetaspace, true);
txtMetaspace.setValidators(new NumberValidator(i18n("input.number"), true));
pane.addRow(1, new Label(i18n("settings.advanced.java_permanent_generation_space")), txtMetaspace);
jvmPane.getContent().setAll(pane);
}
ComponentList workaroundPane = new ComponentList();
workaroundPane.disableProperty().bind(enableSpecificSettings.not());
HintPane workaroundWarning = new HintPane(MessageDialogPane.MessageType.WARNING);
workaroundWarning.setText(i18n("settings.advanced.workaround.warning"));
{
nativesDirItem = new MultiFileItem<>();
nativesDirSublist = new ComponentSublist();
nativesDirSublist.getContent().add(nativesDirItem);
nativesDirSublist.setTitle(i18n("settings.advanced.natives_directory"));
nativesDirSublist.setHasSubtitle(true);
nativesDirCustomOption = new MultiFileItem.FileOption<>(i18n("settings.advanced.natives_directory.custom"), NativesDirectoryType.CUSTOM)
.setChooserTitle(i18n("settings.advanced.natives_directory.choose"))
.setDirectory(true);
nativesDirItem.loadChildren(Arrays.asList(
new MultiFileItem.Option<>(i18n("settings.advanced.natives_directory.default"), NativesDirectoryType.VERSION_FOLDER),
nativesDirCustomOption
));
HintPane nativesDirHint = new HintPane(MessageDialogPane.MessageType.WARNING);
nativesDirHint.setText(i18n("settings.advanced.natives_directory.hint"));
nativesDirItem.getChildren().add(nativesDirHint);
noJVMArgsPane = new OptionToggleButton();
noJVMArgsPane.setTitle(i18n("settings.advanced.no_jvm_args"));
noGameCheckPane = new OptionToggleButton();
noGameCheckPane.setTitle(i18n("settings.advanced.dont_check_game_completeness"));
noJVMCheckPane = new OptionToggleButton();
noJVMCheckPane.setTitle(i18n("settings.advanced.dont_check_jvm_validity"));
noNativesPatchPane = new OptionToggleButton();
noNativesPatchPane.setTitle(i18n("settings.advanced.dont_patch_natives"));
useSoftwareRenderer = new OptionToggleButton();
useSoftwareRenderer.setTitle(i18n("settings.advanced.use_software_renderer"));
useNativeGLFWPane = new OptionToggleButton();
useNativeGLFWPane.setTitle(i18n("settings.advanced.use_native_glfw"));
useNativeOpenALPane = new OptionToggleButton();
useNativeOpenALPane.setTitle(i18n("settings.advanced.use_native_openal"));
workaroundPane.getContent().setAll(
nativesDirSublist,
noJVMArgsPane, noGameCheckPane, noJVMCheckPane, noNativesPatchPane,
useSoftwareRenderer, useNativeGLFWPane, useNativeOpenALPane);
}
rootPane.getChildren().addAll(componentList,
advancedHintPane,
ComponentList.createComponentListTitle(i18n("settings.advanced.custom_commands")), customCommandsPane,
ComponentList.createComponentListTitle(i18n("settings.advanced.jvm")), jvmPane,
ComponentList.createComponentListTitle(i18n("settings.advanced.workaround")), workaroundWarning, workaroundPane);
rootPane.getChildren().add(componentList);
initialize();
specificSettingsListener = any -> {
enableSpecificSettings.set(!lastVersionSetting.isUsesGlobal());
};
specificSettingsListener = any -> enableSpecificSettings.set(!lastVersionSetting.isUsesGlobal());
addEventHandler(Navigator.NavigationEvent.NAVIGATED, this::onDecoratorPageNavigating);
@@ -631,24 +508,10 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
maxMemory.unbindBidirectional(lastVersionSetting.maxMemoryProperty());
javaCustomOption.valueProperty().unbindBidirectional(lastVersionSetting.javaDirProperty());
gameDirCustomOption.valueProperty().unbindBidirectional(lastVersionSetting.gameDirProperty());
nativesDirCustomOption.valueProperty().unbindBidirectional(lastVersionSetting.nativesDirProperty());
FXUtils.unbind(txtJVMArgs, lastVersionSetting.javaArgsProperty());
FXUtils.unbind(txtGameArgs, lastVersionSetting.minecraftArgsProperty());
FXUtils.unbind(txtMetaspace, lastVersionSetting.permSizeProperty());
FXUtils.unbind(txtWrapper, lastVersionSetting.wrapperProperty());
FXUtils.unbind(txtPreLaunchCommand, lastVersionSetting.preLaunchCommandProperty());
FXUtils.unbind(txtPostExitCommand, lastVersionSetting.postExitCommandProperty());
FXUtils.unbind(txtServerIP, lastVersionSetting.serverIpProperty());
FXUtils.unbindBoolean(chkAutoAllocate, lastVersionSetting.autoMemoryProperty());
FXUtils.unbindBoolean(chkFullscreen, lastVersionSetting.fullscreenProperty());
noGameCheckPane.selectedProperty().unbindBidirectional(lastVersionSetting.notCheckGameProperty());
noJVMCheckPane.selectedProperty().unbindBidirectional(lastVersionSetting.notCheckJVMProperty());
noJVMArgsPane.selectedProperty().unbindBidirectional(lastVersionSetting.noJVMArgsProperty());
noNativesPatchPane.selectedProperty().unbindBidirectional(lastVersionSetting.notPatchNativesProperty());
showLogsPane.selectedProperty().unbindBidirectional(lastVersionSetting.showLogsProperty());
useSoftwareRenderer.selectedProperty().unbindBidirectional(lastVersionSetting.useSoftwareRendererProperty());
useNativeGLFWPane.selectedProperty().unbindBidirectional(lastVersionSetting.useNativeGLFWProperty());
useNativeOpenALPane.selectedProperty().unbindBidirectional(lastVersionSetting.useNativeOpenALProperty());
FXUtils.unbindEnum(cboLauncherVisibility);
FXUtils.unbindEnum(cboProcessPriority);
@@ -659,8 +522,10 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
gameDirItem.selectedDataProperty().unbindBidirectional(lastVersionSetting.gameDirTypeProperty());
gameDirSublist.subtitleProperty().unbind();
nativesDirItem.selectedDataProperty().unbindBidirectional(lastVersionSetting.nativesDirTypeProperty());
nativesDirSublist.subtitleProperty().unbind();
if (advancedVersionSettingPage != null) {
advancedVersionSettingPage.unbindProperties();
advancedVersionSettingPage = null;
}
}
// unbind data fields
@@ -673,23 +538,10 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
javaCustomOption.bindBidirectional(versionSetting.javaDirProperty());
gameDirCustomOption.bindBidirectional(versionSetting.gameDirProperty());
nativesDirCustomOption.bindBidirectional(versionSetting.nativesDirProperty());
FXUtils.bindString(txtJVMArgs, versionSetting.javaArgsProperty());
FXUtils.bindString(txtGameArgs, versionSetting.minecraftArgsProperty());
FXUtils.bindString(txtMetaspace, versionSetting.permSizeProperty());
FXUtils.bindString(txtWrapper, versionSetting.wrapperProperty());
FXUtils.bindString(txtPreLaunchCommand, versionSetting.preLaunchCommandProperty());
FXUtils.bindString(txtServerIP, versionSetting.serverIpProperty());
FXUtils.bindBoolean(chkAutoAllocate, versionSetting.autoMemoryProperty());
FXUtils.bindBoolean(chkFullscreen, versionSetting.fullscreenProperty());
noGameCheckPane.selectedProperty().bindBidirectional(versionSetting.notCheckGameProperty());
noJVMCheckPane.selectedProperty().bindBidirectional(versionSetting.notCheckJVMProperty());
noJVMArgsPane.selectedProperty().bindBidirectional(versionSetting.noJVMArgsProperty());
noNativesPatchPane.selectedProperty().bindBidirectional(versionSetting.notPatchNativesProperty());
showLogsPane.selectedProperty().bindBidirectional(versionSetting.showLogsProperty());
useSoftwareRenderer.selectedProperty().bindBidirectional(versionSetting.useSoftwareRendererProperty());
useNativeGLFWPane.selectedProperty().bindBidirectional(versionSetting.useNativeGLFWProperty());
useNativeOpenALPane.selectedProperty().bindBidirectional(versionSetting.useNativeOpenALProperty());
FXUtils.bindEnum(cboLauncherVisibility, versionSetting.launcherVisibilityProperty());
FXUtils.bindEnum(cboProcessPriority, versionSetting.processPriorityProperty());
@@ -716,10 +568,6 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
gameDirSublist.subtitleProperty().bind(Bindings.createStringBinding(() -> Paths.get(profile.getRepository().getRunDirectory(versionId).getAbsolutePath()).normalize().toString(),
versionSetting.gameDirProperty(), versionSetting.gameDirTypeProperty()));
nativesDirItem.selectedDataProperty().bindBidirectional(versionSetting.nativesDirTypeProperty());
nativesDirSublist.subtitleProperty().bind(Bindings.createStringBinding(() -> Paths.get(profile.getRepository().getRunDirectory(versionId).getAbsolutePath() + "/natives").normalize().toString(),
versionSetting.nativesDirProperty(), versionSetting.nativesDirTypeProperty()));
lastVersionSetting = versionSetting;
initJavaSubtitle();
@@ -1,9 +1,7 @@
package org.jackhuang.hmcl.util;
import com.google.gson.reflect.TypeToken;
import org.jackhuang.hmcl.game.Library;
import org.jackhuang.hmcl.game.NativesDirectoryType;
import org.jackhuang.hmcl.game.Version;
import org.jackhuang.hmcl.game.*;
import org.jackhuang.hmcl.setting.VersionSetting;
import org.jackhuang.hmcl.util.gson.JsonUtils;
import org.jackhuang.hmcl.util.platform.Architecture;
@@ -92,9 +90,9 @@ public final class NativePatcher {
return version.setLibraries(newLibraries);
}
public static Library getSoftwareRendererLoader(JavaVersion javaVersion) {
public static Library getMesaLoader(JavaVersion javaVersion, Renderer renderer) {
Map<String, Library> map = Hole.nativeReplacement.get(javaVersion.getPlatform().toString());
return map != null ? map.get("software-renderer-loader") : null;
return map != null ? map.get(renderer == Renderer.LLVMPIPE ? "software-renderer-loader" : "mesa-loader") : null;
}
private static final class Hole {
@@ -952,6 +952,8 @@ selector.custom=Custom
settings=Settings
settings.advanced=Advanced Settings
settings.advanced.modify=Modify Advanced Settings
settings.advanced.title=Advanced Settings - %s
settings.advanced.custom_commands=Custom Commands
settings.advanced.custom_commands.hint=The following environment variables are provided\:\n\
- $INST_NAME: version name\n\
@@ -967,6 +969,7 @@ settings.advanced.custom_commands.hint=The following environment variables are p
settings.advanced.dont_check_game_completeness=Do not check game integrity
settings.advanced.dont_check_jvm_validity=Do not check JVM compatibility
settings.advanced.dont_patch_natives=Do not attempt to automatically replace native libraries
settings.advanced.environment_variables=Environment Variables
settings.advanced.game_dir.default=Default (.minecraft/)
settings.advanced.game_dir.independent=Isolated (.minecraft/versions/<instance name>/, except for assets and libraries)
settings.advanced.java_permanent_generation_space=PermGen Space
@@ -1001,11 +1004,15 @@ settings.advanced.process_priority.above_normal=Above Normal
settings.advanced.process_priority.high=High
settings.advanced.post_exit_command=Post-exit Command
settings.advanced.post_exit_command.prompt=Commands to execute after the game exits
settings.advanced.renderer=Renderer
settings.advanced.renderer.default=OpenGL (Default)
settings.advanced.renderer.d3d12=DirectX 12 (Poor performance and compatibility)
settings.advanced.renderer.llvmpipe=軟渲染器 (Poor efficiency and best compatibility)
settings.advanced.renderer.zink=Vulkan (Best performance and poor compatibility)
settings.advanced.server_ip=Server Address
settings.advanced.server_ip.prompt=Join automatically after launching the game.
settings.advanced.use_native_glfw=[Linux Only] Use system GLFW
settings.advanced.use_native_openal=[Linux Only] Use system OpenAL
settings.advanced.use_software_renderer=Use OpenGL software renderer (better compatibility, but less performance)
settings.advanced.workaround=Workarounds
settings.advanced.workaround.warning=Workaround options are intended only for expert users. Tweaking with these options may crash the game. Unless you know what you are doing, please do not modify these options.
settings.advanced.wrapper_launcher=Wrapper Command
@@ -869,6 +869,7 @@ selector.custom=Personalizar
settings=Configuración
settings.advanced=Configuración avanzada
settings.advanced.title=Configuración avanzada - %s
settings.advanced.custom_commands=Comandos personalizados
settings.advanced.custom_commands.hint=Se proporcionan las siguientes variables de entorno\:\n\
- $INST_NAME: nombre de la versión\n\
@@ -703,6 +703,7 @@ selector.custom=カスタム
settings=設定
settings.advanced=詳細設定
settings.advanced.title=詳細設定 - %s
settings.advanced.custom_commands=カスタムコマンド
settings.advanced.custom_commands.hint=カスタムコマンドは、次の環境変数を使用して実行されます。\n \
\-$ INST_NAME:バージョンの名前\n \
@@ -708,6 +708,7 @@ selector.custom=Пользовательский
settings=Настройки
settings.advanced=Расширенные настройки
settings.advanced.title=Расширенные настройки - %s
settings.advanced.custom_commands=Пользовательские команды
settings.advanced.custom_commands.hint=Пользовательские команды выполняются со следующими переменными окружения:\n\
\ - $INST_NAME: название версии\n\
@@ -827,6 +827,8 @@ selector.custom=自訂
settings=遊戲設定
settings.advanced=進階設定
settings.advanced.modify=修改進階設定
settings.advanced.title=進階設定 - %s
settings.advanced.custom_commands=自訂命令
settings.advanced.custom_commands.hint=自訂命令被調用時將包含如下的環境變數:\n\
\ - $INST_NAME: 版本名稱\n\
@@ -842,6 +844,7 @@ settings.advanced.custom_commands.hint=自訂命令被調用時將包含如下
settings.advanced.dont_check_game_completeness=不檢查遊戲完整性
settings.advanced.dont_check_jvm_validity=不檢查 JVM 與遊戲的相容性
settings.advanced.dont_patch_natives=不嘗試自動替換本機庫
settings.advanced.environment_variables=環境變數
settings.advanced.game_dir.default=預設(.minecraft/)
settings.advanced.game_dir.independent=各版本獨立(.minecraft/versions/<版本名>/,除 assets、libraries)
settings.advanced.java_permanent_generation_space=記憶體永久儲存區域
@@ -874,13 +877,17 @@ settings.advanced.process_priority.above_normal=較高(優先保證遊戲運
settings.advanced.process_priority.high=高(優先保證遊戲運行,但可能會導致其他程式卡頓)
settings.advanced.post_exit_command=遊戲結束後執行命令
settings.advanced.post_exit_command.prompt=將在遊戲結束後呼叫使用
settings.advanced.renderer=渲染器
settings.advanced.renderer.default=OpenGL(默認)
settings.advanced.renderer.d3d12=DirectX 12(效能與相容性較差,用於調試)
settings.advanced.renderer.llvmpipe=軟渲染器(效能較差,相容性最好)
settings.advanced.renderer.zink=Vulkan(效能最好,相容性較差)
settings.advanced.server_ip=伺服器位址
settings.advanced.server_ip.prompt=預設,啟動遊戲後直接進入對應伺服器
settings.advanced.use_native_glfw=[Linux] 使用系統 GLFW
settings.advanced.use_native_openal=[Linux] 使用系統 OpenAL
settings.advanced.use_software_renderer=使用 OpenGL 軟渲染器(相容性更好,但效能較差)
settings.advanced.workaround=除錯選項
settings.advanced.workaround.warning=除錯選項僅提供給專業玩家使用。修改除錯選項可能會導致遊戲無法啟動。除非你知道你在做什麼,否則請你不要修改這些選項。
settings.advanced.workaround.warning=除錯選項僅提供給專業玩家使用。修改除錯選項可能會導致遊戲無法啟動。除非你知道你在做什麼,否則請不要修改這些選項。
settings.advanced.wrapper_launcher=前置指令
settings.advanced.wrapper_launcher.prompt=如填寫 optirun 後,啟動命令將從 "java ..." 變為 "optirun java ..."
@@ -138,8 +138,8 @@ account.methods.yggdrasil.migration.hint=自 2022 年 3 月 10 日起,Mojang
account.methods.yggdrasil.purchase=购买 Minecraft
account.missing=没有游戏帐户
account.missing.add=点击此处添加帐户
account.move_to_global=转换为全局账户
account.move_to_portable=转换为便携账户
account.move_to_global=转换为全局账户\n该账户的信息会保存至用户目录的配置文件中
account.move_to_portable=转换为便携账户\n该账户的信息会保存至 HMCL 同目录的配置文件中
account.not_logged_in=未登录
account.password=密码
account.portable=便携账户
@@ -398,12 +398,12 @@ game.crash.reason.fabric_warnings=Fabric 提供了一些警告信息:\n%1$s \n
game.crash.reason.file_already_exists=当前游戏因为文件 %1$s 已经存在,无法继续运行。\n如果你认为这个文件可以删除,你可以在备份这个文件后尝试删除它,并重新启动游戏。 \n你可以在 <a href="https://docs.hmcl.net/help.html ">此处</a> 寻求帮助。
game.crash.reason.file_changed=当前游戏因为文件校验失败,无法继续运行。\n如果你手动修改了 Minecraft.jar 文件,你需要回退修改,或者重新下载游戏。 \n你可以在 <a href="https://docs.hmcl.net/help.html ">此处</a> 寻求帮助。
game.crash.reason.gl_operation_failure=当前游戏因为你使用的某些 Mod、光影包、材质包,无法继续运行。\n请先尝试禁用你所使用的Mod/光影包/材质包再试。 \n你可以在 <a href="https://docs.hmcl.net/help.html ">此处</a> 寻求帮助。
game.crash.reason.graphics_driver=当前游戏因为你的显卡驱动存在问题崩溃了,请尝试:\n\
game.crash.reason.graphics_driver=当前游戏因为显卡驱动问题而崩溃,请尝试以下操作:\n\
- 如果你的电脑存在独立显卡,请尝试使用 独立显卡 而非 Intel 核显启动 HMCL 与游戏 <a href="https://www.bing.com/search?q=用独立显卡运行程序">详情</a>;\n\
- <a href="https://minecrafthopper.net/help/pixel-format-not-accelerated/">尝试升级你的 显卡驱动 到最新版本</a>,或回退到出厂版本;\n\
- 如果你确实需要使用核芯显卡,请检查你的电脑的 CPU 是否是 Intel(R) Core(TM) 3000 系列或更旧的处理器,如果是,对于 Minecraft 1.16.5 及更旧版本,请你将游戏所使用的 Java 版本降级至 1.8.0_51 及以下版本 <a href="https://www.oracle.com/java/technologies/javase/javase8-archive-downloads.html">Java 1.8.0 历史版本</a> ,否则请跳过;\n\
- 在全局(特定)游戏设置,菜单底部中打开“使用 OpenGL 软渲染器”选项可以尝试解决此问题,但打开此选项后在 CPU 性能不足的情况下帧数会显著降低,请慎重选择(仅推荐以调试为目的或应急时开启)\n\
如果仍有问题,你可能需要考虑换一个新显卡或新电脑。\n\
- 在游戏设置中打开“使用 OpenGL 软渲染器”(开启此选项后帧数会显著降低,仅推荐在以调试为目的或应急时开启)。\n\
如果仍有问题,你可能需要考虑换一张新显卡或一台新电脑。\n\
你可以在 <a href="https://docs.hmcl.net/help.html ">此处</a> 寻求帮助。
game.crash.reason.illegal_access_error=当前游戏因为某些 Mod 的问题,无法继续运行。\n如果你认识:%1$s,你可以更新或删除对应 Mod 再试。\n你可以在 <a href="https://docs.hmcl.net/help.html ">此处</a> 寻求帮助。
game.crash.reason.jdk_9=当前游戏因为 Java 版本过高,无法继续运行。\n你需要下载安装 <a href="https://bell-sw.com/pages/downloads/#downloads">Java 8</a>,并在全局(特定)游戏设置中将 Java 设置为 1.8 的版本。\n你可以在 <a href="https://docs.hmcl.net/help.html ">此处</a> 寻求帮助。
@@ -436,7 +436,7 @@ game.crash.reason.no_class_def_found_error=当前游戏因为代码不完整,
game.crash.reason.no_such_method_error=当前游戏因为代码不完整,无法继续运行。\n你的游戏可能缺失了某个 Mod,或者某些 Mod 文件不完整,或者 Mod 与游戏的版本不匹配。\n你可能需要重新安装游戏和 Mod,或请求他人帮助。 \n你可以在 <a href="https://docs.hmcl.net/help.html ">此处</a> 寻求帮助。
game.crash.reason.opengl_not_supported=当前游戏因为你的显卡驱动存在问题,无法继续运行。\n原因是 OpenGL 不受支持,你现在是否在远程桌面或者串流模式下?如果是,请直接使用原电脑启动游戏。\n或者尝试升级你的显卡驱动到最新版本后再尝试启动游戏。如果你的电脑存在独立显卡,你需要检查游戏是否使用集成/核心显卡启动,如果是,请尝试使用独立显卡启动 HMCL 与游戏。如果仍有问题,你可能需要考虑换一个新显卡或新电脑。 \n你可以在 <a href="https://docs.hmcl.net/help.html ">此处</a> 寻求帮助。
game.crash.reason.openj9=当前游戏无法运行在 OpenJ9 虚拟机上,请你在全局(特定)游戏设置中更换 Hotspot Java 虚拟机,并重新启动游戏。如果没有下载安装,你可以在网上自行下载。 \n你可以在 <a href="https://docs.hmcl.net/help.html ">此处</a> 寻求帮助。
game.crash.reason.out_of_memory=当前游戏因为内存不足,无法继续运行。\n这可能是内存分配太小,或者 Mod 数量过多导致的。\n你可以在全局(特定)游戏设置中调大游戏内存分配值以允许游戏在更大的内存下运行。\n如果仍然出现该错误,你可能需要换一台更好的电脑。 \n你可以在 <a href="https://docs.hmcl.net/help.html ">此处</a> 寻求帮助。
game.crash.reason.out_of_memory=当前游戏因为内存不足,无法继续运行。\n这可能是内存分配太小,或者 Mod 数量过多导致的。\n你可以在全局(特定)游戏设置中调大游戏内存分配值以允许游戏在更大的内存下运行。\n如果仍然出现该错误,你可能需要换一台更好的电脑。 \n你可以在 <a href="https://docs.hmcl.net/help.html ">此处</a> 寻求帮助。
game.crash.reason.resolution_too_high=当前游戏因为材质包分辨率过高,无法继续运行\n你可以更换一个分辨率更低的材质,或者更换一个显存更大的显卡。 \n你可以在 <a href="https://docs.hmcl.net/help.html ">此处</a> 寻求帮助。
game.crash.reason.stacktrace=原因未知,请点击日志按钮查看详细信息。\n下面是一些关键词,其中可能包含 Mod 名称,你可以通过搜索的方式查找有关信息。\n%s
game.crash.reason.too_old_java=当前游戏因为 Java 虚拟机版本过低,无法继续运行。\n你需要在全局(特定)游戏设置中更换 Java %1$s 或更新版本的 Java 虚拟机,并重新启动游戏。如果没有下载安装,你可以点击 <a href="https://bell-sw.com/pages/downloads/#downloads">此处</a> 下载 Liberica JDK。\n你可以在 <a href="https://docs.hmcl.net/help.html ">此处</a> 寻求帮助。
@@ -825,6 +825,8 @@ selector.custom=自定义
settings=设置
settings.advanced=高级设置
settings.advanced.modify=修改高级设置
settings.advanced.title=高级设置 - %s
settings.advanced.custom_commands=自定义命令
settings.advanced.custom_commands.hint=自定义命令被调用时将包含如下的环境变量:\n\
\ - $INST_NAME: 版本名称\n\
@@ -840,6 +842,7 @@ settings.advanced.custom_commands.hint=自定义命令被调用时将包含如
settings.advanced.dont_check_game_completeness=不检查游戏完整性
settings.advanced.dont_check_jvm_validity=不检查 JVM 与游戏的兼容性
settings.advanced.dont_patch_natives=不尝试自动替换本地库
settings.advanced.environment_variables=环境变量
settings.advanced.game_dir.default=默认(.minecraft/)
settings.advanced.game_dir.independent=各版本独立(存放在 .minecraft/versions/<版本名>/,除 assets、libraries 外)
settings.advanced.java_permanent_generation_space=内存永久保存区域
@@ -872,13 +875,17 @@ settings.advanced.process_priority.above_normal=较高(优先保证游戏运
settings.advanced.process_priority.high=高(优先保证游戏运行,但可能会导致其他程序卡顿)
settings.advanced.post_exit_command=游戏结束后执行命令
settings.advanced.post_exit_command.prompt=将在游戏结束后调用
settings.advanced.renderer=渲染器
settings.advanced.renderer.default=OpenGL(默认)
settings.advanced.renderer.d3d12=DirectX 12(性能与兼容性较差,用于调试)
settings.advanced.renderer.llvmpipe=软渲染器(性能较差,兼容性最好)
settings.advanced.renderer.zink=Vulkan(性能最好,兼容性较差)
settings.advanced.server_ip=服务器地址
settings.advanced.server_ip.prompt=默认,启动游戏后可以直接进入对应服务器
settings.advanced.use_native_glfw=[Linux] 使用系统 GLFW
settings.advanced.use_native_openal=[Linux] 使用系统 OpenAL
settings.advanced.use_software_renderer=使用 OpenGL 软渲染器(兼容性更好,但性能较差)
settings.advanced.workaround=调试选项
settings.advanced.workaround.warning=调试选项仅提供给专业玩家使用。调试选项可能会导致游戏无法启动。除非你知道你在做什么,否则请你不要修改这些选项!
settings.advanced.workaround.warning=调试选项仅提供给专业玩家使用。调试选项可能会导致游戏无法启动。除非你知道你在做什么,否则请不要修改这些选项!
settings.advanced.wrapper_launcher=包装命令
settings.advanced.wrapper_launcher.prompt=如填写 optirun 后,启动命令将从 "java ..." 变为 "optirun java ..."
+38 -14
View File
@@ -1530,6 +1530,30 @@
"size": 12964773
}
}
},
"mesa-loader": {
"name": "org.glavo:mesa-loader-windows:0.2.0:x64",
"downloads": {
"artifact": {
"path": "org/glavo/mesa-loader-windows/0.2.0/mesa-loader-windows-0.2.0-x64.jar",
"url": "https://repo1.maven.org/maven2/org/glavo/mesa-loader-windows/0.2.0/mesa-loader-windows-0.2.0-x64.jar",
"sha1": "adb4a16ecb95c8944a016829b05d70f934ea1a29",
"size": 22823052
}
}
}
},
"windows-x86": {
"mesa-loader": {
"name": "org.glavo:mesa-loader-windows:0.2.0:x86",
"downloads": {
"artifact": {
"path": "org/glavo/mesa-loader-windows/0.2.0/mesa-loader-windows-0.2.0-x86.jar",
"url": "https://repo1.maven.org/maven2/org/glavo/mesa-loader-windows/0.2.0/mesa-loader-windows-0.2.0-x86.jar",
"sha1": "93c0b9b7382d984e713d3aa299ceb337fde2897b",
"size": 18273286
}
}
}
},
"windows-arm64": {
@@ -2074,7 +2098,7 @@
"downloads": {
"artifact": {
"path": "org/lwjgl/lwjgl/3.3.1/lwjgl-3.3.1-natives-macos-arm64.jar",
"url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl/3.3.1/lwjgl-3.3.1-natives-macos-arm64.jar",
"url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/3.3.1/lwjgl-3.3.1-natives-macos-arm64.jar",
"sha1": "71d0d5e469c9c95351eb949064497e3391616ac9",
"size": 42693
}
@@ -2096,7 +2120,7 @@
"downloads": {
"artifact": {
"path": "org/lwjgl/lwjgl-jemalloc/3.3.1/lwjgl-jemalloc-3.3.1-natives-macos-arm64.jar",
"url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-jemalloc/3.3.1/lwjgl-jemalloc-3.3.1-natives-macos-arm64.jar",
"url": "https://libraries.minecraft.net/org/lwjgl/lwjgl-jemalloc/3.3.1/lwjgl-jemalloc-3.3.1-natives-macos-arm64.jar",
"sha1": "e577b87d8ad2ade361aaea2fcf226c660b15dee8",
"size": 103475
}
@@ -2118,7 +2142,7 @@
"downloads": {
"artifact": {
"path": "org/lwjgl/lwjgl-openal/3.3.1/lwjgl-openal-3.3.1-natives-macos-arm64.jar",
"url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-openal/3.3.1/lwjgl-openal-3.3.1-natives-macos-arm64.jar",
"url": "https://libraries.minecraft.net/org/lwjgl/lwjgl-openal/3.3.1/lwjgl-openal-3.3.1-natives-macos-arm64.jar",
"sha1": "23d55e7490b57495320f6c9e1936d78fd72c4ef8",
"size": 346125
}
@@ -2140,7 +2164,7 @@
"downloads": {
"artifact": {
"path": "org/lwjgl/lwjgl-opengl/3.3.1/lwjgl-opengl-3.3.1-natives-macos-arm64.jar",
"url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-opengl/3.3.1/lwjgl-opengl-3.3.1-natives-macos-arm64.jar",
"url": "https://libraries.minecraft.net/org/lwjgl/lwjgl-opengl/3.3.1/lwjgl-opengl-3.3.1-natives-macos-arm64.jar",
"sha1": "eafe34b871d966292e8db0f1f3d6b8b110d4e91d",
"size": 41665
}
@@ -2162,7 +2186,7 @@
"downloads": {
"artifact": {
"path": "org/lwjgl/lwjgl-glfw/3.3.1/lwjgl-glfw-3.3.1-natives-macos-arm64.jar",
"url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-glfw/3.3.1/lwjgl-glfw-3.3.1-natives-macos-arm64.jar",
"url": "https://libraries.minecraft.net/org/lwjgl/lwjgl-glfw/3.3.1/lwjgl-glfw-3.3.1-natives-macos-arm64.jar",
"sha1": "cac0d3f712a3da7641fa174735a5f315de7ffe0a",
"size": 129077
}
@@ -2184,7 +2208,7 @@
"downloads": {
"artifact": {
"path": "org/lwjgl/lwjgl-stb/3.3.1/lwjgl-stb-3.3.1-natives-macos-arm64.jar",
"url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-stb/3.3.1/lwjgl-stb-3.3.1-natives-macos-arm64.jar",
"url": "https://libraries.minecraft.net/org/lwjgl/lwjgl-stb/3.3.1/lwjgl-stb-3.3.1-natives-macos-arm64.jar",
"sha1": "fcf073ed911752abdca5f0b00a53cfdf17ff8e8b",
"size": 178408
}
@@ -2206,7 +2230,7 @@
"downloads": {
"artifact": {
"path": "org/lwjgl/lwjgl-tinyfd/3.3.1/lwjgl-tinyfd-3.3.1-natives-macos-arm64.jar",
"url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-tinyfd/3.3.1/lwjgl-tinyfd-3.3.1-natives-macos-arm64.jar",
"url": "https://libraries.minecraft.net/org/lwjgl/lwjgl-tinyfd/3.3.1/lwjgl-tinyfd-3.3.1-natives-macos-arm64.jar",
"sha1": "972ecc17bad3571e81162153077b4d47b7b9eaa9",
"size": 41380
}
@@ -2228,7 +2252,7 @@
"downloads": {
"artifact": {
"path": "org/lwjgl/lwjgl/3.3.1/lwjgl-3.3.1-natives-macos-arm64.jar",
"url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl/3.3.1/lwjgl-3.3.1-natives-macos-arm64.jar",
"url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/3.3.1/lwjgl-3.3.1-natives-macos-arm64.jar",
"sha1": "71d0d5e469c9c95351eb949064497e3391616ac9",
"size": 42693
}
@@ -2250,7 +2274,7 @@
"downloads": {
"artifact": {
"path": "org/lwjgl/lwjgl-jemalloc/3.3.1/lwjgl-jemalloc-3.3.1-natives-macos-arm64.jar",
"url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-jemalloc/3.3.1/lwjgl-jemalloc-3.3.1-natives-macos-arm64.jar",
"url": "https://libraries.minecraft.net/org/lwjgl/lwjgl-jemalloc/3.3.1/lwjgl-jemalloc-3.3.1-natives-macos-arm64.jar",
"sha1": "e577b87d8ad2ade361aaea2fcf226c660b15dee8",
"size": 103475
}
@@ -2272,7 +2296,7 @@
"downloads": {
"artifact": {
"path": "org/lwjgl/lwjgl-openal/3.3.1/lwjgl-openal-3.3.1-natives-macos-arm64.jar",
"url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-openal/3.3.1/lwjgl-openal-3.3.1-natives-macos-arm64.jar",
"url": "https://libraries.minecraft.net/org/lwjgl/lwjgl-openal/3.3.1/lwjgl-openal-3.3.1-natives-macos-arm64.jar",
"sha1": "23d55e7490b57495320f6c9e1936d78fd72c4ef8",
"size": 346125
}
@@ -2294,7 +2318,7 @@
"downloads": {
"artifact": {
"path": "org/lwjgl/lwjgl-opengl/3.3.1/lwjgl-opengl-3.3.1-natives-macos-arm64.jar",
"url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-opengl/3.3.1/lwjgl-opengl-3.3.1-natives-macos-arm64.jar",
"url": "https://libraries.minecraft.net/org/lwjgl/lwjgl-opengl/3.3.1/lwjgl-opengl-3.3.1-natives-macos-arm64.jar",
"sha1": "eafe34b871d966292e8db0f1f3d6b8b110d4e91d",
"size": 41665
}
@@ -2316,7 +2340,7 @@
"downloads": {
"artifact": {
"path": "org/lwjgl/lwjgl-glfw/3.3.1/lwjgl-glfw-3.3.1-natives-macos-arm64.jar",
"url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-glfw/3.3.1/lwjgl-glfw-3.3.1-natives-macos-arm64.jar",
"url": "https://libraries.minecraft.net/org/lwjgl/lwjgl-glfw/3.3.1/lwjgl-glfw-3.3.1-natives-macos-arm64.jar",
"sha1": "cac0d3f712a3da7641fa174735a5f315de7ffe0a",
"size": 129077
}
@@ -2338,7 +2362,7 @@
"downloads": {
"artifact": {
"path": "org/lwjgl/lwjgl-stb/3.3.1/lwjgl-stb-3.3.1-natives-macos-arm64.jar",
"url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-stb/3.3.1/lwjgl-stb-3.3.1-natives-macos-arm64.jar",
"url": "https://libraries.minecraft.net/org/lwjgl/lwjgl-stb/3.3.1/lwjgl-stb-3.3.1-natives-macos-arm64.jar",
"sha1": "fcf073ed911752abdca5f0b00a53cfdf17ff8e8b",
"size": 178408
}
@@ -2360,7 +2384,7 @@
"downloads": {
"artifact": {
"path": "org/lwjgl/lwjgl-tinyfd/3.3.1/lwjgl-tinyfd-3.3.1-natives-macos-arm64.jar",
"url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-tinyfd/3.3.1/lwjgl-tinyfd-3.3.1-natives-macos-arm64.jar",
"url": "https://libraries.minecraft.net/org/lwjgl/lwjgl-tinyfd/3.3.1/lwjgl-tinyfd-3.3.1-natives-macos-arm64.jar",
"sha1": "972ecc17bad3571e81162153077b4d47b7b9eaa9",
"size": 41380
}
+6 -9
View File
@@ -4,16 +4,13 @@ plugins {
dependencies {
api("org.glavo:simple-png-javafx:0.3.0")
api("com.google.code.gson:gson:2.8.1")
api("com.google.code.gson:gson:2.10.1")
api("com.moandjiezana.toml:toml4j:0.7.2")
api("org.tukaani:xz:1.8")
api("org.hildan.fxgson:fx-gson:3.1.0") {
exclude(group = "org.jetbrains", module = "annotations")
}
api("org.tukaani:xz:1.9")
api("org.hildan.fxgson:fx-gson:5.0.0")
api("org.jenkins-ci:constant-pool-scanner:1.2")
api("com.github.steveice10:opennbt:1.1")
api("com.nqzero:permit-reflect:0.3")
api("com.github.steveice10:opennbt:1.4")
api("org.nanohttpd:nanohttpd:2.3.1")
api("org.apache.commons:commons-compress:1.21")
compileOnlyApi("org.jetbrains:annotations:16.0.3")
api("org.apache.commons:commons-compress:1.22")
compileOnlyApi("org.jetbrains:annotations:24.0.0")
}
@@ -31,8 +31,7 @@ public final class EventBus {
@SuppressWarnings("unchecked")
public <T extends Event> EventManager<T> channel(Class<T> clazz) {
events.putIfAbsent(clazz, new EventManager<>());
return (EventManager<T>) events.get(clazz);
return (EventManager<T>) events.computeIfAbsent(clazz, ignored -> new EventManager<>());
}
@SuppressWarnings("unchecked")
@@ -23,9 +23,7 @@ import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.Serializable;
import java.net.Proxy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.*;
/**
*
@@ -42,6 +40,7 @@ public class LaunchOptions implements Serializable {
private final List<String> overrideJavaArguments = new ArrayList<>();
private final List<String> javaArguments = new ArrayList<>();
private final List<String> javaAgents = new ArrayList<>(0);
private final Map<String, String> environmentVariables = new LinkedHashMap<>();
private Integer minMemory;
private Integer maxMemory;
private Integer metaspace;
@@ -59,7 +58,7 @@ public class LaunchOptions implements Serializable {
private NativesDirectoryType nativesDirType;
private String nativesDir;
private ProcessPriority processPriority = ProcessPriority.NORMAL;
private boolean useSoftwareRenderer;
private Renderer renderer = Renderer.DEFAULT;
private boolean useNativeGLFW;
private boolean useNativeOpenAL;
private boolean daemon;
@@ -130,6 +129,10 @@ public class LaunchOptions implements Serializable {
return Collections.unmodifiableList(javaAgents);
}
public Map<String, String> getEnvironmentVariables() {
return environmentVariables;
}
/**
* The minimum memory that the JVM can allocate.
*/
@@ -252,8 +255,8 @@ public class LaunchOptions implements Serializable {
return processPriority;
}
public boolean isUseSoftwareRenderer() {
return useSoftwareRenderer;
public Renderer getRenderer() {
return renderer;
}
public boolean isUseNativeGLFW() {
@@ -279,43 +282,6 @@ public class LaunchOptions implements Serializable {
return options;
}
/**
* The game directory
*/
public File getGameDir() {
return options.gameDir;
}
/**
* The Java Environment that Minecraft runs on.
*/
public JavaVersion getJava() {
return options.java;
}
/**
* Will shown in the left bottom corner of the main menu of Minecraft.
* null if use the id of launch version.
*/
public String getVersionName() {
return options.versionName;
}
/**
* Will shown in the left bottom corner of the main menu of Minecraft.
* null if use Version.versionType.
*/
public String getVersionType() {
return options.versionType;
}
/**
* Don't know what the hell this is.
*/
public String getProfileName() {
return options.profileName;
}
/**
* User custom additional minecraft command line arguments.
*/
@@ -341,123 +307,6 @@ public class LaunchOptions implements Serializable {
return options.javaAgents;
}
/**
* The minimum memory that the JVM can allocate.
*/
public Integer getMinMemory() {
return options.minMemory;
}
/**
* The maximum memory that the JVM can allocate.
*/
public Integer getMaxMemory() {
return options.maxMemory;
}
/**
* The maximum metaspace memory that the JVM can allocate.
* For Java 7 -XX:PermSize and Java 8 -XX:MetaspaceSize
* Containing class instances.
*/
public Integer getMetaspace() {
return options.metaspace;
}
/**
* The initial game window width
*/
public Integer getWidth() {
return options.width;
}
/**
* The initial game window height
*/
public Integer getHeight() {
return options.height;
}
/**
* Is inital game window fullscreen.
*/
public boolean isFullscreen() {
return options.fullscreen;
}
/**
* The server ip that will connect to when enter game main menu.
*/
public String getServerIp() {
return options.serverIp;
}
/**
* i.e. optirun
*/
public String getWrapper() {
return options.wrapper;
}
/**
* Proxy settings
*/
public Proxy getProxy() {
return options.proxy;
}
/**
* The user name of the proxy, optional.
*/
public String getProxyUser() {
return options.proxyUser;
}
/**
* The password of the proxy, optional
*/
public String getProxyPass() {
return options.proxyPass;
}
/**
* Prevent game launcher from generating default JVM arguments like max memory.
*/
public boolean isNoGeneratedJVMArgs() {
return options.noGeneratedJVMArgs;
}
/**
* Called command line before launching the game.
*/
public String getPreLaunchCommand() {
return options.preLaunchCommand;
}
public NativesDirectoryType getNativesDirType() {
return options.nativesDirType;
}
public String getNativesDir() {
return options.nativesDir;
}
public boolean isUseSoftwareRenderer() {
return options.useSoftwareRenderer;
}
public boolean isUseNativeGLFW() {
return options.useNativeGLFW;
}
public boolean isUseNativeOpenAL() {
return options.useNativeOpenAL;
}
public boolean isDaemon() {
return options.daemon;
}
public Builder setGameDir(File gameDir) {
options.gameDir = gameDir;
return this;
@@ -507,6 +356,12 @@ public class LaunchOptions implements Serializable {
return this;
}
public Builder setEnvironmentVariables(Map<String, String> env) {
options.environmentVariables.clear();
options.environmentVariables.putAll(env);
return this;
}
public Builder setMinMemory(Integer minMemory) {
options.minMemory = minMemory;
return this;
@@ -592,8 +447,8 @@ public class LaunchOptions implements Serializable {
return this;
}
public Builder setUseSoftwareRenderer(boolean useSoftwareRenderer) {
options.useSoftwareRenderer = useSoftwareRenderer;
public Builder setRenderer(@NotNull Renderer renderer) {
options.renderer = renderer;
return this;
}
@@ -0,0 +1,8 @@
package org.jackhuang.hmcl.game;
public enum Renderer {
DEFAULT,
ZINK,
LLVMPIPE,
D3D12
}
@@ -462,16 +462,29 @@ public class DefaultLauncher extends Launcher {
private Map<String, String> getEnvVars() {
String versionName = Optional.ofNullable(options.getVersionName()).orElse(version.getId());
Map<String, String> env = new HashMap<>();
Map<String, String> env = new LinkedHashMap<>();
env.put("INST_NAME", versionName);
env.put("INST_ID", versionName);
env.put("INST_DIR", repository.getVersionRoot(version.getId()).getAbsolutePath());
env.put("INST_MC_DIR", repository.getRunDirectory(version.getId()).getAbsolutePath());
env.put("INST_JAVA", options.getJava().getBinary().toString());
if (options.isUseSoftwareRenderer() && OperatingSystem.CURRENT_OS == OperatingSystem.LINUX) {
env.put("LIBGL_ALWAYS_SOFTWARE", "1");
env.put("__GLX_VENDOR_LIBRARY_NAME", "mesa");
Renderer renderer = options.getRenderer();
if (renderer != Renderer.DEFAULT) {
if (OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS) {
if (renderer != Renderer.LLVMPIPE)
env.put("GALLIUM_DRIVER", renderer.name().toLowerCase(Locale.ROOT));
} else if (OperatingSystem.CURRENT_OS == OperatingSystem.LINUX) {
env.put("__GLX_VENDOR_LIBRARY_NAME", "mesa");
switch (renderer) {
case LLVMPIPE:
env.put("LIBGL_ALWAYS_SOFTWARE", "1");
break;
case ZINK:
env.put("MESA_LOADER_DRIVER_OVERRIDE", "zink");
break;
}
}
}
LibraryAnalyzer analyzer = LibraryAnalyzer.analyze(version);
@@ -490,6 +503,9 @@ public class DefaultLauncher extends Launcher {
if (analyzer.has(LibraryAnalyzer.LibraryType.QUILT)) {
env.put("INST_QUILT", "1");
}
env.putAll(options.getEnvironmentVariables());
return env;
}
Binary file not shown.
+1 -1
View File
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-bin.zip
networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Vendored
+2 -2
View File
@@ -144,7 +144,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
# shellcheck disable=SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
@@ -152,7 +152,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
# shellcheck disable=SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac