From e31120be21c7aa86775dd2d03c45684f1d6fc753 Mon Sep 17 00:00:00 2001 From: huangyuhui Date: Sun, 22 Jul 2018 18:50:44 +0800 Subject: [PATCH] Friendly prompt that it cannot download some libraries successfully. --- .../jackhuang/hmcl/game/LauncherHelper.java | 3 ++ .../resources/assets/lang/I18N.properties | 1 + .../resources/assets/lang/I18N_zh.properties | 1 + .../assets/lang/I18N_zh_CN.properties | 1 + .../game/LibraryDownloadException.java | 34 +++++++++++++++++++ .../download/game/LibraryDownloadTask.java | 21 +++++++----- .../java/org/jackhuang/hmcl/task/Task.java | 10 ++++++ .../org/jackhuang/hmcl/task/TaskExecutor.java | 1 + 8 files changed, 63 insertions(+), 9 deletions(-) create mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/LibraryDownloadException.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 629412a05..e17bd7823 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -25,6 +25,7 @@ import org.jackhuang.hmcl.auth.AuthenticationException; import org.jackhuang.hmcl.auth.CredentialExpiredException; import org.jackhuang.hmcl.download.DefaultDependencyManager; import org.jackhuang.hmcl.download.MaintainTask; +import org.jackhuang.hmcl.download.game.LibraryDownloadException; import org.jackhuang.hmcl.launch.*; import org.jackhuang.hmcl.mod.CurseCompletionException; import org.jackhuang.hmcl.mod.CurseCompletionTask; @@ -190,6 +191,8 @@ public final class LauncherHelper { message = i18n("launch.failed.creating_process") + ex.getLocalizedMessage(); } else if (ex instanceof NotDecompressingNativesException) { message = i18n("launch.failed.decompressing_natives") + ex.getLocalizedMessage(); + } else if (ex instanceof LibraryDownloadException) { + message = i18n("launch.failed.download_library", ((LibraryDownloadException) ex).getLibrary().getName()) + "\n" + StringUtils.getStackTrace(ex.getCause()); } else { message = StringUtils.getStackTrace(ex); } diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index f0a3bb6b7..c2bd62f38 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -139,6 +139,7 @@ launch.failed=Unable to launch launch.failed.cannot_create_jvm=Java virtual machine cannot be created. Java arguments may have problems. You can enable the no args mode in the settings. launch.failed.creating_process=Failed to create process, maybe your java path is wrong, please modify your java path. launch.failed.decompressing_natives=Unable to decompress native libraries. +launch.failed.download_library=Unable to download library %s. launch.failed.executable_permission=Unable to add permission to the launch script launch.failed.exited_abnormally=Game exited abnormally, please visit the log, or ask someone for help. launch.state.dependencies=Dependencies diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index c1f4d560b..0feb4e914 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -139,6 +139,7 @@ launch.failed=啓動失敗 launch.failed.cannot_create_jvm=截獲到無法創建 Java 虛擬機,可能是 Java 參數有問題,可以在設置中開啓無參數模式啓動。 launch.failed.creating_process=啓動失敗,在創建新進程時發生錯誤,可能是 Java 路徑錯誤。 launch.failed.decompressing_natives=未能解壓遊戲本地庫。 +launch.failed.download_library=未能下载游戏依赖 %s. launch.failed.executable_permission=未能爲啓動文件添加執行權限。 launch.failed.exited_abnormally=遊戲非正常退出,請查看日志文件,或聯繫他人尋求幫助。 launch.state.dependencies=正在處理遊戲依賴 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 e081bff14..b3225bc20 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -139,6 +139,7 @@ launch.failed=启动失败 launch.failed.cannot_create_jvm=截获到无法创建 Java 虚拟机,可能是 Java 参数有问题,可以在设置中开启无参数模式启动。 launch.failed.creating_process=启动失败,在创建新进程时发生错误,可能是 Java 路径错误。 launch.failed.decompressing_natives=未能解压游戏本地库。 +launch.failed.download_library=未能下载游戏依赖 %s. launch.failed.executable_permission=未能为启动文件添加执行权限。 launch.failed.exited_abnormally=游戏非正常退出,请查看日志文件,或联系他人寻求帮助。 launch.state.dependencies=正在处理游戏依赖 diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/LibraryDownloadException.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/LibraryDownloadException.java new file mode 100644 index 000000000..5787153a1 --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/LibraryDownloadException.java @@ -0,0 +1,34 @@ +/* + * 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.download.game; + +import org.jackhuang.hmcl.game.Library; + +public class LibraryDownloadException extends Exception { + private final Library library; + + public LibraryDownloadException(Library library, Throwable cause) { + super("Unable to download library " + library, cause); + + this.library = library; + } + + public Library getLibrary() { + return library; + } +} 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 67de5b5bf..9340a9db6 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 @@ -55,7 +55,7 @@ public final class LibraryDownloadTask extends Task { @Override public Collection getDependents() { - return library.getChecksums() != null ? Collections.singleton(xzTask) : Collections.emptySet(); + return library.getChecksums() != null ? Collections.singleton(xzTask) : Collections.singleton(task); } @Override @@ -65,20 +65,23 @@ public final class LibraryDownloadTask extends Task { @Override public void execute() throws Exception { - if (isDependentsSucceeded() && library.getChecksums() != null) { + if (!isDependentsSucceeded()) { + // Since FileDownloadTask wraps the actual exception with another IOException. + // We should extract it letting the error message clearer. + Throwable t = library.getChecksums() != null ? xzTask.getLastException() : task.getLastException(); + if (t.getCause() != null && t.getCause() != t) + throw new LibraryDownloadException(library, t.getCause()); + else + throw new LibraryDownloadException(library, t); + } + + if (library.getChecksums() != null) { unpackLibrary(jar, FileUtils.readBytes(xzFile)); if (!checksumValid(jar, library.getChecksums())) throw new IOException("Checksum failed for " + library); - - downloaded = true; } } - @Override - public Collection getDependencies() { - return downloaded ? Collections.emptySet() : Collections.singleton(task); - } - private static boolean checksumValid(File libPath, List checksums) { try { if ((checksums == null) || (checksums.isEmpty())) { 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 faf596ede..424c223e9 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java @@ -63,6 +63,16 @@ public abstract class Task { this.state = state; } + private Throwable lastException = null; + + public Throwable getLastException() { + return lastException; + } + + void setLastException(Throwable e) { + lastException = e; + } + /** * The scheduler that decides how this task runs. */ 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 f3a0ace83..ffba18cf6 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java @@ -190,6 +190,7 @@ public final class TaskExecutor { } catch (SilentException | RejectedExecutionException e) { // do nothing } catch (Exception e) { + task.setLastException(e); lastException = e; variables.set(LAST_EXCEPTION_ID, e); if (task.getSignificance().shouldLog()) {