diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/Main.java b/HMCL/src/main/java/org/jackhuang/hmcl/Main.java index eadf885b8..d576cbf10 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/Main.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/Main.java @@ -57,7 +57,7 @@ public final class Main extends Application { Logging.LOG.info("*** " + TITLE + " ***"); UPDATE_CHECKER.process(false) - .then(Task.of(Controllers::showUpdate)) + .then(Task.of(Schedulers.javafx(), Controllers::showUpdate)) .start(); launch(args); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java index d2da74db1..3912de35a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java @@ -49,6 +49,10 @@ public class HMCLGameRepository extends DefaultGameRepository { this.profile = profile; } + public Profile getProfile() { + return profile; + } + private boolean useSelf(String version, String assetId) { VersionSetting vs = profile.getVersionSetting(version); return new File(getBaseDirectory(), "assets/indexes/" + assetId + ".json").exists() || vs.isNoCommon(); @@ -94,8 +98,6 @@ public class HMCLGameRepository extends DefaultGameRepository { super.refreshVersionsImpl(); versions.keySet().forEach(this::loadVersionSetting); - checkModpack(); - try { File file = new File(getBaseDirectory(), "launcher_profiles.json"); if (!file.exists() && !versions.isEmpty()) @@ -117,26 +119,6 @@ public class HMCLGameRepository extends DefaultGameRepository { refreshVersionsAsync().start(); } - private void checkModpack() { - - if (!checkingModpack) { - checkingModpack = true; - if (getVersionCount() == 0) { - File modpack = new File("modpack.zip").getAbsoluteFile(); - if (modpack.exists()) { - // TODO - } - /* - SwingUtilities.invokeLater(() -> { - if (TaskWindow.factory().execute(ModpackManager.install(MainFrame.INSTANCE, modpack, this, null))) - refreshVersions(); - checkedModpack = true; - }); - */ - } - } - } - private File getVersionSettingFile(String id) { return new File(getVersionRoot(id), "hmclversion.cfg"); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java index d7422f9e3..76f2ac5a3 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -159,8 +159,8 @@ public final class LauncherHelper { if (state == LoadingState.DONE) Controllers.closeDialog(); - launchingStepsPane.setCurrentState(state.getLocalizedMessage()); - launchingStepsPane.setSteps((state.ordinal() + 1) + " / " + LoadingState.values().length); + launchingStepsPane.setTitle(state.getLocalizedMessage()); + launchingStepsPane.setSubtitle((state.ordinal() + 1) + " / " + LoadingState.values().length); Controllers.dialog(launchingStepsPane); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java index 393892415..5e7390eff 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java @@ -81,6 +81,30 @@ public final class ModpackHelper { throw new UnsupportedModpackException(); } + public static Task getInstallTask(Profile profile, File zipFile, String name, Modpack modpack) { + profile.getRepository().markVersionAsModpack(name); + + Task finalizeTask = Task.of(() -> { + profile.getRepository().refreshVersions(); + VersionSetting vs = profile.specializeVersionSetting(name); + profile.getRepository().undoMark(name); + if (vs != null) + vs.setGameDirType(EnumGameDirectory.VERSION_FOLDER); + }); + + if (modpack.getManifest() instanceof CurseManifest) + return new CurseInstallTask(profile.getDependency(), zipFile, ((CurseManifest) modpack.getManifest()), name) + .finalized(finalizeTask); + else if (modpack.getManifest() instanceof HMCLModpackManifest) + return new HMCLModpackInstallTask(profile, zipFile, modpack, name) + .finalized(finalizeTask); + else if (modpack.getManifest() instanceof MultiMCInstanceConfiguration) + return new MultiMCModpackInstallTask(profile.getDependency(), zipFile, ((MultiMCInstanceConfiguration) modpack.getManifest()), name) + .finalized(finalizeTask) + .with(new MultiMCInstallVersionSettingTask(profile, ((MultiMCInstanceConfiguration) modpack.getManifest()), name)); + else throw new IllegalStateException("Unrecognized modpack: " + modpack); + } + public static Task getUpdateTask(Profile profile, File zipFile, String name, ModpackConfiguration configuration) throws UnsupportedModpackException, MismatchedModpackTypeException, IOException { Modpack modpack = ModpackHelper.readModpackManifest(zipFile); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java index 0a569b2f2..4a3c0f0c9 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java @@ -26,9 +26,11 @@ import javafx.stage.Stage; import org.jackhuang.hmcl.Main; import org.jackhuang.hmcl.setting.Settings; import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.task.TaskExecutor; import org.jackhuang.hmcl.ui.construct.InputDialogPane; import org.jackhuang.hmcl.ui.construct.MessageBox; import org.jackhuang.hmcl.ui.construct.MessageDialogPane; +import org.jackhuang.hmcl.ui.construct.TaskExecutorDialogPane; import org.jackhuang.hmcl.util.JavaVersion; import java.util.function.Consumer; @@ -132,6 +134,15 @@ public final class Controllers { dialog(new InputDialogPane(text, decorator.getDialog(), onResult)); } + public static void taskDialog(TaskExecutor executor, String title, String subtitle, Runnable onCancel) { + TaskExecutorDialogPane pane = new TaskExecutorDialogPane(onCancel); + pane.setTitle(title); + pane.setSubtitle(subtitle); + pane.setExecutor(executor); + executor.start(); + dialog(pane); + } + public static void closeDialog() { decorator.getDialog().close(); } @@ -141,6 +152,6 @@ public final class Controllers { } public static void showUpdate() { - + getDecorator().showUpdate(); } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerController.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerController.java index 9ab785ec7..8a303cc9d 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerController.java @@ -83,9 +83,9 @@ public class InstallerController { public void onAdd() { String gameVersion = GameVersion.minecraftVersion(profile.getRepository().getVersionJar(version)); - // TODO: if minecraftVersion returns null. - if (gameVersion == null) return; - - Controllers.getDecorator().startWizard(new InstallerWizardProvider(profile, gameVersion, version, forge, liteLoader, optiFine)); + if (gameVersion == null) + Controllers.dialog("version.cannot_read"); + else + Controllers.getDecorator().startWizard(new InstallerWizardProvider(profile, gameVersion, version, forge, liteLoader, optiFine)); } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java index cc0a70967..b12a853fc 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java @@ -17,6 +17,7 @@ */ package org.jackhuang.hmcl.ui; +import com.jfoenix.concurrency.JFXUtilities; import javafx.application.Platform; import javafx.scene.Node; import javafx.scene.layout.VBox; @@ -26,14 +27,23 @@ import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount; import org.jackhuang.hmcl.event.EventBus; import org.jackhuang.hmcl.event.ProfileChangedEvent; import org.jackhuang.hmcl.event.ProfileLoadingEvent; +import org.jackhuang.hmcl.event.RefreshedVersionsEvent; import org.jackhuang.hmcl.game.AccountHelper; +import org.jackhuang.hmcl.game.HMCLGameRepository; +import org.jackhuang.hmcl.game.ModpackHelper; +import org.jackhuang.hmcl.mod.Modpack; +import org.jackhuang.hmcl.mod.UnsupportedModpackException; import org.jackhuang.hmcl.setting.Profile; import org.jackhuang.hmcl.setting.Settings; +import org.jackhuang.hmcl.task.Schedulers; +import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.ui.construct.IconedItem; import org.jackhuang.hmcl.ui.construct.RipplerContainer; +import org.jackhuang.hmcl.ui.construct.TaskExecutorDialogPane; import org.jackhuang.hmcl.util.Lang; import org.jackhuang.hmcl.util.Pair; +import java.io.File; import java.util.LinkedList; import java.util.Objects; @@ -60,6 +70,7 @@ public final class LeftPaneController { EventBus.EVENT_BUS.channel(ProfileLoadingEvent.class).register(this::onProfilesLoading); EventBus.EVENT_BUS.channel(ProfileChangedEvent.class).register(this::onProfileChanged); + EventBus.EVENT_BUS.channel(RefreshedVersionsEvent.class).register(this::onRefreshedVersions); Controllers.getDecorator().getAddMenuButton().setOnMouseClicked(e -> Controllers.getDecorator().showPage(new ProfilePage(null)) @@ -79,12 +90,9 @@ public final class LeftPaneController { else accountItem.setImage(FXUtils.DEFAULT_ICON, null); }); - - if (Settings.INSTANCE.getAccounts().isEmpty()) - Controllers.navigate(new AccountsPage()); } - public void onProfileChanged(ProfileChangedEvent event) { + private void onProfileChanged(ProfileChangedEvent event) { Profile profile = event.getProfile(); for (Node node : profilePane.getChildren()) { @@ -94,7 +102,7 @@ public final class LeftPaneController { } } - public void onProfilesLoading() { + private void onProfilesLoading() { LinkedList list = new LinkedList<>(); for (Profile profile : Settings.INSTANCE.getProfiles()) { VersionListItem item = new VersionListItem(profile.getName()); @@ -115,4 +123,41 @@ public final class LeftPaneController { } Platform.runLater(() -> profilePane.getChildren().setAll(list)); } + + private boolean checkedModpack = false; + + private void onRefreshedVersions(RefreshedVersionsEvent event) { + JFXUtilities.runInFX(() -> { + boolean flag = true; + HMCLGameRepository repository = (HMCLGameRepository) event.getSource(); + if (!checkedModpack) { + checkedModpack = true; + + if (repository.getVersionCount() == 0) { + File modpackFile = new File("modpack.zip").getAbsoluteFile(); + if (modpackFile.exists()) { + try { + Modpack modpack = ModpackHelper.readModpackManifest(modpackFile); + Controllers.taskDialog(ModpackHelper.getInstallTask(repository.getProfile(), modpackFile, modpack.getName(), modpack) + .with(Task.of(Schedulers.javafx(), () -> { + Controllers.closeDialog(); + checkAccount(); + })).executor(), + Main.i18n("modpack.installing"), "", null); + flag = false; + } catch (UnsupportedModpackException ignore) { + } + } + } + } + + if (flag) + checkAccount(); + }); + } + + private void checkAccount() { + if (Settings.INSTANCE.getAccounts().isEmpty()) + Controllers.navigate(new AccountsPage()); + } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java index 5da095ca9..35ddac36a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java @@ -137,7 +137,7 @@ public final class MainPage extends StackPane implements DecoratorPage { TaskExecutor executor = ModpackHelper.getUpdateTask(profile, selectedFile, version, ModpackHelper.readModpackConfiguration(profile.getRepository().getModpackConfiguration(version))) .then(Task.of(Schedulers.javafx(), Controllers::closeDialog)).executor(); pane.setExecutor(executor); - pane.setCurrentState(Main.i18n("modpack.update")); + pane.setTitle(Main.i18n("modpack.update")); executor.start(); Controllers.dialog(pane); } catch (UnsupportedModpackException e) { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionSettingsController.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionSettingsController.java index fbc09a370..e9668dda5 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionSettingsController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionSettingsController.java @@ -112,6 +112,9 @@ public final class VersionSettingsController { javaItem.loadChildren(variables.>get("list")) ); + if (OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS) + javaItem.getExtensionFilters().add(new FileChooser.ExtensionFilter("Java", "java.exe", "javaw.exe")); + gameDirItem.loadChildren(Arrays.asList( gameDirItem.createChildren(Main.i18n("settings.advanced.game_dir.default"), EnumGameDirectory.ROOT_FOLDER), gameDirItem.createChildren(Main.i18n("settings.advanced.game_dir.independent"), EnumGameDirectory.VERSION_FOLDER) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FileItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FileItem.java index 3a3e9bf6a..3699f2c93 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FileItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FileItem.java @@ -63,8 +63,16 @@ public class FileItem extends BorderPane { public void onExplore() { DirectoryChooser chooser = new DirectoryChooser(); - if (property.getValue() != null) - chooser.setInitialDirectory(new File(property.getValue())); + if (property.getValue() != null) { + File file = new File(property.getValue()); + if (file.exists()) { + if (file.isFile()) + file = file.getAbsoluteFile().getParentFile(); + else if (file.isDirectory()) + file = file.getAbsoluteFile(); + chooser.setInitialDirectory(file); + } + } chooser.titleProperty().bind(titleProperty()); File selectedDir = chooser.showDialog(Controllers.getStage()); if (selectedDir != null) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MultiFileItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MultiFileItem.java index 3cd06fa81..cf3530776 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MultiFileItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MultiFileItem.java @@ -20,8 +20,12 @@ package org.jackhuang.hmcl.ui.construct; import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXRadioButton; import com.jfoenix.controls.JFXTextField; +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; import javafx.geometry.Pos; import javafx.scene.Node; import javafx.scene.control.Label; @@ -30,6 +34,7 @@ import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; import javafx.stage.DirectoryChooser; +import javafx.stage.FileChooser; import org.jackhuang.hmcl.Main; import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.ui.FXUtils; @@ -39,8 +44,10 @@ import java.io.File; import java.util.Collection; public class MultiFileItem extends ComponentList { - private final StringProperty customText = new SimpleStringProperty(this, "customText", "Custom"); - private final StringProperty chooserTitle = new SimpleStringProperty(this, "chooserTitle", "Select a file"); + private final StringProperty customTitle = new SimpleStringProperty(this, "customTitle", Main.i18n("selector.custom")); + private final StringProperty chooserTitle = new SimpleStringProperty(this, "chooserTitle", Main.i18n("selector.choose_file")); + private final BooleanProperty directory = new SimpleBooleanProperty(this, "directory", false); + private ObservableList extensionFilters = FXCollections.observableArrayList(); private final ToggleGroup group = new ToggleGroup(); private final JFXTextField txtCustom = new JFXTextField(); @@ -54,10 +61,23 @@ public class MultiFileItem extends ComponentList { btnSelect.setGraphic(SVG.folderOpen("black", 15, 15)); btnSelect.setOnMouseClicked(e -> { - // TODO + if (isDirectory()) { + DirectoryChooser chooser = new DirectoryChooser(); + chooser.titleProperty().bind(chooserTitle); + File dir = chooser.showDialog(Controllers.getStage()); + if (dir != null) + txtCustom.setText(dir.getAbsolutePath()); + } else { + FileChooser chooser = new FileChooser(); + chooser.getExtensionFilters().addAll(getExtensionFilters()); + chooser.titleProperty().bind(chooserTitle); + File file = chooser.showOpenDialog(Controllers.getStage()); + if (file != null) + txtCustom.setText(file.getAbsolutePath()); + } }); - radioCustom.textProperty().bind(customTextProperty()); + radioCustom.textProperty().bind(customTitleProperty()); radioCustom.setToggleGroup(group); txtCustom.disableProperty().bind(radioCustom.selectedProperty().not()); btnSelect.disableProperty().bind(radioCustom.selectedProperty().not()); @@ -119,16 +139,16 @@ public class MultiFileItem extends ComponentList { return group; } - public String getCustomText() { - return customText.get(); + public String getCustomTitle() { + return customTitle.get(); } - public StringProperty customTextProperty() { - return customText; + public StringProperty customTitleProperty() { + return customTitle; } - public void setCustomText(String customText) { - this.customText.set(customText); + public void setCustomTitle(String customTitle) { + this.customTitle.set(customTitle); } public String getChooserTitle() { @@ -151,7 +171,35 @@ public class MultiFileItem extends ComponentList { return radioCustom; } + public StringProperty customTextProperty() { + return txtCustom.textProperty(); + } + + public String getCustomText() { + return txtCustom.getText(); + } + + public void setCustomText(String customText) { + txtCustom.setText(customText); + } + public JFXTextField getTxtCustom() { return txtCustom; } + + public boolean isDirectory() { + return directory.get(); + } + + public BooleanProperty directoryProperty() { + return directory; + } + + public void setDirectory(boolean directory) { + this.directory.set(directory); + } + + public ObservableList getExtensionFilters() { + return extensionFilters; + } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskExecutorDialogPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskExecutorDialogPane.java index 88c6b6973..5874c5c80 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskExecutorDialogPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskExecutorDialogPane.java @@ -23,10 +23,8 @@ import javafx.beans.property.StringProperty; import javafx.fxml.FXML; import javafx.scene.control.Label; import javafx.scene.layout.StackPane; -import javafx.scene.layout.VBox; import org.jackhuang.hmcl.task.TaskExecutor; import org.jackhuang.hmcl.ui.FXUtils; -import org.jackhuang.hmcl.ui.construct.TaskListPane; import java.util.Optional; @@ -34,18 +32,18 @@ public class TaskExecutorDialogPane extends StackPane { private TaskExecutor executor; @FXML - private JFXProgressBar pgsTasks; + private JFXProgressBar progressBar; @FXML - private Label lblCurrentState; + private Label lblTitle; @FXML - private Label lblSteps; + private Label lblSubtitle; @FXML private JFXButton btnCancel; @FXML private TaskListPane taskListPane; public TaskExecutorDialogPane(Runnable cancel) { - FXUtils.loadFXML(this, "/assets/fxml/launching-steps.fxml"); + FXUtils.loadFXML(this, "/assets/fxml/task-dialog.fxml"); FXUtils.limitHeight(this, 200); FXUtils.limitWidth(this, 400); @@ -64,34 +62,34 @@ public class TaskExecutorDialogPane extends StackPane { taskListPane.setExecutor(executor); } - public StringProperty currentStateProperty() { - return lblCurrentState.textProperty(); + public StringProperty titleProperty() { + return lblTitle.textProperty(); } - public String getCurrentState() { - return lblCurrentState.getText(); + public String getTitle() { + return lblTitle.getText(); } - public void setCurrentState(String currentState) { - lblCurrentState.setText(currentState); + public void setTitle(String currentState) { + lblTitle.setText(currentState); } - public StringProperty stepsProperty() { - return lblSteps.textProperty(); + public StringProperty subtitleProperty() { + return lblSubtitle.textProperty(); } - public String getSteps() { - return lblSteps.getText(); + public String getSubtitle() { + return lblSubtitle.getText(); } - public void setSteps(String steps) { - lblSteps.setText(steps); + public void setSubtitle(String subtitle) { + lblSubtitle.setText(subtitle); } public void setProgress(double progress) { if (progress == Double.MAX_VALUE) - pgsTasks.setVisible(false); + progressBar.setVisible(false); else - pgsTasks.setProgress(progress); + progressBar.setProgress(progress); } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskExecutorDialogWizardDisplayer.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskExecutorDialogWizardDisplayer.java index 4d28fb2fc..0d6d6d56b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskExecutorDialogWizardDisplayer.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskExecutorDialogWizardDisplayer.java @@ -25,7 +25,6 @@ import org.jackhuang.hmcl.task.TaskExecutor; import org.jackhuang.hmcl.task.TaskListener; import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.ui.wizard.AbstractWizardDisplayer; -import org.jackhuang.hmcl.util.OperatingSystem; import org.jackhuang.hmcl.util.StringUtils; import java.util.Map; @@ -39,22 +38,22 @@ public interface TaskExecutorDialogWizardDisplayer extends AbstractWizardDisplay Controllers.navigate(null); }); - pane.setCurrentState(Main.i18n("message.doing")); + pane.setTitle(Main.i18n("message.doing")); pane.setProgress(Double.MAX_VALUE); if (settings.containsKey("title")) { Object title = settings.get("title"); if (title instanceof StringProperty) - pane.currentStateProperty().bind((StringProperty) title); + pane.titleProperty().bind((StringProperty) title); else if (title instanceof String) - pane.setCurrentState((String) title); + pane.setTitle((String) title); } if (settings.containsKey("subtitle")) { Object subtitle = settings.get("subtitle"); if (subtitle instanceof StringProperty) - pane.stepsProperty().bind((StringProperty) subtitle); + pane.subtitleProperty().bind((StringProperty) subtitle); else if (subtitle instanceof String) - pane.setSteps((String) subtitle); + pane.setSubtitle((String) subtitle); } JFXUtilities.runInFX(() -> { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/DownloadWizardProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/DownloadWizardProvider.java index 86125bb3b..68e4bbb6a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/DownloadWizardProvider.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/DownloadWizardProvider.java @@ -23,6 +23,7 @@ import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.download.GameBuilder; import org.jackhuang.hmcl.game.HMCLModpackInstallTask; import org.jackhuang.hmcl.game.HMCLModpackManifest; +import org.jackhuang.hmcl.game.ModpackHelper; import org.jackhuang.hmcl.game.MultiMCInstallVersionSettingTask; import org.jackhuang.hmcl.mod.*; import org.jackhuang.hmcl.setting.EnumGameDirectory; @@ -75,27 +76,7 @@ public final class DownloadWizardProvider implements WizardProvider { String name = Lang.get(settings, ModpackPage.MODPACK_NAME, String.class, null); if (selected == null || modpack == null || name == null) return null; - profile.getRepository().markVersionAsModpack(name); - - Task finalizeTask = Task.of(() -> { - profile.getRepository().refreshVersions(); - VersionSetting vs = profile.specializeVersionSetting(name); - profile.getRepository().undoMark(name); - if (vs != null) - vs.setGameDirType(EnumGameDirectory.VERSION_FOLDER); - }); - - if (modpack.getManifest() instanceof CurseManifest) - return new CurseInstallTask(profile.getDependency(), selected, ((CurseManifest) modpack.getManifest()), name) - .finalized(finalizeTask); - else if (modpack.getManifest() instanceof HMCLModpackManifest) - return new HMCLModpackInstallTask(profile, selected, modpack, name) - .finalized(finalizeTask); - else if (modpack.getManifest() instanceof MultiMCInstanceConfiguration) - return new MultiMCModpackInstallTask(profile.getDependency(), selected, ((MultiMCInstanceConfiguration) modpack.getManifest()), name) - .finalized(finalizeTask) - .with(new MultiMCInstallVersionSettingTask(profile, ((MultiMCInstanceConfiguration) modpack.getManifest()), name)); - else throw new IllegalStateException("Unrecognized modpack: " + modpack); + return ModpackHelper.getInstallTask(profile, selected, name, modpack); } @Override 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 83800626e..b3f5eeda7 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 @@ -28,6 +28,7 @@ import javafx.stage.FileChooser; import org.jackhuang.hmcl.Main; import org.jackhuang.hmcl.game.ModpackHelper; import org.jackhuang.hmcl.mod.Modpack; +import org.jackhuang.hmcl.mod.UnsupportedModpackException; import org.jackhuang.hmcl.setting.Profile; import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.ui.FXUtils; @@ -79,7 +80,6 @@ public final class ModpackPage extends StackPane implements WizardPage { File selectedFile = chooser.showOpenDialog(Controllers.getStage()); if (selectedFile == null) Platform.runLater(() -> Controllers.navigate(null)); else { - // TODO: original HMCL modpack support. controller.getSettings().put(MODPACK_FILE, selectedFile); lblModpackLocation.setText(selectedFile.getAbsolutePath()); txtModpackName.getValidators().addAll( @@ -95,8 +95,7 @@ public final class ModpackPage extends StackPane implements WizardPage { lblVersion.setText(manifest.getVersion()); lblAuthor.setText(manifest.getAuthor()); txtModpackName.setText(manifest.getName() + (StringUtils.isBlank(manifest.getVersion()) ? "" : "-" + manifest.getVersion())); - } catch (Exception e) { - // TODO + } catch (UnsupportedModpackException e) { txtModpackName.setText(Main.i18n("modpack.task.install.error")); } } diff --git a/HMCL/src/main/resources/assets/fxml/launching-steps.fxml b/HMCL/src/main/resources/assets/fxml/task-dialog.fxml similarity index 77% rename from HMCL/src/main/resources/assets/fxml/launching-steps.fxml rename to HMCL/src/main/resources/assets/fxml/task-dialog.fxml index af45194ff..71a8aee36 100644 --- a/HMCL/src/main/resources/assets/fxml/launching-steps.fxml +++ b/HMCL/src/main/resources/assets/fxml/task-dialog.fxml @@ -10,10 +10,10 @@ - + - diff --git a/HMCL/src/main/resources/assets/fxml/version/version-settings.fxml b/HMCL/src/main/resources/assets/fxml/version/version-settings.fxml index 87a98c4c4..fe81a4696 100644 --- a/HMCL/src/main/resources/assets/fxml/version/version-settings.fxml +++ b/HMCL/src/main/resources/assets/fxml/version/version-settings.fxml @@ -41,10 +41,10 @@ + hasSubtitle="true" customText="%settings.custom" directory="false" /> + hasSubtitle="true" customText="%settings.custom" directory="true" /> diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 9ea129e2a..47ec2c658 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -218,7 +218,6 @@ minecraft.not_readable=Not readable minecraft.wrong_path=Wrong Minecraft path, the launcher could not find the path. modpack=Mod pack -modpack.cannot_read_version=Failed to gather the game version modpack.choose=Choose a modpack zip file which you want to import. If you want to update the modpack, please enter the version you want to update. modpack.desc=Describe your modpack, including precautions, changlog, supporting Markdown(also supporting online pictures). modpack.enter_name=Enter your desired name for this game. @@ -239,6 +238,7 @@ modpack.files.scripts=MineTweaker configuration modpack.files.servers_dat=Multiplayer servers list modpack.included_launcher=The modpack is included the launcher, you can publish it directly. modpack.install=Install %s modpack +modpack.installing=Installing modpack modpack.invalid=Invalid modpack file. modpack.mismatched_type=Mismatched modpack type, your current game is %s modpack, but your update file is %s modpack. modpack.name=Modpack Name @@ -285,6 +285,8 @@ profile.new_name=New Profile Name: profile.remove=Sure to remove profile %s? selector.choose=Choose +selector.choose_file=Select a file +selector.custom=Custom settings=Settings @@ -355,6 +357,7 @@ update.newest_version=Newest version: update.no_browser=Cannot open any browser. The link has been copied to the clipboard. Paste it to a browser address bar to update. update.should_open_link=Are you willing to update the launcher? +version.cannot_read=Unable to gather the game version. Cannot continue auto-installing. version.forbidden_name=Forbidden name, do not use this. version.game.old_alpha=Old Alpha version.game.old_beta=Beta 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 eaf9896f7..9931601da 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -218,7 +218,6 @@ minecraft.not_readable=minecraft.jar不可读 minecraft.wrong_path=错误的Minecraft路径,启动器未找到设定的Minecraft路径,请检查。 modpack=整合包 -modpack.cannot_read_version=读取游戏版本失败 modpack.choose=选择要导入的游戏整合包文件,如果您希望更新整合包,请输入要更新的版本名 modpack.desc=描述你要制作的整合包,比如整合包注意事项和更新记录,支持Markdown(图片请用网络图片)。 modpack.enter_name=给游戏起个你喜欢的名字 @@ -239,6 +238,7 @@ modpack.files.scripts=MineTweaker配置 modpack.files.servers_dat=多人游戏服务器列表 modpack.included_launcher=整合包已包含启动器,可直接发布 modpack.install=安装%s整合包 +modpack.installing=正在安装整合包 modpack.invalid=无效的整合包升级文件,可能是下载时出现问题。 modpack.mismatched_type=整合包类型不匹配,当前游戏是 %s 整合包,但是提供的整合包更新文件是 %s 整合包。 modpack.name=整合包名称 @@ -285,6 +285,8 @@ profile.new_name=新配置名: profile.remove=真的要删除配置%s吗? selector.choose=选择 +selector.choose_file=选择文件 +selector.custom=自定义 settings=普通设置 @@ -355,6 +357,7 @@ update.newest_version=最新版本为: update.no_browser=无法打开浏览器,网址已经复制到剪贴板了,您可以手动粘贴网址打开页面 update.should_open_link=是否更新? +version.cannot_read=读取游戏版本失败,无法进行自动安装 version.forbidden_name=此版本名称不受支持,请换一个名字 version.game.old_alpha=远古版 version.game.old_beta=测试版