add: forbids installation buttons for incompatible libraries. Closes #720.

This commit is contained in:
huanghongxun 2020-05-31 22:24:03 +08:00
parent 42d42e9750
commit a2ef477ae0
11 changed files with 254 additions and 189 deletions

View File

@ -19,94 +19,198 @@ package org.jackhuang.hmcl.ui;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.effects.JFXDepthManager;
import javafx.beans.binding.Bindings;
import javafx.beans.property.*;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Cursor;
import javafx.scene.control.Control;
import javafx.scene.control.Label;
import javafx.scene.control.Skin;
import javafx.scene.control.SkinBase;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import org.jackhuang.hmcl.download.LibraryAnalyzer;
import org.jackhuang.hmcl.setting.Theme;
import org.jackhuang.hmcl.ui.construct.TwoLineListItem;
import org.jackhuang.hmcl.util.i18n.I18n;
import org.jetbrains.annotations.Nullable;
import java.util.function.Consumer;
import static org.jackhuang.hmcl.download.LibraryAnalyzer.LibraryType.*;
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
/**
* @author huangyuhui
*/
public class InstallerItem extends BorderPane {
public class InstallerItem extends Control {
private final String id;
private final String imageUrl;
public final StringProperty libraryVersion = new SimpleStringProperty();
public final StringProperty incompatibleLibraryName = new SimpleStringProperty();
public final BooleanProperty incompatibleWithGame = new SimpleBooleanProperty();
public final BooleanProperty removable = new SimpleBooleanProperty();
public final BooleanProperty upgradable = new SimpleBooleanProperty(false);
public final BooleanProperty installable = new SimpleBooleanProperty(true);
public final ObjectProperty<EventHandler<? super MouseEvent>> removeAction = new SimpleObjectProperty<>();
public final ObjectProperty<EventHandler<? super MouseEvent>> action = new SimpleObjectProperty<>();
public InstallerItem(String libraryId, String libraryVersion, @Nullable Runnable upgrade, @Nullable Consumer<InstallerItem> deleteCallback) {
getStyleClass().addAll("two-line-list-item", "card");
JFXDepthManager.setDepth(this, 1);
public InstallerItem(LibraryAnalyzer.LibraryType id) {
this(id.getPatchId());
}
String[] urls = new String[]{"/assets/img/grass.png", "/assets/img/fabric.png", "/assets/img/forge.png", "/assets/img/chicken.png", "/assets/img/command.png"};
String[] libraryIds = new String[]{"game", "fabric", "forge", "liteloader", "optifine"};
public InstallerItem(String id) {
this.id = id;
boolean regularLibrary = false;
for (int i = 0; i < 5; ++i) {
if (libraryIds[i].equals(libraryId)) {
setLeft(FXUtils.limitingSize(new ImageView(new Image(urls[i], 32, 32, true, true)), 32, 32));
Label label = new Label();
BorderPane.setAlignment(label, Pos.CENTER_LEFT);
BorderPane.setMargin(label, new Insets(0, 0, 0, 8));
if (libraryVersion == null) {
label.setText(i18n("install.installer.not_installed", i18n("install.installer." + libraryId)));
} else {
label.setText(i18n("install.installer.version", i18n("install.installer." + libraryId), libraryVersion));
}
setCenter(label);
regularLibrary = true;
switch (id) {
case "game":
imageUrl = "/assets/img/grass.png";
break;
case "fabric":
imageUrl = "/assets/img/fabric.png";
break;
case "forge":
imageUrl = "/assets/img/forge.png";
break;
case "liteloader":
imageUrl = "/assets/img/chicken.png";
break;
case "optifine":
imageUrl = "/assets/img/command.png";
break;
default:
imageUrl = null;
break;
}
}
if (!regularLibrary) {
String title = I18n.hasKey("install.installer." + libraryId) ? i18n("install.installer." + libraryId) : libraryId;
if (libraryVersion != null) {
TwoLineListItem item = new TwoLineListItem();
item.setTitle(title);
item.setSubtitle(i18n("archive.version") + ": " + libraryVersion);
setCenter(item);
} else {
Label label = new Label();
label.setStyle("-fx-font-size: 15px;");
BorderPane.setAlignment(label, Pos.CENTER_LEFT);
setCenter(label);
}
}
{
HBox hBox = new HBox();
if (upgrade != null) {
JFXButton upgradeButton = new JFXButton();
if (libraryVersion == null) {
upgradeButton.setGraphic(SVG.arrowRight(Theme.blackFillBinding(), -1, -1));
} else {
upgradeButton.setGraphic(SVG.update(Theme.blackFillBinding(), -1, -1));
}
upgradeButton.getStyleClass().add("toggle-icon4");
FXUtils.installFastTooltip(upgradeButton, i18n("install.change_version"));
upgradeButton.setOnMouseClicked(e -> upgrade.run());
hBox.getChildren().add(upgradeButton);
}
if (deleteCallback != null) {
JFXButton deleteButton = new JFXButton();
deleteButton.setGraphic(SVG.close(Theme.blackFillBinding(), -1, -1));
deleteButton.getStyleClass().add("toggle-icon4");
deleteButton.setOnMouseClicked(e -> deleteCallback.accept(this));
hBox.getChildren().add(deleteButton);
}
hBox.setAlignment(Pos.CENTER_RIGHT);
setRight(hBox);
}
}
public void setState(String libraryVersion, boolean incompatibleWithGame, boolean removable) {
this.libraryVersion.set(libraryVersion);
this.incompatibleWithGame.set(incompatibleWithGame);
this.removable.set(removable);
}
public String getLibraryId() {
return id;
}
@Override
protected Skin<?> createDefaultSkin() {
return new InstallerItemSkin(this);
}
public static class InstallerItemGroup {
public InstallerItem game = new InstallerItem(MINECRAFT);
public InstallerItem fabric = new InstallerItem(FABRIC);
public InstallerItem forge = new InstallerItem(FORGE);
public InstallerItem liteLoader = new InstallerItem(LITELOADER);
public InstallerItem optiFine = new InstallerItem(OPTIFINE);
public InstallerItemGroup() {
forge.incompatibleLibraryName.bind(Bindings.createStringBinding(() -> {
if (fabric.libraryVersion.get() != null) return FABRIC.getPatchId();
return null;
}, fabric.libraryVersion));
liteLoader.incompatibleLibraryName.bind(Bindings.createStringBinding(() -> {
if (fabric.libraryVersion.get() != null) return FABRIC.getPatchId();
return null;
}, fabric.libraryVersion));
optiFine.incompatibleLibraryName.bind(Bindings.createStringBinding(() -> {
if (fabric.libraryVersion.get() != null) return FABRIC.getPatchId();
return null;
}, fabric.libraryVersion));
fabric.incompatibleLibraryName.bind(Bindings.createStringBinding(() -> {
if (liteLoader.libraryVersion.get() != null) return LITELOADER.getPatchId();
if (optiFine.libraryVersion.get() != null) return OPTIFINE.getPatchId();
if (forge.libraryVersion.get() != null) return FORGE.getPatchId();
return null;
}, optiFine.libraryVersion, forge.libraryVersion));
}
public InstallerItem[] getLibraries() {
return new InstallerItem[]{game, fabric, forge, liteLoader, optiFine};
}
}
public static class InstallerItemSkin extends SkinBase<InstallerItem> {
InstallerItemSkin(InstallerItem control) {
super(control);
HBox hbox = new HBox();
getChildren().setAll(hbox);
JFXDepthManager.setDepth(hbox, 1);
hbox.getStyleClass().add("card");
hbox.setAlignment(Pos.CENTER_LEFT);
if (control.imageUrl != null) {
hbox.getChildren().add(FXUtils.limitingSize(new ImageView(new Image(control.imageUrl, 32, 32, true, true)), 32, 32));
}
Label nameLabel = new Label();
hbox.getChildren().add(nameLabel);
nameLabel.setPrefWidth(80);
nameLabel.textProperty().set(I18n.hasKey("install.installer." + control.id) ? i18n("install.installer." + control.id) : control.id);
HBox.setMargin(nameLabel, new Insets(0, 4, 0, 4));
Label label = new Label();
hbox.getChildren().add(label);
label.setMaxWidth(Double.MAX_VALUE);
HBox.setHgrow(label, Priority.ALWAYS);
label.textProperty().bind(Bindings.createStringBinding(() -> {
String incompatibleWith = control.incompatibleLibraryName.get();
String version = control.libraryVersion.get();
if (control.incompatibleWithGame.get()) {
return i18n("install.installer.change_version", version);
} else if (incompatibleWith != null) {
return i18n("install.installer.incompatible", i18n("install.installer." + incompatibleWith));
} else if (version == null) {
return i18n("install.installer.not_installed");
} else {
return i18n("install.installer.version", version);
}
}, control.incompatibleLibraryName, control.incompatibleWithGame, control.libraryVersion));
BorderPane.setMargin(label, new Insets(0, 0, 0, 8));
BorderPane.setAlignment(label, Pos.CENTER_LEFT);
JFXButton closeButton = new JFXButton();
closeButton.setGraphic(SVG.close(Theme.blackFillBinding(), -1, -1));
closeButton.getStyleClass().add("toggle-icon4");
closeButton.visibleProperty().bind(control.removable);
closeButton.managedProperty().bind(closeButton.visibleProperty());
closeButton.onMouseClickedProperty().bind(control.removeAction);
hbox.getChildren().add(closeButton);
JFXButton arrowButton = new JFXButton();
arrowButton.graphicProperty().bind(Bindings.createObjectBinding(() -> control.upgradable.get()
? SVG.update(Theme.blackFillBinding(), -1, -1)
: SVG.arrowRight(Theme.blackFillBinding(), -1, -1),
control.upgradable));
arrowButton.getStyleClass().add("toggle-icon4");
arrowButton.visibleProperty().bind(Bindings.createBooleanBinding(
() -> control.installable.get() && control.incompatibleLibraryName.get() == null,
control.installable, control.incompatibleLibraryName));
arrowButton.managedProperty().bind(arrowButton.visibleProperty());
arrowButton.onMouseClickedProperty().bind(control.action);
hbox.getChildren().add(arrowButton);
FXUtils.onChangeAndOperate(arrowButton.visibleProperty(), clickable -> {
if (clickable) {
hbox.onMouseClickedProperty().bind(control.action);
hbox.setCursor(Cursor.HAND);
} else {
hbox.onMouseClickedProperty().unbind();
hbox.onMouseClickedProperty().set(null);
hbox.setCursor(Cursor.DEFAULT);
}
});
}
}
}

View File

@ -24,6 +24,7 @@ import org.jackhuang.hmcl.download.LibraryAnalyzer;
import org.jackhuang.hmcl.download.RemoteVersion;
import org.jackhuang.hmcl.game.GameRepository;
import org.jackhuang.hmcl.game.Version;
import org.jackhuang.hmcl.ui.InstallerItem;
import org.jackhuang.hmcl.ui.wizard.WizardController;
import org.jackhuang.hmcl.util.Lang;
@ -53,10 +54,8 @@ class AdditionalInstallersPage extends InstallersPage {
() -> compatible.get() && txtName.validate(),
txtName.textProperty(), compatible));
InstallerPageItem[] libraries = new InstallerPageItem[]{game, fabric, forge, liteLoader, optiFine};
for (InstallerPageItem library : libraries) {
String libraryId = library.id;
for (InstallerItem library : group.getLibraries()) {
String libraryId = library.getLibraryId();
if (libraryId.equals("game")) continue;
library.removeAction.set(e -> {
controller.getSettings().put(libraryId, new UpdateInstallerWizardProvider.RemoveVersionAction(libraryId));
@ -90,28 +89,25 @@ class AdditionalInstallersPage extends InstallersPage {
String liteLoader = analyzer.getVersion(LITELOADER).orElse(null);
String optiFine = analyzer.getVersion(OPTIFINE).orElse(null);
InstallerPageItem[] libraries = new InstallerPageItem[]{this.game, this.fabric, this.forge, this.liteLoader, this.optiFine};
InstallerItem[] libraries = group.getLibraries();
String[] versions = new String[]{game, fabric, forge, liteLoader, optiFine};
String currentGameVersion = Lang.nonNull(getVersion("game"), game);
boolean compatible = true;
for (int i = 0; i < libraries.length; ++i) {
String libraryId = libraries[i].id;
String libraryId = libraries[i].getLibraryId();
String libraryVersion = Lang.nonNull(getVersion(libraryId), versions[i]);
boolean alreadyInstalled = versions[i] != null && !(controller.getSettings().get(libraryId) instanceof UpdateInstallerWizardProvider.RemoveVersionAction);
if (!"game".equals(libraryId) && currentGameVersion != null && !currentGameVersion.equals(game) && getVersion(libraryId) == null && alreadyInstalled) {
// For third-party libraries, if game version is being changed, and the library is not being reinstalled,
// warns the user that we should update the library.
libraries[i].label.set(i18n("install.installer.change_version", i18n("install.installer." + libraryId), libraryVersion));
libraries[i].removable.set(true);
libraries[i].setState(libraryVersion, /* incompatibleWithGame */ true, /* removable */ true);
compatible = false;
} else if (alreadyInstalled || getVersion(libraryId) != null) {
libraries[i].label.set(i18n("install.installer.version", i18n("install.installer." + libraryId), libraryVersion));
libraries[i].removable.set(true);
libraries[i].setState(libraryVersion, /* incompatibleWithGame */ false, /* removable */ true);
} else {
libraries[i].label.set(i18n("install.installer.not_installed", i18n("install.installer." + libraryId)));
libraries[i].removable.set(false);
libraries[i].setState(/* libraryVersion */ null, /* incompatibleWithGame */ false, /* removable */ false);
}
}
this.compatible.set(compatible);

View File

@ -19,29 +19,21 @@ package org.jackhuang.hmcl.ui.download;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXTextField;
import com.jfoenix.effects.JFXDepthManager;
import javafx.beans.binding.Bindings;
import javafx.beans.property.*;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Cursor;
import javafx.scene.control.Control;
import javafx.scene.control.Label;
import javafx.scene.control.Skin;
import javafx.scene.control.SkinBase;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import org.jackhuang.hmcl.download.RemoteVersion;
import org.jackhuang.hmcl.game.GameRepository;
import org.jackhuang.hmcl.setting.Theme;
import org.jackhuang.hmcl.ui.FXUtils;
import org.jackhuang.hmcl.ui.SVG;
import org.jackhuang.hmcl.ui.InstallerItem;
import org.jackhuang.hmcl.ui.construct.Validator;
import org.jackhuang.hmcl.ui.wizard.WizardController;
import org.jackhuang.hmcl.ui.wizard.WizardPage;
@ -55,11 +47,7 @@ import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
public class InstallersPage extends Control implements WizardPage {
protected final WizardController controller;
protected InstallerPageItem game = new InstallerPageItem("game");
protected InstallerPageItem fabric = new InstallerPageItem("fabric");
protected InstallerPageItem forge = new InstallerPageItem("forge");
protected InstallerPageItem liteLoader = new InstallerPageItem("liteloader");
protected InstallerPageItem optiFine = new InstallerPageItem("optifine");
protected InstallerItem.InstallerItemGroup group = new InstallerItem.InstallerItemGroup();
protected JFXTextField txtName = new JFXTextField();
protected BooleanProperty installable = new SimpleBooleanProperty();
@ -75,13 +63,15 @@ public class InstallersPage extends Control implements WizardPage {
txtName.textProperty()));
txtName.setText(gameVersion);
InstallerPageItem[] libraries = new InstallerPageItem[]{game, fabric, forge, liteLoader, optiFine};
group.game.installable.setValue(false);
for (InstallerPageItem library : libraries) {
String libraryId = library.id;
for (InstallerItem library : group.getLibraries()) {
String libraryId = library.getLibraryId();
if (libraryId.equals("game")) continue;
library.action.set(e ->
controller.onNext(new VersionsPage(controller, i18n("install.installer.choose", i18n("install.installer." + libraryId)), gameVersion, downloadProvider, libraryId, () -> controller.onPrev(false))));
library.action.set(e -> {
if (library.incompatibleLibraryName.get() == null)
controller.onNext(new VersionsPage(controller, i18n("install.installer.choose", i18n("install.installer." + libraryId)), gameVersion, downloadProvider, libraryId, () -> controller.onPrev(false)));
});
library.removeAction.set(e -> {
controller.getSettings().remove(libraryId);
reload();
@ -99,15 +89,13 @@ public class InstallersPage extends Control implements WizardPage {
}
protected void reload() {
InstallerPageItem[] libraries = new InstallerPageItem[]{game, fabric, forge, liteLoader, optiFine};
for (InstallerPageItem library : libraries) {
String libraryId = library.id;
for (InstallerItem library : group.getLibraries()) {
String libraryId = library.getLibraryId();
if (controller.getSettings().containsKey(libraryId)) {
library.label.set(i18n("install.installer.version", i18n("install.installer." + libraryId), getVersion(libraryId)));
library.libraryVersion.set(getVersion(libraryId));
library.removable.set(true);
} else {
library.label.setValue(i18n("install.installer.not_installed", i18n("install.installer." + libraryId)));
library.libraryVersion.set(null);
library.removable.set(false);
}
}
@ -133,54 +121,8 @@ public class InstallersPage extends Control implements WizardPage {
return new InstallersPageSkin(this);
}
protected static class InstallerPageItem {
String id;
StringProperty label = new SimpleStringProperty();
BooleanProperty removable = new SimpleBooleanProperty();
ObjectProperty<EventHandler<? super MouseEvent>> removeAction = new SimpleObjectProperty<>();
ObjectProperty<EventHandler<? super MouseEvent>> action = new SimpleObjectProperty<>();
public InstallerPageItem(String id) {
this.id = id;
}
}
protected static class InstallersPageSkin extends SkinBase<InstallersPage> {
protected static class InstallersPageItemSkin extends BorderPane {
final ImageView imageView;
final Label label;
InstallersPageItemSkin(String imageUrl, InstallerPageItem item, boolean clickable) {
getStyleClass().add("card");
setLeft(FXUtils.limitingSize(imageView = new ImageView(new Image(imageUrl, 32, 32, true, true)), 32, 32));
setCenter(label = new Label());
label.textProperty().bind(item.label);
BorderPane.setMargin(label, new Insets(0, 0, 0, 8));
BorderPane.setAlignment(label, Pos.CENTER_LEFT);
if (clickable) {
HBox right = new HBox();
right.setAlignment(Pos.CENTER_RIGHT);
setRight(right);
JFXButton closeButton = new JFXButton();
closeButton.setGraphic(SVG.close(Theme.blackFillBinding(), -1, -1));
right.getChildren().add(closeButton);
closeButton.getStyleClass().add("toggle-icon4");
closeButton.visibleProperty().bind(item.removable);
closeButton.onMouseClickedProperty().bind(item.removeAction);
onMouseClickedProperty().bind(item.action);
JFXButton arrowButton = new JFXButton();
arrowButton.setGraphic(SVG.arrowRight(Theme.blackFillBinding(), -1, -1));
arrowButton.onMouseClickedProperty().bind(item.action);
arrowButton.getStyleClass().add("toggle-icon4");
right.getChildren().add(arrowButton);
setCursor(Cursor.HAND);
}
}
}
/**
* Constructor for all SkinBase instances.
*
@ -207,13 +149,7 @@ public class InstallersPage extends Control implements WizardPage {
list.getChildren().add(versionNamePane);
}
InstallersPageItemSkin game = new InstallersPageItemSkin("/assets/img/grass.png", control.game, false);
InstallersPageItemSkin fabric = new InstallersPageItemSkin("/assets/img/fabric.png", control.fabric, true);
InstallersPageItemSkin forge = new InstallersPageItemSkin("/assets/img/forge.png", control.forge, true);
InstallersPageItemSkin liteLoader = new InstallersPageItemSkin("/assets/img/chicken.png", control.liteLoader, true);
InstallersPageItemSkin optiFine = new InstallersPageItemSkin("/assets/img/command.png", control.optiFine, true);
list.getChildren().addAll(game, fabric, forge, liteLoader, optiFine);
list.getChildren().forEach(node -> JFXDepthManager.setDepth(node, 1));
list.getChildren().addAll(control.group.getLibraries());
{
JFXButton installButton = new JFXButton(i18n("button.install"));

View File

@ -18,6 +18,7 @@
package org.jackhuang.hmcl.ui.versions;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.scene.Node;
import javafx.scene.control.Skin;
import javafx.stage.FileChooser;
@ -42,6 +43,7 @@ import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
import java.util.function.Function;
import static org.jackhuang.hmcl.download.LibraryAnalyzer.LibraryType.*;
import static org.jackhuang.hmcl.ui.FXUtils.runInFX;
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
@ -74,7 +76,7 @@ public class InstallerListPage extends ListPageBase<InstallerItem> {
return LibraryAnalyzer.analyze(profile.getRepository().getResolvedPreservingPatchesVersion(versionId));
}).thenAcceptAsync(analyzer -> {
Function<String, Consumer<InstallerItem>> removeAction = libraryId -> x -> {
Function<String, Runnable> removeAction = libraryId -> () -> {
profile.getDependency().removeLibraryAsync(version, libraryId)
.thenComposeAsync(profile.getRepository()::saveAsync)
.withComposeAsync(profile.getRepository().refreshVersionsAsync())
@ -84,15 +86,28 @@ public class InstallerListPage extends ListPageBase<InstallerItem> {
itemsProperty().clear();
for (LibraryAnalyzer.LibraryType type : LibraryAnalyzer.LibraryType.values()) {
String libraryId = type.getPatchId();
String libraryVersion = analyzer.getVersion(type).orElse(null);
Consumer<InstallerItem> action = "game".equals(libraryId) || libraryVersion == null ? null : removeAction.apply(libraryId);
itemsProperty().add(new InstallerItem(libraryId, libraryVersion, () -> {
InstallerItem.InstallerItemGroup group = new InstallerItem.InstallerItemGroup();
// Conventional libraries: game, fabric, forge, liteloader, optifine
for (InstallerItem installerItem : group.getLibraries()) {
String libraryId = installerItem.getLibraryId();
String libraryVersion = analyzer.getVersion(libraryId).orElse(null);
installerItem.libraryVersion.set(libraryVersion);
installerItem.upgradable.set(libraryVersion != null);
installerItem.installable.set(true);
installerItem.action.set(e -> {
Controllers.getDecorator().startWizard(new UpdateInstallerWizardProvider(profile, gameVersion, version, libraryId, libraryVersion));
}, action));
});
boolean removable = !"game".equals(libraryId) && libraryVersion != null;
installerItem.removable.set(removable);
if (removable) {
Runnable action = removeAction.apply(libraryId);
installerItem.removeAction.set(e -> action.run());
}
itemsProperty().add(installerItem);
}
// other third-party libraries which are unable to manage.
for (LibraryAnalyzer.LibraryMark mark : analyzer) {
String libraryId = mark.getLibraryId();
String libraryVersion = mark.getLibraryVersion();
@ -101,14 +116,23 @@ public class InstallerListPage extends ListPageBase<InstallerItem> {
if (LibraryAnalyzer.LibraryType.fromPatchId(libraryId) != null)
continue;
Consumer<InstallerItem> action = removeAction.apply(libraryId);
if (libraryVersion != null && Lang.test(() -> profile.getDependency().getVersionList(libraryId)))
itemsProperty().add(
new InstallerItem(libraryId, libraryVersion, () -> {
Controllers.getDecorator().startWizard(new UpdateInstallerWizardProvider(profile, gameVersion, version, libraryId, libraryVersion));
}, action));
else
itemsProperty().add(new InstallerItem(libraryId, libraryVersion, null, action));
Runnable action = removeAction.apply(libraryId);
InstallerItem installerItem = new InstallerItem(libraryId);
installerItem.libraryVersion.set(libraryVersion);
installerItem.installable.set(false);
installerItem.upgradable.bind(installerItem.installable);
installerItem.removable.set(true);
installerItem.removeAction.set(e -> action.run());
if (libraryVersion != null && Lang.test(() -> profile.getDependency().getVersionList(libraryId))) {
installerItem.installable.set(true);
installerItem.action.set(e -> {
Controllers.getDecorator().startWizard(new UpdateInstallerWizardProvider(profile, gameVersion, version, libraryId, libraryVersion));
});
}
itemsProperty().add(installerItem);
}
}, Platform::runLater);
}

View File

@ -139,11 +139,12 @@ install.failed.install_online=Unable to recognize the provided installer file
install.failed.malformed=The files just downloaded a moment ago is malformed. You may switch to other download provider to resolve this problem.
install.failed.optifine_conflict=Fabric, OptiFine and Forge are installed simultaneously on Minecraft 1.13
install.failed.version_mismatch=The library requires the game version %s, but the actual version is %s.
install.installer.change_version=%s version: %s, this version is not compatible with current game version. Click here to choose another one.
install.installer.change_version=%s, this version is not compatible with current game version. Click here to choose another one.
install.installer.choose=Choose a %s version
install.installer.fabric=Fabric
install.installer.forge=Forge
install.installer.game=Minecraft
install.installer.incompatible=Incompatible with %s
install.installer.install=Install %s
install.installer.install_offline=Install/Upgrade from file
install.installer.install_offline.extension=Forge/OptiFine installer
@ -151,9 +152,9 @@ install.installer.install_offline.tooltip=Supports import of Forge/OptiFine inst
install.installer.install_online=Install Online
install.installer.install_online.tooltip=Support installation of Fabric, Forge, OptiFine, LiteLoader.
install.installer.liteloader=LiteLoader
install.installer.not_installed=%s Version: not installed
install.installer.not_installed=Not installed
install.installer.optifine=OptiFine
install.installer.version=%s Version: %s
install.installer.version=%s
install.modpack=Install a modpack
install.new_game=Install a New Game
install.new_game.already_exists=This version already exists.

View File

@ -140,6 +140,7 @@ install.installer.choose=Escoja una versión de %s
install.installer.fabric=Fabric
install.installer.forge=Forge
install.installer.game=Minecraft
install.installer.incompatible=Incompatible with %s
install.installer.install=Instalar %s
install.installer.install_offline=Instalar/actualizar con archivo local
install.installer.install_offline.extension=Instalador de Forge/OptiFine
@ -147,9 +148,9 @@ install.installer.install_offline.tooltip=Soporta importación de archivo instal
install.installer.install_online=Instalar en línea
install.installer.install_online.tooltip=Soporta instalación de Fabric, Forge, OptiFine, LiteLoader
install.installer.liteloader=LiteLoader
install.installer.not_installed=%s no está instalado
install.installer.not_installed=no está instalado
install.installer.optifine=OptiFine
install.installer.version=Versión %s: %s
install.installer.version=%s
install.modpack=Instalar un modpack
install.new_game=Instalar un juego nuevo
install.new_game.already_exists=Esta versión ya existe.

View File

@ -139,11 +139,12 @@ install.failed.install_online=Невозможно распознать пред
install.failed.malformed=Файлы, скачаные минуту назад, неправильно сформированы. Для решения этой проблемы можно переключиться на другого поставщика скачивания.
install.failed.optifine_conflict=Fabric, OptiFine и Forge установлены одновременно на Minecraft 1.13
install.failed.version_mismatch=Библиотека требует версию игры %s, но фактическая версия %s.
install.installer.change_version=Версия %s: %s, эта версия не совместима с текущей версией игры. Что бы выбрать другую, нажмите здесь.
install.installer.change_version=%s, эта версия не совместима с текущей версией игры. Что бы выбрать другую, нажмите здесь.
install.installer.choose=Выберите версию %s
install.installer.fabric=Fabric
install.installer.forge=Forge
install.installer.game=Minecraft
install.installer.incompatible=Incompatible with %s
install.installer.install=Установка %s
install.installer.install_offline=Установить/обновить из файла
install.installer.install_offline.extension=Установщик Forge/OptiFine
@ -151,9 +152,9 @@ install.installer.install_offline.tooltip=Поддерживает импорт
install.installer.install_online=Установить из сети
install.installer.install_online.tooltip=Поддерживается установка Fabric, Forge, OptiFine, LiteLoader.
install.installer.liteloader=LiteLoader
install.installer.not_installed=%s не установлен
install.installer.not_installed=не установлен
install.installer.optifine=OptiFine
install.installer.version=%s - версия: %s
install.installer.version=%s
install.modpack=Установить модпак
install.new_game=Установка новой игры
install.new_game.already_exists=Эта версия уже существует.

View File

@ -139,11 +139,12 @@ install.failed.install_online=無法識別要安裝的軟體
install.failed.malformed=剛才下載的檔案格式損壞。您可以切換到其他下載來源以解決此問題。
install.failed.optifine_conflict=暫不支援 OptiFine 與 Forge 同時安裝在 Minecraft 1.13 上
install.failed.version_mismatch=該軟體需要的遊戲版本為 %s但實際的遊戲版本為 %s。
install.installer.change_version=%s 版本: %s,該版本與當前遊戲不相容,您需要點擊此處更換版本或刪除
install.installer.change_version=%s,該版本與當前遊戲不相容,您需要點擊此處更換版本或刪除
install.installer.choose=選擇 %s 版本
install.installer.fabric=Fabric
install.installer.forge=Forge
install.installer.game=Minecraft
install.installer.incompatible=與 %s 不相容
install.installer.install=安裝%s
install.installer.install_offline=從本機檔案安裝或升級
install.installer.install_offline.extension=Forge/OptiFine 安裝器
@ -151,9 +152,9 @@ install.installer.install_offline.tooltip=支援匯入已經下載好的 Forge/O
install.installer.install_online=線上安裝
install.installer.install_online.tooltip=支援安裝 Fabric、Forge、OptiFine、LiteLoader
install.installer.liteloader=LiteLoader
install.installer.not_installed=%s 版本: 不安裝
install.installer.not_installed=不安裝
install.installer.optifine=OptiFine
install.installer.version=%s 版本: %s
install.installer.version=%s
install.modpack=安裝整合包
install.new_game=安裝新遊戲版本
install.new_game.already_exists=此版本已經存在,請重新命名

View File

@ -139,11 +139,12 @@ install.failed.install_online=无法识别要安装的软件
install.failed.malformed=刚才下载的文件格式损坏。您可以切换到其他下载源来解决此问题。
install.failed.optifine_conflict=暂不支持 OptiFine, Fabric 与 Forge 同时安装在 Minecraft 1.13 及以上版本
install.failed.version_mismatch=该软件需要的游戏版本为 %s但实际的游戏版本为 %s。
install.installer.change_version=%s 版本: %s,该版本与当前游戏不兼容,您需要点击此处更换版本或删除
install.installer.change_version=%s,该版本与当前游戏不兼容,您需要点击此处更换版本或删除
install.installer.choose=选择 %s 版本
install.installer.fabric=Fabric
install.installer.forge=Forge
install.installer.game=Minecraft
install.installer.incompatible=与 %s 不兼容
install.installer.install=安装 %s
install.installer.install_offline=从本地文件安装/升级
install.installer.install_offline.extension=Forge/OptiFine 安装器
@ -151,9 +152,9 @@ install.installer.install_offline.tooltip=支持导入已经下载好的 Forge/O
install.installer.install_online=在线安装
install.installer.install_online.tooltip=支持安装 Fabric、Forge、OptiFine、LiteLoader
install.installer.liteloader=LiteLoader
install.installer.not_installed=%s 版本: 不安装
install.installer.not_installed=不安装
install.installer.optifine=OptiFine
install.installer.version=%s 版本: %s
install.installer.version=%s
install.modpack=安装整合包
install.new_game=安装新游戏版本
install.new_game.already_exists=此版本已经存在,请换一个名字

View File

@ -104,7 +104,7 @@ public final class ForgeInstallTask extends Task<Version> {
public void execute() throws IOException, VersionMismatchException, OptiFineInstallTask.UnsupportedOptiFineInstallationException {
String originalMainClass = version.resolve(dependencyManager.getGameRepository()).getMainClass();
if (VersionNumber.VERSION_COMPARATOR.compare("1.13", remote.getGameVersion()) <= 0) {
// Forge 1.13 is not compatible with any other libraries.
// Forge 1.13 is not compatible with fabric.
if (!LibraryAnalyzer.VANILLA_MAIN.equals(originalMainClass) && !LibraryAnalyzer.MOD_LAUNCHER_MAIN.equals(originalMainClass) && !LibraryAnalyzer.LAUNCH_WRAPPER_MAIN.equals(originalMainClass))
throw new OptiFineInstallTask.UnsupportedOptiFineInstallationException();
} else {

View File

@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.4.1-all.zip