Merge commit '9bef8b432b9095bdb470f7a1e7c1ce8fcab37c01' into javafx

This commit is contained in:
huanghongxun
2021-08-28 16:41:29 +08:00
8 changed files with 115 additions and 77 deletions

View File

@@ -1,6 +1,6 @@
/* /*
* Hello Minecraft! Launcher * Hello Minecraft! Launcher
* Copyright (C) 2020 huangyuhui <huanghongxun2008@126.com> and contributors * Copyright (C) 2021 huangyuhui <huanghongxun2008@126.com> and contributors
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -20,14 +20,13 @@ package org.jackhuang.hmcl.game;
import javafx.beans.binding.Bindings; import javafx.beans.binding.Bindings;
import javafx.beans.binding.ObjectBinding; import javafx.beans.binding.ObjectBinding;
import javafx.scene.image.Image; import javafx.scene.image.Image;
import javafx.scene.image.PixelWriter;
import javafx.scene.image.WritableImage;
import org.jackhuang.hmcl.Metadata; import org.jackhuang.hmcl.Metadata;
import org.jackhuang.hmcl.auth.Account; import org.jackhuang.hmcl.auth.Account;
import org.jackhuang.hmcl.auth.ServerResponseMalformedException; import org.jackhuang.hmcl.auth.ServerResponseMalformedException;
import org.jackhuang.hmcl.auth.microsoft.MicrosoftAccount; import org.jackhuang.hmcl.auth.microsoft.MicrosoftAccount;
import org.jackhuang.hmcl.auth.yggdrasil.*; import org.jackhuang.hmcl.auth.yggdrasil.*;
import org.jackhuang.hmcl.task.FileDownloadTask; import org.jackhuang.hmcl.task.FileDownloadTask;
import org.jackhuang.hmcl.ui.FXUtils;
import org.jackhuang.hmcl.util.ResourceNotFoundError; import org.jackhuang.hmcl.util.ResourceNotFoundError;
import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.StringUtils;
import org.jackhuang.hmcl.util.javafx.BindingMapping; import org.jackhuang.hmcl.util.javafx.BindingMapping;
@@ -231,34 +230,18 @@ public final class TexturesLoader {
public static ObjectBinding<Image> fxAvatarBinding(YggdrasilService service, UUID uuid, int size) { public static ObjectBinding<Image> fxAvatarBinding(YggdrasilService service, UUID uuid, int size) {
return BindingMapping.of(skinBinding(service, uuid)) return BindingMapping.of(skinBinding(service, uuid))
.map(it -> toAvatar(it.image, size)) .map(it -> toAvatar(it.image, size))
.map(TexturesLoader::toFXImage); .map(FXUtils::toFXImage);
} }
public static ObjectBinding<Image> fxAvatarBinding(Account account, int size) { public static ObjectBinding<Image> fxAvatarBinding(Account account, int size) {
if (account instanceof YggdrasilAccount || account instanceof MicrosoftAccount) { if (account instanceof YggdrasilAccount || account instanceof MicrosoftAccount) {
return BindingMapping.of(skinBinding(account)) return BindingMapping.of(skinBinding(account))
.map(it -> toAvatar(it.image, size)) .map(it -> toAvatar(it.image, size))
.map(TexturesLoader::toFXImage); .map(FXUtils::toFXImage);
} else { } else {
return Bindings.createObjectBinding( return Bindings.createObjectBinding(
() -> toFXImage(toAvatar(getDefaultSkin(TextureModel.detectUUID(account.getUUID())).image, size))); () -> FXUtils.toFXImage(toAvatar(getDefaultSkin(TextureModel.detectUUID(account.getUUID())).image, size)));
} }
} }
// ==== // ====
// Based on https://stackoverflow.com/a/57552025
// Fix #874: Use it instead of SwingFXUtils.toFXImage
private static WritableImage toFXImage(BufferedImage image) {
WritableImage wr = new WritableImage(image.getWidth(), image.getHeight());
PixelWriter pw = wr.getPixelWriter();
final int iw = image.getWidth();
final int ih = image.getHeight();
for (int x = 0; x < iw; x++) {
for (int y = 0; y < ih; y++) {
pw.setArgb(x, y, image.getRGB(x, y));
}
}
return wr;
}
} }

View File

@@ -38,6 +38,8 @@ import javafx.scene.Node;
import javafx.scene.control.*; import javafx.scene.control.*;
import javafx.scene.image.Image; import javafx.scene.image.Image;
import javafx.scene.image.ImageView; import javafx.scene.image.ImageView;
import javafx.scene.image.PixelWriter;
import javafx.scene.image.WritableImage;
import javafx.scene.input.KeyCode; import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent; import javafx.scene.input.KeyEvent;
import javafx.scene.input.TransferMode; import javafx.scene.input.TransferMode;
@@ -55,6 +57,7 @@ import org.jackhuang.hmcl.util.javafx.ExtendedProperties;
import org.jackhuang.hmcl.util.javafx.SafeStringConverter; import org.jackhuang.hmcl.util.javafx.SafeStringConverter;
import org.jackhuang.hmcl.util.platform.OperatingSystem; import org.jackhuang.hmcl.util.platform.OperatingSystem;
import java.awt.image.BufferedImage;
import java.io.File; import java.io.File;
import java.io.FileFilter; import java.io.FileFilter;
import java.io.IOException; import java.io.IOException;
@@ -552,4 +555,20 @@ public final class FXUtils {
} }
}); });
} }
// Based on https://stackoverflow.com/a/57552025
// Fix #874: Use it instead of SwingFXUtils.toFXImage
public static WritableImage toFXImage(BufferedImage image) {
WritableImage wr = new WritableImage(image.getWidth(), image.getHeight());
PixelWriter pw = wr.getPixelWriter();
final int iw = image.getWidth();
final int ih = image.getHeight();
for (int x = 0; x < iw; x++) {
for (int y = 0; y < ih; y++) {
pw.setArgb(x, y, image.getRGB(x, y));
}
}
return wr;
}
} }

View File

@@ -1,6 +1,6 @@
/* /*
* Hello Minecraft! Launcher * Hello Minecraft! Launcher
* Copyright (C) 2020 huangyuhui <huanghongxun2008@126.com> and contributors * Copyright (C) 2021 huangyuhui <huanghongxun2008@126.com> and contributors
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -20,6 +20,7 @@ package org.jackhuang.hmcl.ui.account;
import javafx.beans.binding.Bindings; import javafx.beans.binding.Bindings;
import javafx.beans.property.ObjectProperty; import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
import javafx.scene.Node; import javafx.scene.Node;
import javafx.scene.control.Tooltip; import javafx.scene.control.Tooltip;
@@ -27,14 +28,19 @@ import javafx.scene.image.ImageView;
import org.jackhuang.hmcl.auth.Account; import org.jackhuang.hmcl.auth.Account;
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccount; import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccount;
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer; import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer;
import org.jackhuang.hmcl.auth.yggdrasil.TextureModel;
import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount; import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount;
import org.jackhuang.hmcl.game.TexturesLoader; import org.jackhuang.hmcl.game.TexturesLoader;
import org.jackhuang.hmcl.setting.Accounts; import org.jackhuang.hmcl.setting.Accounts;
import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.FXUtils;
import org.jackhuang.hmcl.ui.construct.AdvancedListItem; import org.jackhuang.hmcl.ui.construct.AdvancedListItem;
import org.jackhuang.hmcl.util.Pair; import org.jackhuang.hmcl.util.Pair;
import org.jackhuang.hmcl.util.javafx.BindingMapping;
import static org.jackhuang.hmcl.ui.FXUtils.newImage; import static javafx.beans.binding.Bindings.createStringBinding;
import static org.jackhuang.hmcl.setting.Accounts.getAccountFactory;
import static org.jackhuang.hmcl.setting.Accounts.getLocalizedLoginTypeName;
import static org.jackhuang.hmcl.ui.FXUtils.toFXImage;
import static org.jackhuang.hmcl.util.i18n.I18n.i18n; import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
public class AccountAdvancedListItem extends AdvancedListItem { public class AccountAdvancedListItem extends AdvancedListItem {
@@ -48,16 +54,18 @@ public class AccountAdvancedListItem extends AdvancedListItem {
Account account = get(); Account account = get();
if (account == null) { if (account == null) {
titleProperty().unbind(); titleProperty().unbind();
subtitleProperty().unbind();
imageView.imageProperty().unbind();
tooltip.textProperty().unbind();
setTitle(i18n("account.missing")); setTitle(i18n("account.missing"));
setSubtitle(i18n("account.missing.add")); setSubtitle(i18n("account.missing.add"));
imageView.imageProperty().unbind(); imageView.setImage(toFXImage(TexturesLoader.toAvatar(TexturesLoader.getDefaultSkin(TextureModel.STEVE).getImage(), 32)));
imageView.setImage(newImage("/assets/img/steve.png")); tooltip.setText(i18n("account.create"));
tooltip.setText("");
} else { } else {
titleProperty().bind(Bindings.createStringBinding(account::getCharacter, account)); titleProperty().bind(BindingMapping.of(account, Account::getCharacter));
setSubtitle(accountSubtitle(account)); subtitleProperty().bind(accountSubtitle(account));
imageView.imageProperty().bind(TexturesLoader.fxAvatarBinding(account, 32)); imageView.imageProperty().bind(TexturesLoader.fxAvatarBinding(account, 32));
tooltip.setText(account.getCharacter() + " " + accountTooltip(account)); tooltip.textProperty().bind(accountTooltip(account));
} }
} }
}; };
@@ -88,23 +96,27 @@ public class AccountAdvancedListItem extends AdvancedListItem {
return account; return account;
} }
private static String accountSubtitle(Account account) { private static ObservableValue<String> accountSubtitle(Account account) {
String loginTypeName = Accounts.getLocalizedLoginTypeName(Accounts.getAccountFactory(account));
if (account instanceof AuthlibInjectorAccount) { if (account instanceof AuthlibInjectorAccount) {
return ((AuthlibInjectorAccount) account).getServer().getName(); return BindingMapping.of(((AuthlibInjectorAccount) account).getServer(), AuthlibInjectorServer::getName);
} else { } else {
return loginTypeName; return createStringBinding(() -> getLocalizedLoginTypeName(getAccountFactory(account)));
} }
} }
private static String accountTooltip(Account account) { private static ObservableValue<String> accountTooltip(Account account) {
if (account instanceof AuthlibInjectorAccount) { if (account instanceof AuthlibInjectorAccount) {
AuthlibInjectorServer server = ((AuthlibInjectorAccount) account).getServer(); AuthlibInjectorServer server = ((AuthlibInjectorAccount) account).getServer();
return account.getUsername() + ", " + i18n("account.injector.server") + ": " + server.getName(); return Bindings.format("%s (%s) (%s)",
BindingMapping.of(account, Account::getCharacter),
account.getUsername(),
BindingMapping.of(server, AuthlibInjectorServer::getName));
} else if (account instanceof YggdrasilAccount) { } else if (account instanceof YggdrasilAccount) {
return account.getUsername(); return Bindings.format("%s (%s)",
BindingMapping.of(account, Account::getCharacter),
account.getUsername());
} else { } else {
return ""; return BindingMapping.of(account, Account::getCharacter);
} }
} }

View File

@@ -57,6 +57,7 @@ import static java.util.logging.Level.WARNING;
import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toList;
import static org.jackhuang.hmcl.setting.ConfigHolder.config; import static org.jackhuang.hmcl.setting.ConfigHolder.config;
import static org.jackhuang.hmcl.ui.FXUtils.newImage; import static org.jackhuang.hmcl.ui.FXUtils.newImage;
import static org.jackhuang.hmcl.ui.FXUtils.onEscPressed;
import static org.jackhuang.hmcl.util.Logging.LOG; import static org.jackhuang.hmcl.util.Logging.LOG;
import static org.jackhuang.hmcl.util.io.FileUtils.getExtension; import static org.jackhuang.hmcl.util.io.FileUtils.getExtension;
@@ -86,33 +87,39 @@ public class DecoratorController {
setupAuthlibInjectorDnD(); setupAuthlibInjectorDnD();
// pass key events to current dialog // pass key events to current dialog / current page
decorator.addEventFilter(KeyEvent.ANY, e -> { decorator.addEventFilter(KeyEvent.ANY, e -> {
if (dialogPane == null || !dialogPane.peek().isPresent()) {
return;
}
Node currentDialog = dialogPane.peek().get();
if (!(e.getTarget() instanceof Node)) { if (!(e.getTarget() instanceof Node)) {
return; return; // event source can't be determined
} }
boolean targetInDialog = false; Node newTarget;
if (dialogPane != null && dialogPane.peek().isPresent()) {
newTarget = dialogPane.peek().get(); // current dialog
} else {
newTarget = navigator.getCurrentPage(); // current page
}
boolean needsRedirect = true;
Node t = (Node) e.getTarget(); Node t = (Node) e.getTarget();
while (t != null) { while (t != null) {
if (t == currentDialog) { if (t == newTarget) {
targetInDialog = true; // current event target is in newTarget
needsRedirect = false;
break; break;
} }
t = t.getParent(); t = t.getParent();
} }
if (targetInDialog) { if (!needsRedirect) {
return; return;
} }
e.consume(); e.consume();
currentDialog.fireEvent(e.copyFor(e.getSource(), currentDialog)); newTarget.fireEvent(e.copyFor(e.getSource(), newTarget));
}); });
// press ESC to go back
onEscPressed(navigator, this::back);
} }
public Decorator getDecorator() { public Decorator getDecorator() {
@@ -229,10 +236,15 @@ public class DecoratorController {
if (navigator.getCurrentPage() instanceof DecoratorPage) { if (navigator.getCurrentPage() instanceof DecoratorPage) {
DecoratorPage page = (DecoratorPage) navigator.getCurrentPage(); DecoratorPage page = (DecoratorPage) navigator.getCurrentPage();
if (page.back()) if (page.back()) {
navigator.close(); if (navigator.canGoBack()) {
navigator.close();
}
}
} else { } else {
navigator.close(); if (navigator.canGoBack()) {
navigator.close();
}
} }
} }

View File

@@ -1,6 +1,6 @@
/* /*
* Hello Minecraft! Launcher * Hello Minecraft! Launcher
* Copyright (C) 2020 huangyuhui <huanghongxun2008@126.com> and contributors * Copyright (C) 2021 huangyuhui <huanghongxun2008@126.com> and contributors
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -66,7 +66,8 @@ public class RootPage extends DecoratorTabPage {
public RootPage() { public RootPage() {
setLeftPaneWidth(200); setLeftPaneWidth(200);
EventBus.EVENT_BUS.channel(RefreshedVersionsEvent.class).register(event -> onRefreshedVersions((HMCLGameRepository) event.getSource())); EventBus.EVENT_BUS.channel(RefreshedVersionsEvent.class)
.register(event -> onRefreshedVersions((HMCLGameRepository) event.getSource()));
Profile profile = Profiles.getSelectedProfile(); Profile profile = Profiles.getSelectedProfile();
if (profile != null && profile.getRepository().isLoaded()) if (profile != null && profile.getRepository().isLoaded())
@@ -78,7 +79,8 @@ public class RootPage extends DecoratorTabPage {
@Override @Override
public boolean back() { public boolean back() {
if (mainTab.isSelected()) return true; if (mainTab.isSelected())
return true;
else { else {
getSelectionModel().select(mainTab); getSelectionModel().select(mainTab);
return false; return false;
@@ -102,20 +104,23 @@ public class RootPage extends DecoratorTabPage {
MainPage mainPage = new MainPage(); MainPage mainPage = new MainPage();
FXUtils.applyDragListener(mainPage, it -> "zip".equals(FileUtils.getExtension(it)), modpacks -> { FXUtils.applyDragListener(mainPage, it -> "zip".equals(FileUtils.getExtension(it)), modpacks -> {
File modpack = modpacks.get(0); File modpack = modpacks.get(0);
Controllers.getDecorator().startWizard(new ModpackInstallWizardProvider(Profiles.getSelectedProfile(), modpack), i18n("install.modpack")); Controllers.getDecorator().startWizard(
new ModpackInstallWizardProvider(Profiles.getSelectedProfile(), modpack),
i18n("install.modpack"));
}); });
FXUtils.onChangeAndOperate(Profiles.selectedVersionProperty(), mainPage::setCurrentGame); FXUtils.onChangeAndOperate(Profiles.selectedVersionProperty(), mainPage::setCurrentGame);
mainPage.showUpdateProperty().bind(UpdateChecker.outdatedProperty()); mainPage.showUpdateProperty().bind(UpdateChecker.outdatedProperty());
mainPage.latestVersionProperty().bind( mainPage.latestVersionProperty().bind(BindingMapping.of(UpdateChecker.latestVersionProperty())
BindingMapping.of(UpdateChecker.latestVersionProperty()) .map(version -> version == null ? "" : i18n("update.bubble.title", version.getVersion())));
.map(version -> version == null ? "" : i18n("update.bubble.title", version.getVersion())));
Profiles.registerVersionsListener(profile -> { Profiles.registerVersionsListener(profile -> {
HMCLGameRepository repository = profile.getRepository(); HMCLGameRepository repository = profile.getRepository();
List<Version> children = repository.getVersions().parallelStream() List<Version> children = repository.getVersions().parallelStream()
.filter(version -> !version.isHidden()) .filter(version -> !version.isHidden())
.sorted(Comparator.comparing((Version version) -> version.getReleaseTime() == null ? new Date(0L) : version.getReleaseTime()) .sorted(Comparator
.comparing((Version version) -> version.getReleaseTime() == null ? new Date(0L)
: version.getReleaseTime())
.thenComparing(a -> VersionNumber.asVersion(a.getId()))) .thenComparing(a -> VersionNumber.asVersion(a.getId())))
.collect(Collectors.toList()); .collect(Collectors.toList());
runInFX(() -> { runInFX(() -> {
@@ -135,7 +140,13 @@ public class RootPage extends DecoratorTabPage {
// first item in left sidebar // first item in left sidebar
AccountAdvancedListItem accountListItem = new AccountAdvancedListItem(); AccountAdvancedListItem accountListItem = new AccountAdvancedListItem();
accountListItem.setOnAction(e -> Controllers.navigate(Controllers.getAccountListPage())); accountListItem.setOnAction(e -> {
Controllers.navigate(Controllers.getAccountListPage());
if (Accounts.getAccounts().isEmpty()) {
Controllers.dialog(new AddAccountPane());
}
});
accountListItem.accountProperty().bind(Accounts.selectedAccountProperty()); accountListItem.accountProperty().bind(Accounts.selectedAccountProperty());
// second item in left sidebar // second item in left sidebar
@@ -158,20 +169,16 @@ public class RootPage extends DecoratorTabPage {
// fifth item in left sidebar // fifth item in left sidebar
AdvancedListItem launcherSettingsItem = new AdvancedListItem(); AdvancedListItem launcherSettingsItem = new AdvancedListItem();
launcherSettingsItem.setLeftGraphic(AdvancedListItem.createImageView(newImage("/assets/img/command.png")).getKey()); launcherSettingsItem
.setLeftGraphic(AdvancedListItem.createImageView(newImage("/assets/img/command.png")).getKey());
launcherSettingsItem.setActionButtonVisible(false); launcherSettingsItem.setActionButtonVisible(false);
launcherSettingsItem.setTitle(i18n("settings.launcher")); launcherSettingsItem.setTitle(i18n("settings.launcher"));
launcherSettingsItem.setOnAction(e -> Controllers.navigate(Controllers.getSettingsPage())); launcherSettingsItem.setOnAction(e -> Controllers.navigate(Controllers.getSettingsPage()));
// the left sidebar // the left sidebar
AdvancedListBox sideBar = new AdvancedListBox() AdvancedListBox sideBar = new AdvancedListBox().startCategory(i18n("account").toUpperCase())
.startCategory(i18n("account").toUpperCase()) .add(accountListItem).startCategory(i18n("version").toUpperCase()).add(gameListItem).add(gameItem)
.add(accountListItem) .startCategory(i18n("launcher").toUpperCase()).add(launcherSettingsItem);
.startCategory(i18n("version").toUpperCase())
.add(gameListItem)
.add(gameItem)
.startCategory(i18n("launcher").toUpperCase())
.add(launcherSettingsItem);
// the root page, with the sidebar in left, navigator in center. // the root page, with the sidebar in left, navigator in center.
BorderPane root = new BorderPane(); BorderPane root = new BorderPane();
@@ -195,7 +202,8 @@ public class RootPage extends DecoratorTabPage {
private boolean checkedAccont = false; private boolean checkedAccont = false;
public void checkAccount() { public void checkAccount() {
if (checkedAccont) return; if (checkedAccont)
return;
checkedAccont = true; checkedAccont = true;
if (Accounts.getAccounts().isEmpty()) if (Accounts.getAccounts().isEmpty())
Platform.runLater(this::addNewAccount); Platform.runLater(this::addNewAccount);
@@ -217,8 +225,11 @@ public class RootPage extends DecoratorTabPage {
File modpackFile = new File("modpack.zip").getAbsoluteFile(); File modpackFile = new File("modpack.zip").getAbsoluteFile();
if (modpackFile.exists()) { if (modpackFile.exists()) {
Task.supplyAsync(() -> CompressingUtils.findSuitableEncoding(modpackFile.toPath())) Task.supplyAsync(() -> CompressingUtils.findSuitableEncoding(modpackFile.toPath()))
.thenApplyAsync(encoding -> ModpackHelper.readModpackManifest(modpackFile.toPath(), encoding)) .thenApplyAsync(
.thenApplyAsync(modpack -> ModpackHelper.getInstallTask(repository.getProfile(), modpackFile, modpack.getName(), modpack) encoding -> ModpackHelper.readModpackManifest(modpackFile.toPath(), encoding))
.thenApplyAsync(modpack -> ModpackHelper
.getInstallTask(repository.getProfile(), modpackFile, modpack.getName(),
modpack)
.withRunAsync(Schedulers.javafx(), this::checkAccount).executor()) .withRunAsync(Schedulers.javafx(), this::checkAccount).executor())
.thenAcceptAsync(Schedulers.javafx(), executor -> { .thenAcceptAsync(Schedulers.javafx(), executor -> {
Controllers.taskDialog(executor, i18n("modpack.installing")); Controllers.taskDialog(executor, i18n("modpack.installing"));

View File

@@ -88,7 +88,7 @@ public final class SelfDependencyPatcher {
static class DependencyDescriptor { static class DependencyDescriptor {
private static final String REPOSITORY_URL = "https://maven.aliyun.com/repository/central/"; private static final String REPOSITORY_URL = System.getProperty("hmcl.openjfx.repo", "https://maven.aliyun.com/repository/central/");
private static final Path DEPENDENCIES_DIR_PATH = HMCL_DIRECTORY.resolve("dependencies"); private static final Path DEPENDENCIES_DIR_PATH = HMCL_DIRECTORY.resolve("dependencies");
private static String currentArchClassifier() { private static String currentArchClassifier() {

View File

@@ -55,7 +55,7 @@ public class LaunchOptions implements Serializable {
private String preLaunchCommand; private String preLaunchCommand;
private NativesDirectoryType nativesDirType; private NativesDirectoryType nativesDirType;
private String nativesDir; private String nativesDir;
private ProcessPriority processPriority; private ProcessPriority processPriority = ProcessPriority.NORMAL;
/** /**
* The game directory * The game directory
@@ -497,7 +497,7 @@ public class LaunchOptions implements Serializable {
return this; return this;
} }
public Builder setProcessPriority(ProcessPriority processPriority) { public Builder setProcessPriority(@NotNull ProcessPriority processPriority) {
options.processPriority = processPriority; options.processPriority = processPriority;
return this; return this;
} }

View File

@@ -53,3 +53,4 @@ Make sure you have Java installed with JavaFX 8 at least. Liberica full JDK 8~16
|`-Dhmcl.version.override=<version>`|Override the version number.| |`-Dhmcl.version.override=<version>`|Override the version number.|
|`-Dhmcl.update_source.override=<url>`|Override the update source.| |`-Dhmcl.update_source.override=<url>`|Override the update source.|
|`-Dhmcl.authlibinjector.location=<path>`|Use specified authlib-injector (instead of downloading one).| |`-Dhmcl.authlibinjector.location=<path>`|Use specified authlib-injector (instead of downloading one).|
|`-Dhmcl.openjfx.repo=<maven repository url>`|Download OpenJFX from specified Maven repository. Default value is `https://maven.aliyun.com/repository/central/`.|