From 7c8ac4fee8386af25b8cfc361fe10c4ce11dc2c9 Mon Sep 17 00:00:00 2001 From: huangyuhui Date: Wed, 28 Feb 2018 20:36:32 +0800 Subject: [PATCH 01/24] more precise warning in authlib injector add server page --- .../java/org/jackhuang/hmcl/setting/Accounts.java | 12 ++++-------- .../java/org/jackhuang/hmcl/ui/AccountsPage.java | 12 +++++++++++- .../hmcl/ui/AuthlibInjectorServersPage.java | 14 ++++++++++++-- .../assets/fxml/authlib-injector-servers.fxml | 2 ++ .../src/main/resources/assets/lang/I18N.properties | 1 + .../resources/assets/lang/I18N_zh_CN.properties | 1 + 6 files changed, 31 insertions(+), 11 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java index b4e31c246..ca15f364a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java @@ -88,17 +88,13 @@ public final class Accounts { return jar.getAbsolutePath(); } - public static String getAuthlibInjectorServerName(String serverIp) { + public static String getAuthlibInjectorServerName(String serverIp) throws Exception { if (AUTHLIB_INJECTOR_SERVER_NAMES.containsKey(serverIp)) return AUTHLIB_INJECTOR_SERVER_NAMES.get(serverIp); else { - try { - AuthlibInjectorServerResponse response = Constants.GSON.fromJson(NetworkUtils.doGet(NetworkUtils.toURL(serverIp)), AuthlibInjectorServerResponse.class); - AUTHLIB_INJECTOR_SERVER_NAMES.put(serverIp, response.getMeta().getServerName()); - return response.getMeta().getServerName(); - } catch (JsonParseException | IOException | NullPointerException e) { - return null; - } + AuthlibInjectorServerResponse response = Constants.GSON.fromJson(NetworkUtils.doGet(NetworkUtils.toURL(serverIp)), AuthlibInjectorServerResponse.class); + AUTHLIB_INJECTOR_SERVER_NAMES.put(serverIp, response.getMeta().getServerName()); + return response.getMeta().getServerName(); } } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountsPage.java index 34c9c31b9..bc5c020fb 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountsPage.java @@ -49,13 +49,16 @@ import org.jackhuang.hmcl.ui.construct.AdvancedListBox; import org.jackhuang.hmcl.ui.construct.IconedItem; import org.jackhuang.hmcl.ui.construct.Validator; import org.jackhuang.hmcl.ui.wizard.DecoratorPage; +import org.jackhuang.hmcl.util.Logging; import java.util.Collection; import java.util.LinkedList; import java.util.List; import java.util.Optional; import java.util.concurrent.CountDownLatch; +import java.util.logging.Level; import java.util.stream.Collectors; +import java.util.stream.Stream; public final class AccountsPage extends StackPane implements DecoratorPage { private final StringProperty title = new SimpleStringProperty(this, "title", Main.i18n("account")); @@ -133,7 +136,14 @@ public final class AccountsPage extends StackPane implements DecoratorPage { public void loadServers() { Task.ofResult("list", () -> Settings.INSTANCE.getAuthlibInjectorServerURLs().parallelStream() - .map(serverURL -> new TwoLineListItem(Accounts.getAuthlibInjectorServerName(serverURL), serverURL)) + .flatMap(serverURL -> { + try { + return Stream.of(new TwoLineListItem(Accounts.getAuthlibInjectorServerName(serverURL), serverURL)); + } catch (Exception e) { + Logging.LOG.log(Level.WARNING, "Authlib-injector server root " + serverURL + " cannot be recognized.", e); + return Stream.empty(); + } + }) .collect(Collectors.toList())) .subscribe(Task.of(Schedulers.javafx(), variables -> { cboServers.getItems().setAll(variables.>get("list")); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AuthlibInjectorServersPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AuthlibInjectorServersPage.java index f9e874077..b16eaf2f0 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AuthlibInjectorServersPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AuthlibInjectorServersPage.java @@ -18,11 +18,14 @@ import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.ui.animation.ContainerAnimations; import org.jackhuang.hmcl.ui.animation.TransitionHandler; import org.jackhuang.hmcl.ui.wizard.DecoratorPage; +import org.jackhuang.hmcl.util.Logging; import org.jackhuang.hmcl.util.NetworkUtils; import java.util.Collection; import java.util.Objects; +import java.util.logging.Level; import java.util.stream.Collectors; +import java.util.stream.Stream; public class AuthlibInjectorServersPage extends StackPane implements DecoratorPage { private final StringProperty title = new SimpleStringProperty(this, "title", Main.i18n("account.injector.server")); @@ -69,7 +72,14 @@ public class AuthlibInjectorServersPage extends StackPane implements DecoratorPa spinner.setVisible(true); Task.ofResult("list", () -> Settings.INSTANCE.getAuthlibInjectorServerURLs().parallelStream() - .map(serverURL -> new AuthlibInjectorServerItem(new AuthlibInjectorServerInfo(serverURL, Accounts.getAuthlibInjectorServerName(serverURL)), this::removeServer)) + .flatMap(serverURL -> { + try { + return Stream.of(new AuthlibInjectorServerItem(new AuthlibInjectorServerInfo(serverURL, Accounts.getAuthlibInjectorServerName(serverURL)), this::removeServer)); + } catch (Exception e) { + Logging.LOG.log(Level.WARNING, "Authlib-injector server root " + serverURL + " cannot be recognized.", e); + return Stream.empty(); + } + }) .collect(Collectors.toList())) .subscribe(Task.of(Schedulers.javafx(), variables -> { listPane.getChildren().setAll(variables.>get("list")); @@ -105,7 +115,7 @@ public class AuthlibInjectorServersPage extends StackPane implements DecoratorPa progressBar.setVisible(true); addServerPane.setDisable(true); - Task.ofResult("serverName", () -> Objects.requireNonNull(Accounts.getAuthlibInjectorServerName(serverIp))) + Task.ofResult("serverName", () -> Accounts.getAuthlibInjectorServerName(serverIp)) .finalized(Schedulers.javafx(), (variables, isDependentsSucceeded) -> { progressBar.setVisible(false); addServerPane.setDisable(false); diff --git a/HMCL/src/main/resources/assets/fxml/authlib-injector-servers.fxml b/HMCL/src/main/resources/assets/fxml/authlib-injector-servers.fxml index 05ea1066d..c3e330f1b 100644 --- a/HMCL/src/main/resources/assets/fxml/authlib-injector-servers.fxml +++ b/HMCL/src/main/resources/assets/fxml/authlib-injector-servers.fxml @@ -35,6 +35,8 @@ + + diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 382514688..b0984cbd9 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -136,6 +136,7 @@ input.email=The username must be an e-mail. input.number=Must be a number. input.not_empty=Input Requrired! input.url=Must be a valid URL. +input.url.http=Only Http or Https accepted. install=Install New Game install.failed=Failed to install 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 6c5f09b7a..c98e03852 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -136,6 +136,7 @@ input.email=用户名必须是邮箱 input.number=必须是数字 input.not_empty=必填项 input.url=必须是合法的链接 +input.url.http=只支持Http或Https协议 install=添加游戏 install.failed=安装失败 From 9fa48090ce5dfa7dff19967bbe802245090682ca Mon Sep 17 00:00:00 2001 From: huangyuhui Date: Wed, 28 Feb 2018 22:15:46 +0800 Subject: [PATCH 02/24] Show indeterminate progress bar when loading versions in MainPage --- .../jackhuang/hmcl/game/LauncherHelper.java | 15 +++--- .../java/org/jackhuang/hmcl/ui/MainPage.java | 47 ++++++++++++------- HMCL/src/main/resources/assets/fxml/main.fxml | 12 +++-- 3 files changed, 45 insertions(+), 29 deletions(-) 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 715ea22be..d5fc7cdc4 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -55,30 +55,27 @@ public final class LauncherHelper { public static final Queue PROCESSES = new ConcurrentLinkedQueue<>(); private final TaskExecutorDialogPane launchingStepsPane = new TaskExecutorDialogPane(() -> {}); - public void launch(String selectedVersion, File scriptFile) { - Profile profile = Settings.INSTANCE.getSelectedProfile(); - GameRepository repository = profile.getRepository(); - Account account = Settings.INSTANCE.getSelectedAccount(); + public void launch(Profile profile, Account account, String selectedVersion, File scriptFile) { if (account == null) - throw new IllegalStateException("No account"); + throw new IllegalArgumentException("No account"); + + GameRepository repository = profile.getRepository(); Version version = repository.getResolvedVersion(selectedVersion); VersionSetting setting = profile.getVersionSetting(selectedVersion); Platform.runLater(() -> { try { - checkGameState(profile, setting, version, () -> Schedulers.newThread().schedule(() -> launch0(selectedVersion, scriptFile))); + checkGameState(profile, setting, version, () -> Schedulers.newThread().schedule(() -> launch0(profile, account, selectedVersion, scriptFile))); } catch (InterruptedException ignore) { } }); } - private void launch0(String selectedVersion, File scriptFile) { - Profile profile = Settings.INSTANCE.getSelectedProfile(); + private void launch0(Profile profile, Account account, String selectedVersion, File scriptFile) { GameRepository repository = profile.getRepository(); DefaultDependencyManager dependencyManager = profile.getDependency(); Version version = repository.getResolvedVersion(selectedVersion); - Account account = Settings.INSTANCE.getSelectedAccount(); VersionSetting setting = profile.getVersionSetting(selectedVersion); Optional gameVersion = GameVersion.minecraftVersion(repository.getVersionJar(version)); 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 29c7c00a2..fc83adff1 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java @@ -18,10 +18,7 @@ package org.jackhuang.hmcl.ui; import com.jfoenix.concurrency.JFXUtilities; -import com.jfoenix.controls.JFXButton; -import com.jfoenix.controls.JFXListView; -import com.jfoenix.controls.JFXMasonryPane; -import com.jfoenix.controls.JFXPopup; +import com.jfoenix.controls.*; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; import javafx.fxml.FXML; @@ -51,6 +48,7 @@ import org.jackhuang.hmcl.util.StringUtils; import java.io.File; import java.io.IOException; +import java.util.Collections; import java.util.LinkedList; import java.util.List; @@ -60,16 +58,18 @@ public final class MainPage extends StackPane implements DecoratorPage { private Profile profile; private String rightClickedVersion; + private HMCLGameRepository rightClickedRepository; @FXML private JFXButton btnRefresh; - + @FXML + private StackPane contentPane; @FXML private JFXButton btnAdd; - + @FXML + private JFXSpinner spinner; @FXML private JFXMasonryPane masonryPane; - @FXML private JFXListView versionList; @@ -78,11 +78,16 @@ public final class MainPage extends StackPane implements DecoratorPage { { FXUtils.loadFXML(this, "/assets/fxml/main.fxml"); + loadingVersions(); + EventBus.EVENT_BUS.channel(RefreshedVersionsEvent.class).register(event -> { if (event.getSource() == profile.getRepository()) loadVersions((HMCLGameRepository) event.getSource()); }); - EventBus.EVENT_BUS.channel(ProfileChangedEvent.class).register(event -> this.profile = event.getProfile()); + EventBus.EVENT_BUS.channel(ProfileChangedEvent.class).register(event -> { + JFXUtilities.runInFXAndWait(this::loadingVersions); + this.profile = event.getProfile(); + }); versionPopup = new JFXPopup(versionList); getChildren().remove(versionList); @@ -94,6 +99,7 @@ public final class MainPage extends StackPane implements DecoratorPage { } private Node buildNode(HMCLGameRepository repository, Version version, String game) { + Profile profile = repository.getProfile(); String id = version.getId(); VersionItem item = new VersionItem(); item.setUpdate(repository.isModpack(id)); @@ -118,7 +124,7 @@ public final class MainPage extends StackPane implements DecoratorPage { if (Settings.INSTANCE.getSelectedAccount() == null) Controllers.dialog(Main.i18n("login.empty_username")); else - LauncherHelper.INSTANCE.launch(id, null); + LauncherHelper.INSTANCE.launch(profile, Settings.INSTANCE.getSelectedAccount(), id, null); }); item.setOnScriptButtonClicked(e -> { if (Settings.INSTANCE.getSelectedAccount() == null) @@ -132,7 +138,7 @@ public final class MainPage extends StackPane implements DecoratorPage { : new FileChooser.ExtensionFilter(Main.i18n("extension.sh"), "*.sh")); File file = chooser.showSaveDialog(Controllers.getStage()); if (file != null) - LauncherHelper.INSTANCE.launch(id, file); + LauncherHelper.INSTANCE.launch(profile, Settings.INSTANCE.getSelectedAccount(), id, file); } }); item.setOnSettingsButtonClicked(e -> { @@ -165,13 +171,14 @@ public final class MainPage extends StackPane implements DecoratorPage { item.setOnMouseClicked(event -> { if (event.getButton() == MouseButton.SECONDARY) { rightClickedVersion = id; + rightClickedRepository = repository; versionList.getSelectionModel().select(-1); versionPopup.show(item, JFXPopup.PopupVPosition.TOP, JFXPopup.PopupHPosition.LEFT, event.getX(), event.getY()); } else if (event.getButton() == MouseButton.PRIMARY && event.getClickCount() == 2) { if (Settings.INSTANCE.getSelectedAccount() == null) Controllers.dialog(Main.i18n("login.empty_username")); else - LauncherHelper.INSTANCE.launch(id, null); + LauncherHelper.INSTANCE.launch(profile, Settings.INSTANCE.getSelectedAccount(), id, null); } }); File iconFile = repository.getVersionIcon(id); @@ -180,12 +187,20 @@ public final class MainPage extends StackPane implements DecoratorPage { return item; } + private void loadingVersions() { + contentPane.getChildren().setAll(spinner); + FXUtils.resetChildren(masonryPane, Collections.emptyList()); + } + private void loadVersions(HMCLGameRepository repository) { List children = new LinkedList<>(); for (Version version : repository.getVersions()) { children.add(buildNode(repository, version, GameVersion.minecraftVersion(repository.getVersionJar(version.getId())).orElse("Unknown"))); } - JFXUtilities.runInFX(() -> FXUtils.resetChildren(masonryPane, children)); + JFXUtilities.runInFX(() -> { + contentPane.getChildren().setAll(masonryPane); + FXUtils.resetChildren(masonryPane, children); + }); } @FXML @@ -193,16 +208,16 @@ public final class MainPage extends StackPane implements DecoratorPage { versionPopup.hide(); switch (versionList.getSelectionModel().getSelectedIndex()) { case 0: - VersionPage.renameVersion(profile, rightClickedVersion); + VersionPage.renameVersion(rightClickedRepository.getProfile(), rightClickedVersion); break; case 1: - VersionPage.deleteVersion(profile, rightClickedVersion); + VersionPage.deleteVersion(rightClickedRepository.getProfile(), rightClickedVersion); break; case 2: - VersionPage.exportVersion(profile, rightClickedVersion); + VersionPage.exportVersion(rightClickedRepository.getProfile(), rightClickedVersion); break; case 3: - FXUtils.openFolder(profile.getRepository().getRunDirectory(rightClickedVersion)); + FXUtils.openFolder(rightClickedRepository.getRunDirectory(rightClickedVersion)); break; default: throw new Error(); diff --git a/HMCL/src/main/resources/assets/fxml/main.fxml b/HMCL/src/main/resources/assets/fxml/main.fxml index ab850ee43..e7c08a4f1 100644 --- a/HMCL/src/main/resources/assets/fxml/main.fxml +++ b/HMCL/src/main/resources/assets/fxml/main.fxml @@ -6,14 +6,18 @@ + - - - - + + + + + + + From f83777e1d247d0e8eb866fab5613098fb3b35d4d Mon Sep 17 00:00:00 2001 From: huangyuhui Date: Wed, 28 Feb 2018 23:34:31 +0800 Subject: [PATCH 03/24] Terminate when exclaimation mark is in the path --- .../java/org/jackhuang/hmcl/Launcher.java | 144 ++++++++++++++++++ .../main/java/org/jackhuang/hmcl/Main.java | 132 ++-------------- .../jackhuang/hmcl/game/AccountHelper.java | 4 +- .../jackhuang/hmcl/game/HMCLGameLauncher.java | 6 +- .../hmcl/game/HMCLModpackManager.java | 1 - .../jackhuang/hmcl/game/LauncherHelper.java | 41 +++-- .../org/jackhuang/hmcl/game/LoadingState.java | 4 +- .../org/jackhuang/hmcl/setting/Accounts.java | 7 +- .../org/jackhuang/hmcl/setting/Config.java | 4 +- .../hmcl/setting/DownloadProviders.java | 1 - .../org/jackhuang/hmcl/setting/Locales.java | 1 - .../org/jackhuang/hmcl/setting/Profiles.java | 6 +- .../org/jackhuang/hmcl/setting/Proxies.java | 1 - .../org/jackhuang/hmcl/setting/Settings.java | 4 +- .../hmcl/setting/VersionSetting.java | 6 +- .../org/jackhuang/hmcl/ui/AccountsPage.java | 30 ++-- .../hmcl/ui/AuthlibInjectorServersPage.java | 5 +- .../org/jackhuang/hmcl/ui/Controllers.java | 6 +- .../org/jackhuang/hmcl/ui/CrashWindow.java | 14 +- .../java/org/jackhuang/hmcl/ui/Decorator.java | 6 +- .../java/org/jackhuang/hmcl/ui/FXUtils.java | 4 +- .../org/jackhuang/hmcl/ui/InstallerItem.java | 4 +- .../jackhuang/hmcl/ui/LeftPaneController.java | 18 +-- .../java/org/jackhuang/hmcl/ui/LogWindow.java | 4 +- .../java/org/jackhuang/hmcl/ui/MainPage.java | 46 +++--- .../org/jackhuang/hmcl/ui/ModController.java | 35 +++-- .../java/org/jackhuang/hmcl/ui/ModItem.java | 6 +- .../org/jackhuang/hmcl/ui/ProfilePage.java | 4 +- .../org/jackhuang/hmcl/ui/SettingsPage.java | 33 ++-- .../org/jackhuang/hmcl/ui/VersionItem.java | 10 +- .../org/jackhuang/hmcl/ui/VersionPage.java | 18 +-- .../hmcl/ui/VersionSettingsController.java | 21 +-- .../jackhuang/hmcl/ui/construct/FileItem.java | 4 +- .../hmcl/ui/construct/ImagePickerItem.java | 4 +- .../hmcl/ui/construct/MessageBox.java | 4 +- .../hmcl/ui/construct/MessageDialogPane.java | 6 +- .../hmcl/ui/construct/MultiColorItem.java | 8 +- .../hmcl/ui/construct/MultiFileItem.java | 8 +- .../TaskExecutorDialogWizardDisplayer.java | 8 +- .../hmcl/ui/construct/TaskListPane.java | 26 ++-- .../ui/download/AdditionalInstallersPage.java | 20 +-- .../ui/download/DownloadWizardProvider.java | 8 +- .../hmcl/ui/download/InstallTypePage.java | 4 +- .../ui/download/InstallerWizardProvider.java | 6 +- .../hmcl/ui/download/InstallersPage.java | 27 ++-- .../hmcl/ui/download/ModpackPage.java | 16 +- .../hmcl/ui/download/VersionsPageItem.java | 8 +- .../ui/export/ModpackFileSelectionPage.java | 30 ++-- .../hmcl/ui/export/ModpackInfoPage.java | 8 +- .../hmcl/upgrade/AppDataUpgrader.java | 21 ++- .../hmcl/upgrade/NewFileUpgrader.java | 4 +- .../jackhuang/hmcl/upgrade/UpdateChecker.java | 10 +- .../jackhuang/hmcl/util/CrashReporter.java | 24 +-- .../hmcl/auth/yggdrasil/YggdrasilAccount.java | 1 - .../hmcl/download/DefaultGameBuilder.java | 1 - .../jackhuang/hmcl/download/MaintainTask.java | 1 - .../hmcl/download/forge/ForgeVersionList.java | 1 - .../hmcl/download/game/GameLibrariesTask.java | 2 - .../download/game/LibraryDownloadTask.java | 2 - .../liteloader/LiteLoaderVersionList.java | 1 - .../optifine/OptiFineBMCLVersionList.java | 1 - .../org/jackhuang/hmcl/game/GameVersion.java | 2 +- .../org/jackhuang/hmcl/util/Constants.java | 1 - 63 files changed, 460 insertions(+), 433 deletions(-) create mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java b/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java new file mode 100644 index 000000000..a3d064976 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java @@ -0,0 +1,144 @@ +/* + * Hello Minecraft! Launcher. + * Copyright (C) 2017 huangyuhui + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see {http://www.gnu.org/licenses/}. + */ +package org.jackhuang.hmcl; + +import com.jfoenix.concurrency.JFXUtilities; +import javafx.application.Application; +import javafx.application.Platform; +import javafx.stage.Stage; +import org.jackhuang.hmcl.setting.Settings; +import org.jackhuang.hmcl.task.Schedulers; +import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.ui.Controllers; +import org.jackhuang.hmcl.upgrade.AppDataUpgrader; +import org.jackhuang.hmcl.upgrade.IUpgrader; +import org.jackhuang.hmcl.upgrade.UpdateChecker; +import org.jackhuang.hmcl.util.*; + +import java.io.File; +import java.util.Arrays; +import java.util.ResourceBundle; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; + +public final class Launcher extends Application { + + @Override + public void start(Stage primaryStage) { + Thread.currentThread().setUncaughtExceptionHandler(CRASH_REPORTER); + + try { + // When launcher visibility is set to "hide and reopen" without Platform.implicitExit = false, + // Stage.show() cannot work again because JavaFX Toolkit have already shut down. + Platform.setImplicitExit(false); + Controllers.initialize(primaryStage); + primaryStage.setResizable(false); + primaryStage.setScene(Controllers.getScene()); + primaryStage.show(); + } catch (Throwable e) { + CRASH_REPORTER.uncaughtException(Thread.currentThread(), e); + } + } + + public static void main(String[] args) { + Thread.setDefaultUncaughtExceptionHandler(CRASH_REPORTER); + + try { + // NetworkUtils.setUserAgentSupplier(() -> "Hello Minecraft! Launcher"); + Constants.UI_THREAD_SCHEDULER = Constants.JAVAFX_UI_THREAD_SCHEDULER; + UPGRADER.parseArguments(VersionNumber.asVersion(VERSION), Arrays.asList(args)); + + Logging.LOG.info("*** " + TITLE + " ***"); + + UPDATE_CHECKER.process(false) + .then(Task.of(Schedulers.javafx(), () -> { + if (UPDATE_CHECKER.isOutOfDate()) + Controllers.showUpdate(); + })) + .start(); + + launch(args); + } catch (Throwable e) { // Fucking JavaFX will suppress the exception and will break our crash reporter. + CRASH_REPORTER.uncaughtException(Thread.currentThread(), e); + } + } + + public static void stopApplication() { + JFXUtilities.runInFX(() -> { + stopWithoutPlatform(); + Platform.exit(); + }); + } + + public static void stopWithoutPlatform() { + JFXUtilities.runInFX(() -> { + if (Controllers.getStage() == null) + return; + Controllers.getStage().close(); + + Logging.LOG.info("Shutting down executor services."); + Schedulers.shutdown(); + + Controllers.shutdown(); + + Lang.executeDelayed(OperatingSystem::forceGC, TimeUnit.SECONDS, 5, true); + }); + } + + public static File getWorkingDirectory(String folder) { + String home = System.getProperty("user.home", "."); + switch (OperatingSystem.CURRENT_OS) { + case LINUX: + return new File(home, "." + folder + "/"); + case WINDOWS: + String appdata = System.getenv("APPDATA"); + return new File(Lang.nonNull(appdata, home), "." + folder + "/"); + case OSX: + return new File(home, "Library/Application Support/" + folder); + default: + return new File(home, folder + "/"); + } + } + + public static String i18n(String key) { + try { + return RESOURCE_BUNDLE.getString(key); + } catch (Exception e) { + Logging.LOG.log(Level.SEVERE, "Cannot find key " + key + " in resource bundle", e); + return key; + } + } + + public static String i18n(String key, Object... formatArgs) { + return String.format(i18n(key), formatArgs); + } + + public static final File MINECRAFT_DIRECTORY = getWorkingDirectory("minecraft"); + public static final File HMCL_DIRECTORY = getWorkingDirectory("hmcl"); + + public static final String VERSION = "@HELLO_MINECRAFT_LAUNCHER_VERSION_FOR_GRADLE_REPLACING@"; + public static final String NAME = "HMCL"; + public static final String TITLE = NAME + " " + VERSION; + public static final ResourceBundle RESOURCE_BUNDLE = Settings.INSTANCE.getLocale().getResourceBundle(); + public static final UpdateChecker UPDATE_CHECKER = new UpdateChecker(VersionNumber.asVersion(VERSION)); + public static final IUpgrader UPGRADER = new AppDataUpgrader(); + public static final CrashReporter CRASH_REPORTER = new CrashReporter(); + + public static final String CONTACT = "http://huangyuhui.duapp.com/hmcl.php"; + public static final String PUBLISH = "http://www.mcbbs.net/thread-142335-1-1.html"; +} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/Main.java b/HMCL/src/main/java/org/jackhuang/hmcl/Main.java index ed16b143a..1bf1aef23 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/Main.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/Main.java @@ -17,128 +17,24 @@ */ package org.jackhuang.hmcl; -import com.jfoenix.concurrency.JFXUtilities; -import javafx.application.Application; -import javafx.application.Platform; -import javafx.stage.Stage; -import org.jackhuang.hmcl.setting.Settings; -import org.jackhuang.hmcl.task.Schedulers; -import org.jackhuang.hmcl.task.Task; -import org.jackhuang.hmcl.ui.Controllers; -import org.jackhuang.hmcl.upgrade.AppDataUpgrader; -import org.jackhuang.hmcl.upgrade.IUpgrader; -import org.jackhuang.hmcl.upgrade.UpdateChecker; -import org.jackhuang.hmcl.util.*; - +import org.apache.commons.compress.utils.Charsets; +import org.jackhuang.hmcl.util.Logging; +import javax.swing.JOptionPane; import java.io.File; -import java.util.Arrays; -import java.util.ResourceBundle; -import java.util.concurrent.TimeUnit; -import java.util.logging.Level; -public final class Main extends Application { - - @Override - public void start(Stage primaryStage) { - Thread.currentThread().setUncaughtExceptionHandler(CRASH_REPORTER); - - try { - // When launcher visibility is set to "hide and reopen" without Platform.implicitExit = false, - // Stage.show() cannot work again because JavaFX Toolkit have already shut down. - Platform.setImplicitExit(false); - Controllers.initialize(primaryStage); - primaryStage.setResizable(false); - primaryStage.setScene(Controllers.getScene()); - primaryStage.show(); - } catch (Throwable e) { - CRASH_REPORTER.uncaughtException(Thread.currentThread(), e); - } - } +public final class Main { public static void main(String[] args) { - Thread.setDefaultUncaughtExceptionHandler(CRASH_REPORTER); + String currentDirectory = new File("").getAbsolutePath(); + Logging.LOG.info("Current directory: " + currentDirectory); + if (currentDirectory.contains("!")) { + Logging.LOG.severe("Exclamation mark(!) is not allowed in the path where HMCL is in. Forcibly exit."); - try { - // NetworkUtils.setUserAgentSupplier(() -> "Hello Minecraft! Launcher"); - Constants.UI_THREAD_SCHEDULER = Constants.JAVAFX_UI_THREAD_SCHEDULER; - UPGRADER.parseArguments(VersionNumber.asVersion(VERSION), Arrays.asList(args)); - - Logging.LOG.info("*** " + TITLE + " ***"); - - UPDATE_CHECKER.process(false) - .then(Task.of(Schedulers.javafx(), () -> { - if (UPDATE_CHECKER.isOutOfDate()) - Controllers.showUpdate(); - })) - .start(); - - launch(args); - } catch (Throwable e) { // Fucking JavaFX will suppress the exception and will break our crash reporter. - CRASH_REPORTER.uncaughtException(Thread.currentThread(), e); - } + // No Chinese translation because both Swing and JavaFX cannot render Chinese character properly when exclamation mark exists in the path. + String message = "Exclamation mark(!) is not allowed in the path where HMCL is in.\nThe path is " + currentDirectory; + JOptionPane.showMessageDialog(null, message, "Error", JOptionPane.ERROR_MESSAGE); + System.exit(1); + } else + Launcher.main(args); } - - public static void stopApplication() { - JFXUtilities.runInFX(() -> { - stopWithoutPlatform(); - Platform.exit(); - }); - } - - public static void stopWithoutPlatform() { - JFXUtilities.runInFX(() -> { - if (Controllers.getStage() == null) - return; - Controllers.getStage().close(); - - Logging.LOG.info("Shutting down executor services."); - Schedulers.shutdown(); - - Controllers.shutdown(); - - Lang.executeDelayed(OperatingSystem::forceGC, TimeUnit.SECONDS, 5, true); - }); - } - - public static String i18n(String key) { - try { - return RESOURCE_BUNDLE.getString(key); - } catch (Exception e) { - Logging.LOG.log(Level.SEVERE, "Cannot find key " + key + " in resource bundle", e); - return key; - } - } - - public static String i18n(String key, Object... formatArgs) { - return String.format(i18n(key), formatArgs); - } - - public static File getWorkingDirectory(String folder) { - String home = System.getProperty("user.home", "."); - switch (OperatingSystem.CURRENT_OS) { - case LINUX: - return new File(home, "." + folder + "/"); - case WINDOWS: - String appdata = System.getenv("APPDATA"); - return new File(Lang.nonNull(appdata, home), "." + folder + "/"); - case OSX: - return new File(home, "Library/Application Support/" + folder); - default: - return new File(home, folder + "/"); - } - } - - public static final File MINECRAFT_DIRECTORY = getWorkingDirectory("minecraft"); - public static final File HMCL_DIRECTORY = getWorkingDirectory("hmcl"); - - public static final String VERSION = "@HELLO_MINECRAFT_LAUNCHER_VERSION_FOR_GRADLE_REPLACING@"; - public static final String NAME = "HMCL"; - public static final String TITLE = NAME + " " + VERSION; - public static final ResourceBundle RESOURCE_BUNDLE = Settings.INSTANCE.getLocale().getResourceBundle(); - public static final UpdateChecker UPDATE_CHECKER = new UpdateChecker(VersionNumber.asVersion(VERSION)); - public static final IUpgrader UPGRADER = new AppDataUpgrader(); - public static final CrashReporter CRASH_REPORTER = new CrashReporter(); - - public static final String CONTACT = "http://huangyuhui.duapp.com/hmcl.php"; - public static final String PUBLISH = "http://www.mcbbs.net/thread-142335-1-1.html"; } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/AccountHelper.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/AccountHelper.java index 2cfcbf058..a3e50cc26 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/AccountHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/AccountHelper.java @@ -19,7 +19,7 @@ package org.jackhuang.hmcl.game; import javafx.geometry.Rectangle2D; import javafx.scene.image.Image; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.auth.Account; import org.jackhuang.hmcl.auth.yggdrasil.GameProfile; import org.jackhuang.hmcl.auth.yggdrasil.Texture; @@ -43,7 +43,7 @@ public final class AccountHelper { public static final AccountHelper INSTANCE = new AccountHelper(); private AccountHelper() {} - public static final File SKIN_DIR = new File(Main.HMCL_DIRECTORY, "skins"); + public static final File SKIN_DIR = new File(Launcher.HMCL_DIRECTORY, "skins"); public static void loadSkins() { loadSkins(Proxy.NO_PROXY); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameLauncher.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameLauncher.java index a999a6e1a..6bef2d069 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameLauncher.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameLauncher.java @@ -17,7 +17,7 @@ */ package org.jackhuang.hmcl.game; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.auth.AuthInfo; import org.jackhuang.hmcl.launch.DefaultLauncher; import org.jackhuang.hmcl.launch.ProcessListener; @@ -45,7 +45,7 @@ public final class HMCLGameLauncher extends DefaultLauncher { protected void appendJvmArgs(List result) { super.appendJvmArgs(result); - result.add("-Dminecraft.launcher.version=" + Main.VERSION); - result.add("-Dminecraft.launcher.brand=" + Main.NAME); + result.add("-Dminecraft.launcher.version=" + Launcher.VERSION); + result.add("-Dminecraft.launcher.brand=" + Launcher.NAME); } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLModpackManager.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLModpackManager.java index 8791b578d..89544be28 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLModpackManager.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLModpackManager.java @@ -26,7 +26,6 @@ import org.jackhuang.hmcl.util.StringUtils; import java.io.File; import java.io.IOException; -import java.util.Arrays; import java.util.List; /** 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 d5fc7cdc4..97d09da63 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -19,13 +19,12 @@ package org.jackhuang.hmcl.game; import com.jfoenix.concurrency.JFXUtilities; import javafx.application.Platform; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.auth.Account; import org.jackhuang.hmcl.auth.AuthInfo; import org.jackhuang.hmcl.auth.AuthenticationException; import org.jackhuang.hmcl.auth.ServerDisconnectException; import org.jackhuang.hmcl.download.DefaultDependencyManager; -import org.jackhuang.hmcl.download.MaintainTask; import org.jackhuang.hmcl.launch.*; import org.jackhuang.hmcl.mod.CurseCompletionTask; import org.jackhuang.hmcl.setting.LauncherVisibility; @@ -90,7 +89,7 @@ public final class LauncherHelper { .then(Task.of(Schedulers.javafx(), () -> emitStatus(LoadingState.MODS))) .then(new CurseCompletionTask(dependencyManager, selectedVersion)) .then(Task.of(Schedulers.javafx(), () -> emitStatus(LoadingState.LOGGING_IN))) - .then(Task.of(Main.i18n("account.methods"), variables -> { + .then(Task.of(Launcher.i18n("account.methods"), variables -> { try { try { variables.set("account", account.logIn()); @@ -114,12 +113,12 @@ public final class LauncherHelper { .then(variables -> { DefaultLauncher launcher = variables.get("launcher"); if (scriptFile == null) { - return new LaunchTask<>(launcher::launch).setName(Main.i18n("version.launch")); + return new LaunchTask<>(launcher::launch).setName(Launcher.i18n("version.launch")); } else { return new LaunchTask<>(() -> { launcher.makeLaunchScript(scriptFile); return null; - }).setName(Main.i18n("version.launch_script")); + }).setName(Launcher.i18n("version.launch_script")); } }) .then(Task.of(variables -> { @@ -127,7 +126,7 @@ public final class LauncherHelper { ManagedProcess process = variables.get(LaunchTask.LAUNCH_ID); PROCESSES.add(process); if (setting.getLauncherVisibility() == LauncherVisibility.CLOSE) - Main.stopApplication(); + Launcher.stopApplication(); else launchingStepsPane.setCancel(() -> { process.stop(); @@ -135,7 +134,7 @@ public final class LauncherHelper { }); } else Platform.runLater(() -> - Controllers.dialog(Main.i18n("version.launch_script.success", scriptFile.getAbsolutePath()))); + Controllers.dialog(Launcher.i18n("version.launch_script.success", scriptFile.getAbsolutePath()))); })) .executor(); @@ -157,7 +156,7 @@ public final class LauncherHelper { Platform.runLater(() -> { if (executor.getLastException() != null) Controllers.dialog(I18nException.getStackTrace(executor.getLastException()), - scriptFile == null ? Main.i18n("launch.failed") : Main.i18n("version.launch_script.failed"), + scriptFile == null ? Launcher.i18n("launch.failed") : Launcher.i18n("version.launch_script.failed"), MessageBox.ERROR_MESSAGE, Controllers::closeDialog); else Controllers.closeDialog(); @@ -177,35 +176,35 @@ public final class LauncherHelper { VersionNumber gameVersion = VersionNumber.asVersion(GameVersion.minecraftVersion(profile.getRepository().getVersionJar(version)).orElse("Unknown")); JavaVersion java = setting.getJavaVersion(); if (java == null) { - Controllers.dialog(Main.i18n("launch.wrong_javadir"), Main.i18n("message.error"), MessageBox.ERROR_MESSAGE, onAccept); + Controllers.dialog(Launcher.i18n("launch.wrong_javadir"), Launcher.i18n("message.error"), MessageBox.ERROR_MESSAGE, onAccept); setting.setJava(null); java = JavaVersion.fromCurrentEnvironment(); flag = true; } if (java.getParsedVersion() < JavaVersion.JAVA_8) { - Controllers.dialog(Main.i18n("launch.advice.newer_java"), Main.i18n("message.error"), MessageBox.ERROR_MESSAGE, onAccept); + Controllers.dialog(Launcher.i18n("launch.advice.newer_java"), Launcher.i18n("message.error"), MessageBox.ERROR_MESSAGE, onAccept); flag = true; } if (java.getParsedVersion() >= JavaVersion.JAVA_9 && gameVersion.compareTo(VersionNumber.asVersion("1.12.5")) < 0 && version.getMainClass().contains("launchwrapper")) { - Controllers.dialog(Main.i18n("launch.advice.java9"), Main.i18n("message.error"), MessageBox.ERROR_MESSAGE, null); + Controllers.dialog(Launcher.i18n("launch.advice.java9"), Launcher.i18n("message.error"), MessageBox.ERROR_MESSAGE, null); suggest = false; flag = true; } if (java.getPlatform() == org.jackhuang.hmcl.util.Platform.BIT_32 && org.jackhuang.hmcl.util.Platform.IS_64_BIT) { - Controllers.dialog(Main.i18n("launch.advice.different_platform"), Main.i18n("message.error"), MessageBox.ERROR_MESSAGE, onAccept); + Controllers.dialog(Launcher.i18n("launch.advice.different_platform"), Launcher.i18n("message.error"), MessageBox.ERROR_MESSAGE, onAccept); flag = true; } if (java.getPlatform() == org.jackhuang.hmcl.util.Platform.BIT_32 && setting.getMaxMemory() > 1.5 * 1024) { - Controllers.dialog(Main.i18n("launch.advice.too_large_memory_for_32bit"), Main.i18n("message.error"), MessageBox.ERROR_MESSAGE, onAccept); + Controllers.dialog(Launcher.i18n("launch.advice.too_large_memory_for_32bit"), Launcher.i18n("message.error"), MessageBox.ERROR_MESSAGE, onAccept); flag = true; } if (OperatingSystem.TOTAL_MEMORY > 0 && OperatingSystem.TOTAL_MEMORY < setting.getMaxMemory()) { - Controllers.dialog(Main.i18n("launch.advice.not_enough_space", OperatingSystem.TOTAL_MEMORY), Main.i18n("message.error"), MessageBox.ERROR_MESSAGE, onAccept); + Controllers.dialog(Launcher.i18n("launch.advice.not_enough_space", OperatingSystem.TOTAL_MEMORY), Launcher.i18n("message.error"), MessageBox.ERROR_MESSAGE, onAccept); flag = true; } @@ -242,8 +241,8 @@ public final class LauncherHelper { Platform.runLater(() -> { // Shut down the platform when user closed log window. Platform.setImplicitExit(true); - // If we use Main.stop(), log window will be halt immediately. - Main.stopWithoutPlatform(); + // If we use Launcher.stop(), log window will be halt immediately. + Launcher.stopWithoutPlatform(); }); break; } @@ -261,11 +260,11 @@ public final class LauncherHelper { try { setResult(supplier.get()); } catch (PermissionException e) { - throw new I18nException(Main.i18n("launch.failed.executable_permission"), e); + throw new I18nException(Launcher.i18n("launch.failed.executable_permission"), e); } catch (ProcessCreationException e) { - throw new I18nException(Main.i18n("launch.failed.creating_process") + e.getLocalizedMessage(), e); + throw new I18nException(Launcher.i18n("launch.failed.creating_process") + e.getLocalizedMessage(), e); } catch (NotDecompressingNativesException e) { - throw new I18nException(Main.i18n("launch.failed.decompressing_natives") + e.getLocalizedMessage(), e); + throw new I18nException(Launcher.i18n("launch.failed.decompressing_natives") + e.getLocalizedMessage(), e); } } @@ -382,10 +381,10 @@ public final class LauncherHelper { switch (exitType) { case JVM_ERROR: - logWindow.setTitle(Main.i18n("launch.failed.cannot_create_jvm")); + logWindow.setTitle(Launcher.i18n("launch.failed.cannot_create_jvm")); break; case APPLICATION_ERROR: - logWindow.setTitle(Main.i18n("launch.failed.exited_abnormally")); + logWindow.setTitle(Launcher.i18n("launch.failed.exited_abnormally")); break; } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/LoadingState.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/LoadingState.java index da1ab1c10..9f71f91d8 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LoadingState.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LoadingState.java @@ -17,7 +17,7 @@ */ package org.jackhuang.hmcl.game; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; public enum LoadingState { DEPENDENCIES("launch.state.dependencies"), @@ -33,6 +33,6 @@ public enum LoadingState { } public String getLocalizedMessage() { - return Main.i18n(key); + return Launcher.i18n(key); } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java index ca15f364a..ddab99ef3 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java @@ -17,8 +17,7 @@ */ package org.jackhuang.hmcl.setting; -import com.google.gson.JsonParseException; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.auth.Account; import org.jackhuang.hmcl.auth.AccountFactory; import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccount; @@ -74,8 +73,8 @@ public final class Accounts { private static String downloadAuthlibInjector() throws Exception { AuthlibInjectorBuildInfo buildInfo = AuthlibInjectorBuildInfo.requestBuildInfo(); - File jar = new File(Main.HMCL_DIRECTORY, "authlib-injector.jar"); - File local = new File(Main.HMCL_DIRECTORY, "authlib-injector.txt"); + File jar = new File(Launcher.HMCL_DIRECTORY, "authlib-injector.jar"); + File local = new File(Launcher.HMCL_DIRECTORY, "authlib-injector.txt"); int buildNumber = 0; try { buildNumber = Integer.parseInt(FileUtils.readText(local)); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java index be3ed382a..afd722a3c 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java @@ -18,7 +18,7 @@ package org.jackhuang.hmcl.setting; import com.google.gson.annotations.SerializedName; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.util.JavaVersion; import java.util.*; @@ -35,7 +35,7 @@ final class Config { private String backgroundImage = null; @SerializedName("commonpath") - private String commonDirectory = Main.MINECRAFT_DIRECTORY.getAbsolutePath(); + private String commonDirectory = Launcher.MINECRAFT_DIRECTORY.getAbsolutePath(); @SerializedName("hasProxy") private boolean hasProxy = false; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/DownloadProviders.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/DownloadProviders.java index fe69bba78..8b38c133f 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/DownloadProviders.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/DownloadProviders.java @@ -23,7 +23,6 @@ import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.download.MojangDownloadProvider; import org.jackhuang.hmcl.util.Lang; -import java.util.Arrays; import java.util.List; public final class DownloadProviders { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Locales.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Locales.java index e5b625fed..f23274680 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Locales.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Locales.java @@ -20,7 +20,6 @@ package org.jackhuang.hmcl.setting; import org.jackhuang.hmcl.ui.construct.UTF8Control; import org.jackhuang.hmcl.util.Lang; -import java.util.Arrays; import java.util.List; import java.util.Locale; import java.util.ResourceBundle; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Profiles.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Profiles.java index 0f3158d7a..eb22f9607 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Profiles.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Profiles.java @@ -17,7 +17,7 @@ */ package org.jackhuang.hmcl.setting; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; public final class Profiles { private Profiles() { @@ -26,9 +26,9 @@ public final class Profiles { public static String getProfileDisplayName(Profile profile) { switch (profile.getName()) { case Settings.DEFAULT_PROFILE: - return Main.i18n("profile.default"); + return Launcher.i18n("profile.default"); case Settings.HOME_PROFILE: - return Main.i18n("profile.home"); + return Launcher.i18n("profile.home"); default: return profile.getName(); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Proxies.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Proxies.java index db174bff3..919351d30 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Proxies.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Proxies.java @@ -20,7 +20,6 @@ package org.jackhuang.hmcl.setting; import org.jackhuang.hmcl.util.Lang; import java.net.Proxy; -import java.util.Arrays; import java.util.List; /** diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java index ef22ca06b..fe6498d66 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java @@ -23,7 +23,7 @@ import javafx.beans.property.ObjectProperty; import javafx.beans.property.StringProperty; import javafx.beans.value.ObservableValue; import javafx.scene.text.Font; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.auth.Account; import org.jackhuang.hmcl.auth.AccountFactory; import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccount; @@ -525,7 +525,7 @@ public class Settings { private void checkProfileMap() { if (getProfileMap().isEmpty()) { getProfileMap().put(DEFAULT_PROFILE, new Profile(DEFAULT_PROFILE)); - getProfileMap().put(HOME_PROFILE, new Profile(HOME_PROFILE, Main.MINECRAFT_DIRECTORY)); + getProfileMap().put(HOME_PROFILE, new Profile(HOME_PROFILE, Launcher.MINECRAFT_DIRECTORY)); } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java index 6e3e3bf61..834ca4203 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java @@ -19,7 +19,7 @@ package org.jackhuang.hmcl.setting; import com.google.gson.*; import javafx.beans.InvalidationListener; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.game.LaunchOptions; import org.jackhuang.hmcl.util.*; @@ -482,8 +482,8 @@ public final class VersionSetting { return new LaunchOptions.Builder() .setGameDir(gameDir) .setJava(javaVersion) - .setVersionName(Main.TITLE) - .setProfileName(Main.TITLE) + .setVersionName(Launcher.TITLE) + .setProfileName(Launcher.TITLE) .setMinecraftArgs(getMinecraftArgs()) .setJavaArgs(getJavaArgs()) .setMaxMemory(getMaxMemory()) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountsPage.java index bc5c020fb..7fc62cfcd 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountsPage.java @@ -34,7 +34,7 @@ import javafx.scene.image.ImageView; import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; import javafx.scene.layout.StackPane; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.auth.*; import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccount; import org.jackhuang.hmcl.auth.offline.OfflineAccount; @@ -61,7 +61,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; public final class AccountsPage extends StackPane implements DecoratorPage { - private final StringProperty title = new SimpleStringProperty(this, "title", Main.i18n("account")); + private final StringProperty title = new SimpleStringProperty(this, "title", Launcher.i18n("account")); @FXML private ScrollPane scrollPane; @@ -85,7 +85,7 @@ public final class AccountsPage extends StackPane implements DecoratorPage { FXUtils.smoothScrolling(scrollPane); - cboType.getItems().setAll(Main.i18n("account.methods.offline"), Main.i18n("account.methods.yggdrasil"), Main.i18n("account.methods.authlib_injector")); + cboType.getItems().setAll(Launcher.i18n("account.methods.offline"), Launcher.i18n("account.methods.yggdrasil"), Launcher.i18n("account.methods.authlib_injector")); cboType.getSelectionModel().selectedIndexProperty().addListener((a, b, newValue) -> { txtPassword.setVisible(newValue.intValue() != 0); lblPassword.setVisible(newValue.intValue() != 0); @@ -101,7 +101,7 @@ public final class AccountsPage extends StackPane implements DecoratorPage { txtPassword.setOnAction(e -> onCreationAccept()); txtUsername.setOnAction(e -> onCreationAccept()); - txtUsername.getValidators().add(new Validator(Main.i18n("input.email"), str -> !txtPassword.isVisible() || str.contains("@"))); + txtUsername.getValidators().add(new Validator(Launcher.i18n("input.email"), str -> !txtPassword.isVisible() || str.contains("@"))); FXUtils.onChangeAndOperate(Settings.INSTANCE.selectedAccountProperty(), account -> { for (Node node : masonryPane.getChildren()) @@ -227,25 +227,25 @@ public final class AccountsPage extends StackPane implements DecoratorPage { public static String accountException(Exception exception) { if (exception instanceof InvalidCredentialsException) { - return Main.i18n("account.failed.invalid_credentials"); + return Launcher.i18n("account.failed.invalid_credentials"); } else if (exception instanceof NoCharacterException) { - return Main.i18n("account.failed.no_charactor"); + return Launcher.i18n("account.failed.no_charactor"); } else if (exception instanceof ServerDisconnectException) { - return Main.i18n("account.failed.connect_authentication_server"); + return Launcher.i18n("account.failed.connect_authentication_server"); } else if (exception instanceof InvalidTokenException) { - return Main.i18n("account.failed.invalid_token"); + return Launcher.i18n("account.failed.invalid_token"); } else if (exception instanceof InvalidPasswordException) { - return Main.i18n("account.failed.invalid_password"); + return Launcher.i18n("account.failed.invalid_password"); } else { return exception.getClass() + ": " + exception.getLocalizedMessage(); } } public static String accountType(Account account) { - if (account instanceof OfflineAccount) return Main.i18n("account.methods.offline"); - else if (account instanceof AuthlibInjectorAccount) return Main.i18n("account.methods.authlib_injector"); - else if (account instanceof YggdrasilAccount) return Main.i18n("account.methods.yggdrasil"); - else throw new Error(Main.i18n("account.methods.no_method") + ": " + account); + if (account instanceof OfflineAccount) return Launcher.i18n("account.methods.offline"); + else if (account instanceof AuthlibInjectorAccount) return Launcher.i18n("account.methods.authlib_injector"); + else if (account instanceof YggdrasilAccount) return Launcher.i18n("account.methods.yggdrasil"); + else throw new Error(Launcher.i18n("account.methods.no_method") + ": " + account); } private static class Selector extends BorderPane implements CharacterSelector { @@ -258,11 +258,11 @@ public final class AccountsPage extends StackPane implements DecoratorPage { { setStyle("-fx-padding: 8px;"); - cancel.setText(Main.i18n("button.cancel")); + cancel.setText(Launcher.i18n("button.cancel")); StackPane.setAlignment(cancel, Pos.BOTTOM_RIGHT); cancel.setOnMouseClicked(e -> latch.countDown()); - listBox.startCategory(Main.i18n("account.choose")); + listBox.startCategory(Launcher.i18n("account.choose")); setCenter(listBox); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AuthlibInjectorServersPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AuthlibInjectorServersPage.java index b16eaf2f0..dd5e20352 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AuthlibInjectorServersPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AuthlibInjectorServersPage.java @@ -9,7 +9,7 @@ import javafx.scene.control.Label; import javafx.scene.control.ScrollPane; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServerInfo; import org.jackhuang.hmcl.setting.Accounts; import org.jackhuang.hmcl.setting.Settings; @@ -22,13 +22,12 @@ import org.jackhuang.hmcl.util.Logging; import org.jackhuang.hmcl.util.NetworkUtils; import java.util.Collection; -import java.util.Objects; import java.util.logging.Level; import java.util.stream.Collectors; import java.util.stream.Stream; public class AuthlibInjectorServersPage extends StackPane implements DecoratorPage { - private final StringProperty title = new SimpleStringProperty(this, "title", Main.i18n("account.injector.server")); + private final StringProperty title = new SimpleStringProperty(this, "title", Launcher.i18n("account.injector.server")); @FXML private ScrollPane scrollPane; @FXML private StackPane addServerContainer; 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 c734d4d83..8b855ec06 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java @@ -23,7 +23,7 @@ import javafx.scene.Scene; import javafx.scene.image.Image; import javafx.scene.layout.Region; import javafx.stage.Stage; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.setting.Settings; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.task.TaskExecutor; @@ -93,7 +93,7 @@ public final class Controllers { public static void initialize(Stage stage) { Controllers.stage = stage; - decorator = new Decorator(stage, getMainPage(), Main.TITLE, false, true); + decorator = new Decorator(stage, getMainPage(), Launcher.TITLE, false, true); decorator.showPage(null); leftPaneController = new LeftPaneController(decorator.getLeftPane()); @@ -110,7 +110,7 @@ public final class Controllers { stage.setMaxHeight(521); stage.getIcons().add(new Image("/assets/img/icon.png")); - stage.setTitle(Main.TITLE); + stage.setTitle(Launcher.TITLE); } public static Region getDialogContent() { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/CrashWindow.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/CrashWindow.java index e9e4eb16c..285c6e640 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/CrashWindow.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/CrashWindow.java @@ -27,7 +27,7 @@ import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; import javafx.scene.layout.StackPane; import javafx.stage.Stage; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; /** * @author huangyuhui @@ -36,10 +36,10 @@ public class CrashWindow extends Stage { public CrashWindow(String text) { Label lblCrash = new Label(); - if (Main.UPDATE_CHECKER.isOutOfDate()) - lblCrash.setText(Main.i18n("launcher.crash_out_dated")); + if (Launcher.UPDATE_CHECKER.isOutOfDate()) + lblCrash.setText(Launcher.i18n("launcher.crash_out_dated")); else - lblCrash.setText(Main.i18n("launcher.crash")); + lblCrash.setText(Launcher.i18n("launcher.crash")); lblCrash.setWrapText(true); TextArea textArea = new TextArea(); @@ -47,8 +47,8 @@ public class CrashWindow extends Stage { textArea.setEditable(false); Button btnContact = new Button(); - btnContact.setText(Main.i18n("launcher.contact")); - btnContact.setOnMouseClicked(event -> FXUtils.openLink(Main.CONTACT)); + btnContact.setText(Launcher.i18n("launcher.contact")); + btnContact.setOnMouseClicked(event -> FXUtils.openLink(Launcher.CONTACT)); HBox box = new HBox(); box.setStyle("-fx-padding: 8px;"); box.getChildren().add(btnContact); @@ -65,7 +65,7 @@ public class CrashWindow extends Stage { Scene scene = new Scene(pane, 800, 480); setScene(scene); getIcons().add(new Image("/assets/img/icon.png")); - setTitle(Main.i18n("message.error")); + setTitle(Launcher.i18n("message.error")); setOnCloseRequest(e -> System.exit(1)); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java index 096a39c56..9c28cb87e 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java @@ -45,7 +45,7 @@ import javafx.scene.shape.Rectangle; import javafx.stage.Screen; import javafx.stage.Stage; import javafx.stage.StageStyle; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.setting.EnumBackgroundImage; import org.jackhuang.hmcl.setting.Settings; import org.jackhuang.hmcl.setting.Theme; @@ -74,7 +74,7 @@ public final class Decorator extends StackPane implements TaskExecutorDialogWiza private static final SVGGlyph close = Lang.apply(new SVGGlyph(0, "CLOSE", "M810 274l-238 238 238 238-60 60-238-238-238 238-60-60 238-238-238-238 60-60 238 238 238-238z", Color.WHITE), glyph -> { glyph.setPrefSize(12, 12); glyph.setSize(12, 12); }); - private final ObjectProperty onCloseButtonAction = new SimpleObjectProperty<>(Main::stopApplication); + private final ObjectProperty onCloseButtonAction = new SimpleObjectProperty<>(Launcher::stopApplication); private final BooleanProperty customMaximize = new SimpleBooleanProperty(false); private final Stage primaryStage; @@ -144,7 +144,7 @@ public final class Decorator extends StackPane implements TaskExecutorDialogWiza FXUtils.loadFXML(this, "/assets/fxml/decorator.fxml"); updatePane.setCursor(Cursor.HAND); - updatePane.setOnMouseClicked(event -> Main.UPDATE_CHECKER.checkOutdate()); + updatePane.setOnMouseClicked(event -> Launcher.UPDATE_CHECKER.checkOutdate()); primaryStage.initStyle(StageStyle.UNDECORATED); btnClose.setGraphic(close); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java index b8ddba831..e09ed5c0e 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java @@ -41,7 +41,7 @@ import javafx.scene.input.ScrollEvent; import javafx.scene.layout.Region; import javafx.scene.shape.Rectangle; import javafx.util.Duration; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.util.*; import java.io.File; @@ -184,7 +184,7 @@ public final class FXUtils { } public static void loadFXML(Node node, String absolutePath) { - FXMLLoader loader = new FXMLLoader(node.getClass().getResource(absolutePath), Main.RESOURCE_BUNDLE); + FXMLLoader loader = new FXMLLoader(node.getClass().getResource(absolutePath), Launcher.RESOURCE_BUNDLE); loader.setRoot(node); loader.setController(node); Lang.invoke((ExceptionalSupplier) loader::load); 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 f227d90ca..225b8d8df 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerItem.java @@ -21,7 +21,7 @@ import com.jfoenix.effects.JFXDepthManager; import javafx.fxml.FXML; import javafx.scene.control.Label; import javafx.scene.layout.BorderPane; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import java.util.function.Consumer; @@ -44,7 +44,7 @@ public class InstallerItem extends BorderPane { setStyle("-fx-background-radius: 2; -fx-background-color: white; -fx-padding: 8;"); JFXDepthManager.setDepth(this, 1); lblInstallerArtifact.setText(artifact); - lblInstallerVersion.setText(Main.i18n("archive.version") + ": " + version); + lblInstallerVersion.setText(Launcher.i18n("archive.version") + ": " + version); } @FXML 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 b67caaf05..9b28546e3 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java @@ -25,7 +25,7 @@ import javafx.scene.image.Image; import javafx.scene.layout.BorderPane; import javafx.scene.layout.VBox; import javafx.scene.text.Text; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount; import org.jackhuang.hmcl.event.EventBus; import org.jackhuang.hmcl.event.ProfileChangedEvent; @@ -60,18 +60,18 @@ public final class LeftPaneController { public LeftPaneController(AdvancedListBox leftPane) { this.leftPane = leftPane; - leftPane.startCategory(Main.i18n("account").toUpperCase()) + leftPane.startCategory(Launcher.i18n("account").toUpperCase()) .add(Lang.apply(new RipplerContainer(accountItem), rippler -> { rippler.setOnMouseClicked(e -> Controllers.navigate(new AccountsPage())); accountItem.setOnSettingsButtonClicked(() -> Controllers.navigate(new AccountsPage())); })) - .startCategory(Main.i18n("launcher").toUpperCase()) - .add(Lang.apply(new IconedItem(SVG.gear(Theme.blackFillBinding(), 20, 20), Main.i18n("settings.launcher")), iconedItem -> { + .startCategory(Launcher.i18n("launcher").toUpperCase()) + .add(Lang.apply(new IconedItem(SVG.gear(Theme.blackFillBinding(), 20, 20), Launcher.i18n("settings.launcher")), iconedItem -> { iconedItem.prefWidthProperty().bind(leftPane.widthProperty()); iconedItem.setOnMouseClicked(e -> Controllers.navigate(Controllers.getSettingsPage())); })) .add(new ClassTitle(Lang.apply(new BorderPane(), borderPane -> { - borderPane.setLeft(Lang.apply(new VBox(), vBox -> vBox.getChildren().setAll(new Text(Main.i18n("profile.title").toUpperCase())))); + borderPane.setLeft(Lang.apply(new VBox(), vBox -> vBox.getChildren().setAll(new Text(Launcher.i18n("profile.title").toUpperCase())))); JFXButton addProfileButton = new JFXButton(); addProfileButton.setGraphic(SVG.plus(Theme.blackFillBinding(), 10, 10)); addProfileButton.getStyleClass().add("toggle-icon-tiny"); @@ -87,8 +87,8 @@ public final class LeftPaneController { FXUtils.onChangeAndOperate(Settings.INSTANCE.selectedAccountProperty(), it -> { if (it == null) { - accountItem.setVersionName(Main.i18n("account.missing")); - accountItem.setGameVersion(Main.i18n("message.unknown")); + accountItem.setVersionName(Launcher.i18n("account.missing")); + accountItem.setGameVersion(Launcher.i18n("message.unknown")); } else { accountItem.setVersionName(it.getCharacter()); accountItem.setGameVersion(AccountsPage.accountType(it)); @@ -110,7 +110,7 @@ public final class LeftPaneController { if (node instanceof RipplerContainer && node.getProperties().get("profile") instanceof String) { boolean current = Objects.equals(node.getProperties().get("profile"), profile.getName()); ((RipplerContainer) node).setSelected(current); - ((VersionListItem) ((RipplerContainer) node).getContainer()).setGameVersion(current ? Main.i18n("profile.selected") : ""); + ((VersionListItem) ((RipplerContainer) node).getContainer()).setGameVersion(current ? Launcher.i18n("profile.selected") : ""); } } }); @@ -149,7 +149,7 @@ public final class LeftPaneController { Controllers.closeDialog(); checkAccount(); })).executor(), - Main.i18n("modpack.installing"), "", null); + Launcher.i18n("modpack.installing"), "", null); flag = false; } catch (UnsupportedModpackException ignore) { } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindow.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindow.java index 1547b138e..7801ef900 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindow.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindow.java @@ -30,7 +30,7 @@ import javafx.scene.layout.StackPane; import javafx.scene.web.WebEngine; import javafx.scene.web.WebView; import javafx.stage.Stage; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.event.Event; import org.jackhuang.hmcl.event.EventManager; import org.jackhuang.hmcl.game.LauncherHelper; @@ -63,7 +63,7 @@ public final class LogWindow extends Stage { public LogWindow() { setScene(new Scene(impl, 800, 480)); getScene().getStylesheets().addAll(Settings.INSTANCE.getTheme().getStylesheets()); - setTitle(Main.i18n("logwindow.title")); + setTitle(Launcher.i18n("logwindow.title")); getIcons().add(new Image("/assets/img/icon.png")); } 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 fc83adff1..2c8642866 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java @@ -27,10 +27,11 @@ import javafx.scene.image.Image; import javafx.scene.input.MouseButton; import javafx.scene.layout.StackPane; import javafx.stage.FileChooser; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.event.EventBus; import org.jackhuang.hmcl.event.ProfileChangedEvent; import org.jackhuang.hmcl.event.RefreshedVersionsEvent; +import org.jackhuang.hmcl.event.RefreshingVersionsEvent; import org.jackhuang.hmcl.game.*; import org.jackhuang.hmcl.mod.MismatchedModpackTypeException; import org.jackhuang.hmcl.mod.UnsupportedModpackException; @@ -54,7 +55,7 @@ import java.util.List; public final class MainPage extends StackPane implements DecoratorPage { - private final StringProperty title = new SimpleStringProperty(this, "title", Main.i18n("main_page")); + private final StringProperty title = new SimpleStringProperty(this, "title", Launcher.i18n("main_page")); private Profile profile; private String rightClickedVersion; @@ -84,18 +85,21 @@ public final class MainPage extends StackPane implements DecoratorPage { if (event.getSource() == profile.getRepository()) loadVersions((HMCLGameRepository) event.getSource()); }); + EventBus.EVENT_BUS.channel(RefreshingVersionsEvent.class).register(event -> { + if (event.getSource() == profile.getRepository()) + JFXUtilities.runInFXAndWait(this::loadingVersions); + }); EventBus.EVENT_BUS.channel(ProfileChangedEvent.class).register(event -> { - JFXUtilities.runInFXAndWait(this::loadingVersions); this.profile = event.getProfile(); }); versionPopup = new JFXPopup(versionList); getChildren().remove(versionList); - btnAdd.setOnMouseClicked(e -> Controllers.getDecorator().startWizard(new DownloadWizardProvider(), Main.i18n("install"))); - FXUtils.installTooltip(btnAdd, Main.i18n("install")); + btnAdd.setOnMouseClicked(e -> Controllers.getDecorator().startWizard(new DownloadWizardProvider(), Launcher.i18n("install"))); + FXUtils.installTooltip(btnAdd, Launcher.i18n("install")); btnRefresh.setOnMouseClicked(e -> Settings.INSTANCE.getSelectedProfile().getRepository().refreshVersionsAsync().start()); - FXUtils.installTooltip(btnRefresh, Main.i18n("button.refresh")); + FXUtils.installTooltip(btnRefresh, Launcher.i18n("button.refresh")); } private Node buildNode(HMCLGameRepository repository, Version version, String game) { @@ -109,33 +113,33 @@ public final class MainPage extends StackPane implements DecoratorPage { StringBuilder libraries = new StringBuilder(); for (Library library : version.getLibraries()) { if (library.getGroupId().equalsIgnoreCase("net.minecraftforge") && library.getArtifactId().equalsIgnoreCase("forge")) { - libraries.append(Main.i18n("install.installer.forge")).append(": ").append(StringUtils.removeSuffix(StringUtils.removePrefix(library.getVersion().replaceAll("(?i)forge", "").replace(game, "").trim(), "-"), "-")).append("\n"); + libraries.append(Launcher.i18n("install.installer.forge")).append(": ").append(StringUtils.removeSuffix(StringUtils.removePrefix(library.getVersion().replaceAll("(?i)forge", "").replace(game, "").trim(), "-"), "-")).append("\n"); } if (library.getGroupId().equalsIgnoreCase("com.mumfrey") && library.getArtifactId().equalsIgnoreCase("liteloader")) { - libraries.append(Main.i18n("install.installer.liteloader")).append(": ").append(StringUtils.removeSuffix(StringUtils.removePrefix(library.getVersion().replaceAll("(?i)liteloader", "").replace(game, "").trim(), "-"), "-")).append("\n"); + libraries.append(Launcher.i18n("install.installer.liteloader")).append(": ").append(StringUtils.removeSuffix(StringUtils.removePrefix(library.getVersion().replaceAll("(?i)liteloader", "").replace(game, "").trim(), "-"), "-")).append("\n"); } if (library.getGroupId().equalsIgnoreCase("net.optifine") && library.getArtifactId().equalsIgnoreCase("optifine")) { - libraries.append(Main.i18n("install.installer.optifine")).append(": ").append(StringUtils.removeSuffix(StringUtils.removePrefix(library.getVersion().replaceAll("(?i)optifine", "").replace(game, "").trim(), "-"), "-")).append("\n"); + libraries.append(Launcher.i18n("install.installer.optifine")).append(": ").append(StringUtils.removeSuffix(StringUtils.removePrefix(library.getVersion().replaceAll("(?i)optifine", "").replace(game, "").trim(), "-"), "-")).append("\n"); } } item.setLibraries(libraries.toString()); item.setOnLaunchButtonClicked(e -> { if (Settings.INSTANCE.getSelectedAccount() == null) - Controllers.dialog(Main.i18n("login.empty_username")); + Controllers.dialog(Launcher.i18n("login.empty_username")); else LauncherHelper.INSTANCE.launch(profile, Settings.INSTANCE.getSelectedAccount(), id, null); }); item.setOnScriptButtonClicked(e -> { if (Settings.INSTANCE.getSelectedAccount() == null) - Controllers.dialog(Main.i18n("login.empty_username")); + Controllers.dialog(Launcher.i18n("login.empty_username")); else { FileChooser chooser = new FileChooser(); chooser.setInitialDirectory(repository.getRunDirectory(id)); - chooser.setTitle(Main.i18n("version.launch_script.save")); + chooser.setTitle(Launcher.i18n("version.launch_script.save")); chooser.getExtensionFilters().add(OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS - ? new FileChooser.ExtensionFilter(Main.i18n("extension.bat"), "*.bat") - : new FileChooser.ExtensionFilter(Main.i18n("extension.sh"), "*.sh")); + ? new FileChooser.ExtensionFilter(Launcher.i18n("extension.bat"), "*.bat") + : new FileChooser.ExtensionFilter(Launcher.i18n("extension.sh"), "*.sh")); File file = chooser.showSaveDialog(Controllers.getStage()); if (file != null) LauncherHelper.INSTANCE.launch(profile, Settings.INSTANCE.getSelectedAccount(), id, file); @@ -147,8 +151,8 @@ public final class MainPage extends StackPane implements DecoratorPage { }); item.setOnUpdateButtonClicked(event -> { FileChooser chooser = new FileChooser(); - chooser.setTitle(Main.i18n("modpack.choose")); - chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(Main.i18n("modpack"), "*.zip")); + chooser.setTitle(Launcher.i18n("modpack.choose")); + chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(Launcher.i18n("modpack"), "*.zip")); File selectedFile = chooser.showOpenDialog(Controllers.getStage()); if (selectedFile != null) { TaskExecutorDialogPane pane = new TaskExecutorDialogPane(null); @@ -156,15 +160,15 @@ public final class MainPage extends StackPane implements DecoratorPage { TaskExecutor executor = ModpackHelper.getUpdateTask(profile, selectedFile, id, ModpackHelper.readModpackConfiguration(repository.getModpackConfiguration(id))) .then(Task.of(Schedulers.javafx(), Controllers::closeDialog)).executor(); pane.setExecutor(executor); - pane.setTitle(Main.i18n("modpack.update")); + pane.setTitle(Launcher.i18n("modpack.update")); executor.start(); Controllers.dialog(pane); } catch (UnsupportedModpackException e) { - Controllers.dialog(Main.i18n("modpack.unsupported"), Main.i18n("message.error"), MessageBox.ERROR_MESSAGE); + Controllers.dialog(Launcher.i18n("modpack.unsupported"), Launcher.i18n("message.error"), MessageBox.ERROR_MESSAGE); } catch (MismatchedModpackTypeException e) { - Controllers.dialog(Main.i18n("modpack.mismatched_type"), Main.i18n("message.error"), MessageBox.ERROR_MESSAGE); + Controllers.dialog(Launcher.i18n("modpack.mismatched_type"), Launcher.i18n("message.error"), MessageBox.ERROR_MESSAGE); } catch (IOException e) { - Controllers.dialog(Main.i18n("modpack.invalid"), Main.i18n("message.error"), MessageBox.ERROR_MESSAGE); + Controllers.dialog(Launcher.i18n("modpack.invalid"), Launcher.i18n("message.error"), MessageBox.ERROR_MESSAGE); } } }); @@ -176,7 +180,7 @@ public final class MainPage extends StackPane implements DecoratorPage { versionPopup.show(item, JFXPopup.PopupVPosition.TOP, JFXPopup.PopupHPosition.LEFT, event.getX(), event.getY()); } else if (event.getButton() == MouseButton.PRIMARY && event.getClickCount() == 2) { if (Settings.INSTANCE.getSelectedAccount() == null) - Controllers.dialog(Main.i18n("login.empty_username")); + Controllers.dialog(Launcher.i18n("login.empty_username")); else LauncherHelper.INSTANCE.launch(profile, Settings.INSTANCE.getSelectedAccount(), id, null); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/ModController.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/ModController.java index 6cea184f7..459e398f1 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/ModController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/ModController.java @@ -17,16 +17,16 @@ */ package org.jackhuang.hmcl.ui; +import com.jfoenix.concurrency.JFXUtilities; import com.jfoenix.controls.JFXSpinner; import com.jfoenix.controls.JFXTabPane; -import javafx.application.Platform; import javafx.fxml.FXML; import javafx.scene.control.ScrollPane; import javafx.scene.input.TransferMode; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; import javafx.stage.FileChooser; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.mod.ModInfo; import org.jackhuang.hmcl.mod.ModManager; import org.jackhuang.hmcl.task.Schedulers; @@ -93,7 +93,7 @@ public final class ModController { this.versionId = versionId; Task.of(variables -> { synchronized (ModController.this) { - Platform.runLater(() -> { + JFXUtilities.runInFX(() -> { rootPane.getChildren().remove(contentPane); spinner.setVisible(true); }); @@ -121,25 +121,24 @@ public final class ModController { list.add(item); } - Platform.runLater(() -> { - rootPane.getChildren().add(contentPane); - spinner.setVisible(false); - }); variables.set("list", list); } - }).finalized(Schedulers.javafx(), variables -> { - FXUtils.onWeakChangeAndOperate(parentTab.getSelectionModel().selectedItemProperty(), newValue -> { - if (newValue != null && newValue.getUserData() == ModController.this) - modPane.getChildren().setAll(variables.>get("list")); - }); - }, null).start(); + }).finalized(Schedulers.javafx(), (variables, isDependentsSucceeded) -> { + rootPane.getChildren().add(contentPane); + spinner.setVisible(false); + if (isDependentsSucceeded) + FXUtils.onWeakChangeAndOperate(parentTab.getSelectionModel().selectedItemProperty(), newValue -> { + if (newValue != null && newValue.getUserData() == ModController.this) + modPane.getChildren().setAll(variables.>get("list")); + }); + }).start(); } @FXML private void onAdd() { FileChooser chooser = new FileChooser(); - chooser.setTitle(Main.i18n("mods.choose_mod")); - chooser.getExtensionFilters().setAll(new FileChooser.ExtensionFilter(Main.i18n("extension.mod"), "*.jar", "*.zip", "*.litemod")); + chooser.setTitle(Launcher.i18n("mods.choose_mod")); + chooser.getExtensionFilters().setAll(new FileChooser.ExtensionFilter(Launcher.i18n("extension.mod"), "*.jar", "*.zip", "*.litemod")); List res = chooser.showOpenMultipleDialog(Controllers.getStage()); // It's guaranteed that succeeded and failed are thread safe here. @@ -161,10 +160,10 @@ public final class ModController { }).with(Task.of(Schedulers.javafx(), variables -> { List prompt = new LinkedList<>(); if (!succeeded.isEmpty()) - prompt.add(Main.i18n("mods.add.success", String.join(", ", succeeded))); + prompt.add(Launcher.i18n("mods.add.success", String.join(", ", succeeded))); if (!failed.isEmpty()) - prompt.add(Main.i18n("mods.add.failed", String.join(", ", failed))); - Controllers.dialog(String.join("\n", prompt), Main.i18n("mods.add")); + prompt.add(Launcher.i18n("mods.add.failed", String.join(", ", failed))); + Controllers.dialog(String.join("\n", prompt), Launcher.i18n("mods.add")); loadMods(modManager, versionId); })).start(); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/ModItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/ModItem.java index 6c16b627b..7de389ad7 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/ModItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/ModItem.java @@ -22,7 +22,7 @@ import com.jfoenix.controls.JFXCheckBox; import com.jfoenix.effects.JFXDepthManager; import javafx.geometry.Pos; import javafx.scene.layout.BorderPane; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.mod.ModInfo; import org.jackhuang.hmcl.setting.Theme; @@ -40,7 +40,7 @@ public final class ModItem extends BorderPane { setCenter(modItem); JFXButton btnRemove = new JFXButton(); - FXUtils.installTooltip(btnRemove, Main.i18n("mods.remove")); + FXUtils.installTooltip(btnRemove, Launcher.i18n("mods.remove")); btnRemove.setOnMouseClicked(e -> deleteCallback.accept(this)); btnRemove.getStyleClass().add("toggle-icon4"); BorderPane.setAlignment(btnRemove, Pos.CENTER); @@ -50,7 +50,7 @@ public final class ModItem extends BorderPane { setStyle("-fx-background-radius: 2; -fx-background-color: white; -fx-padding: 8;"); JFXDepthManager.setDepth(this, 1); modItem.setTitle(info.getFileName()); - modItem.setSubtitle(info.getName() + ", " + Main.i18n("archive.version") + ": " + info.getVersion() + ", " + Main.i18n("archive.game_version") + ": " + info.getGameVersion() + ", " + Main.i18n("archive.author") + ": " + info.getAuthors()); + modItem.setSubtitle(info.getName() + ", " + Launcher.i18n("archive.version") + ": " + info.getVersion() + ", " + Launcher.i18n("archive.game_version") + ": " + info.getGameVersion() + ", " + Launcher.i18n("archive.author") + ": " + info.getAuthors()); chkEnabled.setSelected(info.isActive()); chkEnabled.selectedProperty().addListener((a, b, newValue) -> info.activeProperty().set(newValue)); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/ProfilePage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/ProfilePage.java index 1384c1df7..c579d135d 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/ProfilePage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/ProfilePage.java @@ -23,7 +23,7 @@ import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; import javafx.fxml.FXML; import javafx.scene.layout.StackPane; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.setting.Profile; import org.jackhuang.hmcl.setting.Profiles; import org.jackhuang.hmcl.setting.Settings; @@ -54,7 +54,7 @@ public final class ProfilePage extends StackPane implements DecoratorPage { String profileDisplayName = Optional.ofNullable(profile).map(Profiles::getProfileDisplayName).orElse(""); title = new SimpleStringProperty(this, "title", - profile == null ? Main.i18n("profile.new") : Main.i18n("profile") + " - " + profileDisplayName); + profile == null ? Launcher.i18n("profile.new") : Launcher.i18n("profile") + " - " + profileDisplayName); location = new SimpleStringProperty(this, "location", Optional.ofNullable(profile).map(Profile::getGameDir).map(File::getAbsolutePath).orElse("")); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsPage.java index 3ae536068..16e28e2ab 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsPage.java @@ -34,9 +34,12 @@ import javafx.scene.layout.Pane; import javafx.scene.layout.StackPane; import javafx.scene.paint.Color; import javafx.scene.text.Font; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.setting.*; -import org.jackhuang.hmcl.ui.construct.*; +import org.jackhuang.hmcl.ui.construct.FileItem; +import org.jackhuang.hmcl.ui.construct.FontComboBox; +import org.jackhuang.hmcl.ui.construct.MultiFileItem; +import org.jackhuang.hmcl.ui.construct.Validator; import org.jackhuang.hmcl.ui.wizard.DecoratorPage; import org.jackhuang.hmcl.util.Lang; @@ -46,7 +49,7 @@ import java.util.Collections; import java.util.stream.Collectors; public final class SettingsPage extends StackPane implements DecoratorPage { - private final StringProperty title = new SimpleStringProperty(this, "title", Main.i18n("settings.launcher")); + private final StringProperty title = new SimpleStringProperty(this, "title", Launcher.i18n("settings.launcher")); @FXML private JFXTextField txtProxyHost; @@ -174,12 +177,12 @@ public final class SettingsPage extends StackPane implements DecoratorPage { fileCommonLocation.setProperty(Settings.INSTANCE.commonPathProperty()); - FXUtils.installTooltip(btnUpdate, Main.i18n("update.tooltip")); + FXUtils.installTooltip(btnUpdate, Launcher.i18n("update.tooltip")); checkUpdate(); // background backgroundItem.loadChildren(Collections.singletonList( - backgroundItem.createChildren(Main.i18n("launcher.background.default"), EnumBackgroundImage.DEFAULT) + backgroundItem.createChildren(Launcher.i18n("launcher.background.default"), EnumBackgroundImage.DEFAULT) )); FXUtils.bindString(backgroundItem.getTxtCustom(), Settings.INSTANCE.backgroundImageProperty()); @@ -196,8 +199,8 @@ public final class SettingsPage extends StackPane implements DecoratorPage { // theme JFXColorPicker picker = new JFXColorPicker(Color.web(Settings.INSTANCE.getTheme().getColor()), null); - picker.setCustomColorText(Main.i18n("color.custom")); - picker.setRecentColorsText(Main.i18n("color.recent")); + picker.setCustomColorText(Launcher.i18n("color.custom")); + picker.setRecentColorsText(Launcher.i18n("color.recent")); picker.getCustomColors().setAll(Arrays.stream(Theme.VALUES).map(Theme::getColor).map(Color::web).collect(Collectors.toList())); picker.setOnAction(e -> { Theme theme = Theme.custom(Theme.getColorDisplayName(picker.getValue())); @@ -211,7 +214,7 @@ public final class SettingsPage extends StackPane implements DecoratorPage { private void initBackgroundItemSubtitle() { switch (Settings.INSTANCE.getBackgroundImageType()) { case DEFAULT: - backgroundItem.setSubtitle(Main.i18n("launcher.background.default")); + backgroundItem.setSubtitle(Launcher.i18n("launcher.background.default")); break; case CUSTOM: backgroundItem.setSubtitle(Settings.INSTANCE.getBackgroundImage()); @@ -233,25 +236,25 @@ public final class SettingsPage extends StackPane implements DecoratorPage { } public void checkUpdate() { - btnUpdate.setVisible(Main.UPDATE_CHECKER.isOutOfDate()); + btnUpdate.setVisible(Launcher.UPDATE_CHECKER.isOutOfDate()); - if (Main.UPDATE_CHECKER.isOutOfDate()) { - lblUpdateSub.setText(Main.i18n("update.newest_version", Main.UPDATE_CHECKER.getNewVersion().toString())); + if (Launcher.UPDATE_CHECKER.isOutOfDate()) { + lblUpdateSub.setText(Launcher.i18n("update.newest_version", Launcher.UPDATE_CHECKER.getNewVersion().toString())); lblUpdateSub.getStyleClass().setAll("update-label"); - lblUpdate.setText(Main.i18n("update.found")); + lblUpdate.setText(Launcher.i18n("update.found")); lblUpdate.getStyleClass().setAll("update-label"); } else { - lblUpdateSub.setText(Main.i18n("update.latest")); + lblUpdateSub.setText(Launcher.i18n("update.latest")); lblUpdateSub.getStyleClass().setAll("subtitle-label"); - lblUpdate.setText(Main.i18n("update")); + lblUpdate.setText(Launcher.i18n("update")); lblUpdate.getStyleClass().setAll(); } } @FXML private void onUpdate() { - Main.UPDATE_CHECKER.checkOutdate(); + Launcher.UPDATE_CHECKER.checkOutdate(); } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionItem.java index f18996d27..7843d3d7e 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionItem.java @@ -32,7 +32,7 @@ import javafx.scene.layout.Pane; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; import javafx.scene.paint.Color; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.setting.Theme; import java.util.Optional; @@ -73,10 +73,10 @@ public final class VersionItem extends StackPane { btnLaunch.setGraphic(SVG.launch(Theme.blackFillBinding(), 15, 15)); btnScript.setGraphic(SVG.script(Theme.blackFillBinding(), 15, 15)); - FXUtils.installTooltip(btnSettings, Main.i18n("version.settings")); - FXUtils.installTooltip(btnUpdate, Main.i18n("version.update")); - FXUtils.installTooltip(btnLaunch, Main.i18n("version.launch")); - FXUtils.installTooltip(btnScript, Main.i18n("version.launch_script")); + FXUtils.installTooltip(btnSettings, Launcher.i18n("version.settings")); + FXUtils.installTooltip(btnUpdate, Launcher.i18n("version.update")); + FXUtils.installTooltip(btnLaunch, Launcher.i18n("version.launch")); + FXUtils.installTooltip(btnScript, Launcher.i18n("version.launch_script")); icon.translateYProperty().bind(Bindings.createDoubleBinding(() -> header.getBoundsInParent().getHeight() - icon.getHeight() / 2 - 16, header.boundsInParentProperty(), icon.heightProperty())); FXUtils.limitSize(iconView, 32, 32); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionPage.java index a819a94a1..eb66d705f 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionPage.java @@ -26,7 +26,7 @@ import javafx.beans.property.StringProperty; import javafx.fxml.FXML; import javafx.scene.control.Tab; import javafx.scene.layout.StackPane; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.download.game.GameAssetIndexDownloadTask; import org.jackhuang.hmcl.setting.Profile; import org.jackhuang.hmcl.ui.export.ExportWizardProvider; @@ -79,17 +79,17 @@ public final class VersionPage extends StackPane implements DecoratorPage { browsePopup = new JFXPopup(browseList); managementPopup = new JFXPopup(managementList); - FXUtils.installTooltip(btnDelete, Main.i18n("version.manage.remove")); - FXUtils.installTooltip(btnBrowseMenu, Main.i18n("settings.game.exploration")); - FXUtils.installTooltip(btnManagementMenu, Main.i18n("settings.game.management")); - FXUtils.installTooltip(btnExport, Main.i18n("modpack.export")); + FXUtils.installTooltip(btnDelete, Launcher.i18n("version.manage.remove")); + FXUtils.installTooltip(btnBrowseMenu, Launcher.i18n("settings.game.exploration")); + FXUtils.installTooltip(btnManagementMenu, Launcher.i18n("settings.game.management")); + FXUtils.installTooltip(btnExport, Launcher.i18n("modpack.export")); } public void load(String id, Profile profile) { this.version = id; this.profile = profile; - title.set(Main.i18n("settings.game") + " - " + id); + title.set(Launcher.i18n("settings.game") + " - " + id); versionSettingsController.loadVersionSetting(profile, id); modController.setParentTab(tabPane); @@ -185,7 +185,7 @@ public final class VersionPage extends StackPane implements DecoratorPage { } public static void deleteVersion(Profile profile, String version) { - Controllers.confirmDialog(Main.i18n("version.manage.remove.confirm", version), Main.i18n("message.confirm"), () -> { + Controllers.confirmDialog(Launcher.i18n("version.manage.remove.confirm", version), Launcher.i18n("message.confirm"), () -> { if (profile.getRepository().removeVersionFromDisk(version)) { profile.getRepository().refreshVersionsAsync().start(); Controllers.navigate(null); @@ -194,7 +194,7 @@ public final class VersionPage extends StackPane implements DecoratorPage { } public static void renameVersion(Profile profile, String version) { - Controllers.inputDialog(Main.i18n("version.manage.rename.message"), res -> { + Controllers.inputDialog(Launcher.i18n("version.manage.rename.message"), res -> { if (profile.getRepository().renameVersion(version, res)) { profile.getRepository().refreshVersionsAsync().start(); Controllers.navigate(null); @@ -203,6 +203,6 @@ public final class VersionPage extends StackPane implements DecoratorPage { } public static void exportVersion(Profile profile, String version) { - Controllers.getDecorator().startWizard(new ExportWizardProvider(profile, version), Main.i18n("modpack.wizard")); + Controllers.getDecorator().startWizard(new ExportWizardProvider(profile, version), Launcher.i18n("modpack.wizard")); } } 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 13829715c..a62277b82 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionSettingsController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionSettingsController.java @@ -17,7 +17,10 @@ */ package org.jackhuang.hmcl.ui; -import com.jfoenix.controls.*; +import com.jfoenix.controls.JFXCheckBox; +import com.jfoenix.controls.JFXComboBox; +import com.jfoenix.controls.JFXTextField; +import com.jfoenix.controls.JFXToggleButton; import javafx.application.Platform; import javafx.fxml.FXML; import javafx.scene.Node; @@ -27,7 +30,7 @@ import javafx.scene.control.Toggle; import javafx.scene.image.Image; import javafx.scene.layout.VBox; import javafx.stage.FileChooser; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.setting.EnumGameDirectory; import org.jackhuang.hmcl.setting.Profile; import org.jackhuang.hmcl.setting.VersionSetting; @@ -77,7 +80,7 @@ public final class VersionSettingsController { @FXML private void initialize() { - lblPhysicalMemory.setText(Main.i18n("settings.physical_memory") + ": " + OperatingSystem.TOTAL_MEMORY + "MB"); + lblPhysicalMemory.setText(Launcher.i18n("settings.physical_memory") + ": " + OperatingSystem.TOTAL_MEMORY + "MB"); FXUtils.smoothScrolling(scroll); @@ -91,13 +94,13 @@ public final class VersionSettingsController { 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) + gameDirItem.createChildren(Launcher.i18n("settings.advanced.game_dir.default"), EnumGameDirectory.ROOT_FOLDER), + gameDirItem.createChildren(Launcher.i18n("settings.advanced.game_dir.independent"), EnumGameDirectory.VERSION_FOLDER) )); globalItem.loadChildren(Arrays.asList( - globalItem.createChildren(Main.i18n("settings.type.global"), true), - globalItem.createChildren(Main.i18n("settings.type.special"), false) + globalItem.createChildren(Launcher.i18n("settings.type.global"), true), + globalItem.createChildren(Launcher.i18n("settings.type.special"), false) )); } @@ -189,7 +192,7 @@ public final class VersionSettingsController { }); versionSetting.usesGlobalProperty().setChangedListenerAndOperate(it -> - globalItem.setSubtitle(Main.i18n(versionSetting.isUsesGlobal() ? "settings.type.global" : "settings.type.special"))); + globalItem.setSubtitle(Launcher.i18n(versionSetting.isUsesGlobal() ? "settings.type.global" : "settings.type.special"))); gameDirItem.getGroup().getToggles().stream() .filter(it -> it.getUserData() == versionSetting.getGameDirType()) @@ -229,7 +232,7 @@ public final class VersionSettingsController { @FXML private void onExploreIcon() { FileChooser chooser = new FileChooser(); - chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(Main.i18n("extension.png"), "*.png")); + chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(Launcher.i18n("extension.png"), "*.png")); File selectedFile = chooser.showOpenDialog(Controllers.getStage()); if (selectedFile != null) { File iconFile = profile.getRepository().getVersionIcon(versionId); 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 0bbfa6bb9..b80c23113 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 @@ -26,7 +26,7 @@ import javafx.scene.control.Tooltip; import javafx.scene.layout.BorderPane; import javafx.scene.layout.VBox; import javafx.stage.DirectoryChooser; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.setting.Theme; import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.ui.FXUtils; @@ -54,7 +54,7 @@ public class FileItem extends BorderPane { right.setGraphic(SVG.pencil(Theme.blackFillBinding(), 15, 15)); right.getStyleClass().add("toggle-icon4"); right.setOnMouseClicked(e -> onExplore()); - FXUtils.installTooltip(right, Main.i18n("button.edit")); + FXUtils.installTooltip(right, Launcher.i18n("button.edit")); setRight(right); Tooltip tip = new Tooltip(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ImagePickerItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ImagePickerItem.java index ee6932e65..178d6b10a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ImagePickerItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ImagePickerItem.java @@ -15,7 +15,7 @@ import javafx.scene.input.MouseEvent; import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.setting.Theme; import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.SVG; @@ -41,7 +41,7 @@ public final class ImagePickerItem extends BorderPane { selectButton.onMouseClickedProperty().bind(onSelectButtonClicked); selectButton.getStyleClass().add("toggle-icon4"); - FXUtils.installTooltip(selectButton, Main.i18n("button.edit")); + FXUtils.installTooltip(selectButton, Launcher.i18n("button.edit")); HBox hBox = new HBox(); hBox.getChildren().setAll(imageView, selectButton); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MessageBox.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MessageBox.java index 71402e1ad..4d10f1a64 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MessageBox.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MessageBox.java @@ -20,7 +20,7 @@ package org.jackhuang.hmcl.ui.construct; import javafx.scene.control.Alert; import javafx.scene.control.ButtonType; import javafx.scene.control.TextInputDialog; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import javax.swing.*; import java.util.Optional; @@ -29,7 +29,7 @@ public final class MessageBox { private MessageBox() { } - private static final String TITLE = Main.i18n("message.info"); + private static final String TITLE = Launcher.i18n("message.info"); /** * User Operation: Yes diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MessageDialogPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MessageDialogPane.java index 340b4e6ea..ca9d30dec 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MessageDialogPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MessageDialogPane.java @@ -23,7 +23,7 @@ import javafx.fxml.FXML; import javafx.scene.control.Label; import javafx.scene.layout.HBox; import javafx.scene.layout.StackPane; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.setting.Theme; import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.SVG; @@ -92,8 +92,8 @@ public final class MessageDialogPane extends StackPane { Optional.ofNullable(onCancel).ifPresent(Runnable::run); }); - acceptButton.setText(Main.i18n("button.yes")); - cancelButton.setText(Main.i18n("button.no")); + acceptButton.setText(Launcher.i18n("button.yes")); + cancelButton.setText(Launcher.i18n("button.no")); actions.getChildren().add(cancelButton); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MultiColorItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MultiColorItem.java index 42285ea61..8e7ec20e3 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MultiColorItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MultiColorItem.java @@ -5,17 +5,15 @@ import com.jfoenix.controls.JFXRadioButton; import javafx.beans.NamedArg; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; -import javafx.geometry.Pos; import javafx.scene.Node; import javafx.scene.control.Label; import javafx.scene.control.Toggle; import javafx.scene.control.ToggleGroup; -import javafx.scene.control.Tooltip; import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; import javafx.scene.paint.Color; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.ui.FXUtils; import java.util.Collection; @@ -23,8 +21,8 @@ import java.util.Optional; import java.util.function.Consumer; public class MultiColorItem extends ComponentList { - 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 StringProperty customTitle = new SimpleStringProperty(this, "customTitle", Launcher.i18n("selector.custom")); + private final StringProperty chooserTitle = new SimpleStringProperty(this, "chooserTitle", Launcher.i18n("selector.choose_file")); private final ToggleGroup group = new ToggleGroup(); private final JFXColorPicker colorPicker = new JFXColorPicker(); 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 c37fdc6ac..b0d1aa76e 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 @@ -38,7 +38,7 @@ 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.Launcher; import org.jackhuang.hmcl.setting.Theme; import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.ui.FXUtils; @@ -49,8 +49,8 @@ import java.util.Collection; import java.util.function.Consumer; public class MultiFileItem extends ComponentList { - 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 StringProperty customTitle = new SimpleStringProperty(this, "customTitle", Launcher.i18n("selector.custom")); + private final StringProperty chooserTitle = new SimpleStringProperty(this, "chooserTitle", Launcher.i18n("selector.choose_file")); private final BooleanProperty directory = new SimpleBooleanProperty(this, "directory", false); private final SimpleStringProperty tooltip = new SimpleStringProperty(this, "tooltip"); private final ObservableList extensionFilters = FXCollections.observableArrayList(); @@ -153,7 +153,7 @@ public class MultiFileItem extends ComponentList { public void onExploreJavaDir() { DirectoryChooser chooser = new DirectoryChooser(); - chooser.setTitle(Main.i18n(getChooserTitle())); + chooser.setTitle(Launcher.i18n(getChooserTitle())); File selectedDir = chooser.showDialog(Controllers.getStage()); if (selectedDir != null) txtCustom.setText(selectedDir.getAbsolutePath()); 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 f79b14805..6394fb4a9 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 @@ -19,7 +19,7 @@ package org.jackhuang.hmcl.ui.construct; import com.jfoenix.concurrency.JFXUtilities; import javafx.beans.property.StringProperty; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.task.TaskExecutor; import org.jackhuang.hmcl.task.TaskListener; @@ -38,7 +38,7 @@ public interface TaskExecutorDialogWizardDisplayer extends AbstractWizardDisplay Controllers.navigate(null); }); - pane.setTitle(Main.i18n("message.doing")); + pane.setTitle(Launcher.i18n("message.doing")); pane.setProgress(Double.MAX_VALUE); if (settings.containsKey("title")) { Object title = settings.get("title"); @@ -64,7 +64,7 @@ public interface TaskExecutorDialogWizardDisplayer extends AbstractWizardDisplay if (settings.containsKey("success_message") && settings.get("success_message") instanceof String) JFXUtilities.runInFX(() -> Controllers.dialog((String) settings.get("success_message"), null, MessageBox.FINE_MESSAGE, () -> Controllers.navigate(null))); else if (!settings.containsKey("forbid_success_message")) - JFXUtilities.runInFX(() -> Controllers.dialog(Main.i18n("message.success"), null, MessageBox.FINE_MESSAGE, () -> Controllers.navigate(null))); + JFXUtilities.runInFX(() -> Controllers.dialog(Launcher.i18n("message.success"), null, MessageBox.FINE_MESSAGE, () -> Controllers.navigate(null))); } else { if (executor.getLastException() == null) return; @@ -72,7 +72,7 @@ public interface TaskExecutorDialogWizardDisplayer extends AbstractWizardDisplay if (settings.containsKey("failure_message") && settings.get("failure_message") instanceof String) JFXUtilities.runInFX(() -> Controllers.dialog(appendix, (String) settings.get("failure_message"), MessageBox.ERROR_MESSAGE, () -> Controllers.navigate(null))); else if (!settings.containsKey("forbid_failure_message")) - JFXUtilities.runInFX(() -> Controllers.dialog(appendix, Main.i18n("wizard.failed"), MessageBox.ERROR_MESSAGE, () -> Controllers.navigate(null))); + JFXUtilities.runInFX(() -> Controllers.dialog(appendix, Launcher.i18n("wizard.failed"), MessageBox.ERROR_MESSAGE, () -> Controllers.navigate(null))); } } }); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskListPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskListPane.java index 9d5c7c2a6..40bdbb3bd 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskListPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskListPane.java @@ -23,7 +23,7 @@ import javafx.scene.control.Label; import javafx.scene.layout.BorderPane; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.download.forge.ForgeInstallTask; import org.jackhuang.hmcl.download.game.GameAssetDownloadTask; import org.jackhuang.hmcl.download.game.GameAssetRefreshTask; @@ -62,29 +62,29 @@ public final class TaskListPane extends StackPane { return; if (task instanceof GameAssetRefreshTask) { - task.setName(Main.i18n("assets.download")); + task.setName(Launcher.i18n("assets.download")); } else if (task instanceof GameAssetDownloadTask) { - task.setName(Main.i18n("assets.download_all")); + task.setName(Launcher.i18n("assets.download_all")); } else if (task instanceof ForgeInstallTask) { - task.setName(Main.i18n("install.installer.install", Main.i18n("install.installer.forge"))); + task.setName(Launcher.i18n("install.installer.install", Launcher.i18n("install.installer.forge"))); } else if (task instanceof LiteLoaderInstallTask) { - task.setName(Main.i18n("install.installer.install", Main.i18n("install.installer.liteloader"))); + task.setName(Launcher.i18n("install.installer.install", Launcher.i18n("install.installer.liteloader"))); } else if (task instanceof OptiFineInstallTask) { - task.setName(Main.i18n("install.installer.install", Main.i18n("install.installer.optifine"))); + task.setName(Launcher.i18n("install.installer.install", Launcher.i18n("install.installer.optifine"))); } else if (task instanceof CurseCompletionTask) { - task.setName(Main.i18n("modpack.type.curse.completion")); + task.setName(Launcher.i18n("modpack.type.curse.completion")); } else if (task instanceof ModpackInstallTask) { - task.setName(Main.i18n("modpack.installing")); + task.setName(Launcher.i18n("modpack.installing")); } else if (task instanceof CurseInstallTask) { - task.setName(Main.i18n("modpack.install", Main.i18n("modpack.type.curse"))); + task.setName(Launcher.i18n("modpack.install", Launcher.i18n("modpack.type.curse"))); } else if (task instanceof MultiMCModpackInstallTask) { - task.setName(Main.i18n("modpack.install", Main.i18n("modpack.type.multimc"))); + task.setName(Launcher.i18n("modpack.install", Launcher.i18n("modpack.type.multimc"))); } else if (task instanceof HMCLModpackInstallTask) { - task.setName(Main.i18n("modpack.install", Main.i18n("modpack.type.hmcl"))); + task.setName(Launcher.i18n("modpack.install", Launcher.i18n("modpack.type.hmcl"))); } else if (task instanceof HMCLModpackExportTask) { - task.setName(Main.i18n("modpack.export")); + task.setName(Launcher.i18n("modpack.export")); } else if (task instanceof MinecraftInstanceTask) { - task.setName(Main.i18n("modpack.scan")); + task.setName(Launcher.i18n("modpack.scan")); } ProgressListNode node = new ProgressListNode(task); 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 597a9f2a9..71d2c9f28 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 @@ -22,7 +22,7 @@ import javafx.fxml.FXML; import javafx.scene.control.Label; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.download.RemoteVersion; import org.jackhuang.hmcl.game.GameRepository; @@ -34,7 +34,7 @@ import org.jackhuang.hmcl.util.Lang; import java.util.Map; import java.util.Optional; -import static org.jackhuang.hmcl.Main.i18n; +import static org.jackhuang.hmcl.Launcher.i18n; class AdditionalInstallersPage extends StackPane implements WizardPage { private final InstallerWizardProvider provider; @@ -100,7 +100,7 @@ class AdditionalInstallersPage extends StackPane implements WizardPage { @Override public String getTitle() { - return Main.i18n("settings.tabs.installers"); + return Launcher.i18n("settings.tabs.installers"); } private String getVersion(String id) { @@ -109,24 +109,24 @@ class AdditionalInstallersPage extends StackPane implements WizardPage { @Override public void onNavigate(Map settings) { - lblGameVersion.setText(Main.i18n("install.new_game.current_game_version") + ": " + provider.getGameVersion()); + lblGameVersion.setText(Launcher.i18n("install.new_game.current_game_version") + ": " + provider.getGameVersion()); btnForge.setDisable(provider.getForge() != null); if (provider.getForge() != null || controller.getSettings().containsKey("forge")) - lblForge.setText(Main.i18n("install.installer.version", Main.i18n("install.installer.forge")) + ": " + Lang.nonNull(provider.getForge(), getVersion("forge"))); + lblForge.setText(Launcher.i18n("install.installer.version", Launcher.i18n("install.installer.forge")) + ": " + Lang.nonNull(provider.getForge(), getVersion("forge"))); else - lblForge.setText(Main.i18n("install.installer.not_installed", Main.i18n("install.installer.forge"))); + lblForge.setText(Launcher.i18n("install.installer.not_installed", Launcher.i18n("install.installer.forge"))); btnLiteLoader.setDisable(provider.getLiteLoader() != null); if (provider.getLiteLoader() != null || controller.getSettings().containsKey("liteloader")) - lblLiteLoader.setText(Main.i18n("install.installer.version", Main.i18n("install.installer.liteloader")) + ": " + Lang.nonNull(provider.getLiteLoader(), getVersion("liteloader"))); + lblLiteLoader.setText(Launcher.i18n("install.installer.version", Launcher.i18n("install.installer.liteloader")) + ": " + Lang.nonNull(provider.getLiteLoader(), getVersion("liteloader"))); else - lblLiteLoader.setText(Main.i18n("install.installer.not_installed", Main.i18n("install.installer.liteloader"))); + lblLiteLoader.setText(Launcher.i18n("install.installer.not_installed", Launcher.i18n("install.installer.liteloader"))); btnOptiFine.setDisable(provider.getOptiFine() != null); if (provider.getOptiFine() != null || controller.getSettings().containsKey("optifine")) - lblOptiFine.setText(Main.i18n("install.installer.version", Main.i18n("install.installer.optifine")) + ": " + Lang.nonNull(provider.getOptiFine(), getVersion("optifine"))); + lblOptiFine.setText(Launcher.i18n("install.installer.version", Launcher.i18n("install.installer.optifine")) + ": " + Lang.nonNull(provider.getOptiFine(), getVersion("optifine"))); else - lblOptiFine.setText(Main.i18n("install.installer.not_installed", Main.i18n("install.installer.optifine"))); + lblOptiFine.setText(Launcher.i18n("install.installer.not_installed", Launcher.i18n("install.installer.optifine"))); } 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 2c3787c8d..b4f0ea869 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 @@ -18,7 +18,7 @@ package org.jackhuang.hmcl.ui.download; import javafx.scene.Node; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.download.GameBuilder; import org.jackhuang.hmcl.download.RemoteVersion; @@ -34,7 +34,7 @@ import org.jackhuang.hmcl.util.Lang; import java.io.File; import java.util.Map; -import static org.jackhuang.hmcl.Main.i18n; +import static org.jackhuang.hmcl.Launcher.i18n; public final class DownloadWizardProvider implements WizardProvider { private Profile profile; @@ -77,8 +77,8 @@ public final class DownloadWizardProvider implements WizardProvider { @Override public Object finish(Map settings) { - settings.put("success_message", Main.i18n("install.success")); - settings.put("failure_message", Main.i18n("install.failed")); + settings.put("success_message", Launcher.i18n("install.success")); + settings.put("failure_message", Launcher.i18n("install.failed")); switch (Lang.parseInt(settings.get(InstallTypePage.INSTALL_TYPE), -1)) { case 0: return finishVersionDownloadingAsync(settings); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallTypePage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallTypePage.java index 2445e59a2..43c3a1379 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallTypePage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallTypePage.java @@ -20,7 +20,7 @@ package org.jackhuang.hmcl.ui.download; import com.jfoenix.controls.JFXListView; import javafx.fxml.FXML; import javafx.scene.layout.StackPane; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.wizard.WizardController; import org.jackhuang.hmcl.ui.wizard.WizardPage; @@ -51,7 +51,7 @@ public final class InstallTypePage extends StackPane implements WizardPage { @Override public String getTitle() { - return Main.i18n("install.select"); + return Launcher.i18n("install.select"); } public static final String INSTALL_TYPE = "INSTALL_TYPE"; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallerWizardProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallerWizardProvider.java index 9272dc7e3..d8e77a3b7 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallerWizardProvider.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallerWizardProvider.java @@ -18,7 +18,7 @@ package org.jackhuang.hmcl.ui.download; import javafx.scene.Node; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.download.BMCLAPIDownloadProvider; import org.jackhuang.hmcl.download.RemoteVersion; import org.jackhuang.hmcl.game.Version; @@ -80,8 +80,8 @@ public final class InstallerWizardProvider implements WizardProvider { @Override public Object finish(Map settings) { - settings.put("success_message", Main.i18n("install.success")); - settings.put("failure_message", Main.i18n("install.failed")); + settings.put("success_message", Launcher.i18n("install.success")); + settings.put("failure_message", Launcher.i18n("install.failed")); Task ret = Task.empty(); 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 6f81fc2bb..32a07ebcc 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 @@ -23,7 +23,7 @@ import javafx.fxml.FXML; import javafx.scene.control.Label; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.download.RemoteVersion; import org.jackhuang.hmcl.game.GameRepository; @@ -34,7 +34,6 @@ import org.jackhuang.hmcl.ui.wizard.WizardPage; import org.jackhuang.hmcl.util.StringUtils; import java.util.Map; -import java.util.Optional; public class InstallersPage extends StackPane implements WizardPage { private final WizardController controller; @@ -80,30 +79,30 @@ public class InstallersPage extends StackPane implements WizardPage { String gameVersion = ((RemoteVersion) controller.getSettings().get("game")).getGameVersion(); Validator hasVersion = new Validator(s -> !repository.hasVersion(s) && StringUtils.isNotBlank(s)); - hasVersion.setMessage(Main.i18n("install.new_game.already_exists")); + hasVersion.setMessage(Launcher.i18n("install.new_game.already_exists")); txtName.getValidators().add(hasVersion); txtName.textProperty().addListener(e -> btnInstall.setDisable(!txtName.validate())); txtName.setText(gameVersion); btnForge.setOnMouseClicked(e -> { controller.getSettings().put(INSTALLER_TYPE, 0); - controller.onNext(new VersionsPage(controller, Main.i18n("install.installer.choose", Main.i18n("install.installer.forge")), gameVersion, downloadProvider, "forge", () -> controller.onPrev(false))); + controller.onNext(new VersionsPage(controller, Launcher.i18n("install.installer.choose", Launcher.i18n("install.installer.forge")), gameVersion, downloadProvider, "forge", () -> controller.onPrev(false))); }); btnLiteLoader.setOnMouseClicked(e -> { controller.getSettings().put(INSTALLER_TYPE, 1); - controller.onNext(new VersionsPage(controller, Main.i18n("install.installer.choose", Main.i18n("install.installer.liteloader")), gameVersion, downloadProvider, "liteloader", () -> controller.onPrev(false))); + controller.onNext(new VersionsPage(controller, Launcher.i18n("install.installer.choose", Launcher.i18n("install.installer.liteloader")), gameVersion, downloadProvider, "liteloader", () -> controller.onPrev(false))); }); btnOptiFine.setOnMouseClicked(e -> { controller.getSettings().put(INSTALLER_TYPE, 2); - controller.onNext(new VersionsPage(controller, Main.i18n("install.installer.choose", Main.i18n("install.installer.optifine")), gameVersion, downloadProvider, "optifine", () -> controller.onPrev(false))); + controller.onNext(new VersionsPage(controller, Launcher.i18n("install.installer.choose", Launcher.i18n("install.installer.optifine")), gameVersion, downloadProvider, "optifine", () -> controller.onPrev(false))); }); } @Override public String getTitle() { - return Main.i18n("install.new_game"); + return Launcher.i18n("install.new_game"); } private String getVersion(String id) { @@ -112,21 +111,21 @@ public class InstallersPage extends StackPane implements WizardPage { @Override public void onNavigate(Map settings) { - lblGameVersion.setText(Main.i18n("install.new_game.current_game_version") + ": " + getVersion("game")); + lblGameVersion.setText(Launcher.i18n("install.new_game.current_game_version") + ": " + getVersion("game")); if (controller.getSettings().containsKey("forge")) - lblForge.setText(Main.i18n("install.installer.version", Main.i18n("install.installer.forge")) + ": " + getVersion("forge")); + lblForge.setText(Launcher.i18n("install.installer.version", Launcher.i18n("install.installer.forge")) + ": " + getVersion("forge")); else - lblForge.setText(Main.i18n("install.installer.not_installed", Main.i18n("install.installer.forge"))); + lblForge.setText(Launcher.i18n("install.installer.not_installed", Launcher.i18n("install.installer.forge"))); if (controller.getSettings().containsKey("liteloader")) - lblLiteLoader.setText(Main.i18n("install.installer.version", Main.i18n("install.installer.liteloader")) + ": " + getVersion("liteloader")); + lblLiteLoader.setText(Launcher.i18n("install.installer.version", Launcher.i18n("install.installer.liteloader")) + ": " + getVersion("liteloader")); else - lblLiteLoader.setText(Main.i18n("install.installer.not_installed", Main.i18n("install.installer.liteloader"))); + lblLiteLoader.setText(Launcher.i18n("install.installer.not_installed", Launcher.i18n("install.installer.liteloader"))); if (controller.getSettings().containsKey("optifine")) - lblOptiFine.setText(Main.i18n("install.installer.version", Main.i18n("install.installer.optifine")) + ": " + getVersion("optifine")); + lblOptiFine.setText(Launcher.i18n("install.installer.version", Launcher.i18n("install.installer.optifine")) + ": " + getVersion("optifine")); else - lblOptiFine.setText(Main.i18n("install.installer.not_installed", Main.i18n("install.installer.optifine"))); + lblOptiFine.setText(Launcher.i18n("install.installer.not_installed", Launcher.i18n("install.installer.optifine"))); } @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 072f55ff5..28853e893 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 @@ -25,7 +25,7 @@ import javafx.scene.control.Label; import javafx.scene.layout.Region; import javafx.scene.layout.StackPane; import javafx.stage.FileChooser; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.game.ModpackHelper; import org.jackhuang.hmcl.mod.Modpack; import org.jackhuang.hmcl.mod.UnsupportedModpackException; @@ -75,16 +75,16 @@ public final class ModpackPage extends StackPane implements WizardPage { Profile profile = (Profile) controller.getSettings().get("PROFILE"); FileChooser chooser = new FileChooser(); - chooser.setTitle(Main.i18n("modpack.choose")); - chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(Main.i18n("modpack"), "*.zip")); + chooser.setTitle(Launcher.i18n("modpack.choose")); + chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(Launcher.i18n("modpack"), "*.zip")); File selectedFile = chooser.showOpenDialog(Controllers.getStage()); if (selectedFile == null) Platform.runLater(() -> Controllers.navigate(null)); else { controller.getSettings().put(MODPACK_FILE, selectedFile); lblModpackLocation.setText(selectedFile.getAbsolutePath()); txtModpackName.getValidators().addAll( - new Validator(Main.i18n("install.new_game.already_exists"), str -> !profile.getRepository().hasVersion(str) && StringUtils.isNotBlank(str)), - new Validator(Main.i18n("version.forbidden_name"), str -> !profile.getRepository().forbidsVersion(str)) + new Validator(Launcher.i18n("install.new_game.already_exists"), str -> !profile.getRepository().hasVersion(str) && StringUtils.isNotBlank(str)), + new Validator(Launcher.i18n("version.forbidden_name"), str -> !profile.getRepository().forbidsVersion(str)) ); txtModpackName.textProperty().addListener(e -> btnInstall.setDisable(!txtModpackName.validate())); @@ -96,7 +96,7 @@ public final class ModpackPage extends StackPane implements WizardPage { lblAuthor.setText(manifest.getAuthor()); txtModpackName.setText(manifest.getName() + (StringUtils.isBlank(manifest.getVersion()) ? "" : "-" + manifest.getVersion())); } catch (UnsupportedModpackException e) { - txtModpackName.setText(Main.i18n("modpack.task.install.error")); + txtModpackName.setText(Launcher.i18n("modpack.task.install.error")); } } } @@ -118,14 +118,14 @@ public final class ModpackPage extends StackPane implements WizardPage { if (manifest != null) { WebStage stage = new WebStage(); stage.getWebView().getEngine().loadContent(manifest.getDescription()); - stage.setTitle(Main.i18n("modpack.wizard.step.3")); + stage.setTitle(Launcher.i18n("modpack.wizard.step.3")); stage.showAndWait(); } } @Override public String getTitle() { - return Main.i18n("modpack.task.install"); + return Launcher.i18n("modpack.task.install"); } public static final String MODPACK_FILE = "MODPACK_FILE"; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPageItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPageItem.java index 99ecf5571..79f2633fc 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPageItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPageItem.java @@ -23,7 +23,7 @@ import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.HBox; import javafx.scene.layout.StackPane; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.download.RemoteVersion; import org.jackhuang.hmcl.download.game.GameRemoteVersionTag; import org.jackhuang.hmcl.download.liteloader.LiteLoaderRemoteVersionTag; @@ -57,15 +57,15 @@ public final class VersionsPageItem extends StackPane { if (remoteVersion.getTag() instanceof GameRemoteVersionTag) { switch (((GameRemoteVersionTag) remoteVersion.getTag()).getType()) { case RELEASE: - lblGameVersion.setText(Main.i18n("version.game.release")); + lblGameVersion.setText(Launcher.i18n("version.game.release")); imageView.setImage(new Image("/assets/img/icon.png", 32, 32, false, true)); break; case SNAPSHOT: - lblGameVersion.setText(Main.i18n("version.game.snapshot")); + lblGameVersion.setText(Launcher.i18n("version.game.snapshot")); imageView.setImage(new Image("/assets/img/command.png", 32, 32, false, true)); break; default: - lblGameVersion.setText(Main.i18n("version.game.old")); + lblGameVersion.setText(Launcher.i18n("version.game.old")); imageView.setImage(new Image("/assets/img/grass.png", 32, 32, false, true)); break; } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackFileSelectionPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackFileSelectionPage.java index 82cb9f1b4..3c46bf7c9 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackFileSelectionPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackFileSelectionPage.java @@ -25,7 +25,7 @@ import javafx.scene.control.Label; import javafx.scene.control.TreeItem; import javafx.scene.layout.HBox; import javafx.scene.layout.StackPane; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.game.ModAdviser; import org.jackhuang.hmcl.setting.Profile; import org.jackhuang.hmcl.ui.FXUtils; @@ -147,23 +147,23 @@ public final class ModpackFileSelectionPage extends StackPane implements WizardP @Override public String getTitle() { - return Main.i18n("modpack.wizard.step.2.title"); + return Launcher.i18n("modpack.wizard.step.2.title"); } public static final String MODPACK_FILE_SELECTION = "modpack.accepted"; private static final Map TRANSLATION = Lang.mapOf( - new Pair<>("minecraft/servers.dat", Main.i18n("modpack.files.servers_dat")), - new Pair<>("minecraft/saves", Main.i18n("modpack.files.saves")), - new Pair<>("minecraft/mods", Main.i18n("modpack.files.mods")), - new Pair<>("minecraft/config", Main.i18n("modpack.files.config")), - new Pair<>("minecraft/liteconfig", Main.i18n("modpack.files.liteconfig")), - new Pair<>("minecraft/resourcepacks", Main.i18n("modpack.files.resourcepacks")), - new Pair<>("minecraft/resources", Main.i18n("modpack.files.resourcepacks")), - new Pair<>("minecraft/options.txt", Main.i18n("modpack.files.options_txt")), - new Pair<>("minecraft/optionsshaders.txt", Main.i18n("modpack.files.optionsshaders_txt")), - new Pair<>("minecraft/mods/VoxelMods", Main.i18n("modpack.files.mods.voxelmods")), - new Pair<>("minecraft/dumps", Main.i18n("modpack.files.dumps")), - new Pair<>("minecraft/blueprints", Main.i18n("modpack.files.blueprints")), - new Pair<>("minecraft/scripts", Main.i18n("modpack.files.scripts")) + new Pair<>("minecraft/servers.dat", Launcher.i18n("modpack.files.servers_dat")), + new Pair<>("minecraft/saves", Launcher.i18n("modpack.files.saves")), + new Pair<>("minecraft/mods", Launcher.i18n("modpack.files.mods")), + new Pair<>("minecraft/config", Launcher.i18n("modpack.files.config")), + new Pair<>("minecraft/liteconfig", Launcher.i18n("modpack.files.liteconfig")), + new Pair<>("minecraft/resourcepacks", Launcher.i18n("modpack.files.resourcepacks")), + new Pair<>("minecraft/resources", Launcher.i18n("modpack.files.resourcepacks")), + new Pair<>("minecraft/options.txt", Launcher.i18n("modpack.files.options_txt")), + new Pair<>("minecraft/optionsshaders.txt", Launcher.i18n("modpack.files.optionsshaders_txt")), + new Pair<>("minecraft/mods/VoxelMods", Launcher.i18n("modpack.files.mods.voxelmods")), + new Pair<>("minecraft/dumps", Launcher.i18n("modpack.files.dumps")), + new Pair<>("minecraft/blueprints", Launcher.i18n("modpack.files.blueprints")), + new Pair<>("minecraft/scripts", Launcher.i18n("modpack.files.scripts")) ); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackInfoPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackInfoPage.java index 3911c154e..e903d6f5d 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackInfoPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackInfoPage.java @@ -26,7 +26,7 @@ import javafx.scene.control.Label; import javafx.scene.control.ScrollPane; import javafx.scene.layout.StackPane; import javafx.stage.FileChooser; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.auth.Account; import org.jackhuang.hmcl.setting.Settings; import org.jackhuang.hmcl.ui.Controllers; @@ -72,8 +72,8 @@ public final class ModpackInfoPage extends StackPane implements WizardPage { @FXML private void onNext() { FileChooser fileChooser = new FileChooser(); - fileChooser.setTitle(Main.i18n("modpack.wizard.step.initialization.save")); - fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(Main.i18n("modpack"), "*.zip")); + fileChooser.setTitle(Launcher.i18n("modpack.wizard.step.initialization.save")); + fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(Launcher.i18n("modpack"), "*.zip")); File file = fileChooser.showSaveDialog(Controllers.getStage()); if (file == null) { Controllers.navigate(null); @@ -100,7 +100,7 @@ public final class ModpackInfoPage extends StackPane implements WizardPage { @Override public String getTitle() { - return Main.i18n("modpack.wizard.step.1.title"); + return Launcher.i18n("modpack.wizard.step.1.title"); } public static final String MODPACK_NAME = "modpack.name"; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/AppDataUpgrader.java b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/AppDataUpgrader.java index 12df8ecb2..c92185bd1 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/AppDataUpgrader.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/AppDataUpgrader.java @@ -18,9 +18,8 @@ package org.jackhuang.hmcl.upgrade; import com.google.gson.JsonParseException; -import com.google.gson.JsonSyntaxException; import com.google.gson.reflect.TypeToken; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.task.FileDownloadTask; import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.task.Task; @@ -100,15 +99,15 @@ public class AppDataUpgrader extends IUpgrader { checker.requestDownloadLink().then(Task.of(Schedulers.javafx(), variables -> { Map map = variables.get(UpdateChecker.REQUEST_DOWNLOAD_LINK_ID); - if (MessageBox.confirm(Main.i18n("update.newest_version") + version.toString() + "\n" - + Main.i18n("update.should_open_link"), + if (MessageBox.confirm(Launcher.i18n("update.newest_version") + version.toString() + "\n" + + Launcher.i18n("update.should_open_link"), MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION) if (map != null && map.containsKey("jar") && !StringUtils.isBlank(map.get("jar"))) try { String hash = null; if (map.containsKey("jarsha1")) hash = map.get("jarsha1"); - Controllers.dialog(Main.i18n("message.downloading")); + Controllers.dialog(Launcher.i18n("message.downloading")); if (new AppDataUpgraderJarTask(NetworkUtils.toURL(map.get("jar")), version.toString(), hash).test()) { new ProcessBuilder(JavaVersion.fromCurrentEnvironment().getBinary().getAbsolutePath(), "-jar", AppDataUpgraderJarTask.getSelf(version.toString()).getAbsolutePath()) .directory(new File("").getAbsoluteFile()).start(); @@ -123,7 +122,7 @@ public class AppDataUpgrader extends IUpgrader { String hash = null; if (map.containsKey("packsha1")) hash = map.get("packsha1"); - Controllers.dialog(Main.i18n("message.downloading")); + Controllers.dialog(Launcher.i18n("message.downloading")); if (new AppDataUpgraderPackGzTask(NetworkUtils.toURL(map.get("pack")), version.toString(), hash).test()) { new ProcessBuilder(JavaVersion.fromCurrentEnvironment().getBinary().getAbsolutePath(), "-jar", AppDataUpgraderPackGzTask.getSelf(version.toString()).getAbsolutePath()) .directory(new File("").getAbsoluteFile()).start(); @@ -134,20 +133,20 @@ public class AppDataUpgrader extends IUpgrader { Logging.LOG.log(Level.SEVERE, "Failed to create upgrader", ex); } else { - String url = Main.PUBLISH; + String url = Launcher.PUBLISH; if (map != null) if (map.containsKey(OperatingSystem.CURRENT_OS.getCheckedName())) url = map.get(OperatingSystem.CURRENT_OS.getCheckedName()); else if (map.containsKey(OperatingSystem.UNKNOWN.getCheckedName())) url = map.get(OperatingSystem.UNKNOWN.getCheckedName()); if (url == null) - url = Main.PUBLISH; + url = Launcher.PUBLISH; try { java.awt.Desktop.getDesktop().browse(new URI(url)); } catch (URISyntaxException | IOException e) { Logging.LOG.log(Level.SEVERE, "Failed to browse uri: " + url, e); OperatingSystem.setClipboard(url); - MessageBox.show(Main.i18n("update.no_browser")); + MessageBox.show(Launcher.i18n("update.no_browser")); } } })).start(); @@ -155,7 +154,7 @@ public class AppDataUpgrader extends IUpgrader { public static class AppDataUpgraderPackGzTask extends Task { - public static final File BASE_FOLDER = Main.HMCL_DIRECTORY; + public static final File BASE_FOLDER = Launcher.HMCL_DIRECTORY; public static final File HMCL_VER_FILE = new File(BASE_FOLDER, "hmclver.json"); public static File getSelf(String ver) { @@ -205,7 +204,7 @@ public class AppDataUpgrader extends IUpgrader { public static class AppDataUpgraderJarTask extends Task { - public static final File BASE_FOLDER = Main.getWorkingDirectory("hmcl"); + public static final File BASE_FOLDER = Launcher.getWorkingDirectory("hmcl"); public static final File HMCL_VER_FILE = new File(BASE_FOLDER, "hmclver.json"); public static File getSelf(String ver) { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/NewFileUpgrader.java b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/NewFileUpgrader.java index 728626a0a..5437a0c01 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/NewFileUpgrader.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/NewFileUpgrader.java @@ -17,7 +17,7 @@ */ package org.jackhuang.hmcl.upgrade; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.task.FileDownloadTask; import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.util.Charsets; @@ -51,7 +51,7 @@ public class NewFileUpgrader extends IUpgrader { URL url = requestDownloadLink(); if (url == null) return; File newf = new File(url.getFile()); - Controllers.dialog(Main.i18n("message.downloading")); + Controllers.dialog(Launcher.i18n("message.downloading")); if (new FileDownloadTask(url, newf).test()) { try { new ProcessBuilder(newf.getCanonicalPath(), "--removeOldLauncher", getRealPath()) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateChecker.java b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateChecker.java index 9e209b655..ff860ffdf 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateChecker.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateChecker.java @@ -18,7 +18,7 @@ package org.jackhuang.hmcl.upgrade; import com.google.gson.JsonSyntaxException; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.event.Event; import org.jackhuang.hmcl.event.EventBus; import org.jackhuang.hmcl.event.OutOfDateEvent; @@ -67,18 +67,18 @@ public final class UpdateChecker { return new TaskResult() { @Override public void execute() throws Exception { - if (Main.VERSION.contains("@")) + if (Launcher.VERSION.contains("@")) return; if (value == null) { - versionString = NetworkUtils.doGet(NetworkUtils.toURL("http://huangyuhui.duapp.com/hmcl/update.php?version=" + Main.VERSION)); + versionString = NetworkUtils.doGet(NetworkUtils.toURL("http://huangyuhui.duapp.com/hmcl/update.php?version=" + Launcher.VERSION)); value = VersionNumber.asVersion(versionString); } if (value == null) { Logging.LOG.warning("Unable to check update..."); if (showMessage) - MessageBox.show(Main.i18n("update.failed")); + MessageBox.show(Launcher.i18n("update.failed")); } else if (base.compareTo(value) < 0) outOfDate = true; if (outOfDate) @@ -134,7 +134,7 @@ public final class UpdateChecker { public void checkOutdate() { if (outOfDate) if (EventBus.EVENT_BUS.fireEvent(new OutOfDateEvent(this, getNewVersion())) != Event.Result.DENY) { - Main.UPGRADER.download(this, getNewVersion()); + Launcher.UPGRADER.download(this, getNewVersion()); } } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/util/CrashReporter.java b/HMCL/src/main/java/org/jackhuang/hmcl/util/CrashReporter.java index b927743f8..a42ddce13 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/util/CrashReporter.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/util/CrashReporter.java @@ -18,7 +18,7 @@ package org.jackhuang.hmcl.util; import javafx.application.Platform; -import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.ui.CrashWindow; import org.jackhuang.hmcl.ui.construct.MessageBox; @@ -36,15 +36,15 @@ public class CrashReporter implements Thread.UncaughtExceptionHandler { private static final HashMap SOURCE = new HashMap() { { - put("javafx.fxml.LoadException", Main.i18n("crash.NoClassDefFound")); - put("UnsatisfiedLinkError", Main.i18n("crash.user_fault")); - put("java.lang.NoClassDefFoundError", Main.i18n("crash.NoClassDefFound")); - put("java.lang.VerifyError", Main.i18n("crash.NoClassDefFound")); - put("java.lang.NoSuchMethodError", Main.i18n("crash.NoClassDefFound")); - put("java.lang.IncompatibleClassChangeError", Main.i18n("crash.NoClassDefFound")); - put("java.lang.ClassFormatError", Main.i18n("crash.NoClassDefFound")); + put("javafx.fxml.LoadException", Launcher.i18n("crash.NoClassDefFound")); + put("UnsatisfiedLinkError", Launcher.i18n("crash.user_fault")); + put("java.lang.NoClassDefFoundError", Launcher.i18n("crash.NoClassDefFound")); + put("java.lang.VerifyError", Launcher.i18n("crash.NoClassDefFound")); + put("java.lang.NoSuchMethodError", Launcher.i18n("crash.NoClassDefFound")); + put("java.lang.IncompatibleClassChangeError", Launcher.i18n("crash.NoClassDefFound")); + put("java.lang.ClassFormatError", Launcher.i18n("crash.NoClassDefFound")); put("java.lang.OutOfMemoryError", "FUCKING MEMORY LIMIT!"); - put("Trampoline", Main.i18n("launcher.update_java")); + put("Trampoline", Launcher.i18n("launcher.update_java")); put("NoSuchAlgorithmException", "Has your operating system been installed completely or is a ghost system?"); } }; @@ -80,7 +80,7 @@ public class CrashReporter implements Thread.UncaughtExceptionHandler { try { StringBuilder builder = new StringBuilder(); builder.append("---- Hello Minecraft! Crash Report ----\n"); - builder.append(" Version: " + Main.VERSION + "\n"); + builder.append(" Version: " + Launcher.VERSION + "\n"); builder.append(" Time: ").append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())).append("\n"); builder.append(" Thread: ").append(t.toString()).append("\n"); builder.append("\n Content: \n "); @@ -95,7 +95,7 @@ public class CrashReporter implements Thread.UncaughtExceptionHandler { if (checkThrowable(e) && !text.contains("OpenJDK")) { Platform.runLater(() -> new CrashWindow(text).show()); - if (!Main.UPDATE_CHECKER.isOutOfDate()) + if (!Launcher.UPDATE_CHECKER.isOutOfDate()) reportToServer(text); } } catch (Throwable ex) { @@ -110,7 +110,7 @@ public class CrashReporter implements Thread.UncaughtExceptionHandler { Thread t = new Thread(() -> { HashMap map = new HashMap<>(); map.put("crash_report", text); - map.put("version", Main.VERSION); + map.put("version", Launcher.VERSION); try { String response = NetworkUtils.doPost(NetworkUtils.toURL("http://huangyuhui.duapp.com/hmcl/crash.php"), map); if (StringUtils.isNotBlank(response)) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilAccount.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilAccount.java index 5af8b4524..f6dcbb7ca 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilAccount.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilAccount.java @@ -17,7 +17,6 @@ */ package org.jackhuang.hmcl.auth.yggdrasil; -import com.google.gson.Gson; import com.google.gson.GsonBuilder; import org.jackhuang.hmcl.auth.*; import org.jackhuang.hmcl.util.StringUtils; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java index 811fc972f..b3f838b47 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.download; import org.jackhuang.hmcl.download.game.*; -import org.jackhuang.hmcl.game.SimpleVersionProvider; import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.task.ParallelTask; import org.jackhuang.hmcl.task.Task; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MaintainTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MaintainTask.java index 709cb38b0..bad83a75f 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MaintainTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MaintainTask.java @@ -17,7 +17,6 @@ */ package org.jackhuang.hmcl.download; -import org.jackhuang.hmcl.game.GameRepository; import org.jackhuang.hmcl.game.Library; import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.task.TaskResult; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeVersionList.java index c87a57a0a..e7645ad85 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeVersionList.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.download.forge; import org.jackhuang.hmcl.download.DownloadProvider; -import org.jackhuang.hmcl.download.RemoteVersion; import org.jackhuang.hmcl.download.VersionList; import org.jackhuang.hmcl.task.GetTask; import org.jackhuang.hmcl.task.Task; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameLibrariesTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameLibrariesTask.java index eabd1b2f8..46baf515c 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameLibrariesTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameLibrariesTask.java @@ -20,9 +20,7 @@ package org.jackhuang.hmcl.download.game; import org.jackhuang.hmcl.download.AbstractDependencyManager; import org.jackhuang.hmcl.game.Library; import org.jackhuang.hmcl.game.Version; -import org.jackhuang.hmcl.task.FileDownloadTask; import org.jackhuang.hmcl.task.Task; -import org.jackhuang.hmcl.util.NetworkUtils; import java.io.File; import java.util.LinkedList; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/LibraryDownloadTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/LibraryDownloadTask.java index 4648b5c6c..401ef63cb 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/LibraryDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/LibraryDownloadTask.java @@ -4,8 +4,6 @@ import org.apache.commons.compress.compressors.xz.XZCompressorInputStream; import org.jackhuang.hmcl.download.AbstractDependencyManager; import org.jackhuang.hmcl.game.Library; import org.jackhuang.hmcl.task.FileDownloadTask; -import org.jackhuang.hmcl.task.Scheduler; -import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.util.*; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/liteloader/LiteLoaderVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/liteloader/LiteLoaderVersionList.java index 4e48e1be4..d3b243e46 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/liteloader/LiteLoaderVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/liteloader/LiteLoaderVersionList.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.download.liteloader; import org.jackhuang.hmcl.download.DownloadProvider; -import org.jackhuang.hmcl.download.RemoteVersion; import org.jackhuang.hmcl.download.VersionList; import org.jackhuang.hmcl.task.GetTask; import org.jackhuang.hmcl.task.Task; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/optifine/OptiFineBMCLVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/optifine/OptiFineBMCLVersionList.java index 55d03006b..65b25a352 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/optifine/OptiFineBMCLVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/optifine/OptiFineBMCLVersionList.java @@ -19,7 +19,6 @@ package org.jackhuang.hmcl.download.optifine; import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.download.DownloadProvider; -import org.jackhuang.hmcl.download.RemoteVersion; import org.jackhuang.hmcl.download.VersionList; import org.jackhuang.hmcl.task.GetTask; import org.jackhuang.hmcl.task.Task; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameVersion.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameVersion.java index 0f6d31303..ff1629a31 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameVersion.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameVersion.java @@ -116,7 +116,7 @@ public final class GameVersion { .getEntry("net/minecraft/client/Minecraft.class"); if (minecraft != null) return getVersionOfOldMinecraft(f, minecraft); - ZipArchiveEntry main = f.getEntry("net/minecraft/client/main/Main.class"); + ZipArchiveEntry main = f.getEntry("net/minecraft/client/main/Launcher.class"); ZipArchiveEntry minecraftServer = f.getEntry("net/minecraft/server/MinecraftServer.class"); if ((main != null) && (minecraftServer != null)) return getVersionOfNewMinecraft(f, minecraftServer); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Constants.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Constants.java index 00c5708f2..52f9a121e 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Constants.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Constants.java @@ -28,7 +28,6 @@ import org.jackhuang.hmcl.task.Schedulers; import java.awt.*; import java.io.File; import java.nio.charset.Charset; -import java.text.SimpleDateFormat; import java.util.Date; import java.util.UUID; import java.util.function.Consumer; From 1bcef2bab0db7b7782e8c2819b27df1b87bd55c9 Mon Sep 17 00:00:00 2001 From: huangyuhui Date: Thu, 1 Mar 2018 00:27:07 +0800 Subject: [PATCH 04/24] Added event logs. Cloese #244 --- .../java/org/jackhuang/hmcl/ui/MainPage.java | 6 +- .../download/game/GameAssetDownloadTask.java | 2 +- .../java/org/jackhuang/hmcl/event/Event.java | 11 ++-- .../org/jackhuang/hmcl/event/EventBus.java | 4 ++ .../hmcl/event/GameJsonParseFailedEvent.java | 11 ++++ .../hmcl/event/JVMLaunchFailedEvent.java | 9 +++ .../hmcl/event/LoadedOneVersionEvent.java | 9 +++ .../event/ProcessExitedAbnormallyEvent.java | 9 +++ .../hmcl/event/ProcessStoppedEvent.java | 9 +++ .../hmcl/event/RefreshingVersionsEvent.java | 4 ++ .../hmcl/event/RemoveVersionEvent.java | 59 +++++++++++++++++ .../hmcl/event/RenameVersionEvent.java | 65 +++++++++++++++++++ .../hmcl/game/DefaultGameRepository.java | 21 +++++- .../java/org/jackhuang/hmcl/game/Version.java | 7 +- .../jackhuang/hmcl/task/FileDownloadTask.java | 2 +- .../java/org/jackhuang/hmcl/task/GetTask.java | 2 +- .../org/jackhuang/hmcl/task/TaskExecutor.java | 4 +- .../java/org/jackhuang/hmcl/util/Logging.java | 2 +- 18 files changed, 219 insertions(+), 17 deletions(-) create mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/event/RemoveVersionEvent.java create mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/event/RenameVersionEvent.java 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 2c8642866..725a635ec 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java @@ -202,8 +202,10 @@ public final class MainPage extends StackPane implements DecoratorPage { children.add(buildNode(repository, version, GameVersion.minecraftVersion(repository.getVersionJar(version.getId())).orElse("Unknown"))); } JFXUtilities.runInFX(() -> { - contentPane.getChildren().setAll(masonryPane); - FXUtils.resetChildren(masonryPane, children); + if (profile == repository.getProfile()) { + contentPane.getChildren().setAll(masonryPane); + FXUtils.resetChildren(masonryPane, children); + } }); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetDownloadTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetDownloadTask.java index be65124e9..160342b31 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetDownloadTask.java @@ -82,7 +82,7 @@ public final class GameAssetDownloadTask extends Task { AssetObject assetObject = entry.getValue(); String url = dependencyManager.getDownloadProvider().getAssetBaseURL() + assetObject.getLocation(); if (!FileUtils.makeDirectory(file.getAbsoluteFile().getParentFile())) { - Logging.LOG.log(Level.SEVERE, "Unable to create new file {0}, because parent directory cannot be created", file); + Logging.LOG.log(Level.SEVERE, "Unable to create new file " + file + ", because parent directory cannot be created"); continue; } if (file.isDirectory()) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/event/Event.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/event/Event.java index 248334cc8..68adc2bc9 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/event/Event.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/event/Event.java @@ -17,6 +17,8 @@ */ package org.jackhuang.hmcl.event; +import org.jackhuang.hmcl.util.ToStringBuilder; + import java.util.Objects; /** @@ -28,13 +30,13 @@ public class Event { /** * The object on which the Event initially occurred. */ - protected transient Object source; + protected transient Object source; /** * Constructs a prototypical Event. * * @param source The object on which the Event initially occurred. - * @throws NullPointerException if source is null. + * @throws NullPointerException if source is null. */ public Event(Object source) { Objects.requireNonNull(source); @@ -54,10 +56,10 @@ public class Event { /** * Returns a String representation of this Event. * - * @return A a String representation of this Event. + * @return A a String representation of this Event. */ public String toString() { - return getClass().getName() + "[source=" + source + "]"; + return new ToStringBuilder(this).append("source", source).toString(); } private boolean canceled; @@ -72,7 +74,6 @@ public class Event { } /** - * * @param canceled new value * @throws UnsupportedOperationException if trying to cancel a non-cancelable event. */ diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/event/EventBus.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/event/EventBus.java index ea3ede46e..944bbe52a 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/event/EventBus.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/event/EventBus.java @@ -17,6 +17,8 @@ */ package org.jackhuang.hmcl.event; +import org.jackhuang.hmcl.util.Logging; + import java.util.HashMap; /** @@ -36,6 +38,8 @@ public final class EventBus { @SuppressWarnings("unchecked") public Event.Result fireEvent(Event obj) { + Logging.LOG.info(obj + " gets fired"); + return channel((Class) obj.getClass()).fireEvent(obj); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/event/GameJsonParseFailedEvent.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/event/GameJsonParseFailedEvent.java index 011bda099..d070df240 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/event/GameJsonParseFailedEvent.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/event/GameJsonParseFailedEvent.java @@ -17,6 +17,8 @@ */ package org.jackhuang.hmcl.event; +import org.jackhuang.hmcl.util.ToStringBuilder; + import java.io.File; /** @@ -49,4 +51,13 @@ public final class GameJsonParseFailedEvent extends Event { public String getVersion() { return version; } + + @Override + public String toString() { + return new ToStringBuilder(this) + .append("source", source) + .append("jsonFile", jsonFile) + .append("version", version) + .toString(); + } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/event/JVMLaunchFailedEvent.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/event/JVMLaunchFailedEvent.java index 70e75d259..4bf6ff40d 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/event/JVMLaunchFailedEvent.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/event/JVMLaunchFailedEvent.java @@ -18,6 +18,7 @@ package org.jackhuang.hmcl.event; import org.jackhuang.hmcl.util.ManagedProcess; +import org.jackhuang.hmcl.util.ToStringBuilder; /** * This event gets fired when we launch the JVM and it got crashed. @@ -44,4 +45,12 @@ public class JVMLaunchFailedEvent extends Event { public ManagedProcess getProcess() { return process; } + + @Override + public String toString() { + return new ToStringBuilder(this) + .append("source", source) + .append("process", process) + .toString(); + } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/event/LoadedOneVersionEvent.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/event/LoadedOneVersionEvent.java index e71bac3a6..47e44da64 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/event/LoadedOneVersionEvent.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/event/LoadedOneVersionEvent.java @@ -18,6 +18,7 @@ package org.jackhuang.hmcl.event; import org.jackhuang.hmcl.game.Version; +import org.jackhuang.hmcl.util.ToStringBuilder; /** * This event gets fired when a minecraft version has been loaded. @@ -48,4 +49,12 @@ public final class LoadedOneVersionEvent extends Event { public boolean hasResult() { return true; } + + @Override + public String toString() { + return new ToStringBuilder(this) + .append("source", source) + .append("version", version) + .toString(); + } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/event/ProcessExitedAbnormallyEvent.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/event/ProcessExitedAbnormallyEvent.java index 410ee1759..e8e5b0d82 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/event/ProcessExitedAbnormallyEvent.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/event/ProcessExitedAbnormallyEvent.java @@ -18,6 +18,7 @@ package org.jackhuang.hmcl.event; import org.jackhuang.hmcl.util.ManagedProcess; +import org.jackhuang.hmcl.util.ToStringBuilder; /** * This event gets fired when a JavaProcess exited abnormally and the exit code is not zero. @@ -44,4 +45,12 @@ public final class ProcessExitedAbnormallyEvent extends Event { public ManagedProcess getProcess() { return process; } + + @Override + public String toString() { + return new ToStringBuilder(this) + .append("source", source) + .append("process", process) + .toString(); + } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/event/ProcessStoppedEvent.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/event/ProcessStoppedEvent.java index 7786c13d5..2fbe901b8 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/event/ProcessStoppedEvent.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/event/ProcessStoppedEvent.java @@ -18,6 +18,7 @@ package org.jackhuang.hmcl.event; import org.jackhuang.hmcl.util.ManagedProcess; +import org.jackhuang.hmcl.util.ToStringBuilder; /** * This event gets fired when minecraft process exited successfully and the exit code is 0. @@ -44,4 +45,12 @@ public class ProcessStoppedEvent extends Event { public ManagedProcess getProcess() { return process; } + + @Override + public String toString() { + return new ToStringBuilder(this) + .append("source", source) + .append("process", process) + .toString(); + } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/event/RefreshingVersionsEvent.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/event/RefreshingVersionsEvent.java index f85c09d29..2f7291b6f 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/event/RefreshingVersionsEvent.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/event/RefreshingVersionsEvent.java @@ -35,4 +35,8 @@ public final class RefreshingVersionsEvent extends Event { super(source); } + @Override + public boolean hasResult() { + return true; + } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/event/RemoveVersionEvent.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/event/RemoveVersionEvent.java new file mode 100644 index 000000000..3deab872c --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/event/RemoveVersionEvent.java @@ -0,0 +1,59 @@ +/* + * Hello Minecraft! Launcher. + * Copyright (C) 2018 huangyuhui + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see {http://www.gnu.org/licenses/}. + */ +package org.jackhuang.hmcl.event; + +import org.jackhuang.hmcl.util.ToStringBuilder; + +/** + * This event gets fired when a minecraft version is being removed. + *
+ * This event is fired on the {@link org.jackhuang.hmcl.event.EventBus#EVENT_BUS} + * + * @author huangyuhui + */ +public class RemoveVersionEvent extends Event { + + private final String version; + + /** + * + * @param source {@link org.jackhuang.hmcl.game.GameRepository} + * @param version the version id. + */ + public RemoveVersionEvent(Object source, String version) { + super(source); + this.version = version; + } + + public String getVersion() { + return version; + } + + @Override + public boolean hasResult() { + return true; + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .append("source", source) + .append("version", version) + .toString(); + } +} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/event/RenameVersionEvent.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/event/RenameVersionEvent.java new file mode 100644 index 000000000..fb2597c39 --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/event/RenameVersionEvent.java @@ -0,0 +1,65 @@ +/* + * Hello Minecraft! Launcher. + * Copyright (C) 2018 huangyuhui + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see {http://www.gnu.org/licenses/}. + */ +package org.jackhuang.hmcl.event; + +import org.jackhuang.hmcl.util.ToStringBuilder; + +/** + * This event gets fired when a minecraft version is being removed. + *
+ * This event is fired on the {@link org.jackhuang.hmcl.event.EventBus#EVENT_BUS} + * + * @author huangyuhui + */ +public class RenameVersionEvent extends Event { + + private final String from, to; + + /** + * + * @param source {@link org.jackhuang.hmcl.game.GameRepository} + * @param from the version id. + */ + public RenameVersionEvent(Object source, String from, String to) { + super(source); + this.from = from; + this.to = to; + } + + public String getFromVersion() { + return from; + } + + public String getToVersion() { + return to; + } + + @Override + public boolean hasResult() { + return true; + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .append("source", source) + .append("from", from) + .append("to", to) + .toString(); + } +} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java index 4c510f006..63e669fb8 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java @@ -24,6 +24,7 @@ import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.util.Constants; import org.jackhuang.hmcl.util.FileUtils; import org.jackhuang.hmcl.util.Logging; +import org.jackhuang.hmcl.util.ToStringBuilder; import java.io.File; import java.io.IOException; @@ -116,6 +117,9 @@ public class DefaultGameRepository implements GameRepository { @Override public boolean renameVersion(String from, String to) { + if (EventBus.EVENT_BUS.fireEvent(new RenameVersionEvent(this, from, to)) == Event.Result.DENY) + return false; + try { Version fromVersion = getVersion(from); File fromDir = getVersionRoot(from); @@ -145,6 +149,8 @@ public class DefaultGameRepository implements GameRepository { public boolean removeVersionFromDisk(String id) { if (!versions.containsKey(id)) return true; + if (EventBus.EVENT_BUS.fireEvent(new RemoveVersionEvent(this, id)) == Event.Result.DENY) + return false; File file = getVersionRoot(id); if (!file.exists()) return true; @@ -201,7 +207,7 @@ public class DefaultGameRepository implements GameRepository { try { FileUtils.writeText(json, Constants.GSON.toJson(version)); } catch (Exception e) { - Logging.LOG.log(Level.WARNING, "Ignoring version {0} because wrong id {1} is set and cannot correct it.", new Object[]{id, version.getId()}); + Logging.LOG.log(Level.WARNING, "Ignoring version " + id + " because wrong id " + version.getId() + " is set and cannot correct it."); continue; } } @@ -217,7 +223,7 @@ public class DefaultGameRepository implements GameRepository { EventBus.EVENT_BUS.fireEvent(new LoadedOneVersionEvent(this, resolved)) != Event.Result.DENY) versions.put(version.getId(), version); } catch (VersionNotFoundException e) { - Logging.LOG.log(Level.WARNING, "Ignoring version {0} because it inherits from a nonexistent version.", version.getId()); + Logging.LOG.log(Level.WARNING, "Ignoring version " + version.getId() + " because it inherits from a nonexistent version."); } } @@ -227,7 +233,9 @@ public class DefaultGameRepository implements GameRepository { @Override public void refreshVersions() { - EventBus.EVENT_BUS.fireEvent(new RefreshingVersionsEvent(this)); + if (EventBus.EVENT_BUS.fireEvent(new RefreshingVersionsEvent(this)) == Event.Result.DENY) + return; + Schedulers.newThread().schedule(() -> { refreshVersionsImpl(); EventBus.EVENT_BUS.fireEvent(new RefreshedVersionsEvent(this)); @@ -337,4 +345,11 @@ public class DefaultGameRepository implements GameRepository { return getModpackConfiguration(version).exists(); } + @Override + public String toString() { + return new ToStringBuilder(this) + .append("versions", versions == null ? null : versions.keySet()) + .append("baseDirectory", baseDirectory) + .toString(); + } } 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 06202d055..e4ccd4928 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/Version.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/Version.java @@ -156,7 +156,7 @@ public class Version implements Comparable, Validation { // To maximize the compatibility. if (!resolvedSoFar.add(id)) { - Logging.LOG.log(Level.WARNING, "Found circular dependency versions: {0}", resolvedSoFar); + Logging.LOG.log(Level.WARNING, "Found circular dependency versions: " + resolvedSoFar); return this; } @@ -233,6 +233,11 @@ public class Version implements Comparable, Validation { return id.compareTo(o.id); } + @Override + public String toString() { + return new ToStringBuilder(this).append("id", id).toString(); + } + @Override public void validate() throws JsonParseException { if (StringUtils.isBlank(id)) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FileDownloadTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FileDownloadTask.java index 6887466c8..066401682 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FileDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FileDownloadTask.java @@ -119,7 +119,7 @@ public class FileDownloadTask extends Task { @Override public void execute() throws Exception { URL currentURL = url; - Logging.LOG.log(Level.FINER, "Downloading {0} to {1}", new Object[] { currentURL, file }); + Logging.LOG.log(Level.FINER, "Downloading " + currentURL + " to " + file); Exception exception = null; for (int repeat = 0; repeat < retry; repeat++) { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/GetTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/GetTask.java index a04f4135c..0495a2c9c 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/GetTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/GetTask.java @@ -84,7 +84,7 @@ public final class GetTask extends TaskResult { Exception exception = null; for (int time = 0; time < retry; ++time) { if (time > 0) - Logging.LOG.log(Level.WARNING, "Failed to download, repeat times: {0}", time); + Logging.LOG.log(Level.WARNING, "Failed to download, repeat times: " + time); try { updateProgress(0); HttpURLConnection conn = NetworkUtils.createConnection(url, proxy); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java index c85ea57b6..f3a0ace83 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java @@ -134,7 +134,7 @@ public final class TaskExecutor { task.setState(Task.TaskState.READY); if (task.getSignificance().shouldLog()) - Logging.LOG.log(Level.FINE, "Executing task: {0}", task.getName()); + Logging.LOG.log(Level.FINE, "Executing task: " + task.getName()); taskListeners.forEach(it -> it.onReady(task)); @@ -176,7 +176,7 @@ public final class TaskExecutor { flag = true; if (task.getSignificance().shouldLog()) { - Logging.LOG.log(Level.FINER, "Task finished: {0}", task.getName()); + Logging.LOG.log(Level.FINER, "Task finished: " + task.getName()); } task.onDone().fireEvent(new TaskEvent(this, task, false)); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Logging.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Logging.java index 6e1005bb8..3776040e9 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Logging.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Logging.java @@ -63,7 +63,7 @@ public final class Logging { String date = format.format(new Date(record.getMillis())); String log = String.format("[%s] [%s.%s/%s] %s%n", date, record.getSourceClassName(), record.getSourceMethodName(), - record.getLevel().getName(), MessageFormat.format(record.getMessage(), record.getParameters()) + record.getLevel().getName(), record.getMessage() ); ByteArrayOutputStream builder = new ByteArrayOutputStream(); if (record.getThrown() != null) From eba0990538b505ea30ad293f44fc14243b35db62 Mon Sep 17 00:00:00 2001 From: huangyuhui Date: Thu, 1 Mar 2018 01:02:05 +0800 Subject: [PATCH 05/24] Collect log when launcher crashed --- .../org/jackhuang/hmcl/util/CrashReporter.java | 1 + .../java/org/jackhuang/hmcl/util/Logging.java | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/util/CrashReporter.java b/HMCL/src/main/java/org/jackhuang/hmcl/util/CrashReporter.java index a42ddce13..6072fd5c2 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/util/CrashReporter.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/util/CrashReporter.java @@ -111,6 +111,7 @@ public class CrashReporter implements Thread.UncaughtExceptionHandler { HashMap map = new HashMap<>(); map.put("crash_report", text); map.put("version", Launcher.VERSION); + map.put("log", Logging.getLogs()); try { String response = NetworkUtils.doPost(NetworkUtils.toURL("http://huangyuhui.duapp.com/hmcl/crash.php"), map); if (StringUtils.isNotBlank(response)) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Logging.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Logging.java index 3776040e9..aecb4eec7 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Logging.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Logging.java @@ -32,6 +32,7 @@ import java.util.logging.*; public final class Logging { public static final Logger LOG; + private static final ByteArrayOutputStream OUTPUT_STREAM = new ByteArrayOutputStream(); static { LOG = Logger.getLogger("HMCL"); @@ -51,6 +52,20 @@ public final class Logging { consoleHandler.setLevel(Level.FINER); consoleHandler.setFormatter(DefaultFormatter.INSTANCE); LOG.addHandler(consoleHandler); + + StreamHandler streamHandler = new StreamHandler(OUTPUT_STREAM, DefaultFormatter.INSTANCE) { + @Override + public synchronized void publish(LogRecord record) { + super.publish(record); + flush(); + } + }; + streamHandler.setLevel(Level.FINEST); + LOG.addHandler(streamHandler); + } + + public static String getLogs() { + return OUTPUT_STREAM.toString(); } static final class DefaultFormatter extends Formatter { From 5e1e2c6047a20d9d0e7e360ca24e883a06b48d65 Mon Sep 17 00:00:00 2001 From: huangyuhui Date: Fri, 2 Mar 2018 00:43:33 +0800 Subject: [PATCH 06/24] Remove accountsPage --- .../hmcl/event/AccountLoadingEvent.java | 39 ++++ .../org/jackhuang/hmcl/setting/Accounts.java | 6 + .../org/jackhuang/hmcl/setting/Settings.java | 9 + .../org/jackhuang/hmcl/ui/AccountItem.java | 133 -------------- .../jackhuang/hmcl/ui/AccountLoginPane.java | 2 +- .../org/jackhuang/hmcl/ui/AccountPage.java | 104 +++++++++++ ...{AccountsPage.java => AddAccountPane.java} | 172 ++++++------------ .../jackhuang/hmcl/ui/LeftPaneController.java | 145 +++++++++++---- .../java/org/jackhuang/hmcl/ui/MainPage.java | 64 +++---- .../hmcl/ui/construct/ClassTitle.java | 9 + .../hmcl/ui/construct/ComponentList.java | 5 + .../resources/assets/fxml/account-add.fxml | 64 +++++++ .../resources/assets/fxml/account-login.fxml | 2 +- .../main/resources/assets/fxml/account.fxml | 135 +++++++------- .../assets/fxml/authlib-injector-servers.fxml | 2 +- HMCL/src/main/resources/assets/fxml/main.fxml | 10 - .../resources/assets/lang/I18N.properties | 1 + .../assets/lang/I18N_zh_CN.properties | 1 + 18 files changed, 504 insertions(+), 399 deletions(-) create mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/event/AccountLoadingEvent.java delete mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountItem.java create mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountPage.java rename HMCL/src/main/java/org/jackhuang/hmcl/ui/{AccountsPage.java => AddAccountPane.java} (72%) create mode 100644 HMCL/src/main/resources/assets/fxml/account-add.fxml diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/event/AccountLoadingEvent.java b/HMCL/src/main/java/org/jackhuang/hmcl/event/AccountLoadingEvent.java new file mode 100644 index 000000000..1fc343485 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hmcl/event/AccountLoadingEvent.java @@ -0,0 +1,39 @@ +/* + * Hello Minecraft! Launcher. + * Copyright (C) 2018 huangyuhui + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see {http://www.gnu.org/licenses/}. + */ +package org.jackhuang.hmcl.event; + +/** + * This event gets fired when loading accounts. + *
+ * This event is fired on the {@link org.jackhuang.hmcl.event.EventBus#EVENT_BUS} + * + * @author huangyuhui + */ +public class AccountLoadingEvent extends Event { + + /** + * Constructor. + * + * @param source {@link org.jackhuang.hmcl.setting.Settings} + */ + public AccountLoadingEvent(Object source) { + super(source); + } + +} + diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java index ddab99ef3..b1d6ac5e9 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java @@ -30,6 +30,8 @@ import org.jackhuang.hmcl.auth.yggdrasil.MojangYggdrasilProvider; import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount; import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccountFactory; import org.jackhuang.hmcl.task.FileDownloadTask; +import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.task.TaskResult; import org.jackhuang.hmcl.util.*; import java.io.File; @@ -96,4 +98,8 @@ public final class Accounts { return response.getMeta().getServerName(); } } + + public static TaskResult getAuthlibInjectorServerNameAsync(AuthlibInjectorAccount account) { + return Task.ofResult("serverName", () -> Accounts.getAuthlibInjectorServerName(account.getServerBaseURL())); + } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java index fe6498d66..cb00fdd8f 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java @@ -28,6 +28,7 @@ import org.jackhuang.hmcl.auth.Account; import org.jackhuang.hmcl.auth.AccountFactory; import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccount; import org.jackhuang.hmcl.download.DownloadProvider; +import org.jackhuang.hmcl.event.AccountLoadingEvent; import org.jackhuang.hmcl.event.EventBus; import org.jackhuang.hmcl.event.ProfileChangedEvent; import org.jackhuang.hmcl.event.ProfileLoadingEvent; @@ -368,6 +369,7 @@ public class Settings { public void addAccount(Account account) { accounts.put(Accounts.getAccountId(account), account); + onAccountLoading(); } public Account getAccount(String name, String character) { @@ -381,12 +383,14 @@ public class Settings { public void deleteAccount(String name, String character) { accounts.remove(Accounts.getAccountId(name, character)); + onAccountLoading(); selectedAccount.get(); } public void deleteAccount(Account account) { accounts.remove(Accounts.getAccountId(account)); + onAccountLoading(); selectedAccount.get(); } @@ -506,6 +510,7 @@ public class Settings { throw new IllegalArgumentException("Profile's name is empty"); getProfileMap().put(ver.getName(), ver); + Schedulers.computation().schedule(this::onProfileLoading); ver.nameProperty().setChangedListener(this::profileNameChanged); @@ -546,4 +551,8 @@ public class Settings { EventBus.EVENT_BUS.fireEvent(new ProfileLoadingEvent(SETTINGS)); onProfileChanged(); } + + public void onAccountLoading() { + EventBus.EVENT_BUS.fireEvent(new AccountLoadingEvent(SETTINGS)); + } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountItem.java deleted file mode 100644 index 57c0db788..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountItem.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2018 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.ui; - -import com.jfoenix.controls.JFXButton; -import com.jfoenix.controls.JFXProgressBar; -import com.jfoenix.controls.JFXRadioButton; -import javafx.beans.binding.Bindings; -import javafx.event.EventHandler; -import javafx.fxml.FXML; -import javafx.scene.control.Label; -import javafx.scene.control.ToggleGroup; -import javafx.scene.effect.BlurType; -import javafx.scene.effect.DropShadow; -import javafx.scene.image.ImageView; -import javafx.scene.input.MouseEvent; -import javafx.scene.layout.HBox; -import javafx.scene.layout.Pane; -import javafx.scene.layout.StackPane; -import javafx.scene.layout.VBox; -import javafx.scene.paint.Color; -import org.jackhuang.hmcl.auth.Account; -import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccount; -import org.jackhuang.hmcl.auth.offline.OfflineAccount; -import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount; -import org.jackhuang.hmcl.game.AccountHelper; -import org.jackhuang.hmcl.setting.Accounts; -import org.jackhuang.hmcl.setting.Settings; -import org.jackhuang.hmcl.setting.Theme; -import org.jackhuang.hmcl.task.Schedulers; -import org.jackhuang.hmcl.task.Task; - -public final class AccountItem extends StackPane { - - private final Account account; - - @FXML - private Pane icon; - @FXML private VBox content; - @FXML private StackPane header; - @FXML private StackPane body; - @FXML private JFXButton btnDelete; - @FXML private JFXButton btnRefresh; - @FXML private Label lblUser; - @FXML private Label lblType; - @FXML private Label lblEmail; - @FXML private Label lblServer; - @FXML private Label lblCurrentAccount; - @FXML private JFXRadioButton chkSelected; - @FXML private JFXProgressBar pgsSkin; - @FXML private ImageView portraitView; - @FXML private HBox buttonPane; - - public AccountItem(int i, Account account, ToggleGroup toggleGroup) { - this.account = account; - - FXUtils.loadFXML(this, "/assets/fxml/account-item.fxml"); - - setEffect(new DropShadow(BlurType.GAUSSIAN, Color.rgb(0, 0, 0, 0.26), 5.0, 0.12, -0.5, 1.0)); - - chkSelected.setToggleGroup(toggleGroup); - btnDelete.setGraphic(SVG.delete(Theme.blackFillBinding(), 15, 15)); - btnRefresh.setGraphic(SVG.refresh(Theme.blackFillBinding(), 15, 15)); - - // create image view - icon.translateYProperty().bind(Bindings.createDoubleBinding(() -> header.getBoundsInParent().getHeight() - icon.getHeight() / 2 - 16, header.boundsInParentProperty(), icon.heightProperty())); - - chkSelected.getProperties().put("account", account); - setSelected(Settings.INSTANCE.getSelectedAccount() == account); - - lblUser.setText(account.getCharacter()); - lblType.setText(AccountsPage.accountType(account)); - lblEmail.setText(account.getUsername()); - - if (account instanceof AuthlibInjectorAccount) { - Task.ofResult("serverName", () -> Accounts.getAuthlibInjectorServerName(((AuthlibInjectorAccount) account).getServerBaseURL())) - .subscribe(Schedulers.javafx(), variables -> lblServer.setText(variables.get("serverName"))); - } - - if (account instanceof YggdrasilAccount) { - btnRefresh.setOnMouseClicked(e -> { - pgsSkin.setVisible(true); - AccountHelper.refreshSkinAsync((YggdrasilAccount) account) - .subscribe(Schedulers.javafx(), this::loadSkin); - }); - AccountHelper.loadSkinAsync((YggdrasilAccount) account) - .subscribe(Schedulers.javafx(), this::loadSkin); - } else - loadSkin(); - - if (account instanceof OfflineAccount) { // Offline Account cannot be refreshed, - buttonPane.getChildren().remove(btnRefresh); - } - } - - private void loadSkin() { - pgsSkin.setVisible(false); - portraitView.setViewport(AccountHelper.getViewport(4)); - if (account instanceof YggdrasilAccount) - portraitView.setImage(AccountHelper.getSkin((YggdrasilAccount) account, 4)); - else - portraitView.setImage(AccountHelper.getDefaultSkin(account, 4)); - FXUtils.limitSize(portraitView, 32, 32); - } - - public Account getAccount() { - return account; - } - - public void setSelected(boolean selected) { - lblCurrentAccount.setVisible(selected); - chkSelected.setSelected(selected); - } - - public void setOnDeleteButtonMouseClicked(EventHandler eventHandler) { - btnDelete.setOnMouseClicked(eventHandler); - } -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountLoginPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountLoginPane.java index 955b1b750..4d66c6935 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountLoginPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountLoginPane.java @@ -73,7 +73,7 @@ public class AccountLoginPane extends StackPane { } else if (account instanceof NoSelectedCharacterException) { dialog.close(); } else if (account instanceof Exception) { - lblCreationWarning.setText(AccountsPage.accountException((Exception) account)); + lblCreationWarning.setText(AddAccountPane.accountException((Exception) account)); } progressBar.setVisible(false); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountPage.java new file mode 100644 index 000000000..1028b5ea2 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountPage.java @@ -0,0 +1,104 @@ +/* + * Hello Minecraft! Launcher. + * Copyright (C) 2017 huangyuhui + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see {http://www.gnu.org/licenses/}. + */ +package org.jackhuang.hmcl.ui; + +import com.jfoenix.controls.JFXButton; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; +import javafx.fxml.FXML; +import javafx.scene.control.Label; +import javafx.scene.layout.BorderPane; +import javafx.scene.layout.StackPane; +import org.jackhuang.hmcl.Launcher; +import org.jackhuang.hmcl.auth.Account; +import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccount; +import org.jackhuang.hmcl.auth.offline.OfflineAccount; +import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount; +import org.jackhuang.hmcl.game.AccountHelper; +import org.jackhuang.hmcl.setting.Accounts; +import org.jackhuang.hmcl.setting.Settings; +import org.jackhuang.hmcl.task.Schedulers; +import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.ui.construct.ComponentList; +import org.jackhuang.hmcl.ui.wizard.DecoratorPage; + +public class AccountPage extends StackPane implements DecoratorPage { + private final StringProperty title; + + private final Account account; + + @FXML + private Label lblType; + @FXML + private Label lblServer; + @FXML + private Label lblCharacter; + @FXML + private Label lblEmail; + @FXML + private BorderPane paneServer; + @FXML + private ComponentList componentList; + @FXML + private JFXButton btnRefresh; + + public AccountPage(Account account) { + this.account = account; + title = new SimpleStringProperty(this, "title", Launcher.i18n("account") + " - " + account.getCharacter()); + + FXUtils.loadFXML(this, "/assets/fxml/account.fxml"); + + if (account instanceof AuthlibInjectorAccount) { + Task.ofResult("serverName", () -> Accounts.getAuthlibInjectorServerName(((AuthlibInjectorAccount) account).getServerBaseURL())) + .subscribe(Schedulers.javafx(), variables -> lblServer.setText(variables.get("serverName"))); + } else { + componentList.removeChildren(paneServer); + } + + lblCharacter.setText(account.getCharacter()); + lblType.setText(AddAccountPane.accountType(account)); + lblEmail.setText(account.getUsername()); + + btnRefresh.setDisable(account instanceof OfflineAccount); + + if (account instanceof YggdrasilAccount) { + btnRefresh.setOnMouseClicked(e -> { + AccountHelper.refreshSkinAsync((YggdrasilAccount) account).start(); + }); + } + } + + @FXML + private void onDelete() { + Settings.INSTANCE.deleteAccount(account); + Controllers.navigate(null); + } + + public String getTitle() { + return title.get(); + } + + @Override + public StringProperty titleProperty() { + return title; + } + + public void setTitle(String title) { + this.title.set(title); + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AddAccountPane.java similarity index 72% rename from HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountsPage.java rename to HMCL/src/main/java/org/jackhuang/hmcl/ui/AddAccountPane.java index 7fc62cfcd..643ad47da 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AddAccountPane.java @@ -1,6 +1,6 @@ /* * Hello Minecraft! Launcher. - * Copyright (C) 2018 huangyuhui + * Copyright (C) 2017 huangyuhui * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,16 +19,11 @@ package org.jackhuang.hmcl.ui; import com.jfoenix.concurrency.JFXUtilities; import com.jfoenix.controls.*; -import javafx.application.Platform; -import javafx.beans.property.SimpleStringProperty; -import javafx.beans.property.StringProperty; import javafx.fxml.FXML; import javafx.geometry.Pos; import javafx.scene.Node; import javafx.scene.control.Hyperlink; import javafx.scene.control.Label; -import javafx.scene.control.ScrollPane; -import javafx.scene.control.ToggleGroup; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.BorderPane; @@ -48,11 +43,9 @@ import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.ui.construct.AdvancedListBox; import org.jackhuang.hmcl.ui.construct.IconedItem; import org.jackhuang.hmcl.ui.construct.Validator; -import org.jackhuang.hmcl.ui.wizard.DecoratorPage; import org.jackhuang.hmcl.util.Logging; import java.util.Collection; -import java.util.LinkedList; import java.util.List; import java.util.Optional; import java.util.concurrent.CountDownLatch; @@ -60,13 +53,8 @@ import java.util.logging.Level; import java.util.stream.Collectors; import java.util.stream.Stream; -public final class AccountsPage extends StackPane implements DecoratorPage { - private final StringProperty title = new SimpleStringProperty(this, "title", Launcher.i18n("account")); +public class AddAccountPane extends StackPane { - @FXML - private ScrollPane scrollPane; - @FXML private JFXMasonryPane masonryPane; - @FXML private JFXDialog dialog; @FXML private JFXTextField txtUsername; @FXML private JFXPasswordField txtPassword; @FXML private Label lblCreationWarning; @@ -76,14 +64,15 @@ public final class AccountsPage extends StackPane implements DecoratorPage { @FXML private JFXProgressBar progressBar; @FXML private Label lblAddInjectorServer; @FXML private Hyperlink linkAddInjectorServer; + @FXML private JFXDialogLayout layout; + private final Runnable finalization; - { - FXUtils.loadFXML(this, "/assets/fxml/account.fxml"); + public AddAccountPane(Runnable finalization) { + this.finalization = finalization; - getChildren().remove(dialog); - dialog.setDialogContainer(this); + FXUtils.loadFXML(this, "/assets/fxml/account-add.fxml"); - FXUtils.smoothScrolling(scrollPane); + loadServers(); cboType.getItems().setAll(Launcher.i18n("account.methods.offline"), Launcher.i18n("account.methods.yggdrasil"), Launcher.i18n("account.methods.authlib_injector")); cboType.getSelectionModel().selectedIndexProperty().addListener((a, b, newValue) -> { @@ -103,38 +92,9 @@ public final class AccountsPage extends StackPane implements DecoratorPage { txtUsername.setOnAction(e -> onCreationAccept()); txtUsername.getValidators().add(new Validator(Launcher.i18n("input.email"), str -> !txtPassword.isVisible() || str.contains("@"))); - FXUtils.onChangeAndOperate(Settings.INSTANCE.selectedAccountProperty(), account -> { - for (Node node : masonryPane.getChildren()) - if (node instanceof AccountItem) - ((AccountItem) node).setSelected(account == ((AccountItem) node).getAccount()); - }); - - loadAccounts(); - loadServers(); - - if (Settings.INSTANCE.getAccounts().isEmpty()) - addNewAccount(); } - public void loadAccounts() { - List children = new LinkedList<>(); - int i = 0; - ToggleGroup group = new ToggleGroup(); - for (Account account : Settings.INSTANCE.getAccounts()) { - children.add(buildNode(++i, account, group)); - } - group.selectedToggleProperty().addListener((a, b, newValue) -> { - if (newValue != null) - Settings.INSTANCE.setSelectedAccount((Account) newValue.getProperties().get("account")); - }); - FXUtils.resetChildren(masonryPane, children); - Platform.runLater(() -> { - masonryPane.requestLayout(); - scrollPane.requestLayout(); - }); - } - - public void loadServers() { + private void loadServers() { Task.ofResult("list", () -> Settings.INSTANCE.getAuthlibInjectorServerURLs().parallelStream() .flatMap(serverURL -> { try { @@ -152,28 +112,6 @@ public final class AccountsPage extends StackPane implements DecoratorPage { })); } - private Node buildNode(int i, Account account, ToggleGroup group) { - AccountItem item = new AccountItem(i, account, group); - item.setOnDeleteButtonMouseClicked(e -> { - Settings.INSTANCE.deleteAccount(account); - Platform.runLater(this::loadAccounts); - }); - return item; - } - - @FXML - private void addNewAccount() { - txtUsername.setText(""); - txtPassword.setText(""); - lblCreationWarning.setText(""); - dialog.show(); - } - - @FXML - private void onAddInjecterServer() { - Controllers.navigate(Controllers.getServersPage()); - } - @FXML private void onCreationAccept() { int type = cboType.getSelectionModel().getSelectedIndex(); @@ -183,23 +121,22 @@ public final class AccountsPage extends StackPane implements DecoratorPage { progressBar.setVisible(true); lblCreationWarning.setText(""); Task.ofResult("create_account", () -> { - AccountFactory factory; - switch (type) { - case 0: factory = Accounts.ACCOUNT_FACTORY.get(Accounts.OFFLINE_ACCOUNT_KEY); break; - case 1: factory = Accounts.ACCOUNT_FACTORY.get(Accounts.YGGDRASIL_ACCOUNT_KEY); break; - case 2: factory = Accounts.ACCOUNT_FACTORY.get(Accounts.AUTHLIB_INJECTOR_ACCOUNT_KEY); break; - default: throw new Error(); - } + AccountFactory factory; + switch (type) { + case 0: factory = Accounts.ACCOUNT_FACTORY.get(Accounts.OFFLINE_ACCOUNT_KEY); break; + case 1: factory = Accounts.ACCOUNT_FACTORY.get(Accounts.YGGDRASIL_ACCOUNT_KEY); break; + case 2: factory = Accounts.ACCOUNT_FACTORY.get(Accounts.AUTHLIB_INJECTOR_ACCOUNT_KEY); break; + default: throw new Error(); + } - return factory.create(new Selector(), username, password, apiRoot, Settings.INSTANCE.getProxy()); + return factory.create(new Selector(), username, password, apiRoot, Settings.INSTANCE.getProxy()); }).finalized(Schedulers.javafx(), variables -> { Settings.INSTANCE.addAccount(variables.get("create_account")); - dialog.close(); - loadAccounts(); progressBar.setVisible(false); + finalization.run(); }, exception -> { if (exception instanceof NoSelectedCharacterException) { - dialog.close(); + finalization.run(); } else { lblCreationWarning.setText(accountException(exception)); } @@ -209,46 +146,24 @@ public final class AccountsPage extends StackPane implements DecoratorPage { @FXML private void onCreationCancel() { - dialog.close(); + finalization.run(); } - public String getTitle() { - return title.get(); + @FXML + private void onAddInjecterServer() { + finalization.run(); + Controllers.navigate(Controllers.getServersPage()); } - @Override - public StringProperty titleProperty() { - return title; + private void showSelector(Node node) { + getChildren().setAll(node); } - public void setTitle(String title) { - this.title.set(title); + private void closeSelector() { + getChildren().setAll(layout); } - public static String accountException(Exception exception) { - if (exception instanceof InvalidCredentialsException) { - return Launcher.i18n("account.failed.invalid_credentials"); - } else if (exception instanceof NoCharacterException) { - return Launcher.i18n("account.failed.no_charactor"); - } else if (exception instanceof ServerDisconnectException) { - return Launcher.i18n("account.failed.connect_authentication_server"); - } else if (exception instanceof InvalidTokenException) { - return Launcher.i18n("account.failed.invalid_token"); - } else if (exception instanceof InvalidPasswordException) { - return Launcher.i18n("account.failed.invalid_password"); - } else { - return exception.getClass() + ": " + exception.getLocalizedMessage(); - } - } - - public static String accountType(Account account) { - if (account instanceof OfflineAccount) return Launcher.i18n("account.methods.offline"); - else if (account instanceof AuthlibInjectorAccount) return Launcher.i18n("account.methods.authlib_injector"); - else if (account instanceof YggdrasilAccount) return Launcher.i18n("account.methods.yggdrasil"); - else throw new Error(Launcher.i18n("account.methods.no_method") + ": " + account); - } - - private static class Selector extends BorderPane implements CharacterSelector { + private class Selector extends BorderPane implements CharacterSelector { private final AdvancedListBox listBox = new AdvancedListBox(); private final JFXButton cancel = new JFXButton(); @@ -303,20 +218,43 @@ public final class AccountsPage extends StackPane implements DecoratorPage { listBox.add(accountItem); } - JFXUtilities.runInFX(() -> Controllers.dialog(this)); + JFXUtilities.runInFX(() -> showSelector(this)); try { latch.await(); - JFXUtilities.runInFX(Controllers::closeDialog); - if (selectedProfile == null) throw new NoSelectedCharacterException(account); + JFXUtilities.runInFX(AddAccountPane.this::closeSelector); + return selectedProfile; } catch (InterruptedException ignore) { throw new NoSelectedCharacterException(account); } } } + + public static String accountException(Exception exception) { + if (exception instanceof InvalidCredentialsException) { + return Launcher.i18n("account.failed.invalid_credentials"); + } else if (exception instanceof NoCharacterException) { + return Launcher.i18n("account.failed.no_charactor"); + } else if (exception instanceof ServerDisconnectException) { + return Launcher.i18n("account.failed.connect_authentication_server"); + } else if (exception instanceof InvalidTokenException) { + return Launcher.i18n("account.failed.invalid_token"); + } else if (exception instanceof InvalidPasswordException) { + return Launcher.i18n("account.failed.invalid_password"); + } else { + return exception.getClass() + ": " + exception.getLocalizedMessage(); + } + } + + public static String accountType(Account account) { + if (account instanceof OfflineAccount) return Launcher.i18n("account.methods.offline"); + else if (account instanceof AuthlibInjectorAccount) return Launcher.i18n("account.methods.authlib_injector"); + else if (account instanceof YggdrasilAccount) return Launcher.i18n("account.methods.yggdrasil"); + else throw new Error(Launcher.i18n("account.methods.no_method") + ": " + account); + } } 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 9b28546e3..211bb34d4 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java @@ -19,27 +19,26 @@ package org.jackhuang.hmcl.ui; import com.jfoenix.concurrency.JFXUtilities; import com.jfoenix.controls.JFXButton; +import com.jfoenix.controls.JFXListView; +import com.jfoenix.controls.JFXPopup; import javafx.application.Platform; import javafx.scene.Node; +import javafx.scene.control.Tooltip; import javafx.scene.image.Image; -import javafx.scene.layout.BorderPane; +import javafx.scene.input.MouseButton; import javafx.scene.layout.VBox; -import javafx.scene.text.Text; import org.jackhuang.hmcl.Launcher; +import org.jackhuang.hmcl.auth.Account; +import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccount; +import org.jackhuang.hmcl.auth.offline.OfflineAccount; 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.event.*; 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.Profiles; -import org.jackhuang.hmcl.setting.Settings; -import org.jackhuang.hmcl.setting.Theme; +import org.jackhuang.hmcl.setting.*; import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.ui.construct.AdvancedListBox; @@ -55,50 +54,53 @@ import java.util.Objects; public final class LeftPaneController { private final AdvancedListBox leftPane; private final VBox profilePane = new VBox(); - private final VersionListItem accountItem = new VersionListItem("", ""); + private final VBox accountPane = new VBox(); + private final VersionListItem missingAccountItem = new VersionListItem(Launcher.i18n("account.missing"), Launcher.i18n("message.unknown")); public LeftPaneController(AdvancedListBox leftPane) { this.leftPane = leftPane; - leftPane.startCategory(Launcher.i18n("account").toUpperCase()) - .add(Lang.apply(new RipplerContainer(accountItem), rippler -> { - rippler.setOnMouseClicked(e -> Controllers.navigate(new AccountsPage())); - accountItem.setOnSettingsButtonClicked(() -> Controllers.navigate(new AccountsPage())); - })) + leftPane + .add(new ClassTitle(Launcher.i18n("account").toUpperCase(), Lang.apply(new JFXButton(), button -> { + button.setGraphic(SVG.plus(Theme.blackFillBinding(), 10, 10)); + button.getStyleClass().add("toggle-icon-tiny"); + button.setOnMouseClicked(e -> addNewAccount()); + }))) + .add(accountPane) .startCategory(Launcher.i18n("launcher").toUpperCase()) .add(Lang.apply(new IconedItem(SVG.gear(Theme.blackFillBinding(), 20, 20), Launcher.i18n("settings.launcher")), iconedItem -> { iconedItem.prefWidthProperty().bind(leftPane.widthProperty()); iconedItem.setOnMouseClicked(e -> Controllers.navigate(Controllers.getSettingsPage())); })) - .add(new ClassTitle(Lang.apply(new BorderPane(), borderPane -> { - borderPane.setLeft(Lang.apply(new VBox(), vBox -> vBox.getChildren().setAll(new Text(Launcher.i18n("profile.title").toUpperCase())))); - JFXButton addProfileButton = new JFXButton(); - addProfileButton.setGraphic(SVG.plus(Theme.blackFillBinding(), 10, 10)); - addProfileButton.getStyleClass().add("toggle-icon-tiny"); - addProfileButton.setOnMouseClicked(e -> + .add(new ClassTitle(Launcher.i18n("profile.title").toUpperCase(), Lang.apply(new JFXButton(), button -> { + button.setGraphic(SVG.plus(Theme.blackFillBinding(), 10, 10)); + button.getStyleClass().add("toggle-icon-tiny"); + button.setOnMouseClicked(e -> Controllers.getDecorator().showPage(new ProfilePage(null))); - borderPane.setRight(addProfileButton); }))) .add(profilePane); + EventBus.EVENT_BUS.channel(AccountLoadingEvent.class).register(this::onAccountsLoading); 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); - FXUtils.onChangeAndOperate(Settings.INSTANCE.selectedAccountProperty(), it -> { - if (it == null) { - accountItem.setVersionName(Launcher.i18n("account.missing")); - accountItem.setGameVersion(Launcher.i18n("message.unknown")); - } else { - accountItem.setVersionName(it.getCharacter()); - accountItem.setGameVersion(AccountsPage.accountType(it)); - } + FXUtils.onChangeAndOperate(Settings.INSTANCE.selectedAccountProperty(), this::onSelectedAccountChanged); + onAccountsLoading(); + } - if (it instanceof YggdrasilAccount) { - Image image = AccountHelper.getSkin((YggdrasilAccount) it, 4); - accountItem.setImage(image, AccountHelper.getViewport(4)); - } else - accountItem.setImage(AccountHelper.getDefaultSkin(it, 4), AccountHelper.getViewport(4)); + private void addNewAccount() { + Controllers.dialog(new AddAccountPane(Controllers::closeDialog)); + } + + private void onSelectedAccountChanged(Account newAccount) { + Platform.runLater(() -> { + for (Node node : accountPane.getChildren()) { + if (node instanceof RipplerContainer && node.getProperties().get("account") instanceof Account) { + boolean current = Objects.equals(node.getProperties().get("account"), newAccount); + ((RipplerContainer) node).setSelected(current); + } + } }); } @@ -130,6 +132,73 @@ public final class LeftPaneController { Platform.runLater(() -> profilePane.getChildren().setAll(list)); } + private static String accountType(Account account) { + if (account instanceof OfflineAccount) return Launcher.i18n("account.methods.offline"); + else if (account instanceof YggdrasilAccount) return account.getUsername(); + else throw new Error(Launcher.i18n("account.methods.no_method") + ": " + account); + } + + private void onAccountsLoading() { + LinkedList list = new LinkedList<>(); + Account selectedAccount = Settings.INSTANCE.getSelectedAccount(); + for (Account account : Settings.INSTANCE.getAccounts()) { + VersionListItem item = new VersionListItem(account.getCharacter(), accountType(account)); + RipplerContainer ripplerContainer = new RipplerContainer(item); + item.setOnSettingsButtonClicked(() -> Controllers.getDecorator().showPage(new AccountPage(account))); + ripplerContainer.setOnMouseClicked(e -> { + if (e.getButton() == MouseButton.PRIMARY) + Settings.INSTANCE.setSelectedAccount(account); + else if (e.getButton() == MouseButton.SECONDARY) { + JFXListView listView = new JFXListView<>(); + JFXPopup popup = new JFXPopup(listView); + listView.getStyleClass().add("option-list-view"); + listView.getItems().add(Launcher.i18n("button.delete")); + if (account instanceof YggdrasilAccount) + listView.getItems().add(Launcher.i18n("button.refresh")); + listView.setOnMouseClicked(e2 ->{ + popup.hide(); + switch (listView.getSelectionModel().getSelectedIndex()) { + case 0: + Settings.INSTANCE.deleteAccount(account); + break; + case 1: + if (account instanceof YggdrasilAccount) + AccountHelper.refreshSkinAsync((YggdrasilAccount) account).start(); + break; + default: + throw new Error(); + }}); + popup.show(item, JFXPopup.PopupVPosition.TOP, JFXPopup.PopupHPosition.LEFT, e.getX(), e.getY()); + } + }); + ripplerContainer.getProperties().put("account", account); + ripplerContainer.maxWidthProperty().bind(leftPane.widthProperty()); + + if (account instanceof YggdrasilAccount) { + Image image = AccountHelper.getSkin((YggdrasilAccount) account, 4); + item.setImage(image, AccountHelper.getViewport(4)); + } else + item.setImage(AccountHelper.getDefaultSkin(account, 4), AccountHelper.getViewport(4)); + + if (account instanceof AuthlibInjectorAccount) + Accounts.getAuthlibInjectorServerNameAsync((AuthlibInjectorAccount) account) + .subscribe(Schedulers.javafx(), variables -> FXUtils.installTooltip(ripplerContainer, 500, 5000, 0, new Tooltip(variables.get("serverName")))); + + if (selectedAccount == account) + ripplerContainer.setSelected(true); + + list.add(ripplerContainer); + } + + if (Settings.INSTANCE.getAccounts().isEmpty()) { + RipplerContainer container = new RipplerContainer(missingAccountItem); + missingAccountItem.setOnSettingsButtonClicked(this::addNewAccount); + list.add(container); + } + + Platform.runLater(() -> accountPane.getChildren().setAll(list)); + } + private boolean checkedModpack = false; private void onRefreshedVersions(RefreshedVersionsEvent event) { @@ -162,8 +231,8 @@ public final class LeftPaneController { }); } - private void checkAccount() { + public void checkAccount() { if (Settings.INSTANCE.getAccounts().isEmpty()) - Controllers.navigate(new AccountsPage()); + addNewAccount(); } } 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 725a635ec..e6977c24d 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java @@ -44,6 +44,7 @@ import org.jackhuang.hmcl.ui.construct.MessageBox; import org.jackhuang.hmcl.ui.construct.TaskExecutorDialogPane; import org.jackhuang.hmcl.ui.download.DownloadWizardProvider; import org.jackhuang.hmcl.ui.wizard.DecoratorPage; +import org.jackhuang.hmcl.util.Lang; import org.jackhuang.hmcl.util.OperatingSystem; import org.jackhuang.hmcl.util.StringUtils; @@ -58,8 +59,6 @@ public final class MainPage extends StackPane implements DecoratorPage { private final StringProperty title = new SimpleStringProperty(this, "title", Launcher.i18n("main_page")); private Profile profile; - private String rightClickedVersion; - private HMCLGameRepository rightClickedRepository; @FXML private JFXButton btnRefresh; @@ -71,10 +70,6 @@ public final class MainPage extends StackPane implements DecoratorPage { private JFXSpinner spinner; @FXML private JFXMasonryPane masonryPane; - @FXML - private JFXListView versionList; - - private final JFXPopup versionPopup; { FXUtils.loadFXML(this, "/assets/fxml/main.fxml"); @@ -93,9 +88,6 @@ public final class MainPage extends StackPane implements DecoratorPage { this.profile = event.getProfile(); }); - versionPopup = new JFXPopup(versionList); - getChildren().remove(versionList); - btnAdd.setOnMouseClicked(e -> Controllers.getDecorator().startWizard(new DownloadWizardProvider(), Launcher.i18n("install"))); FXUtils.installTooltip(btnAdd, Launcher.i18n("install")); btnRefresh.setOnMouseClicked(e -> Settings.INSTANCE.getSelectedProfile().getRepository().refreshVersionsAsync().start()); @@ -126,7 +118,7 @@ public final class MainPage extends StackPane implements DecoratorPage { item.setLibraries(libraries.toString()); item.setOnLaunchButtonClicked(e -> { if (Settings.INSTANCE.getSelectedAccount() == null) - Controllers.dialog(Launcher.i18n("login.empty_username")); + Controllers.getLeftPaneController().checkAccount(); else LauncherHelper.INSTANCE.launch(profile, Settings.INSTANCE.getSelectedAccount(), id, null); }); @@ -174,9 +166,34 @@ public final class MainPage extends StackPane implements DecoratorPage { }); item.setOnMouseClicked(event -> { if (event.getButton() == MouseButton.SECONDARY) { - rightClickedVersion = id; - rightClickedRepository = repository; - versionList.getSelectionModel().select(-1); + JFXListView versionList = new JFXListView<>(); + JFXPopup versionPopup = new JFXPopup(versionList); + versionList.getStyleClass().add("option-list-view"); + FXUtils.setLimitWidth(versionList, 150); + versionList.getItems().setAll(Lang.immutableListOf( + Launcher.i18n("version.manage.rename"), + Launcher.i18n("version.manage.remove"), + Launcher.i18n("modpack.export"), + Launcher.i18n("folder.game") + )); + versionList.setOnMouseClicked(e ->{ + versionPopup.hide(); + switch (versionList.getSelectionModel().getSelectedIndex()) { + case 0: + VersionPage.renameVersion(profile, id); + break; + case 1: + VersionPage.deleteVersion(profile, id); + break; + case 2: + VersionPage.exportVersion(profile, id); + break; + case 3: + FXUtils.openFolder(repository.getRunDirectory(id)); + break; + default: + throw new Error(); + }}); versionPopup.show(item, JFXPopup.PopupVPosition.TOP, JFXPopup.PopupHPosition.LEFT, event.getX(), event.getY()); } else if (event.getButton() == MouseButton.PRIMARY && event.getClickCount() == 2) { if (Settings.INSTANCE.getSelectedAccount() == null) @@ -209,27 +226,6 @@ public final class MainPage extends StackPane implements DecoratorPage { }); } - @FXML - private void onVersionManagement() { - versionPopup.hide(); - switch (versionList.getSelectionModel().getSelectedIndex()) { - case 0: - VersionPage.renameVersion(rightClickedRepository.getProfile(), rightClickedVersion); - break; - case 1: - VersionPage.deleteVersion(rightClickedRepository.getProfile(), rightClickedVersion); - break; - case 2: - VersionPage.exportVersion(rightClickedRepository.getProfile(), rightClickedVersion); - break; - case 3: - FXUtils.openFolder(rightClickedRepository.getRunDirectory(rightClickedVersion)); - break; - default: - throw new Error(); - } - } - public String getTitle() { return title.get(); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ClassTitle.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ClassTitle.java index 90abf3c26..88c168d43 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ClassTitle.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ClassTitle.java @@ -18,11 +18,13 @@ package org.jackhuang.hmcl.ui.construct; import javafx.scene.Node; +import javafx.scene.layout.BorderPane; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; import javafx.scene.paint.Color; import javafx.scene.shape.Rectangle; import javafx.scene.text.Text; +import org.jackhuang.hmcl.util.Lang; /** * @author huangyuhui @@ -48,6 +50,13 @@ public class ClassTitle extends StackPane { getStyleClass().add("class-title"); } + public ClassTitle(String text, Node rightNode) { + this(Lang.apply(new BorderPane(), borderPane -> { + borderPane.setLeft(Lang.apply(new VBox(), vBox -> vBox.getChildren().setAll(new Text(text)))); + borderPane.setRight(rightNode); + })); + } + public Node getContent() { return content; } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ComponentList.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ComponentList.java index b79bfb431..6a3439202 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ComponentList.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ComponentList.java @@ -60,9 +60,14 @@ public class ComponentList extends StackPane { child.getStyleClass().add("options-list-item-ahead"); else child.getStyleClass().add("options-list-item"); + child.getProperties().put("node", node); vbox.getChildren().add(child); } + public void removeChildren(Node node) { + vbox.getChildren().removeIf(node1 -> node1.getProperties().get("node") == node); + } + public String getTitle() { return title.get(); } diff --git a/HMCL/src/main/resources/assets/fxml/account-add.fxml b/HMCL/src/main/resources/assets/fxml/account-add.fxml new file mode 100644 index 000000000..f6ff6f095 --- /dev/null +++ b/HMCL/src/main/resources/assets/fxml/account-add.fxml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/HMCL/src/main/resources/assets/fxml/account-login.fxml b/HMCL/src/main/resources/assets/fxml/account-login.fxml index 9402eae99..97065068e 100644 --- a/HMCL/src/main/resources/assets/fxml/account-login.fxml +++ b/HMCL/src/main/resources/assets/fxml/account-login.fxml @@ -26,7 +26,7 @@ diff --git a/HMCL/src/main/resources/assets/fxml/account.fxml b/HMCL/src/main/resources/assets/fxml/account.fxml index 75fc2add3..c79517b9e 100644 --- a/HMCL/src/main/resources/assets/fxml/account.fxml +++ b/HMCL/src/main/resources/assets/fxml/account.fxml @@ -4,72 +4,79 @@ - + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + diff --git a/HMCL/src/main/resources/assets/fxml/authlib-injector-servers.fxml b/HMCL/src/main/resources/assets/fxml/authlib-injector-servers.fxml index c3e330f1b..e37c03188 100644 --- a/HMCL/src/main/resources/assets/fxml/authlib-injector-servers.fxml +++ b/HMCL/src/main/resources/assets/fxml/authlib-injector-servers.fxml @@ -32,7 +32,7 @@
- - - -
diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index b0984cbd9..54a07b9e1 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -29,6 +29,7 @@ about.open_source=Open Source about.open_source.statement=GPL v3 (https://github.com/huanghongxun/HMCL/) account=Accounts +account.character=character account.choose=Choose a character account.current=Current account.create=Create a new account 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 c98e03852..0f0ab104e 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -29,6 +29,7 @@ about.open_source=开源 about.open_source.statement=GPL v3 (https://github.com/huanghongxun/HMCL/) account=账户 +account.character=角色 account.choose=选择一个角色 account.current=当前账户 account.create=新建账户 From a675f4cb68c603636e7c2c5c0ef0e19872615503 Mon Sep 17 00:00:00 2001 From: huangyuhui Date: Fri, 2 Mar 2018 00:56:16 +0800 Subject: [PATCH 07/24] Upgrade message --- .../java/org/jackhuang/hmcl/ui/AccountPage.java | 2 +- .../java/org/jackhuang/hmcl/ui/Controllers.java | 2 +- .../java/org/jackhuang/hmcl/ui/Decorator.java | 9 --------- .../jackhuang/hmcl/ui/LeftPaneController.java | 17 +++++++++++++---- .../jackhuang/hmcl/ui/construct/IconedItem.java | 14 ++++++++++---- .../main/resources/assets/fxml/decorator.fxml | 17 +++-------------- 6 files changed, 28 insertions(+), 33 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountPage.java index 1028b5ea2..2738bdc95 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountPage.java @@ -64,7 +64,7 @@ public class AccountPage extends StackPane implements DecoratorPage { FXUtils.loadFXML(this, "/assets/fxml/account.fxml"); if (account instanceof AuthlibInjectorAccount) { - Task.ofResult("serverName", () -> Accounts.getAuthlibInjectorServerName(((AuthlibInjectorAccount) account).getServerBaseURL())) + Accounts.getAuthlibInjectorServerNameAsync((AuthlibInjectorAccount) account) .subscribe(Schedulers.javafx(), variables -> lblServer.setText(variables.get("serverName"))); } else { componentList.removeChildren(paneServer); 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 8b855ec06..d8eaa1b1b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java @@ -168,7 +168,7 @@ public final class Controllers { } public static void showUpdate() { - getDecorator().showUpdate(); + getLeftPaneController().showUpdate(); } public static void shutdown() { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java index 9c28cb87e..ae221046a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java @@ -127,8 +127,6 @@ public final class Decorator extends StackPane implements TaskExecutorDialogWiza @FXML private JFXButton btnClose; @FXML - private HBox updatePane; - @FXML private HBox navLeft; public Decorator(Stage primaryStage, Node mainPage, String title) { @@ -143,9 +141,6 @@ public final class Decorator extends StackPane implements TaskExecutorDialogWiza FXUtils.loadFXML(this, "/assets/fxml/decorator.fxml"); - updatePane.setCursor(Cursor.HAND); - updatePane.setOnMouseClicked(event -> Launcher.UPDATE_CHECKER.checkOutdate()); - primaryStage.initStyle(StageStyle.UNDECORATED); btnClose.setGraphic(close); btnMin.setGraphic(minus); @@ -474,10 +469,6 @@ public final class Decorator extends StackPane implements TaskExecutorDialogWiza } } - public void showUpdate() { - updatePane.setVisible(true); - } - private void showCloseNavButton() { navLeft.getChildren().add(closeNavButton); } 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 211bb34d4..a83019242 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java @@ -27,6 +27,7 @@ import javafx.scene.control.Tooltip; import javafx.scene.image.Image; import javafx.scene.input.MouseButton; import javafx.scene.layout.VBox; +import javafx.scene.paint.Color; import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.auth.Account; import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccount; @@ -55,11 +56,17 @@ public final class LeftPaneController { private final AdvancedListBox leftPane; private final VBox profilePane = new VBox(); private final VBox accountPane = new VBox(); + private final IconedItem launcherSettingsItem; private final VersionListItem missingAccountItem = new VersionListItem(Launcher.i18n("account.missing"), Launcher.i18n("message.unknown")); public LeftPaneController(AdvancedListBox leftPane) { this.leftPane = leftPane; + this.launcherSettingsItem = Lang.apply(new IconedItem(SVG.gear(Theme.blackFillBinding(), 20, 20), Launcher.i18n("settings.launcher")), iconedItem -> { + iconedItem.prefWidthProperty().bind(leftPane.widthProperty()); + iconedItem.setOnMouseClicked(e -> Controllers.navigate(Controllers.getSettingsPage())); + }); + leftPane .add(new ClassTitle(Launcher.i18n("account").toUpperCase(), Lang.apply(new JFXButton(), button -> { button.setGraphic(SVG.plus(Theme.blackFillBinding(), 10, 10)); @@ -68,10 +75,7 @@ public final class LeftPaneController { }))) .add(accountPane) .startCategory(Launcher.i18n("launcher").toUpperCase()) - .add(Lang.apply(new IconedItem(SVG.gear(Theme.blackFillBinding(), 20, 20), Launcher.i18n("settings.launcher")), iconedItem -> { - iconedItem.prefWidthProperty().bind(leftPane.widthProperty()); - iconedItem.setOnMouseClicked(e -> Controllers.navigate(Controllers.getSettingsPage())); - })) + .add(launcherSettingsItem) .add(new ClassTitle(Launcher.i18n("profile.title").toUpperCase(), Lang.apply(new JFXButton(), button -> { button.setGraphic(SVG.plus(Theme.blackFillBinding(), 10, 10)); button.getStyleClass().add("toggle-icon-tiny"); @@ -199,6 +203,11 @@ public final class LeftPaneController { Platform.runLater(() -> accountPane.getChildren().setAll(list)); } + public void showUpdate() { + launcherSettingsItem.setText(Launcher.i18n("update.found")); + launcherSettingsItem.setTextFill(Color.RED); + } + private boolean checkedModpack = false; private void onRefreshedVersions(RefreshedVersionsEvent event) { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/IconedItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/IconedItem.java index 46c4aab27..38ecd9933 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/IconedItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/IconedItem.java @@ -21,21 +21,19 @@ import javafx.geometry.Pos; import javafx.scene.Node; import javafx.scene.control.Label; import javafx.scene.layout.HBox; +import javafx.scene.paint.Paint; public class IconedItem extends RipplerContainer { - private final Node icon; - private final String text; public IconedItem(Node icon, String text) { super(createHBox(icon, text)); - this.icon = icon; - this.text = text; } private static HBox createHBox(Node icon, String text) { HBox hBox = new HBox(); icon.setMouseTransparent(true); Label textLabel = new Label(text); + textLabel.setId("label"); textLabel.setAlignment(Pos.CENTER); textLabel.setMouseTransparent(true); hBox.getChildren().addAll(icon, textLabel); @@ -43,4 +41,12 @@ public class IconedItem extends RipplerContainer { hBox.setAlignment(Pos.CENTER_LEFT); return hBox; } + + public void setText(String text) { + ((Label) lookup("#label")).setText(text); + } + + public void setTextFill(Paint paint) { + ((Label) lookup("#label")).setTextFill(paint); + } } diff --git a/HMCL/src/main/resources/assets/fxml/decorator.fxml b/HMCL/src/main/resources/assets/fxml/decorator.fxml index 5bce78d2b..c59288d70 100644 --- a/HMCL/src/main/resources/assets/fxml/decorator.fxml +++ b/HMCL/src/main/resources/assets/fxml/decorator.fxml @@ -26,20 +26,9 @@
- -
- -
- - - - - - - - -
+ + +
From f826eb224cb8850af5e378a585b3135b5d671923 Mon Sep 17 00:00:00 2001 From: huangyuhui Date: Fri, 2 Mar 2018 10:41:25 +0800 Subject: [PATCH 08/24] AccountPage maintainence --- .../org/jackhuang/hmcl/ui/AccountPage.java | 30 ++++- .../jackhuang/hmcl/ui/LeftPaneController.java | 34 ++--- .../jackhuang/hmcl/ui/VersionListItem.java | 14 +- .../resources/assets/fxml/account-item.fxml | 51 ------- .../main/resources/assets/fxml/account.fxml | 126 +++++++++--------- .../assets/fxml/version-list-item.fxml | 2 +- 6 files changed, 100 insertions(+), 157 deletions(-) delete mode 100644 HMCL/src/main/resources/assets/fxml/account-item.fxml diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountPage.java index 2738bdc95..8515f563e 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountPage.java @@ -32,6 +32,7 @@ import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount; import org.jackhuang.hmcl.game.AccountHelper; import org.jackhuang.hmcl.setting.Accounts; import org.jackhuang.hmcl.setting.Settings; +import org.jackhuang.hmcl.setting.Theme; import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.ui.construct.ComponentList; @@ -53,8 +54,12 @@ public class AccountPage extends StackPane implements DecoratorPage { @FXML private BorderPane paneServer; @FXML + private BorderPane paneEmail; + @FXML private ComponentList componentList; @FXML + private JFXButton btnDelete; + @FXML private JFXButton btnRefresh; public AccountPage(Account account) { @@ -63,24 +68,29 @@ public class AccountPage extends StackPane implements DecoratorPage { FXUtils.loadFXML(this, "/assets/fxml/account.fxml"); + FXUtils.setLimitWidth(this, 300); if (account instanceof AuthlibInjectorAccount) { Accounts.getAuthlibInjectorServerNameAsync((AuthlibInjectorAccount) account) .subscribe(Schedulers.javafx(), variables -> lblServer.setText(variables.get("serverName"))); + FXUtils.setLimitHeight(this, 182); } else { componentList.removeChildren(paneServer); + + if (account instanceof OfflineAccount) { + componentList.removeChildren(paneEmail); + FXUtils.setLimitHeight(this, 110); + } else + FXUtils.setLimitHeight(this, 145); } + btnDelete.setGraphic(SVG.delete(Theme.blackFillBinding(), 15, 15)); + btnRefresh.setGraphic(SVG.refresh(Theme.blackFillBinding(), 15, 15)); + lblCharacter.setText(account.getCharacter()); lblType.setText(AddAccountPane.accountType(account)); lblEmail.setText(account.getUsername()); - btnRefresh.setDisable(account instanceof OfflineAccount); - - if (account instanceof YggdrasilAccount) { - btnRefresh.setOnMouseClicked(e -> { - AccountHelper.refreshSkinAsync((YggdrasilAccount) account).start(); - }); - } + btnRefresh.setVisible(account instanceof YggdrasilAccount); } @FXML @@ -89,6 +99,12 @@ public class AccountPage extends StackPane implements DecoratorPage { Controllers.navigate(null); } + @FXML + private void onRefresh() { + if (account instanceof YggdrasilAccount) + AccountHelper.refreshSkinAsync((YggdrasilAccount) account).start(); + } + public String getTitle() { return title.get(); } 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 a83019242..2ca95b0bf 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java @@ -19,7 +19,6 @@ package org.jackhuang.hmcl.ui; import com.jfoenix.concurrency.JFXUtilities; import com.jfoenix.controls.JFXButton; -import com.jfoenix.controls.JFXListView; import com.jfoenix.controls.JFXPopup; import javafx.application.Platform; import javafx.scene.Node; @@ -127,7 +126,7 @@ public final class LeftPaneController { for (Profile profile : Settings.INSTANCE.getProfiles()) { VersionListItem item = new VersionListItem(Profiles.getProfileDisplayName(profile)); RipplerContainer ripplerContainer = new RipplerContainer(item); - item.setOnSettingsButtonClicked(() -> Controllers.getDecorator().showPage(new ProfilePage(profile))); + item.setOnSettingsButtonClicked(e -> Controllers.getDecorator().showPage(new ProfilePage(profile))); ripplerContainer.setOnMouseClicked(e -> Settings.INSTANCE.setSelectedProfile(profile)); ripplerContainer.getProperties().put("profile", profile.getName()); ripplerContainer.maxWidthProperty().bind(leftPane.widthProperty()); @@ -148,32 +147,14 @@ public final class LeftPaneController { for (Account account : Settings.INSTANCE.getAccounts()) { VersionListItem item = new VersionListItem(account.getCharacter(), accountType(account)); RipplerContainer ripplerContainer = new RipplerContainer(item); - item.setOnSettingsButtonClicked(() -> Controllers.getDecorator().showPage(new AccountPage(account))); + item.setOnSettingsButtonClicked(e -> { + AccountPage accountPage = new AccountPage(account); + JFXPopup popup = new JFXPopup(accountPage); + popup.show((Node) e.getSource(), JFXPopup.PopupVPosition.TOP, JFXPopup.PopupHPosition.LEFT, e.getX(), e.getY()); + }); ripplerContainer.setOnMouseClicked(e -> { if (e.getButton() == MouseButton.PRIMARY) Settings.INSTANCE.setSelectedAccount(account); - else if (e.getButton() == MouseButton.SECONDARY) { - JFXListView listView = new JFXListView<>(); - JFXPopup popup = new JFXPopup(listView); - listView.getStyleClass().add("option-list-view"); - listView.getItems().add(Launcher.i18n("button.delete")); - if (account instanceof YggdrasilAccount) - listView.getItems().add(Launcher.i18n("button.refresh")); - listView.setOnMouseClicked(e2 ->{ - popup.hide(); - switch (listView.getSelectionModel().getSelectedIndex()) { - case 0: - Settings.INSTANCE.deleteAccount(account); - break; - case 1: - if (account instanceof YggdrasilAccount) - AccountHelper.refreshSkinAsync((YggdrasilAccount) account).start(); - break; - default: - throw new Error(); - }}); - popup.show(item, JFXPopup.PopupVPosition.TOP, JFXPopup.PopupHPosition.LEFT, e.getX(), e.getY()); - } }); ripplerContainer.getProperties().put("account", account); ripplerContainer.maxWidthProperty().bind(leftPane.widthProperty()); @@ -196,7 +177,8 @@ public final class LeftPaneController { if (Settings.INSTANCE.getAccounts().isEmpty()) { RipplerContainer container = new RipplerContainer(missingAccountItem); - missingAccountItem.setOnSettingsButtonClicked(this::addNewAccount); + missingAccountItem.setOnSettingsButtonClicked(e -> addNewAccount()); + container.setOnMouseClicked(e -> addNewAccount()); list.add(container); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionListItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionListItem.java index 7078d9dd9..140c64fd2 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionListItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionListItem.java @@ -17,11 +17,14 @@ */ package org.jackhuang.hmcl.ui; +import com.jfoenix.controls.JFXButton; +import javafx.event.EventHandler; import javafx.fxml.FXML; import javafx.geometry.Rectangle2D; import javafx.scene.control.Label; import javafx.scene.image.Image; import javafx.scene.image.ImageView; +import javafx.scene.input.MouseEvent; import javafx.scene.layout.StackPane; public final class VersionListItem extends StackPane { @@ -33,7 +36,7 @@ public final class VersionListItem extends StackPane { private Label lblGameVersion; @FXML private ImageView imageView; - private Runnable handler; + @FXML private JFXButton btnSettings; public VersionListItem(String versionName) { this(versionName, ""); @@ -48,13 +51,8 @@ public final class VersionListItem extends StackPane { FXUtils.limitSize(imageView, 32, 32); } - @FXML - private void onSettings() { - handler.run(); - } - - public void setOnSettingsButtonClicked(Runnable handler) { - this.handler = handler; + public void setOnSettingsButtonClicked(EventHandler handler) { + btnSettings.setOnMouseClicked(handler); } public void setVersionName(String versionName) { diff --git a/HMCL/src/main/resources/assets/fxml/account-item.fxml b/HMCL/src/main/resources/assets/fxml/account-item.fxml deleted file mode 100644 index 347b92021..000000000 --- a/HMCL/src/main/resources/assets/fxml/account-item.fxml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/HMCL/src/main/resources/assets/fxml/account.fxml b/HMCL/src/main/resources/assets/fxml/account.fxml index c79517b9e..ea116d355 100644 --- a/HMCL/src/main/resources/assets/fxml/account.fxml +++ b/HMCL/src/main/resources/assets/fxml/account.fxml @@ -1,82 +1,80 @@ - - + - - - - + - + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + - - - + + - + - + diff --git a/HMCL/src/main/resources/assets/fxml/version-list-item.fxml b/HMCL/src/main/resources/assets/fxml/version-list-item.fxml index bc3fa3872..34109b66b 100644 --- a/HMCL/src/main/resources/assets/fxml/version-list-item.fxml +++ b/HMCL/src/main/resources/assets/fxml/version-list-item.fxml @@ -31,7 +31,7 @@ - + From ba359305f67f5e2c780c0479f81754bd860f2b1c Mon Sep 17 00:00:00 2001 From: huangyuhui Date: Fri, 2 Mar 2018 19:22:10 +0800 Subject: [PATCH 09/24] Hide refresh and add button in MainPage --- .../jackhuang/hmcl/game/LauncherHelper.java | 3 ++- .../java/org/jackhuang/hmcl/ui/MainPage.java | 4 +-- HMCL/src/main/resources/assets/fxml/main.fxml | 26 +++++++++---------- .../hmcl/game/DefaultGameRepository.java | 2 +- 4 files changed, 18 insertions(+), 17 deletions(-) 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 97d09da63..00d5046fd 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -356,7 +356,8 @@ public final class LauncherHelper { }); break; case CLOSE: - throw new Error("Never come to here"); + // Never come to here. + break; case KEEP: // No operations here break; 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 e6977c24d..9b1eb0ea3 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java @@ -209,7 +209,7 @@ public final class MainPage extends StackPane implements DecoratorPage { } private void loadingVersions() { - contentPane.getChildren().setAll(spinner); + getChildren().setAll(spinner); FXUtils.resetChildren(masonryPane, Collections.emptyList()); } @@ -220,7 +220,7 @@ public final class MainPage extends StackPane implements DecoratorPage { } JFXUtilities.runInFX(() -> { if (profile == repository.getProfile()) { - contentPane.getChildren().setAll(masonryPane); + getChildren().setAll(contentPane); FXUtils.resetChildren(masonryPane, children); } }); diff --git a/HMCL/src/main/resources/assets/fxml/main.fxml b/HMCL/src/main/resources/assets/fxml/main.fxml index a8882ce04..6d1ff1a6b 100644 --- a/HMCL/src/main/resources/assets/fxml/main.fxml +++ b/HMCL/src/main/resources/assets/fxml/main.fxml @@ -10,23 +10,23 @@ maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" type="StackPane" pickOnBounds="false" xmlns="http://javafx.com/javafx/8.0.112" xmlns:fx="http://javafx.com/fxml/1"> + - + + + + + + + + + + + + - - - - - - - - - - - - diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java index 63e669fb8..9278516a6 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java @@ -62,7 +62,7 @@ public class DefaultGameRepository implements GameRepository { @Override public Version getVersion(String id) { if (!hasVersion(id)) - throw new VersionNotFoundException("Version '" + id + "' does not exist."); + throw new VersionNotFoundException("Version '" + id + "' does not exist in " + versions.keySet() + "."); return versions.get(id); } From 3bf92e6f1200fbec08e8f1d7e293c5a387cac095 Mon Sep 17 00:00:00 2001 From: huangyuhui Date: Fri, 2 Mar 2018 22:54:36 +0800 Subject: [PATCH 10/24] Fix process not exited when pressed Alt+F4 --- HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java | 2 ++ HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java | 2 ++ HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java | 4 +++- HMCL/src/main/java/org/jackhuang/hmcl/util/CrashReporter.java | 1 + 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java b/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java index a3d064976..058b33b4a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java @@ -86,6 +86,8 @@ public final class Launcher extends Application { } public static void stopWithoutPlatform() { + Logging.LOG.info("Stopping application without JavaFX Toolkit"); + JFXUtilities.runInFX(() -> { if (Controllers.getStage() == null) return; 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 d8eaa1b1b..610753499 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java @@ -93,6 +93,8 @@ public final class Controllers { public static void initialize(Stage stage) { Controllers.stage = stage; + stage.setOnCloseRequest(e -> Launcher.stopApplication()); + decorator = new Decorator(stage, getMainPage(), Launcher.TITLE, false, true); decorator.showPage(null); leftPaneController = new LeftPaneController(decorator.getLeftPane()); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java index ae221046a..253cfa765 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java @@ -74,7 +74,7 @@ public final class Decorator extends StackPane implements TaskExecutorDialogWiza private static final SVGGlyph close = Lang.apply(new SVGGlyph(0, "CLOSE", "M810 274l-238 238 238 238-60 60-238-238-238 238-60-60 238-238-238-238 60-60 238 238 238-238z", Color.WHITE), glyph -> { glyph.setPrefSize(12, 12); glyph.setSize(12, 12); }); - private final ObjectProperty onCloseButtonAction = new SimpleObjectProperty<>(Launcher::stopApplication); + private final ObjectProperty onCloseButtonAction; private final BooleanProperty customMaximize = new SimpleBooleanProperty(false); private final Stage primaryStage; @@ -141,6 +141,8 @@ public final class Decorator extends StackPane implements TaskExecutorDialogWiza FXUtils.loadFXML(this, "/assets/fxml/decorator.fxml"); + onCloseButtonAction = new SimpleObjectProperty<>(this, "onCloseButtonAction", primaryStage::close); + primaryStage.initStyle(StageStyle.UNDECORATED); btnClose.setGraphic(close); btnMin.setGraphic(minus); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/util/CrashReporter.java b/HMCL/src/main/java/org/jackhuang/hmcl/util/CrashReporter.java index 6072fd5c2..c61c17af2 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/util/CrashReporter.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/util/CrashReporter.java @@ -45,6 +45,7 @@ public class CrashReporter implements Thread.UncaughtExceptionHandler { put("java.lang.ClassFormatError", Launcher.i18n("crash.NoClassDefFound")); put("java.lang.OutOfMemoryError", "FUCKING MEMORY LIMIT!"); put("Trampoline", Launcher.i18n("launcher.update_java")); + put("com.sun.javafx.css.StyleManager.findMatchingStyles", Launcher.i18n("launcher.update_java")); put("NoSuchAlgorithmException", "Has your operating system been installed completely or is a ghost system?"); } }; From 99e85eba37c17afd6f7a7553224e9bbbade9643f Mon Sep 17 00:00:00 2001 From: huangyuhui Date: Fri, 2 Mar 2018 23:11:17 +0800 Subject: [PATCH 11/24] Fix NPE in LauncherHelper.executor.onFinish: executor.getRunningTasks --- HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 00d5046fd..e16322193 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -78,7 +78,7 @@ public final class LauncherHelper { VersionSetting setting = profile.getVersionSetting(selectedVersion); Optional gameVersion = GameVersion.minecraftVersion(repository.getVersionJar(version)); - executor = Task.of(Schedulers.javafx(), () -> Controllers.dialog(launchingStepsPane)) + TaskExecutor executor = this.executor = Task.of(Schedulers.javafx(), () -> Controllers.dialog(launchingStepsPane)) .then(Task.of(Schedulers.javafx(), () -> emitStatus(LoadingState.DEPENDENCIES))) .then(variables -> { if (setting.isNotCheckGame()) From c6ab7878e773b8669545ce54999707688f2d1731 Mon Sep 17 00:00:00 2001 From: huangyuhui Date: Fri, 2 Mar 2018 23:42:38 +0800 Subject: [PATCH 12/24] Optimize code --- HMCL/build.gradle | 9 ++++---- .../main/java/org/jackhuang/hmcl/Main.java | 4 ++-- .../hmcl/game/HMCLModpackInstallTask.java | 3 +-- .../org/jackhuang/hmcl/setting/Settings.java | 4 ++-- .../org/jackhuang/hmcl/ui/AccountPage.java | 1 - .../java/org/jackhuang/hmcl/ui/Decorator.java | 1 - .../hmcl/ui/download/InstallTypePage.java | 2 -- .../hmcl/ui/download/InstallersPage.java | 4 ---- .../hmcl/ui/download/VersionsPage.java | 4 ---- .../hmcl/upgrade/AppDataUpgrader.java | 2 +- .../jackhuang/hmcl/util/CrashReporter.java | 22 +++++++++---------- .../assets/fxml/version/version-settings.fxml | 1 - .../hmcl/download/MojangDownloadProvider.java | 2 +- .../hmcl/download/forge/ForgeInstallTask.java | 2 +- .../liteloader/LiteLoaderInstallTask.java | 2 +- .../optifine/OptiFineInstallTask.java | 2 +- .../java/org/jackhuang/hmcl/event/Event.java | 2 +- .../hmcl/game/LibrariesDownloadInfo.java | 2 +- .../jackhuang/hmcl/game/StringArgument.java | 2 +- .../hmcl/mod/MultiMCModpackInstallTask.java | 5 +---- .../org/jackhuang/hmcl/task/Schedulers.java | 4 +--- .../org/jackhuang/hmcl/util/Log4jLevel.java | 4 ++-- .../java/org/jackhuang/hmcl/util/Logging.java | 1 - 23 files changed, 32 insertions(+), 53 deletions(-) diff --git a/HMCL/build.gradle b/HMCL/build.gradle index 11fb43bae..b162ec9f8 100644 --- a/HMCL/build.gradle +++ b/HMCL/build.gradle @@ -1,3 +1,6 @@ +import org.apache.tools.ant.filters.ReplaceTokens +import proguard.gradle.ProGuardTask + import java.security.MessageDigest import java.util.jar.JarFile import java.util.jar.Pack200 @@ -17,9 +20,7 @@ def versionroot = System.getenv("VERSION_ROOT") if (versionroot == null) versionroot = "3.0" -String mavenGroupId = 'HMCL' String mavenVersion = versionroot + '.' + buildnumber -String bundleName = "Hello Minecraft! Launcher" version = mavenVersion dependencies { @@ -30,7 +31,7 @@ dependencies { task generateSources(type: Sync) { from 'src/main/java' into "$buildDir/generated-src" - filter(org.apache.tools.ant.filters.ReplaceTokens, tokens: [ + filter(ReplaceTokens, tokens: [ 'HELLO_MINECRAFT_LAUNCHER_VERSION_FOR_GRADLE_REPLACING': mavenVersion ]) } @@ -122,7 +123,7 @@ task makePackGZ(dependsOn: jar) doLast { fileEx.append sha1Hex } -task proguard(type: proguard.gradle.ProGuardTask, dependsOn: jar) { +task proguard(type: ProGuardTask, dependsOn: jar) { ext { def re = jar.classifier injar = jar.archivePath diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/Main.java b/HMCL/src/main/java/org/jackhuang/hmcl/Main.java index 1bf1aef23..7642e2153 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/Main.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/Main.java @@ -17,9 +17,9 @@ */ package org.jackhuang.hmcl; -import org.apache.commons.compress.utils.Charsets; import org.jackhuang.hmcl.util.Logging; -import javax.swing.JOptionPane; + +import javax.swing.*; import java.io.File; public final class Main { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLModpackInstallTask.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLModpackInstallTask.java index df29d0ad1..0fcb82976 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLModpackInstallTask.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLModpackInstallTask.java @@ -42,7 +42,6 @@ public final class HMCLModpackInstallTask extends Task { private final String name; private final HMCLGameRepository repository; private final Modpack modpack; - private final File run; private final List dependencies = new LinkedList<>(); private final List dependents = new LinkedList<>(); @@ -52,8 +51,8 @@ public final class HMCLModpackInstallTask extends Task { this.zipFile = zipFile; this.name = name; this.modpack = modpack; - this.run = repository.getRunDirectory(name); + File run = repository.getRunDirectory(name); File json = repository.getModpackConfiguration(name); if (repository.hasVersion(name) && !json.exists()) throw new IllegalArgumentException("Version " + name + " already exists"); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java index cb00fdd8f..9a8830b5b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java @@ -63,7 +63,7 @@ public class Settings { private final Config SETTINGS = initSettings(); - private Map accounts = new HashMap<>(); + private final Map accounts = new HashMap<>(); { loadProxy(); @@ -473,7 +473,7 @@ public class Settings { checkProfileMap(); if (!hasProfile(SETTINGS.getSelectedProfile())) { - SETTINGS.setSelectedProfile(getProfileMap().keySet().stream().findFirst().get()); + getProfileMap().keySet().stream().findFirst().ifPresent(SETTINGS::setSelectedProfile); Schedulers.computation().schedule(this::onProfileChanged); } return getProfile(SETTINGS.getSelectedProfile()); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountPage.java index 8515f563e..be8aded3b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountPage.java @@ -34,7 +34,6 @@ import org.jackhuang.hmcl.setting.Accounts; import org.jackhuang.hmcl.setting.Settings; import org.jackhuang.hmcl.setting.Theme; import org.jackhuang.hmcl.task.Schedulers; -import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.ui.construct.ComponentList; import org.jackhuang.hmcl.ui.wizard.DecoratorPage; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java index 253cfa765..7867986b7 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java @@ -45,7 +45,6 @@ import javafx.scene.shape.Rectangle; import javafx.stage.Screen; import javafx.stage.Stage; import javafx.stage.StageStyle; -import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.setting.EnumBackgroundImage; import org.jackhuang.hmcl.setting.Settings; import org.jackhuang.hmcl.setting.Theme; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallTypePage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallTypePage.java index 43c3a1379..5c8212ee3 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallTypePage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallTypePage.java @@ -28,12 +28,10 @@ import org.jackhuang.hmcl.ui.wizard.WizardPage; import java.util.Map; public final class InstallTypePage extends StackPane implements WizardPage { - private final WizardController controller; @FXML private JFXListView list; public InstallTypePage(WizardController controller) { - this.controller = controller; FXUtils.loadFXML(this, "/assets/fxml/download/dltype.fxml"); list.setOnMouseClicked(e -> { 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 32a07ebcc..df52ef8c7 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 @@ -37,8 +37,6 @@ import java.util.Map; public class InstallersPage extends StackPane implements WizardPage { private final WizardController controller; - private final GameRepository repository; - private final DownloadProvider downloadProvider; @FXML private VBox list; @@ -72,8 +70,6 @@ public class InstallersPage extends StackPane implements WizardPage { public InstallersPage(WizardController controller, GameRepository repository, DownloadProvider downloadProvider) { this.controller = controller; - this.repository = repository; - this.downloadProvider = downloadProvider; FXUtils.loadFXML(this, "/assets/fxml/download/installers.fxml"); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java index bf02c6990..1e6d8a9cd 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java @@ -44,11 +44,9 @@ import java.util.Objects; import java.util.stream.Collectors; public final class VersionsPage extends StackPane implements WizardPage, Refreshable { - private final WizardController controller; private final String gameVersion; private final DownloadProvider downloadProvider; private final String libraryId; - private final Runnable callback; private final String title; @FXML @@ -73,12 +71,10 @@ public final class VersionsPage extends StackPane implements WizardPage, Refresh private TaskExecutor executor; public VersionsPage(WizardController controller, String title, String gameVersion, DownloadProvider downloadProvider, String libraryId, Runnable callback) { - this.controller = controller; this.title = title; this.gameVersion = gameVersion; this.downloadProvider = downloadProvider; this.libraryId = libraryId; - this.callback = callback; this.versionList = downloadProvider.getVersionListById(libraryId); FXUtils.loadFXML(this, "/assets/fxml/download/versions.fxml"); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/AppDataUpgrader.java b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/AppDataUpgrader.java index c92185bd1..b0c590e58 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/AppDataUpgrader.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/AppDataUpgrader.java @@ -176,7 +176,7 @@ public class AppDataUpgrader extends IUpgrader { @Override public Collection getDependents() { - return Arrays.asList(new FileDownloadTask(downloadLink, tempFile, Proxy.NO_PROXY, hash)); + return Collections.singleton(new FileDownloadTask(downloadLink, tempFile, Proxy.NO_PROXY, hash)); } @Override diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/util/CrashReporter.java b/HMCL/src/main/java/org/jackhuang/hmcl/util/CrashReporter.java index c61c17af2..d4e673776 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/util/CrashReporter.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/util/CrashReporter.java @@ -79,18 +79,16 @@ public class CrashReporter implements Thread.UncaughtExceptionHandler { THROWABLE_SET.add(stackTrace); try { - StringBuilder builder = new StringBuilder(); - builder.append("---- Hello Minecraft! Crash Report ----\n"); - builder.append(" Version: " + Launcher.VERSION + "\n"); - builder.append(" Time: ").append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())).append("\n"); - builder.append(" Thread: ").append(t.toString()).append("\n"); - builder.append("\n Content: \n "); - builder.append(stackTrace).append("\n\n"); - builder.append("-- System Details --\n"); - builder.append(" Operating System: ").append(System.getProperty("os.name")).append(' ').append(OperatingSystem.SYSTEM_VERSION).append("\n"); - builder.append(" Java Version: ").append(System.getProperty("java.version")).append(", ").append(System.getProperty("java.vendor")).append("\n"); - builder.append(" Java VM Version: ").append(System.getProperty("java.vm.name")).append(" (").append(System.getProperty("java.vm.info")).append("), ").append(System.getProperty("java.vm.vendor")).append("\n"); - String text = builder.toString(); + String text = "---- Hello Minecraft! Crash Report ----\n" + + " Version: " + Launcher.VERSION + "\n" + + " Time: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "\n" + + " Thread: " + t.toString() + "\n" + + "\n Content: \n " + + stackTrace + "\n\n" + + "-- System Details --\n" + + " Operating System: " + System.getProperty("os.name") + ' ' + OperatingSystem.SYSTEM_VERSION + "\n" + + " Java Version: " + System.getProperty("java.version") + ", " + System.getProperty("java.vendor") + "\n" + + " Java VM Version: " + System.getProperty("java.vm.name") + " (" + System.getProperty("java.vm.info") + "), " + System.getProperty("java.vm.vendor") + "\n"; Logging.LOG.log(Level.SEVERE, text); 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 75e5d8eff..29a22ecf8 100644 --- a/HMCL/src/main/resources/assets/fxml/version/version-settings.fxml +++ b/HMCL/src/main/resources/assets/fxml/version/version-settings.fxml @@ -5,7 +5,6 @@ - diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MojangDownloadProvider.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MojangDownloadProvider.java index 45d897ebf..a181e596d 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MojangDownloadProvider.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MojangDownloadProvider.java @@ -28,7 +28,7 @@ import org.jackhuang.hmcl.download.optifine.OptiFineVersionList; */ public class MojangDownloadProvider implements DownloadProvider { - private boolean isChina; + private final boolean isChina; public MojangDownloadProvider(boolean isChina) { this.isChina = isChina; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeInstallTask.java index 489ef4009..d82b27713 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeInstallTask.java @@ -47,7 +47,7 @@ public final class ForgeInstallTask extends TaskResult { private final DefaultDependencyManager dependencyManager; private final Version version; private final File installer = new File("forge-installer.jar").getAbsoluteFile(); - private ForgeRemoteVersion remote; + private final ForgeRemoteVersion remote; private final List dependents = new LinkedList<>(); private final List dependencies = new LinkedList<>(); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/liteloader/LiteLoaderInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/liteloader/LiteLoaderInstallTask.java index 50479681b..3cf3b2b22 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/liteloader/LiteLoaderInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/liteloader/LiteLoaderInstallTask.java @@ -41,7 +41,7 @@ public final class LiteLoaderInstallTask extends TaskResult { private final DefaultDependencyManager dependencyManager; private final Version version; - private LiteLoaderRemoteVersion remote; + private final LiteLoaderRemoteVersion remote; private final List dependents = new LinkedList<>(); private final List dependencies = new LinkedList<>(); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/optifine/OptiFineInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/optifine/OptiFineInstallTask.java index 29617a14c..1a930d1f8 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/optifine/OptiFineInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/optifine/OptiFineInstallTask.java @@ -38,7 +38,7 @@ public final class OptiFineInstallTask extends TaskResult { private final DefaultDependencyManager dependencyManager; private final Version version; - private OptiFineRemoteVersion remote; + private final OptiFineRemoteVersion remote; private final List dependents = new LinkedList<>(); private final List dependencies = new LinkedList<>(); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/event/Event.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/event/Event.java index 68adc2bc9..c55de587a 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/event/Event.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/event/Event.java @@ -30,7 +30,7 @@ public class Event { /** * The object on which the Event initially occurred. */ - protected transient Object source; + protected final transient Object source; /** * Constructs a prototypical Event. diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/LibrariesDownloadInfo.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/LibrariesDownloadInfo.java index 219c5e93b..e3b0e64f4 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/LibrariesDownloadInfo.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/LibrariesDownloadInfo.java @@ -39,7 +39,7 @@ public final class LibrariesDownloadInfo { public LibrariesDownloadInfo(LibraryDownloadInfo artifact, Map classifiers) { this.artifact = artifact; - this.classifiers = new HashMap<>(classifiers); + this.classifiers = classifiers == null ? null : new HashMap<>(classifiers); } public LibraryDownloadInfo getArtifact() { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/StringArgument.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/StringArgument.java index 02aff228e..acfd86e10 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/StringArgument.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/StringArgument.java @@ -45,7 +45,7 @@ public final class StringArgument implements Argument { @Override public List toString(Map keys, Map features) { String res = argument; - Pattern pattern = Pattern.compile("\\$\\{(.*?)\\}"); + Pattern pattern = Pattern.compile("\\$\\{(.*?)}"); Matcher m = pattern.matcher(argument); while (m.find()) { String entry = m.group(); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MultiMCModpackInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MultiMCModpackInstallTask.java index b2539f3b3..b796d1e9f 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MultiMCModpackInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MultiMCModpackInstallTask.java @@ -44,23 +44,20 @@ import java.util.Objects; */ public final class MultiMCModpackInstallTask extends Task { - private final DefaultDependencyManager dependencyManager; private final File zipFile; private final MultiMCInstanceConfiguration manifest; private final String name; - private final File run; private final DefaultGameRepository repository; private final List dependencies = new LinkedList<>(); private final List dependents = new LinkedList<>(); public MultiMCModpackInstallTask(DefaultDependencyManager dependencyManager, File zipFile, MultiMCInstanceConfiguration manifest, String name) { - this.dependencyManager = dependencyManager; this.zipFile = zipFile; this.manifest = manifest; this.name = name; this.repository = dependencyManager.getGameRepository(); - this.run = repository.getRunDirectory(name); + File run = repository.getRunDirectory(name); File json = repository.getModpackConfiguration(name); if (repository.hasVersion(name) && !json.exists()) throw new IllegalArgumentException("Version " + name + " already exists."); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Schedulers.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Schedulers.java index 7ba61c2b9..e1c2ca9fe 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Schedulers.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Schedulers.java @@ -35,9 +35,7 @@ public final class Schedulers { private static synchronized ExecutorService getCachedExecutorService() { if (CACHED_EXECUTOR == null) CACHED_EXECUTOR = new ThreadPoolExecutor(0, Integer.MAX_VALUE, - 60, TimeUnit.SECONDS, new SynchronousQueue<>(), runnable -> { - return Executors.defaultThreadFactory().newThread(runnable); - }); + 60, TimeUnit.SECONDS, new SynchronousQueue<>(), Executors.defaultThreadFactory()); return CACHED_EXECUTOR; } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Log4jLevel.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Log4jLevel.java index 98145f463..c6295c1cc 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Log4jLevel.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Log4jLevel.java @@ -54,8 +54,8 @@ public enum Log4jLevel { public boolean lessOrEqual(Log4jLevel level) { return this.level <= level.level; } - public static final Pattern MINECRAFT_LOGGER = Pattern.compile("\\[(?[0-9:]+)\\] \\[[^/]+/(?[^\\]]+)\\]"); - public static final Pattern MINECRAFT_LOGGER_CATEGORY = Pattern.compile("\\[(?[0-9:]+)\\] \\[[^/]+/(?[^\\]]+)\\] \\[(?[^\\]]+)\\]"); + public static final Pattern MINECRAFT_LOGGER = Pattern.compile("\\[(?[0-9:]+)] \\[[^/]+/(?[^]]+)]"); + public static final Pattern MINECRAFT_LOGGER_CATEGORY = Pattern.compile("\\[(?[0-9:]+)] \\[[^/]+/(?[^]]+)] \\[(?[^]]+)]"); public static final String JAVA_SYMBOL = "([a-zA-Z_$][a-zA-Z\\d_$]*\\.)+[a-zA-Z_$][a-zA-Z\\d_$]*"; public static Log4jLevel guessLevel(String line) { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Logging.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Logging.java index aecb4eec7..107d69aca 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Logging.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Logging.java @@ -20,7 +20,6 @@ package org.jackhuang.hmcl.util; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.PrintWriter; -import java.text.MessageFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.logging.*; From 5b5a58a8673c53c4592ee5eaa30efcb971a1b09b Mon Sep 17 00:00:00 2001 From: huangyuhui Date: Sat, 3 Mar 2018 22:56:42 +0800 Subject: [PATCH 13/24] Fixed not terminating the process when closed window --- .../hmcl/event/AccountLoadingEvent.java | 24 ++++++++++++++++++- .../jackhuang/hmcl/event/OutOfDateEvent.java | 8 +++++++ .../hmcl/event/ProfileChangedEvent.java | 8 +++++++ .../hmcl/event/ProfileLoadingEvent.java | 23 +++++++++++++++++- .../jackhuang/hmcl/game/LauncherHelper.java | 6 ++--- .../org/jackhuang/hmcl/setting/Profile.java | 9 +++++++ .../org/jackhuang/hmcl/setting/Settings.java | 6 ++--- .../java/org/jackhuang/hmcl/ui/Decorator.java | 3 ++- .../ui/construct/TaskExecutorDialogPane.java | 4 +++- .../jackhuang/hmcl/util/CrashReporter.java | 1 + .../java/org/jackhuang/hmcl/auth/Account.java | 11 +++++++++ 11 files changed, 92 insertions(+), 11 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/event/AccountLoadingEvent.java b/HMCL/src/main/java/org/jackhuang/hmcl/event/AccountLoadingEvent.java index 1fc343485..02485fc97 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/event/AccountLoadingEvent.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/event/AccountLoadingEvent.java @@ -17,6 +17,13 @@ */ package org.jackhuang.hmcl.event; +import org.jackhuang.hmcl.auth.Account; +import org.jackhuang.hmcl.setting.Profile; +import org.jackhuang.hmcl.util.ToStringBuilder; + +import java.util.Collection; +import java.util.Collections; + /** * This event gets fired when loading accounts. *
@@ -26,14 +33,29 @@ package org.jackhuang.hmcl.event; */ public class AccountLoadingEvent extends Event { + private final Collection accounts; + /** * Constructor. * * @param source {@link org.jackhuang.hmcl.setting.Settings} */ - public AccountLoadingEvent(Object source) { + public AccountLoadingEvent(Object source, Collection accounts) { super(source); + this.accounts = Collections.unmodifiableCollection(accounts); } + + public Collection getAccounts() { + return accounts; + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .append("source", source) + .append("accounts", accounts) + .toString(); + } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/event/OutOfDateEvent.java b/HMCL/src/main/java/org/jackhuang/hmcl/event/OutOfDateEvent.java index 9f5d25840..fe6fbfd4b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/event/OutOfDateEvent.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/event/OutOfDateEvent.java @@ -17,6 +17,7 @@ */ package org.jackhuang.hmcl.event; +import org.jackhuang.hmcl.util.ToStringBuilder; import org.jackhuang.hmcl.util.VersionNumber; /** @@ -42,4 +43,11 @@ public final class OutOfDateEvent extends Event { return true; } + @Override + public String toString() { + return new ToStringBuilder(this) + .append("source", getSource()) + .append("version", getVersion()) + .toString(); + } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/event/ProfileChangedEvent.java b/HMCL/src/main/java/org/jackhuang/hmcl/event/ProfileChangedEvent.java index 87d229e44..2155d94cc 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/event/ProfileChangedEvent.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/event/ProfileChangedEvent.java @@ -18,6 +18,7 @@ package org.jackhuang.hmcl.event; import org.jackhuang.hmcl.setting.Profile; +import org.jackhuang.hmcl.util.ToStringBuilder; /** * This event gets fired when the selected profile changed. @@ -44,4 +45,11 @@ public final class ProfileChangedEvent extends Event { return profile; } + @Override + public String toString() { + return new ToStringBuilder(this) + .append("source", source) + .append("profile", profile) + .toString(); + } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/event/ProfileLoadingEvent.java b/HMCL/src/main/java/org/jackhuang/hmcl/event/ProfileLoadingEvent.java index f5ef78dc8..81ff05379 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/event/ProfileLoadingEvent.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/event/ProfileLoadingEvent.java @@ -17,6 +17,12 @@ */ package org.jackhuang.hmcl.event; +import org.jackhuang.hmcl.setting.Profile; +import org.jackhuang.hmcl.util.ToStringBuilder; + +import java.util.Collection; +import java.util.Collections; + /** * This event gets fired when loading profiles. *
@@ -26,14 +32,29 @@ package org.jackhuang.hmcl.event; */ public class ProfileLoadingEvent extends Event { + private final Collection profiles; + /** * Constructor. * * @param source {@link org.jackhuang.hmcl.setting.Settings} */ - public ProfileLoadingEvent(Object source) { + public ProfileLoadingEvent(Object source, Collection profiles) { super(source); + + this.profiles = Collections.unmodifiableCollection(profiles); } + public Collection getProfiles() { + return profiles; + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .append("source", source) + .append("profiles", profiles) + .toString(); + } } 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 e16322193..2f5596e5d 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -50,7 +50,6 @@ public final class LauncherHelper { public static final LauncherHelper INSTANCE = new LauncherHelper(); private LauncherHelper(){} - private TaskExecutor executor; public static final Queue PROCESSES = new ConcurrentLinkedQueue<>(); private final TaskExecutorDialogPane launchingStepsPane = new TaskExecutorDialogPane(() -> {}); @@ -78,7 +77,7 @@ public final class LauncherHelper { VersionSetting setting = profile.getVersionSetting(selectedVersion); Optional gameVersion = GameVersion.minecraftVersion(repository.getVersionJar(version)); - TaskExecutor executor = this.executor = Task.of(Schedulers.javafx(), () -> Controllers.dialog(launchingStepsPane)) + TaskExecutor executor = Task.of(Schedulers.javafx(), () -> Controllers.dialog(launchingStepsPane)) .then(Task.of(Schedulers.javafx(), () -> emitStatus(LoadingState.DEPENDENCIES))) .then(variables -> { if (setting.isNotCheckGame()) @@ -162,8 +161,7 @@ public final class LauncherHelper { Controllers.closeDialog(); }); } - - LauncherHelper.this.executor = null; + launchingStepsPane.setExecutor(null); } }); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Profile.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Profile.java index 4d56d93d6..6b7c4257b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Profile.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Profile.java @@ -24,6 +24,7 @@ import org.jackhuang.hmcl.game.HMCLGameRepository; import org.jackhuang.hmcl.mod.ModManager; import org.jackhuang.hmcl.util.ImmediateObjectProperty; import org.jackhuang.hmcl.util.ImmediateStringProperty; +import org.jackhuang.hmcl.util.ToStringBuilder; import java.io.File; import java.lang.reflect.Type; @@ -146,6 +147,14 @@ public final class Profile { vs.setUsesGlobal(true); } + @Override + public String toString() { + return new ToStringBuilder(this) + .append("gameDir", getGameDir()) + .append("name", getName()) + .toString(); + } + public void addPropertyChangedListener(InvalidationListener listener) { nameProperty.addListener(listener); globalProperty.addListener(listener); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java index 9a8830b5b..584d2e6a5 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java @@ -535,7 +535,7 @@ public class Settings { } private void onProfileChanged() { - EventBus.EVENT_BUS.fireEvent(new ProfileChangedEvent(SETTINGS, getSelectedProfile())); + EventBus.EVENT_BUS.fireEvent(new ProfileChangedEvent(this, getSelectedProfile())); getSelectedProfile().getRepository().refreshVersionsAsync().start(); } @@ -548,11 +548,11 @@ public class Settings { * Invoked by loading GUI phase. */ public void onProfileLoading() { - EventBus.EVENT_BUS.fireEvent(new ProfileLoadingEvent(SETTINGS)); + EventBus.EVENT_BUS.fireEvent(new ProfileLoadingEvent(this, getProfiles())); onProfileChanged(); } public void onAccountLoading() { - EventBus.EVENT_BUS.fireEvent(new AccountLoadingEvent(SETTINGS)); + EventBus.EVENT_BUS.fireEvent(new AccountLoadingEvent(this, getAccounts())); } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java index 7867986b7..a903880e4 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java @@ -45,6 +45,7 @@ import javafx.scene.shape.Rectangle; import javafx.stage.Screen; import javafx.stage.Stage; import javafx.stage.StageStyle; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.setting.EnumBackgroundImage; import org.jackhuang.hmcl.setting.Settings; import org.jackhuang.hmcl.setting.Theme; @@ -140,7 +141,7 @@ public final class Decorator extends StackPane implements TaskExecutorDialogWiza FXUtils.loadFXML(this, "/assets/fxml/decorator.fxml"); - onCloseButtonAction = new SimpleObjectProperty<>(this, "onCloseButtonAction", primaryStage::close); + onCloseButtonAction = new SimpleObjectProperty<>(this, "onCloseButtonAction", Launcher::stopApplication); primaryStage.initStyle(StageStyle.UNDECORATED); btnClose.setGraphic(close); 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 249b4dd57..0038117a9 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 @@ -57,7 +57,9 @@ public class TaskExecutorDialogPane extends StackPane { public void setExecutor(TaskExecutor executor) { this.executor = executor; - taskListPane.setExecutor(executor); + + if (executor != null) + taskListPane.setExecutor(executor); } public StringProperty titleProperty() { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/util/CrashReporter.java b/HMCL/src/main/java/org/jackhuang/hmcl/util/CrashReporter.java index d4e673776..a02afc07b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/util/CrashReporter.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/util/CrashReporter.java @@ -37,6 +37,7 @@ public class CrashReporter implements Thread.UncaughtExceptionHandler { private static final HashMap SOURCE = new HashMap() { { put("javafx.fxml.LoadException", Launcher.i18n("crash.NoClassDefFound")); + put("Location is not set", Launcher.i18n("crash.NoClassDefFound")); put("UnsatisfiedLinkError", Launcher.i18n("crash.user_fault")); put("java.lang.NoClassDefFoundError", Launcher.i18n("crash.NoClassDefFound")); put("java.lang.VerifyError", Launcher.i18n("crash.NoClassDefFound")); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/Account.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/Account.java index 9bc41f637..389a64d1f 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/Account.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/Account.java @@ -17,6 +17,8 @@ */ package org.jackhuang.hmcl.auth; +import org.jackhuang.hmcl.util.ToStringBuilder; + import java.util.Map; import java.util.UUID; @@ -64,4 +66,13 @@ public abstract class Account { public abstract Map toStorage(); public abstract void clearCache(); + + @Override + public String toString() { + return new ToStringBuilder(this) + .append("username", getUsername()) + .append("character", getCharacter()) + .append("uuid", getUUID()) + .toString(); + } } From ecf24a746eac3115abb4074482da2741d8b43d6e Mon Sep 17 00:00:00 2001 From: huangyuhui Date: Sun, 4 Mar 2018 15:33:54 +0800 Subject: [PATCH 14/24] Fix crashing when unable to save version setting --- .../jackhuang/hmcl/game/HMCLGameRepository.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) 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 ee7695306..b98f7355f 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java @@ -173,10 +173,20 @@ public class HMCLGameRepository extends DefaultGameRepository { return new File(getVersionRoot(id), "icon.png"); } - public void saveVersionSetting(String id) { + public boolean saveVersionSetting(String id) { if (!versionSettings.containsKey(id)) - return; - Lang.invoke(() -> FileUtils.writeText(getVersionSettingFile(id), GSON.toJson(versionSettings.get(id)))); + return false; + File file = getVersionSettingFile(id); + if (!FileUtils.makeDirectory(file.getAbsoluteFile().getParentFile())) + return false; + + try { + FileUtils.writeText(file, GSON.toJson(versionSettings.get(id))); + return true; + } catch (IOException e) { + Logging.LOG.log(Level.SEVERE, "Unable to save version setting of " + id, e); + return false; + } } public boolean forbidsVersion(String id) { From 5656c9f35109a5bab3ba428598892da6141e94f0 Mon Sep 17 00:00:00 2001 From: huangyuhui Date: Sun, 4 Mar 2018 16:54:35 +0800 Subject: [PATCH 15/24] update update_link.php --- .../src/main/java/org/jackhuang/hmcl/upgrade/UpdateChecker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateChecker.java b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateChecker.java index ff860ffdf..2a1701b08 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateChecker.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateChecker.java @@ -115,7 +115,7 @@ public final class UpdateChecker { public void execute() { if (download_link == null) try { - download_link = Constants.GSON.>fromJson(NetworkUtils.doGet(NetworkUtils.toURL("http://huangyuhui.duapp.com/update_link.php?type=hmcl")), Map.class); + download_link = Constants.GSON.>fromJson(NetworkUtils.doGet(NetworkUtils.toURL("http://huangyuhui.duapp.com/hmcl/update_link.php")), Map.class); } catch (JsonSyntaxException | IOException e) { Logging.LOG.log(Level.SEVERE, "Failed to get update link.", e); } From 9ba6cddde7178051c0e3c887cf1d46dac095eacb Mon Sep 17 00:00:00 2001 From: huangyuhui Date: Sun, 4 Mar 2018 19:09:11 +0800 Subject: [PATCH 16/24] Fix update --- HMCL/build.gradle | 2 +- .../main/java/org/jackhuang/hmcl/Launcher.java | 15 ++++++++------- .../java/org/jackhuang/hmcl/ui/Controllers.java | 1 + .../org/jackhuang/hmcl/util/IntVersionNumber.java | 13 ++++++++----- .../org/jackhuang/hmcl/util/VersionNumber.java | 12 +++++------- 5 files changed, 23 insertions(+), 20 deletions(-) diff --git a/HMCL/build.gradle b/HMCL/build.gradle index b162ec9f8..673386f29 100644 --- a/HMCL/build.gradle +++ b/HMCL/build.gradle @@ -18,7 +18,7 @@ if (buildnumber == null) def versionroot = System.getenv("VERSION_ROOT") if (versionroot == null) - versionroot = "3.0" + versionroot = "3.1" String mavenVersion = versionroot + '.' + buildnumber version = mavenVersion diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java b/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java index 058b33b4a..74911b03b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java @@ -49,6 +49,14 @@ public final class Launcher extends Application { Controllers.initialize(primaryStage); primaryStage.setResizable(false); primaryStage.setScene(Controllers.getScene()); + + UPDATE_CHECKER.process(false) + .then(Task.of(Schedulers.javafx(), () -> { + if (UPDATE_CHECKER.isOutOfDate()) + Controllers.showUpdate(); + })) + .start(); + primaryStage.show(); } catch (Throwable e) { CRASH_REPORTER.uncaughtException(Thread.currentThread(), e); @@ -65,13 +73,6 @@ public final class Launcher extends Application { Logging.LOG.info("*** " + TITLE + " ***"); - UPDATE_CHECKER.process(false) - .then(Task.of(Schedulers.javafx(), () -> { - if (UPDATE_CHECKER.isOutOfDate()) - Controllers.showUpdate(); - })) - .start(); - launch(args); } catch (Throwable e) { // Fucking JavaFX will suppress the exception and will break our crash reporter. CRASH_REPORTER.uncaughtException(Thread.currentThread(), e); 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 610753499..cbca99630 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java @@ -17,6 +17,7 @@ */ package org.jackhuang.hmcl.ui; +import com.jfoenix.concurrency.JFXUtilities; import com.jfoenix.controls.JFXDialog; import javafx.scene.Node; import javafx.scene.Scene; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/IntVersionNumber.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/IntVersionNumber.java index c96425e11..b2c5e966d 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/IntVersionNumber.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/IntVersionNumber.java @@ -43,11 +43,14 @@ public final class IntVersionNumber extends VersionNumber { if (!(o instanceof IntVersionNumber)) return 0; IntVersionNumber other = (IntVersionNumber) o; - int len = Math.min(this.version.size(), other.version.size()); - for (int i = 0; i < len; ++i) - if (!version.get(i).equals(other.version.get(i))) - return version.get(i).compareTo(other.version.get(i)); - return Integer.compare(this.version.size(), other.version.size()); + int len = Math.max(this.version.size(), other.version.size()); + for (int i = 0; i < len; ++i) { + int thisInt = Lang.get(this.version, i).orElse(0); + int otherInt = Lang.get(other.version, i).orElse(0); + if (thisInt != otherInt) + return Integer.compare(thisInt, otherInt); + } + return 0; } @Override diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/VersionNumber.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/VersionNumber.java index d9fefc1f3..a510439ab 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/VersionNumber.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/VersionNumber.java @@ -40,13 +40,11 @@ public abstract class VersionNumber implements Comparable { throw new IllegalArgumentException("The version " + version + " is malformed, only dots and digits are allowed."); String[] s = version.split("\\."); - int last = s.length - 1; - for (int i = s.length - 1; i >= 0; --i) - if (Integer.parseInt(s[i]) == 0) - last = i; - ArrayList versions = new ArrayList<>(last + 1); - for (int i = 0; i <= last; ++i) - versions.add(Integer.parseInt(s[i])); + ArrayList versions = new ArrayList<>(s.length); + for (String value : s) versions.add(Integer.parseInt(value)); + while (!versions.isEmpty() && versions.get(versions.size() - 1) == 0) + versions.remove(versions.size() - 1); + return new IntVersionNumber(Collections.unmodifiableList(versions)); } From affe36a568ac1b9cfa9098a99c90b94ef514bd41 Mon Sep 17 00:00:00 2001 From: huangyuhui Date: Sun, 4 Mar 2018 23:29:27 +0800 Subject: [PATCH 17/24] Fix update again --- .../java/org/jackhuang/hmcl/Launcher.java | 4 +- .../main/java/org/jackhuang/hmcl/Main.java | 3 +- .../java/org/jackhuang/hmcl/ui/FXUtils.java | 29 +++++++++++ .../hmcl/ui/construct/MessageBox.java | 52 ++++++++++--------- .../hmcl/upgrade/AppDataUpgrader.java | 26 ++++++---- .../java/org/jackhuang/hmcl/util/Logging.java | 8 +++ 6 files changed, 86 insertions(+), 36 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java b/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java index 74911b03b..17855e8b7 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java @@ -67,6 +67,8 @@ public final class Launcher extends Application { Thread.setDefaultUncaughtExceptionHandler(CRASH_REPORTER); try { + Logging.start(); + // NetworkUtils.setUserAgentSupplier(() -> "Hello Minecraft! Launcher"); Constants.UI_THREAD_SCHEDULER = Constants.JAVAFX_UI_THREAD_SCHEDULER; UPGRADER.parseArguments(VersionNumber.asVersion(VERSION), Arrays.asList(args)); @@ -134,7 +136,7 @@ public final class Launcher extends Application { public static final File MINECRAFT_DIRECTORY = getWorkingDirectory("minecraft"); public static final File HMCL_DIRECTORY = getWorkingDirectory("hmcl"); - public static final String VERSION = "@HELLO_MINECRAFT_LAUNCHER_VERSION_FOR_GRADLE_REPLACING@"; + public static final String VERSION = "2.9"; public static final String NAME = "HMCL"; public static final String TITLE = NAME + " " + VERSION; public static final ResourceBundle RESOURCE_BUNDLE = Settings.INSTANCE.getLocale().getResourceBundle(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/Main.java b/HMCL/src/main/java/org/jackhuang/hmcl/Main.java index 7642e2153..d59c831a2 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/Main.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/Main.java @@ -26,9 +26,8 @@ public final class Main { public static void main(String[] args) { String currentDirectory = new File("").getAbsolutePath(); - Logging.LOG.info("Current directory: " + currentDirectory); if (currentDirectory.contains("!")) { - Logging.LOG.severe("Exclamation mark(!) is not allowed in the path where HMCL is in. Forcibly exit."); + System.err.println("Exclamation mark(!) is not allowed in the path where HMCL is in. Forcibly exit."); // No Chinese translation because both Swing and JavaFX cannot render Chinese character properly when exclamation mark exists in the path. String message = "Exclamation mark(!) is not allowed in the path where HMCL is in.\nThe path is " + currentDirectory; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java index e09ed5c0e..d62349ce6 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java @@ -23,6 +23,7 @@ import javafx.animation.Animation; import javafx.animation.Interpolator; import javafx.animation.KeyFrame; import javafx.animation.Timeline; +import javafx.application.Platform; import javafx.beans.property.Property; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; @@ -48,7 +49,10 @@ import java.io.File; import java.io.IOException; import java.net.URI; import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; +import java.util.function.Supplier; import java.util.logging.Level; import static org.jackhuang.hmcl.util.ReflectionHelper.call; @@ -368,6 +372,31 @@ public final class FXUtils { }); } + public static T runInUIThread(Supplier supplier) { + if (javafx.application.Platform.isFxApplicationThread()) { + return supplier.get(); + } else { + CountDownLatch doneLatch = new CountDownLatch(1); + AtomicReference reference = new AtomicReference<>(); + Platform.runLater(() -> { + try { + reference.set(supplier.get()); + } finally { + doneLatch.countDown(); + } + + }); + + try { + doneLatch.await(); + } catch (InterruptedException var3) { + Thread.currentThread().interrupt(); + } + + return reference.get(); + } + } + public static final Image DEFAULT_ICON = new Image("/assets/img/icon.png"); public static final Interpolator SINE = new Interpolator() { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MessageBox.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MessageBox.java index 4d10f1a64..528e0b55a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MessageBox.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MessageBox.java @@ -17,10 +17,12 @@ */ package org.jackhuang.hmcl.ui.construct; +import com.jfoenix.concurrency.JFXUtilities; import javafx.scene.control.Alert; import javafx.scene.control.ButtonType; import javafx.scene.control.TextInputDialog; import org.jackhuang.hmcl.Launcher; +import org.jackhuang.hmcl.ui.FXUtils; import javax.swing.*; import java.util.Optional; @@ -123,30 +125,32 @@ public final class MessageBox { } public static int confirm(String message, String title, int option) { - Alert alert = new Alert(Alert.AlertType.CONFIRMATION); - alert.setTitle(title); - alert.setHeaderText(title); - alert.setContentText(message); - switch (option) { - case YES_NO_OPTION: - alert.getButtonTypes().setAll(ButtonType.YES, ButtonType.NO); - break; - case YES_NO_CANCEL_OPTION: - alert.getButtonTypes().setAll(ButtonType.YES, ButtonType.NO, ButtonType.CANCEL); - break; - case OK_CANCEL_OPTION: - alert.getButtonTypes().setAll(ButtonType.OK, ButtonType.CANCEL); - break; - default: - throw new IllegalArgumentException("Unrecognized message box option " + option); - } - Optional buttonType = alert.showAndWait(); - if (!buttonType.isPresent()) return CLOSED_OPTION; - else if (buttonType.get() == ButtonType.OK) return OK_OPTION; - else if (buttonType.get() == ButtonType.YES) return YES_OPTION; - else if (buttonType.get() == ButtonType.NO) return NO_OPTION; - else if (buttonType.get() == ButtonType.CANCEL) return CANCEL_OPTION; - else throw new IllegalStateException("Unrecognized button type:" + buttonType.get()); + return FXUtils.runInUIThread(() -> { + Alert alert = new Alert(Alert.AlertType.CONFIRMATION); + alert.setTitle(title); + alert.setHeaderText(title); + alert.setContentText(message); + switch (option) { + case YES_NO_OPTION: + alert.getButtonTypes().setAll(ButtonType.YES, ButtonType.NO); + break; + case YES_NO_CANCEL_OPTION: + alert.getButtonTypes().setAll(ButtonType.YES, ButtonType.NO, ButtonType.CANCEL); + break; + case OK_CANCEL_OPTION: + alert.getButtonTypes().setAll(ButtonType.OK, ButtonType.CANCEL); + break; + default: + throw new IllegalArgumentException("Unrecognized message box option " + option); + } + Optional buttonType = alert.showAndWait(); + if (!buttonType.isPresent()) return CLOSED_OPTION; + else if (buttonType.get() == ButtonType.OK) return OK_OPTION; + else if (buttonType.get() == ButtonType.YES) return YES_OPTION; + else if (buttonType.get() == ButtonType.NO) return NO_OPTION; + else if (buttonType.get() == ButtonType.CANCEL) return CANCEL_OPTION; + else throw new IllegalStateException("Unexpected button type:" + buttonType.get()); + }); } public static Optional input(String message) { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/AppDataUpgrader.java b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/AppDataUpgrader.java index b0c590e58..eca7caf91 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/AppDataUpgrader.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/AppDataUpgrader.java @@ -19,6 +19,7 @@ package org.jackhuang.hmcl.upgrade; import com.google.gson.JsonParseException; import com.google.gson.reflect.TypeToken; +import com.jfoenix.concurrency.JFXUtilities; import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.task.FileDownloadTask; import org.jackhuang.hmcl.task.Schedulers; @@ -54,12 +55,19 @@ public class AppDataUpgrader extends IUpgrader { if (mainClass != null) { ArrayList al = new ArrayList<>(args); al.add("--noupdate"); - AccessController.doPrivileged((PrivilegedExceptionAction) () -> { - new URLClassLoader(new URL[]{jar.toURI().toURL()}, - ClassLoader.getSystemClassLoader().getParent()).loadClass(mainClass) - .getMethod("main", String[].class).invoke(null, new Object[]{al.toArray(new String[0])}); - return null; - }); + ClassLoader pre = Thread.currentThread().getContextClassLoader(); + try { + AccessController.doPrivileged((PrivilegedExceptionAction) () -> { + Logging.stop(); + ClassLoader now = new URLClassLoader(new URL[]{jar.toURI().toURL()}, ClassLoader.getSystemClassLoader().getParent()); + Thread.currentThread().setContextClassLoader(now); + now.loadClass(mainClass).getMethod("main", String[].class).invoke(null, new Object[]{al.toArray(new String[0])}); + return null; + }); + } finally { + Logging.start(); + Thread.currentThread().setContextClassLoader(pre); + } return true; } } @@ -96,10 +104,10 @@ public class AppDataUpgrader extends IUpgrader { if (!(ver instanceof IntVersionNumber)) return; IntVersionNumber version = (IntVersionNumber) ver; - checker.requestDownloadLink().then(Task.of(Schedulers.javafx(), variables -> { + checker.requestDownloadLink().then(Task.of(variables -> { Map map = variables.get(UpdateChecker.REQUEST_DOWNLOAD_LINK_ID); - if (MessageBox.confirm(Launcher.i18n("update.newest_version") + version.toString() + "\n" + if (MessageBox.confirm(Launcher.i18n("update.newest_version", version.toString()) + "\n" + Launcher.i18n("update.should_open_link"), MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION) if (map != null && map.containsKey("jar") && !StringUtils.isBlank(map.get("jar"))) @@ -122,7 +130,7 @@ public class AppDataUpgrader extends IUpgrader { String hash = null; if (map.containsKey("packsha1")) hash = map.get("packsha1"); - Controllers.dialog(Launcher.i18n("message.downloading")); + JFXUtilities.runInFX(() -> Controllers.dialog(Launcher.i18n("message.downloading"))); if (new AppDataUpgraderPackGzTask(NetworkUtils.toURL(map.get("pack")), version.toString(), hash).test()) { new ProcessBuilder(JavaVersion.fromCurrentEnvironment().getBinary().getAbsolutePath(), "-jar", AppDataUpgraderPackGzTask.getSelf(version.toString()).getAbsolutePath()) .directory(new File("").getAbsoluteFile()).start(); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Logging.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Logging.java index 107d69aca..26b88cac9 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Logging.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Logging.java @@ -35,6 +35,9 @@ public final class Logging { static { LOG = Logger.getLogger("HMCL"); + } + + public static void start() { LOG.setLevel(Level.FINER); LOG.setUseParentHandlers(false); @@ -63,6 +66,11 @@ public final class Logging { LOG.addHandler(streamHandler); } + public static void stop() { + for (Handler handler : LOG.getHandlers()) + LOG.removeHandler(handler); + } + public static String getLogs() { return OUTPUT_STREAM.toString(); } From 58c3ed9254363e061d0f6c74c7153389982265c3 Mon Sep 17 00:00:00 2001 From: huangyuhui Date: Sun, 4 Mar 2018 23:33:08 +0800 Subject: [PATCH 18/24] Fixed #302 --- HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java | 2 +- .../java/org/jackhuang/hmcl/ui/download/VersionsPage.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java b/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java index 17855e8b7..14909feba 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java @@ -136,7 +136,7 @@ public final class Launcher extends Application { public static final File MINECRAFT_DIRECTORY = getWorkingDirectory("minecraft"); public static final File HMCL_DIRECTORY = getWorkingDirectory("hmcl"); - public static final String VERSION = "2.9"; + public static final String VERSION = "@HELLO_MINECRAFT_LAUNCHER_VERSION_FOR_GRADLE_REPLACING@"; public static final String NAME = "HMCL"; public static final String TITLE = NAME + " " + VERSION; public static final ResourceBundle RESOURCE_BUNDLE = Settings.INSTANCE.getLocale().getResourceBundle(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java index 1e6d8a9cd..c8611384a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java @@ -89,10 +89,10 @@ public final class VersionsPage extends StackPane implements WizardPage, Refresh chkSnapshot.selectedProperty().addListener(listener); chkOld.selectedProperty().addListener(listener); - list.getSelectionModel().selectedItemProperty().addListener((a, b, newValue) -> { - if (newValue == null) + list.setOnMouseClicked(e -> { + if (list.getSelectionModel().getSelectedIndex() < 0) return; - controller.getSettings().put(libraryId, newValue.getRemoteVersion()); + controller.getSettings().put(libraryId, list.getSelectionModel().getSelectedItem().getRemoteVersion()); callback.run(); }); refresh(); From 41d313baffa17b176268dccd880e67e33768a4f1 Mon Sep 17 00:00:00 2001 From: huangyuhui Date: Sun, 4 Mar 2018 23:35:42 +0800 Subject: [PATCH 19/24] Fix #303 --- HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameVersion.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameVersion.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameVersion.java index ff1629a31..0f6d31303 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameVersion.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameVersion.java @@ -116,7 +116,7 @@ public final class GameVersion { .getEntry("net/minecraft/client/Minecraft.class"); if (minecraft != null) return getVersionOfOldMinecraft(f, minecraft); - ZipArchiveEntry main = f.getEntry("net/minecraft/client/main/Launcher.class"); + ZipArchiveEntry main = f.getEntry("net/minecraft/client/main/Main.class"); ZipArchiveEntry minecraftServer = f.getEntry("net/minecraft/server/MinecraftServer.class"); if ((main != null) && (minecraftServer != null)) return getVersionOfNewMinecraft(f, minecraftServer); From db08b61cfa85f3a70e27cfac63be8d760f15e86f Mon Sep 17 00:00:00 2001 From: huangyuhui Date: Mon, 5 Mar 2018 19:02:13 +0800 Subject: [PATCH 20/24] Fix #301 --- .../jackhuang/hmcl/game/LauncherHelper.java | 22 +++++---- .../org/jackhuang/hmcl/ui/Controllers.java | 8 +++- .../java/org/jackhuang/hmcl/ui/Decorator.java | 30 +++++++++---- .../hmcl/ui/InstallerController.java | 3 +- .../jackhuang/hmcl/ui/LeftPaneController.java | 2 +- .../java/org/jackhuang/hmcl/ui/MainPage.java | 11 +++-- .../hmcl/ui/construct/StackContainerPane.java | 45 +++++++++++++++++++ .../hmcl/upgrade/AppDataUpgrader.java | 11 ++--- .../main/resources/assets/fxml/decorator.fxml | 1 - .../java/org/jackhuang/hmcl/task/Task.java | 7 +++ 10 files changed, 104 insertions(+), 36 deletions(-) create mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/StackContainerPane.java 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 2f5596e5d..3fa53c0c1 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -100,7 +100,6 @@ public final class LauncherHelper { } } catch (AuthenticationException e) { variables.set("account", DialogController.logIn(account)); - JFXUtilities.runInFX(() -> Controllers.dialog(launchingStepsPane)); } })) .then(Task.of(Schedulers.javafx(), () -> emitStatus(LoadingState.LAUNCHING))) @@ -132,8 +131,10 @@ public final class LauncherHelper { Controllers.closeDialog(); }); } else - Platform.runLater(() -> - Controllers.dialog(Launcher.i18n("version.launch_script.success", scriptFile.getAbsolutePath()))); + Platform.runLater(() -> { + Controllers.closeDialog(); + Controllers.dialog(Launcher.i18n("version.launch_script.success", scriptFile.getAbsolutePath())); + }); })) .executor(); @@ -153,12 +154,11 @@ public final class LauncherHelper { public void onStop(boolean success, TaskExecutor executor) { if (!success) { Platform.runLater(() -> { + Controllers.closeDialog(); if (executor.getLastException() != null) Controllers.dialog(I18nException.getStackTrace(executor.getLastException()), scriptFile == null ? Launcher.i18n("launch.failed") : Launcher.i18n("version.launch_script.failed"), MessageBox.ERROR_MESSAGE, Controllers::closeDialog); - else - Controllers.closeDialog(); }); } launchingStepsPane.setExecutor(null); @@ -180,28 +180,28 @@ public final class LauncherHelper { flag = true; } - if (java.getParsedVersion() < JavaVersion.JAVA_8) { + if (!flag && java.getParsedVersion() < JavaVersion.JAVA_8) { Controllers.dialog(Launcher.i18n("launch.advice.newer_java"), Launcher.i18n("message.error"), MessageBox.ERROR_MESSAGE, onAccept); flag = true; } - if (java.getParsedVersion() >= JavaVersion.JAVA_9 && gameVersion.compareTo(VersionNumber.asVersion("1.12.5")) < 0 && version.getMainClass().contains("launchwrapper")) { + if (!flag && java.getParsedVersion() >= JavaVersion.JAVA_9 && gameVersion.compareTo(VersionNumber.asVersion("1.12.5")) < 0 && version.getMainClass().contains("launchwrapper")) { Controllers.dialog(Launcher.i18n("launch.advice.java9"), Launcher.i18n("message.error"), MessageBox.ERROR_MESSAGE, null); suggest = false; flag = true; } - if (java.getPlatform() == org.jackhuang.hmcl.util.Platform.BIT_32 && + if (!flag && java.getPlatform() == org.jackhuang.hmcl.util.Platform.BIT_32 && org.jackhuang.hmcl.util.Platform.IS_64_BIT) { Controllers.dialog(Launcher.i18n("launch.advice.different_platform"), Launcher.i18n("message.error"), MessageBox.ERROR_MESSAGE, onAccept); flag = true; } - if (java.getPlatform() == org.jackhuang.hmcl.util.Platform.BIT_32 && + if (!flag && java.getPlatform() == org.jackhuang.hmcl.util.Platform.BIT_32 && setting.getMaxMemory() > 1.5 * 1024) { Controllers.dialog(Launcher.i18n("launch.advice.too_large_memory_for_32bit"), Launcher.i18n("message.error"), MessageBox.ERROR_MESSAGE, onAccept); flag = true; } - if (OperatingSystem.TOTAL_MEMORY > 0 && OperatingSystem.TOTAL_MEMORY < setting.getMaxMemory()) { + if (!flag && OperatingSystem.TOTAL_MEMORY > 0 && OperatingSystem.TOTAL_MEMORY < setting.getMaxMemory()) { Controllers.dialog(Launcher.i18n("launch.advice.not_enough_space", OperatingSystem.TOTAL_MEMORY), Launcher.i18n("message.error"), MessageBox.ERROR_MESSAGE, onAccept); flag = true; } @@ -219,10 +219,8 @@ public final class LauncherHelper { } public void emitStatus(LoadingState state) { - launchingStepsPane.setTitle(state.getLocalizedMessage()); launchingStepsPane.setSubtitle((state.ordinal() + 1) + " / " + LoadingState.values().length); - Controllers.dialog(launchingStepsPane); } private void checkExit(LauncherVisibility v) { 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 cbca99630..52dad1769 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java @@ -33,6 +33,7 @@ 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 org.jackhuang.hmcl.util.Lang; import java.util.function.Consumer; @@ -122,7 +123,7 @@ public final class Controllers { public static JFXDialog dialog(Region content) { // TODO: temp fix - decorator.showDialog(new Region()); + decorator.showDialog(Lang.apply(new Region(), region -> region.getProperties().put("controllers", true))); return decorator.showDialog(content); } @@ -150,12 +151,15 @@ public final class Controllers { dialog(new InputDialogPane(text, decorator.getDialog(), onResult)); } + public static void taskDialog(TaskExecutor executor, String title, String subtitle) { + taskDialog(executor, title, subtitle, null); + } + 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); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java index a903880e4..863fb4c3d 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java @@ -17,6 +17,7 @@ */ package org.jackhuang.hmcl.ui; +import com.jfoenix.concurrency.JFXUtilities; import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXDialog; import com.jfoenix.controls.JFXDrawer; @@ -53,6 +54,7 @@ import org.jackhuang.hmcl.ui.animation.AnimationProducer; import org.jackhuang.hmcl.ui.animation.ContainerAnimations; import org.jackhuang.hmcl.ui.animation.TransitionHandler; import org.jackhuang.hmcl.ui.construct.AdvancedListBox; +import org.jackhuang.hmcl.ui.construct.StackContainerPane; import org.jackhuang.hmcl.ui.construct.TaskExecutorDialogWizardDisplayer; import org.jackhuang.hmcl.ui.wizard.*; import org.jackhuang.hmcl.util.FileUtils; @@ -82,11 +84,13 @@ public final class Decorator extends StackPane implements TaskExecutorDialogWiza private final boolean max, min; private final WizardController wizardController = new WizardController(this); private final Queue cancelQueue = new ConcurrentLinkedQueue<>(); + private final JFXDialog dialog; private double xOffset, yOffset, newX, newY, initX, initY; - private boolean allowMove, isDragging, dialogShown, maximized; + private boolean allowMove, isDragging, maximized; private BoundingBox originalBox, maximizedBox; private final TransitionHandler animationHandler; + private final StackContainerPane dialogPane = new StackContainerPane(); @FXML private StackPane contentPlaceHolder; @@ -119,8 +123,6 @@ public final class Decorator extends StackPane implements TaskExecutorDialogWiza @FXML private JFXHamburger titleBurger; @FXML - private JFXDialog dialog; - @FXML private JFXButton btnMin; @FXML private JFXButton btnMax; @@ -165,9 +167,21 @@ public final class Decorator extends StackPane implements TaskExecutorDialogWiza btnMax.fire(); }); + dialog = new JFXDialog() { + @Override + public void close() { + dialogPane.pop(); + if (dialogPane.getChildren().isEmpty()) + Platform.runLater(() -> { + if (dialogPane.getChildren().isEmpty()) + super.close(); + }); + } + }; + dialog.setOverlayClose(false); + drawerWrapper.getChildren().add(0, dialog); dialog.setDialogContainer(drawerWrapper); - dialog.setOnDialogClosed(e -> dialogShown = false); - dialog.setOnDialogOpened(e -> dialogShown = true); + dialog.setContent(dialogPane); if (!min) buttonsContainer.getChildren().remove(btnMin); if (!max) buttonsContainer.getChildren().remove(btnMax); @@ -531,10 +545,10 @@ public final class Decorator extends StackPane implements TaskExecutorDialogWiza } } - public JFXDialog showDialog(Region content) { - dialog.setContent(content); - if (!dialogShown) + public JFXDialog showDialog(Node node) { + if (dialogPane.isEmpty()) dialog.show(); + dialogPane.push(node); return dialog; } 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 10c614e0d..4a5ce5886 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerController.java @@ -20,6 +20,7 @@ package org.jackhuang.hmcl.ui; import javafx.fxml.FXML; import javafx.scene.control.ScrollPane; import javafx.scene.layout.VBox; +import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.download.MaintainTask; import org.jackhuang.hmcl.download.game.VersionJsonSaveTask; import org.jackhuang.hmcl.game.GameVersion; @@ -89,7 +90,7 @@ public class InstallerController { Optional gameVersion = GameVersion.minecraftVersion(profile.getRepository().getVersionJar(version)); if (!gameVersion.isPresent()) - Controllers.dialog("version.cannot_read"); + Controllers.dialog(Launcher.i18n("version.cannot_read")); else Controllers.getDecorator().startWizard(new InstallerWizardProvider(profile, gameVersion.get(), 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 2ca95b0bf..3f02eaa97 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java @@ -208,7 +208,7 @@ public final class LeftPaneController { .with(Task.of(Schedulers.javafx(), () -> { Controllers.closeDialog(); checkAccount(); - })).executor(), + })).executor(true), Launcher.i18n("modpack.installing"), "", null); flag = false; } catch (UnsupportedModpackException ignore) { 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 9b1eb0ea3..7c5ea4805 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java @@ -147,19 +147,18 @@ public final class MainPage extends StackPane implements DecoratorPage { chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(Launcher.i18n("modpack"), "*.zip")); File selectedFile = chooser.showOpenDialog(Controllers.getStage()); if (selectedFile != null) { - TaskExecutorDialogPane pane = new TaskExecutorDialogPane(null); try { TaskExecutor executor = ModpackHelper.getUpdateTask(profile, selectedFile, id, ModpackHelper.readModpackConfiguration(repository.getModpackConfiguration(id))) - .then(Task.of(Schedulers.javafx(), Controllers::closeDialog)).executor(); - pane.setExecutor(executor); - pane.setTitle(Launcher.i18n("modpack.update")); - executor.start(); - Controllers.dialog(pane); + .then(Task.of(Schedulers.javafx(), Controllers::closeDialog)).executor(true); + Controllers.taskDialog(executor, Launcher.i18n("modpack.update"), "", null); } catch (UnsupportedModpackException e) { + Controllers.closeDialog(); Controllers.dialog(Launcher.i18n("modpack.unsupported"), Launcher.i18n("message.error"), MessageBox.ERROR_MESSAGE); } catch (MismatchedModpackTypeException e) { + Controllers.closeDialog(); Controllers.dialog(Launcher.i18n("modpack.mismatched_type"), Launcher.i18n("message.error"), MessageBox.ERROR_MESSAGE); } catch (IOException e) { + Controllers.closeDialog(); Controllers.dialog(Launcher.i18n("modpack.invalid"), Launcher.i18n("message.error"), MessageBox.ERROR_MESSAGE); } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/StackContainerPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/StackContainerPane.java new file mode 100644 index 000000000..78f2a75d0 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/StackContainerPane.java @@ -0,0 +1,45 @@ +/* + * Hello Minecraft! Launcher. + * Copyright (C) 2017 huangyuhui + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see {http://www.gnu.org/licenses/}. + */ +package org.jackhuang.hmcl.ui.construct; + +import javafx.scene.Node; +import javafx.scene.layout.StackPane; + +import java.util.Stack; + +public class StackContainerPane extends StackPane { + private final Stack stack = new Stack<>(); + + public void push(Node node) { + if (node.getProperties().containsKey("controllers")) + stack.push(node); + getChildren().setAll(node); + } + + public void pop() { + stack.pop(); + if (stack.isEmpty()) + getChildren().setAll(); + else + getChildren().setAll(stack.peek()); + } + + public boolean isEmpty() { + return stack.isEmpty(); + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/AppDataUpgrader.java b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/AppDataUpgrader.java index eca7caf91..5ac4d50d1 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/AppDataUpgrader.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/AppDataUpgrader.java @@ -24,6 +24,7 @@ import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.task.FileDownloadTask; import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.task.TaskExecutor; import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.ui.construct.MessageBox; import org.jackhuang.hmcl.util.*; @@ -130,13 +131,15 @@ public class AppDataUpgrader extends IUpgrader { String hash = null; if (map.containsKey("packsha1")) hash = map.get("packsha1"); - JFXUtilities.runInFX(() -> Controllers.dialog(Launcher.i18n("message.downloading"))); - if (new AppDataUpgraderPackGzTask(NetworkUtils.toURL(map.get("pack")), version.toString(), hash).test()) { + Task task = new AppDataUpgraderPackGzTask(NetworkUtils.toURL(map.get("pack")), version.toString(), hash); + TaskExecutor executor = task.executor(); + JFXUtilities.runInFX(() -> Controllers.taskDialog(executor, Launcher.i18n("message.downloading"), "", null)); + if (executor.test()) { new ProcessBuilder(JavaVersion.fromCurrentEnvironment().getBinary().getAbsolutePath(), "-jar", AppDataUpgraderPackGzTask.getSelf(version.toString()).getAbsolutePath()) .directory(new File("").getAbsoluteFile()).start(); System.exit(0); } - Controllers.closeDialog(); + JFXUtilities.runInFX(Controllers::closeDialog); } catch (IOException ex) { Logging.LOG.log(Level.SEVERE, "Failed to create upgrader", ex); } @@ -147,8 +150,6 @@ public class AppDataUpgrader extends IUpgrader { url = map.get(OperatingSystem.CURRENT_OS.getCheckedName()); else if (map.containsKey(OperatingSystem.UNKNOWN.getCheckedName())) url = map.get(OperatingSystem.UNKNOWN.getCheckedName()); - if (url == null) - url = Launcher.PUBLISH; try { java.awt.Desktop.getDesktop().browse(new URI(url)); } catch (URISyntaxException | IOException e) { diff --git a/HMCL/src/main/resources/assets/fxml/decorator.fxml b/HMCL/src/main/resources/assets/fxml/decorator.fxml index c59288d70..fdbda6f8f 100644 --- a/HMCL/src/main/resources/assets/fxml/decorator.fxml +++ b/HMCL/src/main/resources/assets/fxml/decorator.fxml @@ -20,7 +20,6 @@ maxWidth="800">
- diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java index 1f614007b..281fb3dd0 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java @@ -205,6 +205,13 @@ public abstract class Task { return new TaskExecutor(this); } + public final TaskExecutor executor(boolean start) { + TaskExecutor executor = new TaskExecutor(this); + if (start) + executor.start(); + return executor; + } + public final TaskExecutor executor(TaskListener taskListener) { TaskExecutor executor = new TaskExecutor(this); executor.addTaskListener(taskListener); From 5eb46395ae66cbabe887beba63bf246aa9c58e03 Mon Sep 17 00:00:00 2001 From: huangyuhui Date: Mon, 5 Mar 2018 19:13:58 +0800 Subject: [PATCH 21/24] Close popup when deleted an account --- .../org/jackhuang/hmcl/ui/AccountPage.java | 19 ++++++++++++++++++- .../jackhuang/hmcl/ui/LeftPaneController.java | 1 + 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountPage.java index be8aded3b..05de0e601 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountPage.java @@ -18,6 +18,8 @@ package org.jackhuang.hmcl.ui; import com.jfoenix.controls.JFXButton; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; import javafx.fxml.FXML; @@ -37,8 +39,11 @@ import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.ui.construct.ComponentList; import org.jackhuang.hmcl.ui.wizard.DecoratorPage; +import java.util.Optional; + public class AccountPage extends StackPane implements DecoratorPage { private final StringProperty title; + private final ObjectProperty onDelete = new SimpleObjectProperty<>(this, "onDelete"); private final Account account; @@ -95,7 +100,7 @@ public class AccountPage extends StackPane implements DecoratorPage { @FXML private void onDelete() { Settings.INSTANCE.deleteAccount(account); - Controllers.navigate(null); + Optional.ofNullable(onDelete.get()).ifPresent(Runnable::run); } @FXML @@ -116,4 +121,16 @@ public class AccountPage extends StackPane implements DecoratorPage { public void setTitle(String title) { this.title.set(title); } + + public Runnable getOnDelete() { + return onDelete.get(); + } + + public ObjectProperty onDeleteProperty() { + return onDelete; + } + + public void setOnDelete(Runnable onDelete) { + this.onDelete.set(onDelete); + } } 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 3f02eaa97..87dc236fa 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java @@ -150,6 +150,7 @@ public final class LeftPaneController { item.setOnSettingsButtonClicked(e -> { AccountPage accountPage = new AccountPage(account); JFXPopup popup = new JFXPopup(accountPage); + accountPage.setOnDelete(popup::hide); popup.show((Node) e.getSource(), JFXPopup.PopupVPosition.TOP, JFXPopup.PopupHPosition.LEFT, e.getX(), e.getY()); }); ripplerContainer.setOnMouseClicked(e -> { From c60ae111efb8cffc10699a5545a796aebaa8b124 Mon Sep 17 00:00:00 2001 From: huangyuhui Date: Mon, 5 Mar 2018 20:07:30 +0800 Subject: [PATCH 22/24] Progress bar in account page --- .../org/jackhuang/hmcl/ui/AccountPage.java | 24 +++++++++++++++---- .../jackhuang/hmcl/ui/DialogController.java | 6 +---- .../jackhuang/hmcl/ui/LeftPaneController.java | 2 +- .../resources/assets/fxml/account-login.fxml | 2 +- .../main/resources/assets/fxml/account.fxml | 2 ++ 5 files changed, 25 insertions(+), 11 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountPage.java index 05de0e601..18d5a96c0 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountPage.java @@ -18,12 +18,14 @@ package org.jackhuang.hmcl.ui; import com.jfoenix.controls.JFXButton; +import com.jfoenix.controls.JFXProgressBar; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; import javafx.fxml.FXML; import javafx.scene.control.Label; +import javafx.scene.image.Image; import javafx.scene.layout.BorderPane; import javafx.scene.layout.StackPane; import org.jackhuang.hmcl.Launcher; @@ -44,7 +46,7 @@ import java.util.Optional; public class AccountPage extends StackPane implements DecoratorPage { private final StringProperty title; private final ObjectProperty onDelete = new SimpleObjectProperty<>(this, "onDelete"); - + private final VersionListItem item; private final Account account; @FXML @@ -65,9 +67,13 @@ public class AccountPage extends StackPane implements DecoratorPage { private JFXButton btnDelete; @FXML private JFXButton btnRefresh; + @FXML + private JFXProgressBar progressBar; - public AccountPage(Account account) { + public AccountPage(Account account, VersionListItem item) { this.account = account; + this.item = item; + title = new SimpleStringProperty(this, "title", Launcher.i18n("account") + " - " + account.getCharacter()); FXUtils.loadFXML(this, "/assets/fxml/account.fxml"); @@ -105,8 +111,18 @@ public class AccountPage extends StackPane implements DecoratorPage { @FXML private void onRefresh() { - if (account instanceof YggdrasilAccount) - AccountHelper.refreshSkinAsync((YggdrasilAccount) account).start(); + if (account instanceof YggdrasilAccount) { + progressBar.setVisible(true); + AccountHelper.refreshSkinAsync((YggdrasilAccount) account) + .finalized(Schedulers.javafx(), (variables, isDependentsSucceeded) -> { + progressBar.setVisible(false); + + if (isDependentsSucceeded) { + Image image = AccountHelper.getSkin((YggdrasilAccount) account, 4); + item.setImage(image, AccountHelper.getViewport(4)); + } + }).start(); + } } public String getTitle() { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/DialogController.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/DialogController.java index 97325326c..f3d7c48e2 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/DialogController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/DialogController.java @@ -37,11 +37,7 @@ public final class DialogController { AccountLoginPane pane = new AccountLoginPane(account, it -> { res.set(it); latch.countDown(); - Controllers.closeDialog(); - }, () -> { - latch.countDown(); - Controllers.closeDialog(); - }); + }, latch::countDown); pane.setDialog(Controllers.dialog(pane)); }); latch.await(); 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 87dc236fa..6b845f048 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java @@ -148,7 +148,7 @@ public final class LeftPaneController { VersionListItem item = new VersionListItem(account.getCharacter(), accountType(account)); RipplerContainer ripplerContainer = new RipplerContainer(item); item.setOnSettingsButtonClicked(e -> { - AccountPage accountPage = new AccountPage(account); + AccountPage accountPage = new AccountPage(account, item); JFXPopup popup = new JFXPopup(accountPage); accountPage.setOnDelete(popup::hide); popup.show((Node) e.getSource(), JFXPopup.PopupVPosition.TOP, JFXPopup.PopupHPosition.LEFT, e.getX(), e.getY()); diff --git a/HMCL/src/main/resources/assets/fxml/account-login.fxml b/HMCL/src/main/resources/assets/fxml/account-login.fxml index 97065068e..9402eae99 100644 --- a/HMCL/src/main/resources/assets/fxml/account-login.fxml +++ b/HMCL/src/main/resources/assets/fxml/account-login.fxml @@ -26,7 +26,7 @@ diff --git a/HMCL/src/main/resources/assets/fxml/account.fxml b/HMCL/src/main/resources/assets/fxml/account.fxml index ea116d355..98666ef13 100644 --- a/HMCL/src/main/resources/assets/fxml/account.fxml +++ b/HMCL/src/main/resources/assets/fxml/account.fxml @@ -4,6 +4,7 @@ + @@ -77,4 +78,5 @@ prefWidth="30" prefHeight="30"/> + From a03e3fea12b8e336770d896e5b0366d66065b91f Mon Sep 17 00:00:00 2001 From: huangyuhui Date: Mon, 5 Mar 2018 20:23:23 +0800 Subject: [PATCH 23/24] Logs stopApplication stack trace --- .../java/org/jackhuang/hmcl/Launcher.java | 25 +++++++++++-------- .../org/jackhuang/hmcl/task/Schedulers.java | 3 +++ 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java b/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java index 14909feba..5ad5a770a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java @@ -82,25 +82,28 @@ public final class Launcher extends Application { } public static void stopApplication() { - JFXUtilities.runInFX(() -> { - stopWithoutPlatform(); - Platform.exit(); - }); - } - - public static void stopWithoutPlatform() { - Logging.LOG.info("Stopping application without JavaFX Toolkit"); + Logging.LOG.info("Stopping application.\n" + StringUtils.getStackTrace(Thread.currentThread().getStackTrace())); JFXUtilities.runInFX(() -> { if (Controllers.getStage() == null) return; Controllers.getStage().close(); - - Logging.LOG.info("Shutting down executor services."); Schedulers.shutdown(); - Controllers.shutdown(); + Platform.exit(); + Lang.executeDelayed(OperatingSystem::forceGC, TimeUnit.SECONDS, 5, true); + }); + } + public static void stopWithoutPlatform() { + Logging.LOG.info("Stopping application without JavaFX Toolkit.\n" + StringUtils.getStackTrace(Thread.currentThread().getStackTrace())); + + JFXUtilities.runInFX(() -> { + if (Controllers.getStage() == null) + return; + Controllers.getStage().close(); + Schedulers.shutdown(); + Controllers.shutdown(); Lang.executeDelayed(OperatingSystem::forceGC, TimeUnit.SECONDS, 5, true); }); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Schedulers.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Schedulers.java index e1c2ca9fe..d6ed22131 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Schedulers.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Schedulers.java @@ -18,6 +18,7 @@ package org.jackhuang.hmcl.task; import org.jackhuang.hmcl.util.Constants; +import org.jackhuang.hmcl.util.Logging; import java.util.concurrent.*; @@ -115,6 +116,8 @@ public final class Schedulers { static final Scheduler NONE = new SchedulerImpl(Constants.emptyConsumer()); public static synchronized void shutdown() { + Logging.LOG.info("Shutting down executor services."); + if (CACHED_EXECUTOR != null) CACHED_EXECUTOR.shutdown(); From eb1a109afcc59bfe598de622f48c74191e090e4b Mon Sep 17 00:00:00 2001 From: huangyuhui Date: Mon, 5 Mar 2018 20:36:38 +0800 Subject: [PATCH 24/24] Fix IllegalArgumentException: Folder parameter must be a valid folder --- HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java | 3 ++- .../jackhuang/hmcl/ui/export/ModpackFileSelectionPage.java | 3 +++ HMCLCore/src/main/java/org/jackhuang/hmcl/util/ZipEngine.java | 4 ++-- 3 files changed, 7 insertions(+), 3 deletions(-) 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 7c5ea4805..c69ded871 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java @@ -127,7 +127,8 @@ public final class MainPage extends StackPane implements DecoratorPage { Controllers.dialog(Launcher.i18n("login.empty_username")); else { FileChooser chooser = new FileChooser(); - chooser.setInitialDirectory(repository.getRunDirectory(id)); + if (repository.getRunDirectory(id).isDirectory()) + chooser.setInitialDirectory(repository.getRunDirectory(id)); chooser.setTitle(Launcher.i18n("version.launch_script.save")); chooser.getExtensionFilters().add(OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS ? new FileChooser.ExtensionFilter(Launcher.i18n("extension.bat"), "*.bat") diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackFileSelectionPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackFileSelectionPage.java index 3c46bf7c9..16910cc5f 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackFileSelectionPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackFileSelectionPage.java @@ -66,6 +66,9 @@ public final class ModpackFileSelectionPage extends StackPane implements WizardP } private CheckBoxTreeItem getTreeItem(File file, String basePath) { + if (!file.exists()) + return null; + ModAdviser.ModSuggestion state = ModAdviser.ModSuggestion.SUGGESTED; if (basePath.length() > "minecraft/".length()) { state = adviser.advise(StringUtils.substringAfter(basePath, "minecraft/") + (file.isDirectory() ? "/" : ""), file.isDirectory()); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ZipEngine.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ZipEngine.java index ba11d3712..c121b576c 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ZipEngine.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ZipEngine.java @@ -70,10 +70,10 @@ public final class ZipEngine implements Closeable { * modified pathName, null if you dont want this file zipped */ private void putDirectoryImpl(File source, String basePath, BiFunction pathNameCallback) throws IOException { - File[] files; + File[] files = null; if (source.isDirectory()) files = source.listFiles(); - else + else if (source.isFile()) files = new File[] { source }; if (files == null)