mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-03-13 17:46:58 +08:00
* Fix #3099 * Fix: checkstyle * Fix. * Fix #3144 * Update * Fix bugs. * Change I18N * Fix #3164 * Delete State.SEALED * fix typo --------- Co-authored-by: Glavo <zjx001202@gmail.com>
This commit is contained in:
parent
6f7c922ac0
commit
e8306ea59a
@ -337,7 +337,7 @@ public class GameCrashWindow extends Stage {
|
||||
|
||||
TwoLineListItem version = new TwoLineListItem();
|
||||
version.getStyleClass().setAll("two-line-item-second-large");
|
||||
version.setTitle(i18n("archive.game_version"));
|
||||
version.setTitle(i18n("game.version"));
|
||||
version.setSubtitle(GameCrashWindow.this.version.getId());
|
||||
|
||||
TwoLineListItem total_memory = new TwoLineListItem();
|
||||
|
@ -18,9 +18,10 @@
|
||||
package org.jackhuang.hmcl.ui;
|
||||
|
||||
import com.jfoenix.controls.JFXButton;
|
||||
import javafx.beans.InvalidationListener;
|
||||
import javafx.beans.Observable;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.property.*;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.css.PseudoClass;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.geometry.Insets;
|
||||
@ -55,29 +56,77 @@ import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||
public class InstallerItem extends Control {
|
||||
private final String id;
|
||||
private final VersionIconType iconType;
|
||||
public final StringProperty libraryVersion = new SimpleStringProperty();
|
||||
public final StringProperty incompatibleLibraryName = new SimpleStringProperty();
|
||||
public final StringProperty dependencyName = 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<>();
|
||||
private final Style style;
|
||||
private final ObjectProperty<InstalledState> versionProperty = new SimpleObjectProperty<>(this, "version", null);
|
||||
private final ObjectProperty<State> resolvedStateProperty = new SimpleObjectProperty<>(this, "resolvedState", InstallableState.INSTANCE);
|
||||
|
||||
private Style style = Style.LIST_ITEM;
|
||||
private final ObjectProperty<EventHandler<? super MouseEvent>> installActionProperty = new SimpleObjectProperty<>(this, "installAction");
|
||||
private final ObjectProperty<EventHandler<? super MouseEvent>> removeActionProperty = new SimpleObjectProperty<>(this, "removeAction");
|
||||
|
||||
public interface State {
|
||||
}
|
||||
|
||||
public static final class InstallableState implements State {
|
||||
public static final InstallableState INSTANCE = new InstallableState();
|
||||
|
||||
private InstallableState() {
|
||||
}
|
||||
}
|
||||
|
||||
public static final class IncompatibleState implements State {
|
||||
private final String incompatibleItemName;
|
||||
private final String incompatibleItemVersion;
|
||||
|
||||
public IncompatibleState(String incompatibleItemName, String incompatibleItemVersion) {
|
||||
this.incompatibleItemName = incompatibleItemName;
|
||||
this.incompatibleItemVersion = incompatibleItemVersion;
|
||||
}
|
||||
|
||||
public String getIncompatibleItemName() {
|
||||
return incompatibleItemName;
|
||||
}
|
||||
|
||||
public String getIncompatibleItemVersion() {
|
||||
return incompatibleItemVersion;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class InstalledState implements State {
|
||||
private final String version;
|
||||
private final boolean external;
|
||||
private final boolean incompatibleWithGame;
|
||||
|
||||
public InstalledState(String version, boolean external, boolean incompatibleWithGame) {
|
||||
this.version = version;
|
||||
this.external = external;
|
||||
this.incompatibleWithGame = incompatibleWithGame;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public boolean isExternal() {
|
||||
return external;
|
||||
}
|
||||
|
||||
public boolean isIncompatibleWithGame() {
|
||||
return incompatibleWithGame;
|
||||
}
|
||||
}
|
||||
|
||||
public enum Style {
|
||||
LIST_ITEM,
|
||||
CARD,
|
||||
}
|
||||
|
||||
public InstallerItem(LibraryAnalyzer.LibraryType id) {
|
||||
this(id.getPatchId());
|
||||
public InstallerItem(LibraryAnalyzer.LibraryType id, Style style) {
|
||||
this(id.getPatchId(), style);
|
||||
}
|
||||
|
||||
public InstallerItem(String id) {
|
||||
public InstallerItem(String id, Style style) {
|
||||
this.id = id;
|
||||
this.style = style;
|
||||
|
||||
switch (id) {
|
||||
case "game":
|
||||
@ -109,55 +158,51 @@ public class InstallerItem extends Control {
|
||||
}
|
||||
}
|
||||
|
||||
public void setStyleMode(Style style) {
|
||||
this.style = style;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public ObjectProperty<InstalledState> versionProperty() {
|
||||
return versionProperty;
|
||||
}
|
||||
|
||||
public ObjectProperty<State> resolvedStateProperty() {
|
||||
return resolvedStateProperty;
|
||||
}
|
||||
|
||||
public ObjectProperty<EventHandler<? super MouseEvent>> installActionProperty() {
|
||||
return installActionProperty;
|
||||
}
|
||||
|
||||
public ObjectProperty<EventHandler<? super MouseEvent>> removeActionProperty() {
|
||||
return removeActionProperty;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Skin<?> createDefaultSkin() {
|
||||
return new InstallerItemSkin(this);
|
||||
}
|
||||
|
||||
public final static class InstallerItemGroup {
|
||||
public final InstallerItem game = new InstallerItem(MINECRAFT);
|
||||
public final InstallerItem fabric = new InstallerItem(FABRIC);
|
||||
public final InstallerItem fabricApi = new InstallerItem(FABRIC_API);
|
||||
public final InstallerItem forge = new InstallerItem(FORGE);
|
||||
public final InstallerItem neoForge = new InstallerItem(NEO_FORGE);
|
||||
public final InstallerItem liteLoader = new InstallerItem(LITELOADER);
|
||||
public final InstallerItem optiFine = new InstallerItem(OPTIFINE);
|
||||
public final InstallerItem quilt = new InstallerItem(QUILT);
|
||||
public final InstallerItem quiltApi = new InstallerItem(QUILT_API);
|
||||
private final InstallerItem game;
|
||||
|
||||
private final InstallerItem[] libraries;
|
||||
|
||||
private final HashMap<InstallerItem, Set<InstallerItem>> incompatibleMap = new HashMap<>();
|
||||
|
||||
private Set<InstallerItem> getIncompatibles(InstallerItem item) {
|
||||
private Set<InstallerItem> getIncompatibles(Map<InstallerItem, Set<InstallerItem>> incompatibleMap, InstallerItem item) {
|
||||
return incompatibleMap.computeIfAbsent(item, it -> new HashSet<>());
|
||||
}
|
||||
|
||||
private void addIncompatibles(InstallerItem item, InstallerItem... others) {
|
||||
Set<InstallerItem> set = getIncompatibles(item);
|
||||
private void addIncompatibles(Map<InstallerItem, Set<InstallerItem>> incompatibleMap, InstallerItem item, InstallerItem... others) {
|
||||
Set<InstallerItem> set = getIncompatibles(incompatibleMap, item);
|
||||
for (InstallerItem other : others) {
|
||||
set.add(other);
|
||||
getIncompatibles(other).add(item);
|
||||
getIncompatibles(incompatibleMap, other).add(item);
|
||||
}
|
||||
}
|
||||
|
||||
private void mutualIncompatible(InstallerItem... items) {
|
||||
private void mutualIncompatible(Map<InstallerItem, Set<InstallerItem>> incompatibleMap, InstallerItem... items) {
|
||||
for (InstallerItem item : items) {
|
||||
Set<InstallerItem> set = getIncompatibles(item);
|
||||
Set<InstallerItem> set = getIncompatibles(incompatibleMap, item);
|
||||
|
||||
for (InstallerItem item2 : items) {
|
||||
if (item2 != item) {
|
||||
@ -167,43 +212,65 @@ public class InstallerItem extends Control {
|
||||
}
|
||||
}
|
||||
|
||||
public InstallerItemGroup(String gameVersion) {
|
||||
mutualIncompatible(forge, fabric, quilt, neoForge, liteLoader);
|
||||
addIncompatibles(optiFine, fabric, quilt, neoForge);
|
||||
addIncompatibles(fabricApi, forge, quiltApi, neoForge, liteLoader, optiFine);
|
||||
addIncompatibles(quiltApi, forge, fabric, fabricApi, neoForge, liteLoader, optiFine);
|
||||
public InstallerItemGroup(String gameVersion, Style style) {
|
||||
game = new InstallerItem(MINECRAFT, style);
|
||||
InstallerItem fabric = new InstallerItem(FABRIC, style);
|
||||
InstallerItem fabricApi = new InstallerItem(FABRIC_API, style);
|
||||
InstallerItem forge = new InstallerItem(FORGE, style);
|
||||
InstallerItem neoForge = new InstallerItem(NEO_FORGE, style);
|
||||
InstallerItem liteLoader = new InstallerItem(LITELOADER, style);
|
||||
InstallerItem optiFine = new InstallerItem(OPTIFINE, style);
|
||||
InstallerItem quilt = new InstallerItem(QUILT, style);
|
||||
InstallerItem quiltApi = new InstallerItem(QUILT_API, style);
|
||||
|
||||
InvalidationListener listener = o -> {
|
||||
for (Map.Entry<InstallerItem, Set<InstallerItem>> entry : incompatibleMap.entrySet()) {
|
||||
InstallerItem item = entry.getKey();
|
||||
Map<InstallerItem, Set<InstallerItem>> incompatibleMap = new HashMap<>();
|
||||
mutualIncompatible(incompatibleMap, forge, fabric, quilt, neoForge, liteLoader);
|
||||
addIncompatibles(incompatibleMap, optiFine, fabric, quilt, neoForge);
|
||||
addIncompatibles(incompatibleMap, fabricApi, forge, quiltApi, neoForge, liteLoader, optiFine);
|
||||
addIncompatibles(incompatibleMap, quiltApi, forge, fabric, fabricApi, neoForge, liteLoader, optiFine);
|
||||
|
||||
String incompatibleId = null;
|
||||
for (InstallerItem other : entry.getValue()) {
|
||||
if (other.libraryVersion.get() != null) {
|
||||
incompatibleId = other.id;
|
||||
break;
|
||||
for (Map.Entry<InstallerItem, Set<InstallerItem>> entry : incompatibleMap.entrySet()) {
|
||||
InstallerItem item = entry.getKey();
|
||||
Set<InstallerItem> incompatibleItems = entry.getValue();
|
||||
|
||||
Observable[] bindings = new Observable[incompatibleItems.size() + 1];
|
||||
bindings[0] = item.versionProperty;
|
||||
int i = 1;
|
||||
for (InstallerItem other : incompatibleItems) {
|
||||
bindings[i++] = other.versionProperty;
|
||||
}
|
||||
|
||||
item.resolvedStateProperty.bind(Bindings.createObjectBinding(() -> {
|
||||
InstalledState itemVersion = item.versionProperty.get();
|
||||
if (itemVersion != null) {
|
||||
return itemVersion;
|
||||
}
|
||||
|
||||
for (InstallerItem other : incompatibleItems) {
|
||||
InstalledState otherVersion = other.versionProperty.get();
|
||||
if (otherVersion != null) {
|
||||
return new IncompatibleState(other.id, otherVersion.version);
|
||||
}
|
||||
}
|
||||
|
||||
item.incompatibleLibraryName.set(incompatibleId);
|
||||
}
|
||||
};
|
||||
for (InstallerItem item : incompatibleMap.keySet()) {
|
||||
item.libraryVersion.addListener(listener);
|
||||
return InstallableState.INSTANCE;
|
||||
}, bindings));
|
||||
}
|
||||
|
||||
fabricApi.dependencyName.bind(Bindings.createStringBinding(() -> {
|
||||
if (fabric.libraryVersion.get() == null) return FABRIC.getPatchId();
|
||||
else return null;
|
||||
}, fabric.libraryVersion));
|
||||
if (gameVersion != null) {
|
||||
game.versionProperty.set(new InstalledState(gameVersion, false, false));
|
||||
}
|
||||
|
||||
quiltApi.dependencyName.bind(Bindings.createStringBinding(() -> {
|
||||
if (quilt.libraryVersion.get() == null) return QUILT.getPatchId();
|
||||
else return null;
|
||||
}, quilt.libraryVersion));
|
||||
InstallerItem[] all = {game, forge, neoForge, liteLoader, optiFine, fabric, fabricApi, quilt, quiltApi};
|
||||
|
||||
for (InstallerItem item : all) {
|
||||
if (!item.resolvedStateProperty.isBound()) {
|
||||
item.resolvedStateProperty.bind(item.versionProperty);
|
||||
}
|
||||
}
|
||||
|
||||
if (gameVersion == null) {
|
||||
this.libraries = new InstallerItem[]{game, forge, neoForge, liteLoader, optiFine, fabric, fabricApi, quilt, quiltApi};
|
||||
this.libraries = all;
|
||||
} else if (GameVersionNumber.compare(gameVersion, "1.13") < 0) {
|
||||
this.libraries = new InstallerItem[]{game, forge, liteLoader, optiFine};
|
||||
} else {
|
||||
@ -211,15 +278,19 @@ public class InstallerItem extends Control {
|
||||
}
|
||||
}
|
||||
|
||||
public InstallerItem getGame() {
|
||||
return game;
|
||||
}
|
||||
|
||||
public InstallerItem[] getLibraries() {
|
||||
return libraries;
|
||||
}
|
||||
}
|
||||
|
||||
public static class InstallerItemSkin extends SkinBase<InstallerItem> {
|
||||
|
||||
private static final class InstallerItemSkin extends SkinBase<InstallerItem> {
|
||||
private static final PseudoClass LIST_ITEM = PseudoClass.getPseudoClass("list-item");
|
||||
private static final PseudoClass CARD = PseudoClass.getPseudoClass("card");
|
||||
private static final WeakListenerHolder holder = new WeakListenerHolder();
|
||||
|
||||
InstallerItemSkin(InstallerItem control) {
|
||||
super(control);
|
||||
@ -227,6 +298,7 @@ public class InstallerItem extends Control {
|
||||
Pane pane;
|
||||
if (control.style == Style.CARD) {
|
||||
pane = new VBox();
|
||||
holder.add(FXUtils.onWeakChangeAndOperate(pane.widthProperty(), v -> FXUtils.setLimitHeight(pane, v.doubleValue() * 0.7)));
|
||||
} else {
|
||||
pane = new HBox();
|
||||
}
|
||||
@ -262,20 +334,25 @@ public class InstallerItem extends Control {
|
||||
pane.getChildren().add(statusLabel);
|
||||
HBox.setHgrow(statusLabel, Priority.ALWAYS);
|
||||
statusLabel.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) {
|
||||
State state = control.resolvedStateProperty.get();
|
||||
|
||||
if (state instanceof InstalledState) {
|
||||
InstalledState s = (InstalledState) state;
|
||||
if (s.incompatibleWithGame) {
|
||||
return i18n("install.installer.change_version", s.version);
|
||||
}
|
||||
if (s.external) {
|
||||
return i18n("install.installer.external_version", s.version);
|
||||
}
|
||||
return i18n("install.installer.version", s.version);
|
||||
} else if (state instanceof InstallableState) {
|
||||
return i18n("install.installer.not_installed");
|
||||
} else if (control.id.equals(MINECRAFT.getPatchId()) || control.removable.get() || control.upgradable.get()) {
|
||||
return i18n("install.installer.version", version);
|
||||
} else if (state instanceof IncompatibleState) {
|
||||
return i18n("install.installer.incompatible", i18n("install.installer." + ((IncompatibleState) state).incompatibleItemName));
|
||||
} else {
|
||||
return i18n("install.installer.external_version", version);
|
||||
throw new AssertionError("Unknown state type: " + state.getClass());
|
||||
}
|
||||
}, control.incompatibleLibraryName, control.incompatibleWithGame, control.libraryVersion, control.installable, control.removable, control.upgradable));
|
||||
}, control.resolvedStateProperty));
|
||||
BorderPane.setMargin(statusLabel, new Insets(0, 0, 0, 8));
|
||||
BorderPane.setAlignment(statusLabel, Pos.CENTER_LEFT);
|
||||
|
||||
@ -284,31 +361,48 @@ public class InstallerItem extends Control {
|
||||
buttonsContainer.setAlignment(Pos.CENTER);
|
||||
pane.getChildren().add(buttonsContainer);
|
||||
|
||||
JFXButton closeButton = new JFXButton();
|
||||
closeButton.setGraphic(SVG.CLOSE.createIcon(Theme.blackFill(), -1, -1));
|
||||
closeButton.getStyleClass().add("toggle-icon4");
|
||||
closeButton.visibleProperty().bind(control.removable);
|
||||
closeButton.managedProperty().bind(closeButton.visibleProperty());
|
||||
closeButton.onMouseClickedProperty().bind(control.removeAction);
|
||||
buttonsContainer.getChildren().add(closeButton);
|
||||
JFXButton removeButton = new JFXButton();
|
||||
removeButton.setGraphic(SVG.CLOSE.createIcon(Theme.blackFill(), -1, -1));
|
||||
removeButton.getStyleClass().add("toggle-icon4");
|
||||
if (control.id.equals(MINECRAFT.getPatchId())) {
|
||||
removeButton.setVisible(false);
|
||||
} else {
|
||||
removeButton.visibleProperty().bind(Bindings.createBooleanBinding(() -> control.resolvedStateProperty.get() instanceof InstalledState, control.resolvedStateProperty));
|
||||
}
|
||||
removeButton.managedProperty().bind(removeButton.visibleProperty());
|
||||
removeButton.onMouseClickedProperty().bind(control.removeActionProperty);
|
||||
buttonsContainer.getChildren().add(removeButton);
|
||||
|
||||
JFXButton arrowButton = new JFXButton();
|
||||
arrowButton.graphicProperty().bind(Bindings.createObjectBinding(() -> control.upgradable.get()
|
||||
? SVG.UPDATE.createIcon(Theme.blackFill(), -1, -1)
|
||||
: SVG.ARROW_RIGHT.createIcon(Theme.blackFill(), -1, -1),
|
||||
control.upgradable));
|
||||
arrowButton.getStyleClass().add("toggle-icon4");
|
||||
arrowButton.visibleProperty().bind(Bindings.createBooleanBinding(
|
||||
() -> control.installable.get() && control.libraryVersion.get() == null && control.incompatibleLibraryName.get() == null,
|
||||
control.installable, control.libraryVersion, control.incompatibleLibraryName
|
||||
JFXButton installButton = new JFXButton();
|
||||
installButton.graphicProperty().bind(Bindings.createObjectBinding(() ->
|
||||
control.resolvedStateProperty.get() instanceof InstallableState ?
|
||||
SVG.ARROW_RIGHT.createIcon(Theme.blackFill(), -1, -1) :
|
||||
SVG.UPDATE.createIcon(Theme.blackFill(), -1, -1),
|
||||
control.resolvedStateProperty
|
||||
));
|
||||
arrowButton.managedProperty().bind(arrowButton.visibleProperty());
|
||||
arrowButton.onMouseClickedProperty().bind(control.action);
|
||||
buttonsContainer.getChildren().add(arrowButton);
|
||||
installButton.getStyleClass().add("toggle-icon4");
|
||||
installButton.visibleProperty().bind(Bindings.createBooleanBinding(() -> {
|
||||
if (control.installActionProperty.get() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FXUtils.onChangeAndOperate(arrowButton.visibleProperty(), clickable -> {
|
||||
State state = control.resolvedStateProperty.get();
|
||||
if (state instanceof InstallableState) {
|
||||
return true;
|
||||
}
|
||||
if (state instanceof InstalledState) {
|
||||
return !((InstalledState) state).external;
|
||||
}
|
||||
|
||||
return false;
|
||||
}, control.resolvedStateProperty, control.installActionProperty));
|
||||
installButton.managedProperty().bind(installButton.visibleProperty());
|
||||
installButton.onMouseClickedProperty().bind(control.installActionProperty);
|
||||
buttonsContainer.getChildren().add(installButton);
|
||||
|
||||
FXUtils.onChangeAndOperate(installButton.visibleProperty(), clickable -> {
|
||||
if (clickable) {
|
||||
container.onMouseClickedProperty().bind(control.action);
|
||||
container.onMouseClickedProperty().bind(control.installActionProperty);
|
||||
pane.setCursor(Cursor.HAND);
|
||||
} else {
|
||||
container.onMouseClickedProperty().unbind();
|
||||
|
@ -33,7 +33,7 @@ import org.jackhuang.hmcl.util.Lang;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.jackhuang.hmcl.download.LibraryAnalyzer.LibraryType.*;
|
||||
import static org.jackhuang.hmcl.download.LibraryAnalyzer.LibraryType.MINECRAFT;
|
||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||
|
||||
class AdditionalInstallersPage extends InstallersPage {
|
||||
@ -59,7 +59,7 @@ class AdditionalInstallersPage extends InstallersPage {
|
||||
for (InstallerItem library : group.getLibraries()) {
|
||||
String libraryId = library.getLibraryId();
|
||||
if (libraryId.equals("game")) continue;
|
||||
library.removeAction.set(e -> {
|
||||
library.removeActionProperty().set(e -> {
|
||||
controller.getSettings().put(libraryId, new UpdateInstallerWizardProvider.RemoveVersionAction(libraryId));
|
||||
reload();
|
||||
});
|
||||
@ -99,12 +99,12 @@ class AdditionalInstallersPage extends InstallersPage {
|
||||
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.
|
||||
library.setState(libraryVersion, /* incompatibleWithGame */ true, /* removable */ true);
|
||||
library.versionProperty().set(new InstallerItem.InstalledState(libraryVersion, false, true));
|
||||
compatible = false;
|
||||
} else if (alreadyInstalled || getVersion(libraryId) != null) {
|
||||
library.setState(libraryVersion, /* incompatibleWithGame */ false, /* removable */ true);
|
||||
library.versionProperty().set(new InstallerItem.InstalledState(libraryVersion, false, false));
|
||||
} else {
|
||||
library.setState(/* libraryVersion */ null, /* incompatibleWithGame */ false, /* removable */ false);
|
||||
library.versionProperty().set(null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -162,7 +162,7 @@ public class DownloadPage extends DecoratorAnimatedPage implements DecoratorPage
|
||||
|
||||
Path runDirectory = profile.getRepository().hasVersion(version) ? profile.getRepository().getRunDirectory(version).toPath() : profile.getRepository().getBaseDirectory().toPath();
|
||||
|
||||
Controllers.prompt(i18n("archive.name"), (result, resolve, reject) -> {
|
||||
Controllers.prompt(i18n("archive.file.name"), (result, resolve, reject) -> {
|
||||
if (!OperatingSystem.isNameValid(result)) {
|
||||
reject.accept(i18n("install.new_game.malformed"));
|
||||
return;
|
||||
|
@ -54,7 +54,7 @@ public class InstallersPage extends Control implements WizardPage {
|
||||
|
||||
public InstallersPage(WizardController controller, HMCLGameRepository repository, String gameVersion, DownloadProvider downloadProvider) {
|
||||
this.controller = controller;
|
||||
this.group = new InstallerItem.InstallerItemGroup(gameVersion);
|
||||
this.group = new InstallerItem.InstallerItemGroup(gameVersion, getInstallerItemStyle());
|
||||
|
||||
txtName.getValidators().addAll(
|
||||
new RequiredValidator(),
|
||||
@ -63,33 +63,31 @@ public class InstallersPage extends Control implements WizardPage {
|
||||
installable.bind(createBooleanBinding(txtName::validate, txtName.textProperty()));
|
||||
txtName.setText(gameVersion);
|
||||
|
||||
group.game.installable.setValue(false);
|
||||
|
||||
for (InstallerItem item : group.getLibraries()) {
|
||||
item.setStyleMode(InstallerItem.Style.CARD);
|
||||
}
|
||||
|
||||
for (InstallerItem library : group.getLibraries()) {
|
||||
String libraryId = library.getLibraryId();
|
||||
if (libraryId.equals(LibraryAnalyzer.LibraryType.MINECRAFT.getPatchId())) continue;
|
||||
library.action.set(e -> {
|
||||
library.installActionProperty().set(e -> {
|
||||
if (LibraryAnalyzer.LibraryType.FABRIC_API.getPatchId().equals(libraryId)) {
|
||||
Controllers.dialog(i18n("install.installer.fabric-api.warning"), i18n("message.warning"), MessageDialogPane.MessageType.WARNING);
|
||||
}
|
||||
|
||||
if (library.incompatibleLibraryName.get() == null)
|
||||
if (!(library.resolvedStateProperty().get() instanceof InstallerItem.IncompatibleState))
|
||||
controller.onNext(new VersionsPage(controller, i18n("install.installer.choose", i18n("install.installer." + libraryId)), gameVersion, downloadProvider, libraryId, () -> controller.onPrev(false)));
|
||||
});
|
||||
library.removeAction.set(e -> {
|
||||
library.removeActionProperty().set(e -> {
|
||||
controller.getSettings().remove(libraryId);
|
||||
reload();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
protected InstallerItem.Style getInstallerItemStyle() {
|
||||
return InstallerItem.Style.CARD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return i18n("install.new_game");
|
||||
return group.getGame().versionProperty().get().getVersion();
|
||||
}
|
||||
|
||||
private String getVersion(String id) {
|
||||
@ -100,11 +98,9 @@ public class InstallersPage extends Control implements WizardPage {
|
||||
for (InstallerItem library : group.getLibraries()) {
|
||||
String libraryId = library.getLibraryId();
|
||||
if (controller.getSettings().containsKey(libraryId)) {
|
||||
library.libraryVersion.set(getVersion(libraryId));
|
||||
library.removable.set(true);
|
||||
library.versionProperty().set(new InstallerItem.InstalledState(getVersion(libraryId), false, false));
|
||||
} else {
|
||||
library.libraryVersion.set(null);
|
||||
library.removable.set(false);
|
||||
library.versionProperty().set(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -148,7 +144,7 @@ public class InstallersPage extends Control implements WizardPage {
|
||||
versionNamePane.setAlignment(Pos.CENTER_LEFT);
|
||||
|
||||
control.txtName.setMaxWidth(300);
|
||||
versionNamePane.getChildren().setAll(new Label(i18n("archive.name")), control.txtName);
|
||||
versionNamePane.getChildren().setAll(new Label(i18n("version.name")), control.txtName);
|
||||
root.setTop(versionNamePane);
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ public abstract class ModpackPage extends SpinnerPane implements WizardPage {
|
||||
|
||||
BorderPane archiveNamePane = new BorderPane();
|
||||
{
|
||||
Label label = new Label(i18n("archive.name"));
|
||||
Label label = new Label(i18n("archive.file.name"));
|
||||
BorderPane.setAlignment(label, Pos.CENTER_LEFT);
|
||||
archiveNamePane.setLeft(label);
|
||||
|
||||
|
@ -38,7 +38,6 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static org.jackhuang.hmcl.ui.FXUtils.runInFX;
|
||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||
@ -73,37 +72,36 @@ public class InstallerListPage extends ListPageBase<InstallerItem> implements Ve
|
||||
|
||||
return LibraryAnalyzer.analyze(profile.getRepository().getResolvedPreservingPatchesVersion(versionId), gameVersion);
|
||||
}).thenAcceptAsync(analyzer -> {
|
||||
Function<String, Runnable> removeAction = libraryId -> () -> {
|
||||
profile.getDependency().removeLibraryAsync(version, libraryId)
|
||||
itemsProperty().clear();
|
||||
|
||||
InstallerItem.InstallerItemGroup group = new InstallerItem.InstallerItemGroup(gameVersion, InstallerItem.Style.LIST_ITEM);
|
||||
|
||||
// Conventional libraries: game, fabric, forge, neoforge, liteloader, optifine
|
||||
for (InstallerItem item : group.getLibraries()) {
|
||||
String libraryId = item.getLibraryId();
|
||||
String libraryVersion = analyzer.getVersion(libraryId).orElse(null);
|
||||
|
||||
if (libraryVersion != null) {
|
||||
item.versionProperty().set(new InstallerItem.InstalledState(
|
||||
libraryVersion,
|
||||
analyzer.getLibraryStatus(libraryId) != LibraryAnalyzer.LibraryMark.LibraryStatus.CLEAR,
|
||||
false
|
||||
));
|
||||
} else {
|
||||
item.versionProperty().set(null);
|
||||
}
|
||||
|
||||
item.installActionProperty().set(e -> {
|
||||
Controllers.getDecorator().startWizard(new UpdateInstallerWizardProvider(profile, gameVersion, version, libraryId, libraryVersion));
|
||||
});
|
||||
|
||||
item.removeActionProperty().set(e -> profile.getDependency().removeLibraryAsync(version, libraryId)
|
||||
.thenComposeAsync(profile.getRepository()::saveAsync)
|
||||
.withComposeAsync(profile.getRepository().refreshVersionsAsync())
|
||||
.withRunAsync(Schedulers.javafx(), () -> loadVersion(this.profile, this.versionId))
|
||||
.start();
|
||||
};
|
||||
.start());
|
||||
|
||||
itemsProperty().clear();
|
||||
|
||||
InstallerItem.InstallerItemGroup group = new InstallerItem.InstallerItemGroup(gameVersion);
|
||||
|
||||
// Conventional libraries: game, fabric, forge, neoforge, liteloader, optifine
|
||||
for (InstallerItem installerItem : group.getLibraries()) {
|
||||
String libraryId = installerItem.getLibraryId();
|
||||
String libraryVersion = analyzer.getVersion(libraryId).orElse(null);
|
||||
boolean libraryConfigurable = libraryVersion != null && analyzer.getLibraryStatus(libraryId) == LibraryAnalyzer.LibraryMark.LibraryStatus.CLEAR;
|
||||
|
||||
installerItem.libraryVersion.set(libraryVersion);
|
||||
installerItem.upgradable.set(libraryConfigurable);
|
||||
installerItem.installable.set(true);
|
||||
installerItem.action.set(e -> {
|
||||
Controllers.getDecorator().startWizard(new UpdateInstallerWizardProvider(profile, gameVersion, version, libraryId, libraryVersion));
|
||||
});
|
||||
boolean removable = !LibraryAnalyzer.LibraryType.MINECRAFT.getPatchId().equals(libraryId) && libraryConfigurable;
|
||||
installerItem.removable.set(removable);
|
||||
if (removable) {
|
||||
Runnable action = removeAction.apply(libraryId);
|
||||
installerItem.removeAction.set(e -> action.run());
|
||||
}
|
||||
itemsProperty().add(installerItem);
|
||||
itemsProperty().add(item);
|
||||
}
|
||||
|
||||
// other third-party libraries which are unable to manage.
|
||||
@ -115,14 +113,13 @@ public class InstallerListPage extends ListPageBase<InstallerItem> implements Ve
|
||||
if (LibraryAnalyzer.LibraryType.fromPatchId(libraryId) != null)
|
||||
continue;
|
||||
|
||||
Runnable action = removeAction.apply(libraryId);
|
||||
|
||||
InstallerItem installerItem = new InstallerItem(libraryId);
|
||||
installerItem.libraryVersion.set(libraryVersion);
|
||||
installerItem.installable.set(false);
|
||||
installerItem.upgradable.set(false);
|
||||
installerItem.removable.set(true);
|
||||
installerItem.removeAction.set(e -> action.run());
|
||||
InstallerItem installerItem = new InstallerItem(libraryId, InstallerItem.Style.LIST_ITEM);
|
||||
installerItem.versionProperty().set(new InstallerItem.InstalledState(libraryVersion, false, false));
|
||||
installerItem.removeActionProperty().set(e -> profile.getDependency().removeLibraryAsync(version, libraryId)
|
||||
.thenComposeAsync(profile.getRepository()::saveAsync)
|
||||
.withComposeAsync(profile.getRepository().refreshVersionsAsync())
|
||||
.withRunAsync(Schedulers.javafx(), () -> loadVersion(this.profile, this.versionId))
|
||||
.start());
|
||||
|
||||
itemsProperty().add(installerItem);
|
||||
}
|
||||
|
@ -260,7 +260,7 @@ class ModListPageSkin extends SkinBase<ModListPage> {
|
||||
|
||||
StringBuilder message = new StringBuilder(localModFile.getFileName());
|
||||
if (isNotBlank(localModFile.getGameVersion()))
|
||||
message.append(", ").append(i18n("archive.game_version")).append(": ").append(localModFile.getGameVersion());
|
||||
message.append(", ").append(i18n("game.version")).append(": ").append(localModFile.getGameVersion());
|
||||
if (isNotBlank(localModFile.getAuthors()))
|
||||
message.append(", ").append(i18n("archive.author")).append(": ").append(localModFile.getAuthors());
|
||||
this.message = message.toString();
|
||||
|
@ -159,8 +159,7 @@ account.username=Username
|
||||
|
||||
archive.author=Author(s)
|
||||
archive.date=Publish Date
|
||||
archive.game_version=Game Version
|
||||
archive.name=Filename
|
||||
archive.file.name=File Name
|
||||
archive.version=Version
|
||||
|
||||
assets.download=Downloading Assets
|
||||
@ -615,7 +614,7 @@ install.failed.malformed=The downloaded files are corrupted. You can try fixing
|
||||
install.failed.optifine_conflict=Cannot install both Fabric, OptiFine, and Forge on Minecraft 1.13 or above.
|
||||
install.failed.optifine_forge_1.17=For Minecraft version 1.17.1 or lower, Forge only supports OptiFine H1 Pre2 or newer. You can install them under the snapshot versions tab.
|
||||
install.failed.version_mismatch=This library requires the game version %s, but the installed one is %s.
|
||||
install.installer.change_version=Version %s is not compatible with the current game version. Click here to replace it with another version or delete it.
|
||||
install.installer.change_version=%s Incompatible
|
||||
install.installer.choose=Choose Your %s Version
|
||||
install.installer.depend=Requires %s
|
||||
install.installer.fabric=Fabric
|
||||
@ -1224,6 +1223,7 @@ update.no_browser=Cannot open in the system browser. But, we copied the link to
|
||||
update.tooltip=Update
|
||||
|
||||
version=Games
|
||||
version.name=Instance Name
|
||||
version.cannot_read=Unable to parse the game version, automatic installation cannot continue.
|
||||
version.empty=No Instances
|
||||
version.empty.add=Add an Instance
|
||||
|
@ -138,8 +138,7 @@ account.username=Nombre de usuario
|
||||
|
||||
archive.author=Autor(es)
|
||||
archive.date=Fecha de publicación
|
||||
archive.game_version=Versión del juego
|
||||
archive.name=Nombre de archivo
|
||||
archive.file.name=Nombre de archivo
|
||||
archive.version=Versión
|
||||
|
||||
assets.download=Descargando assets
|
||||
|
@ -125,8 +125,7 @@ account.username=ユーザー名
|
||||
|
||||
archive.author=作成者
|
||||
archive.date=公開日
|
||||
archive.game_version=ゲームバージョン
|
||||
archive.name=名前
|
||||
archive.file.name=名前
|
||||
archive.version=バージョン
|
||||
|
||||
Assets.download=アセットのダウンロード
|
||||
|
@ -133,8 +133,7 @@ account.username=Имя пользователя
|
||||
|
||||
archive.author=Автор(ы)
|
||||
archive.date=Дата публикации
|
||||
archive.game_version=Версия игры
|
||||
archive.name=Имя файла
|
||||
archive.file.name=Имя файла
|
||||
archive.version=Версия
|
||||
|
||||
assets.download=Скачивание Assets
|
||||
|
@ -168,8 +168,7 @@ account.username=使用者名稱
|
||||
|
||||
archive.author=作者
|
||||
archive.date=發布日期
|
||||
archive.game_version=遊戲版本
|
||||
archive.name=名稱
|
||||
archive.file.name=檔案名稱
|
||||
archive.version=版本
|
||||
|
||||
assets.download=下載資源
|
||||
@ -499,7 +498,7 @@ install.failed.malformed=剛才下載的檔案格式損壞。您可以切換到
|
||||
install.failed.optifine_conflict=暫不支援 OptiFine 與 Forge 同時安裝在 Minecraft 1.13 上
|
||||
install.failed.optifine_forge_1.17=Minecraft 1.17.1 下,僅 OptiFine H1 Pre2 及以上版本能相容 Forge。你可以從 OptiFine 測試版中選擇最新版本。
|
||||
install.failed.version_mismatch=該軟體需要的遊戲版本為 %s,但實際的遊戲版本為 %s。
|
||||
install.installer.change_version=%s,該版本與當前遊戲不相容,您需要點擊此處更換版本或刪除
|
||||
install.installer.change_version=%s 與當前遊戲不相容,請更換版本
|
||||
install.installer.choose=選擇 %s 版本
|
||||
install.installer.depend=需要先安裝 %s
|
||||
install.installer.fabric=Fabric
|
||||
@ -1081,6 +1080,7 @@ update.no_browser=無法開啟瀏覽器,網址已經複製到剪貼簿了,
|
||||
update.tooltip=更新
|
||||
|
||||
version=遊戲
|
||||
version.name=遊戲版本名稱
|
||||
version.cannot_read=讀取遊戲版本失敗,無法進行自動安裝
|
||||
version.empty=沒有遊戲版本
|
||||
version.empty.add=進入下載頁安裝遊戲
|
||||
|
@ -169,8 +169,7 @@ account.username=用户名
|
||||
|
||||
archive.author=作者
|
||||
archive.date=发布日期
|
||||
archive.game_version=游戏版本
|
||||
archive.name=名称
|
||||
archive.file.name=文件名
|
||||
archive.version=版本
|
||||
|
||||
assets.download=下载资源
|
||||
@ -498,7 +497,7 @@ install.failed.malformed=下载的文件格式损坏。您可以在设置-下载
|
||||
install.failed.optifine_conflict=暂不支持 OptiFine, Fabric 或 OptiFine , Forge 同时安装在 Minecraft 1.13 及以上版本
|
||||
install.failed.optifine_forge_1.17=Minecraft 1.17.1 下,仅 OptiFine H1 Pre2 及以上版本能兼容 Forge。你可以从 OptiFine 测试版中选择最新版本。
|
||||
install.failed.version_mismatch=该组件需要的游戏版本为 %s,但实际的游戏版本为 %s。
|
||||
install.installer.change_version=%s,该版本与当前游戏不兼容,您需要点击此处更换版本或删除
|
||||
install.installer.change_version=%s 与当前游戏不兼容,请更换版本
|
||||
install.installer.choose=选择 %s 版本
|
||||
install.installer.depend=需要先安装 %s
|
||||
install.installer.fabric=Fabric
|
||||
@ -1080,6 +1079,7 @@ update.no_browser=无法打开浏览器,网址已经复制到剪贴板了,
|
||||
update.tooltip=更新
|
||||
|
||||
version=游戏
|
||||
version.name=游戏版本名称
|
||||
version.cannot_read=读取游戏版本失败,无法进行自动安装
|
||||
version.empty=没有游戏版本
|
||||
version.empty.add=进入下载页安装游戏
|
||||
|
@ -296,8 +296,8 @@ public class Version implements Comparable<Version>, Validation {
|
||||
}
|
||||
|
||||
if (patches == null) {
|
||||
// This is a version from external launcher.
|
||||
thisVersion = thisVersion.merge(this, true);
|
||||
// This is a version from external launcher. NO need to resolve the patches.
|
||||
return thisVersion;
|
||||
} else if (!patches.isEmpty()) {
|
||||
// Assume patches themselves do not have patches recursively.
|
||||
List<Version> sortedPatches = patches.stream()
|
||||
|
@ -54,7 +54,7 @@
|
||||
<module name="ThrowsCount"> <!-- max 5 throws definitions per method: http://checkstyle.sourceforge.net/config_design.html#ThrowsCount -->
|
||||
<property name="max" value="5"/>
|
||||
</module>
|
||||
<module name="InterfaceIsType"/> <!-- interface must contain methods, should not be used for const only: http://checkstyle.sourceforge.net/config_design.html#InterfaceIsType -->
|
||||
<!--<module name="InterfaceIsType"/> interface must contain methods, should not be used for const only: http://checkstyle.sourceforge.net/config_design.html#InterfaceIsType -->
|
||||
<module name="OuterTypeFilename"/> <!-- class Foo must be in Foo.java: http://checkstyle.sourceforge.net/config_misc.html#OuterTypeFilename -->
|
||||
|
||||
<module name="HideUtilityClassConstructor"/> <!-- utility class constructor must be private: http://checkstyle.sourceforge.net/config_design.html#HideUtilityClassConstructor -->
|
||||
|
Loading…
x
Reference in New Issue
Block a user