From e8306ea59a517b4367c070dca8bc5029ccf5895e Mon Sep 17 00:00:00 2001 From: Burning_TNT <88144530+burningtnt@users.noreply.github.com> Date: Sun, 28 Jul 2024 02:41:08 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20#3099=20=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=AE=89=E8=A3=85=E9=80=89=E9=A1=B9=E5=8D=A1=E9=87=8D=E6=96=B0?= =?UTF-8?q?=E9=80=89=E6=8B=A9=E7=89=88=E6=9C=AC=EF=BC=88Minecraft=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E5=92=8C=E6=A8=A1=E7=BB=84=E5=8A=A0=E8=BD=BD=E5=99=A8?= =?UTF-8?q?=E7=89=88=E6=9C=AC=EF=BC=89=E7=9A=84=E6=8C=89=E9=92=AE=E6=B6=88?= =?UTF-8?q?=E5=A4=B1=E7=9A=84=E9=97=AE=E9=A2=98=20(#3117)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix #3099 * Fix: checkstyle * Fix. * Fix #3144 * Update * Fix bugs. * Change I18N * Fix #3164 * Delete State.SEALED * fix typo --------- Co-authored-by: Glavo --- .../jackhuang/hmcl/ui/GameCrashWindow.java | 2 +- .../org/jackhuang/hmcl/ui/InstallerItem.java | 300 ++++++++++++------ .../ui/download/AdditionalInstallersPage.java | 10 +- .../hmcl/ui/download/DownloadPage.java | 2 +- .../hmcl/ui/download/InstallersPage.java | 28 +- .../hmcl/ui/download/ModpackPage.java | 2 +- .../hmcl/ui/versions/InstallerListPage.java | 69 ++-- .../hmcl/ui/versions/ModListPageSkin.java | 2 +- .../resources/assets/lang/I18N.properties | 6 +- .../resources/assets/lang/I18N_es.properties | 3 +- .../resources/assets/lang/I18N_ja.properties | 3 +- .../resources/assets/lang/I18N_ru.properties | 3 +- .../resources/assets/lang/I18N_zh.properties | 6 +- .../assets/lang/I18N_zh_CN.properties | 6 +- .../java/org/jackhuang/hmcl/game/Version.java | 4 +- config/checkstyle/checkstyle.xml | 2 +- 16 files changed, 266 insertions(+), 182 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameCrashWindow.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameCrashWindow.java index 327d17a30..50ec8535a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameCrashWindow.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameCrashWindow.java @@ -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(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerItem.java index b6cf2a2de..4a6bffe79 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerItem.java @@ -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> removeAction = new SimpleObjectProperty<>(); - public final ObjectProperty> action = new SimpleObjectProperty<>(); + private final Style style; + private final ObjectProperty versionProperty = new SimpleObjectProperty<>(this, "version", null); + private final ObjectProperty resolvedStateProperty = new SimpleObjectProperty<>(this, "resolvedState", InstallableState.INSTANCE); - private Style style = Style.LIST_ITEM; + private final ObjectProperty> installActionProperty = new SimpleObjectProperty<>(this, "installAction"); + private final ObjectProperty> 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 versionProperty() { + return versionProperty; + } + + public ObjectProperty resolvedStateProperty() { + return resolvedStateProperty; + } + + public ObjectProperty> installActionProperty() { + return installActionProperty; + } + + public ObjectProperty> 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> incompatibleMap = new HashMap<>(); - - private Set getIncompatibles(InstallerItem item) { + private Set getIncompatibles(Map> incompatibleMap, InstallerItem item) { return incompatibleMap.computeIfAbsent(item, it -> new HashSet<>()); } - private void addIncompatibles(InstallerItem item, InstallerItem... others) { - Set set = getIncompatibles(item); + private void addIncompatibles(Map> incompatibleMap, InstallerItem item, InstallerItem... others) { + Set 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> incompatibleMap, InstallerItem... items) { for (InstallerItem item : items) { - Set set = getIncompatibles(item); + Set 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> entry : incompatibleMap.entrySet()) { - InstallerItem item = entry.getKey(); + Map> 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> entry : incompatibleMap.entrySet()) { + InstallerItem item = entry.getKey(); + Set 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 { - + private static final class InstallerItemSkin extends SkinBase { 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(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/AdditionalInstallersPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/AdditionalInstallersPage.java index 0bbb02d65..e2b14a598 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/AdditionalInstallersPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/AdditionalInstallersPage.java @@ -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); } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/DownloadPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/DownloadPage.java index 72d033ca8..20a0692bd 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/DownloadPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/DownloadPage.java @@ -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; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java index aa6cc4fa8..b9c8e0c33 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java @@ -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); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackPage.java index 0f93bd0ce..2240b5d18 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackPage.java @@ -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); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java index d65df18fc..aea2967a7 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java @@ -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 implements Ve return LibraryAnalyzer.analyze(profile.getRepository().getResolvedPreservingPatchesVersion(versionId), gameVersion); }).thenAcceptAsync(analyzer -> { - Function 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 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); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java index 188a72bb8..acd647a5f 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java @@ -260,7 +260,7 @@ class ModListPageSkin extends SkinBase { 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(); diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 18b995dac..dc1bdd651 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -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 diff --git a/HMCL/src/main/resources/assets/lang/I18N_es.properties b/HMCL/src/main/resources/assets/lang/I18N_es.properties index a629abbda..0172d1c54 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_es.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_es.properties @@ -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 diff --git a/HMCL/src/main/resources/assets/lang/I18N_ja.properties b/HMCL/src/main/resources/assets/lang/I18N_ja.properties index d77dd2b54..057ddc5e9 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ja.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ja.properties @@ -125,8 +125,7 @@ account.username=ユーザー名 archive.author=作成者 archive.date=公開日 -archive.game_version=ゲームバージョン -archive.name=名前 +archive.file.name=名前 archive.version=バージョン Assets.download=アセットのダウンロード diff --git a/HMCL/src/main/resources/assets/lang/I18N_ru.properties b/HMCL/src/main/resources/assets/lang/I18N_ru.properties index 928b699d2..37b91035a 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ru.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ru.properties @@ -133,8 +133,7 @@ account.username=Имя пользователя archive.author=Автор(ы) archive.date=Дата публикации -archive.game_version=Версия игры -archive.name=Имя файла +archive.file.name=Имя файла archive.version=Версия assets.download=Скачивание Assets diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index dc00ac149..a11eb2474 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -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=進入下載頁安裝遊戲 diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties index 8a5028d8f..ededc00cd 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -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=进入下载页安装游戏 diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/Version.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/Version.java index b50bdd83c..16bda75f0 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/Version.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/Version.java @@ -296,8 +296,8 @@ public class Version implements Comparable, 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 sortedPatches = patches.stream() diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index daa5be2bf..900c4340d 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -54,7 +54,7 @@ - +